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. // form expr.a = ...; expr.b = ...; etc.
class InitializationBlockFinder : public ParserFinder { class InitializationBlockFinder : public ParserFinder {
public: public:
InitializationBlockFinder() // We find and mark the initialization blocks in top level
: first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {} // 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() { ~InitializationBlockFinder() {
if (!enabled_) return;
if (InBlock()) EndBlock(); if (InBlock()) EndBlock();
} }
void Update(Statement* stat) { void Update(Statement* stat) {
if (!enabled_) return;
Assignment* assignment = AsAssignment(stat); Assignment* assignment = AsAssignment(stat);
if (InBlock()) { if (InBlock()) {
if (BlockContinues(assignment)) { if (BlockContinues(assignment)) {
@ -851,6 +861,14 @@ class InitializationBlockFinder : public ParserFinder {
// the overhead exceeds the savings below this limit. // the overhead exceeds the savings below this limit.
static const int kMinInitializationBlock = 3; 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. // Returns true if the expressions appear to denote the same object.
// In the context of initialization blocks, we only consider expressions // In the context of initialization blocks, we only consider expressions
// of the form 'expr.x' or expr["x"]. // of the form 'expr.x' or expr["x"].
@ -913,6 +931,7 @@ class InitializationBlockFinder : public ParserFinder {
bool InBlock() { return first_in_block_ != NULL; } bool InBlock() { return first_in_block_ != NULL; }
const bool enabled_;
Assignment* first_in_block_; Assignment* first_in_block_;
Assignment* last_in_block_; Assignment* last_in_block_;
int block_size_; int block_size_;
@ -1078,7 +1097,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
TargetScope scope(&this->target_stack_); TargetScope scope(&this->target_stack_);
ASSERT(processor != NULL); ASSERT(processor != NULL);
InitializationBlockFinder block_finder; InitializationBlockFinder block_finder(top_scope_, target_stack_);
ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate());
bool directive_prologue = true; // Parsing directive prologue. 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); block_finder.Update(stat);
}
// Find and mark all assignments to named properties in this (this.x =) // Find and mark all assignments to named properties in this (this.x =)
if (top_scope_->is_function_scope()) { if (top_scope_->is_function_scope()) {
this_property_assignment_finder.Update(top_scope_, stat); 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); Block* result = new(zone()) Block(labels, 16, false);
Target target(&this->target_stack_, result); Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK); Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
while (peek() != Token::RBRACE) { while (peek() != Token::RBRACE) {
Statement* stat = ParseStatement(NULL, CHECK_OK); 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); Expect(Token::RBRACE, CHECK_OK);
return result; return result;