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:
parent
53a5b07992
commit
28d5392bc0
@ -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.
|
block_finder.Update(stat);
|
||||||
// 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 =)
|
// 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;
|
||||||
|
Loading…
Reference in New Issue
Block a user