Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Unified Diff: src/hydrogen.cc

Issue 9425045: Support fast case for-in in Crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: port to x64&arm, cleanup Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index de7d4236f69f5980ee95709879ff9057e8b1726e..aaf23a01d2ec61f8d9052f6c00aa9f11b8fd2e32 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2742,12 +2742,20 @@ void HGraphBuilder::VisitIfStatement(IfStatement* stmt) {
HBasicBlock* HGraphBuilder::BreakAndContinueScope::Get(
BreakableStatement* stmt,
- BreakType type) {
+ BreakType type,
+ int* drop_extra) {
+ *drop_extra = 0;
BreakAndContinueScope* current = this;
while (current != NULL && current->info()->target() != stmt) {
+ *drop_extra += current->info()->drop_extra();
current = current->next();
}
ASSERT(current != NULL); // Always found (unless stack is malformed).
+
+ if (type == BREAK) {
+ *drop_extra += current->info()->drop_extra();
+ }
+
HBasicBlock* block = NULL;
switch (type) {
case BREAK:
@@ -2775,7 +2783,11 @@ void HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE);
+ int drop_extra = 0;
+ HBasicBlock* continue_block = break_scope()->Get(stmt->target(),
+ CONTINUE,
+ &drop_extra);
+ Drop(drop_extra);
current_block()->Goto(continue_block);
set_current_block(NULL);
}
@@ -2785,7 +2797,11 @@ void HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK);
+ int drop_extra = 0;
+ HBasicBlock* break_block = break_scope()->Get(stmt->target(),
+ BREAK,
+ &drop_extra);
+ Drop(drop_extra);
current_block()->Goto(break_block);
set_current_block(NULL);
}
@@ -3146,7 +3162,6 @@ void HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
BreakAndContinueInfo break_info(stmt);
if (current_block() != NULL) {
- BreakAndContinueScope push(&break_info, this);
CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
}
HBasicBlock* body_exit =
@@ -3191,7 +3206,6 @@ void HGraphBuilder::VisitForStatement(ForStatement* stmt) {
BreakAndContinueInfo break_info(stmt);
if (current_block() != NULL) {
- BreakAndContinueScope push(&break_info, this);
CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
}
HBasicBlock* body_exit =
@@ -3216,7 +3230,104 @@ void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
ASSERT(current_block()->HasPredecessor());
- return Bailout("ForInStatement");
+
+ if (!stmt->each()->IsVariableProxy() ||
+ !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
+ return Bailout("ForInStatement with non-local each variable");
+ }
+
+ Variable* each_var = stmt->each()->AsVariableProxy()->var();
+
+ CHECK_ALIVE(VisitForValue(stmt->enumerable()));
+ HValue* enumerable = Top(); // Leave enumerable at the top.
+
+ HValue* context = environment()->LookupContext();
+
+ HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap(
+ context, enumerable));
+ AddSimulate(stmt->PrepareId());
+
+ HInstruction* array = AddInstruction(
+ new(zone()) HForInCacheArray(
+ enumerable,
+ map,
+ DescriptorArray::kEnumCacheBridgeCacheIndex));
+
+ HInstruction* array_length = AddInstruction(
+ new(zone()) HFixedArrayBaseLength(array));
+
+ HInstruction* start_index = AddInstruction(new(zone()) HConstant(
+ Handle<Object>(Smi::FromInt(0)), Representation::Integer32()));
+
+ Push(map);
+ Push(array);
+ Push(array_length);
+ Push(start_index);
+
+ HInstruction* index_cache = AddInstruction(
+ new(zone()) HForInCacheArray(
+ enumerable,
+ map,
+ DescriptorArray::kEnumCacheBridgeIndicesCacheIndex));
+ HForInCacheArray::cast(array)->set_index_cache(
+ HForInCacheArray::cast(index_cache));
+
+ HBasicBlock* loop_entry = CreateLoopHeaderBlock();
+ current_block()->Goto(loop_entry);
+ set_current_block(loop_entry);
+
+ HValue* index = Top();
+
+ // Check that we still have more keys.
+ HCompareIDAndBranch* compare_index =
+ new(zone()) HCompareIDAndBranch(index, array_length, Token::LT);
+ compare_index->SetInputRepresentation(Representation::Integer32());
+
+ HBasicBlock* loop_body = graph()->CreateBasicBlock();
+ HBasicBlock* loop_successor = graph()->CreateBasicBlock();
+
+ compare_index->SetSuccessorAt(0, loop_body);
+ compare_index->SetSuccessorAt(1, loop_successor);
+ current_block()->Finish(compare_index);
+
+ set_current_block(loop_successor);
+ Drop(5);
+
+ set_current_block(loop_body);
+
+ HValue* key = AddInstruction(
+ new(zone()) HLoadKeyedFastElement(
+ array, index, HLoadKeyedFastElement::OMIT_HOLE_CHECK));
+
+ // Check if the expected map still matches that of the enumerable.
+ // If not just deoptimize.
+ AddInstruction(new(zone()) HCheckMapValue(enumerable, map));
+
+ Bind(each_var, key);
+
+ BreakAndContinueInfo break_info(stmt, 5);
+ CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info));
+
+ HBasicBlock* body_exit =
+ JoinContinue(stmt, current_block(), break_info.continue_block());
+
+ if (body_exit != NULL) {
+ set_current_block(body_exit);
+
+ HValue* current_index = Pop();
+ PushAndAdd(
+ new(zone()) HAdd(context, current_index, graph()->GetConstant1()));
+
+ body_exit = current_block();
+ }
+
+ HBasicBlock* loop_exit = CreateLoop(stmt,
+ loop_entry,
+ body_exit,
+ loop_successor,
+ break_info.break_block());
+
+ set_current_block(loop_exit);
}

Powered by Google App Engine
This is Rietveld 408576698