Group property assignments in top-level blocks.

This patch enables insertion of To{Slow,Fast}Properties around a group
of assigments to the same object even when they are put in a block
(e.g. try-catch, if, etc.). Catching exceptions and disabling parts of
code based on some config vars is rather common in top-level code.

R=vegorov@chromium.org

Review URL: http://codereview.chromium.org/7314002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8558 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2011-07-06 17:21:32 +00:00
parent 53a5b07992
commit 28d5392bc0

View File

@ -823,14 +823,24 @@ class ParserFinder {
// form expr.a = ...; expr.b = ...; etc.
class InitializationBlockFinder : public ParserFinder {
public:
InitializationBlockFinder()
: first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
// We find and mark the initialization blocks in top level
// non-looping code only. This is because the optimization prevents
// reuse of the map transitions, so it should be used only for code
// that will only be run once.
InitializationBlockFinder(Scope* top_scope, Target* target)
: enabled_(top_scope->DeclarationScope()->is_global_scope() &&
!IsLoopTarget(target)),
first_in_block_(NULL),
last_in_block_(NULL),
block_size_(0) {}
~InitializationBlockFinder() {
if (!enabled_) return;
if (InBlock()) EndBlock();
}
void Update(Statement* stat) {
if (!enabled_) return;
Assignment* assignment = AsAssignment(stat);
if (InBlock()) {
if (BlockContinues(assignment)) {
@ -851,6 +861,14 @@ class InitializationBlockFinder : public ParserFinder {
// the overhead exceeds the savings below this limit.
static const int kMinInitializationBlock = 3;
static bool IsLoopTarget(Target* target) {
while (target != NULL) {
if (target->node()->AsIterationStatement() != NULL) return true;
target = target->previous();
}
return false;
}
// Returns true if the expressions appear to denote the same object.
// In the context of initialization blocks, we only consider expressions
// of the form 'expr.x' or expr["x"].
@ -913,6 +931,7 @@ class InitializationBlockFinder : public ParserFinder {
bool InBlock() { return first_in_block_ != NULL; }
const bool enabled_;
Assignment* first_in_block_;
Assignment* last_in_block_;
int block_size_;
@ -1078,7 +1097,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
TargetScope scope(&this->target_stack_);
ASSERT(processor != NULL);
InitializationBlockFinder block_finder;
InitializationBlockFinder block_finder(top_scope_, target_stack_);
ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
bool directive_prologue = true; // Parsing directive prologue.
@ -1133,12 +1152,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
}
}
// We find and mark the initialization blocks on top level code only.
// This is because the optimization prevents reuse of the map transitions,
// so it should be used only for code that will only be run once.
if (top_scope_->is_global_scope()) {
block_finder.Update(stat);
}
// Find and mark all assignments to named properties in this (this.x =)
if (top_scope_->is_function_scope()) {
this_property_assignment_finder.Update(top_scope_, stat);
@ -1478,9 +1492,13 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
Block* result = new(zone()) Block(labels, 16, false);
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
while (peek() != Token::RBRACE) {
Statement* stat = ParseStatement(NULL, CHECK_OK);
if (stat && !stat->IsEmpty()) result->AddStatement(stat);
if (stat && !stat->IsEmpty()) {
result->AddStatement(stat);
block_finder.Update(stat);
}
}
Expect(Token::RBRACE, CHECK_OK);
return result;