Reviewers: fschneider,

Description:
Support OSR in for-in loops.

Modify PreProcessOsrEntry to work with OSR entries that have non-empty
expression stack.

Modify graph builder to take for-in state from environment instead of directly
referencing emitted instructions

R=fschnei...@chromium.org
TEST=test/mjsunit/compiler/optimized-for-in.js


Please review this at https://chromiumcodereview.appspot.com/9431030/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/hydrogen.h
  M src/hydrogen.cc
  M test/mjsunit/compiler/optimized-for-in.js


Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index dd8b402024834247cfcb252ab61acdc44667a5a8..9918e8518096044441006ae7a39ec0fe137b169d 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3058,15 +3058,24 @@ void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {

   set_current_block(osr_entry);
   int osr_entry_id = statement->OsrEntryId();
-  // We want the correct environment at the OsrEntry instruction.  Build
-  // it explicitly.  The expression stack should be empty.
-  ASSERT(environment()->ExpressionStackIsEmpty());
-  for (int i = 0; i < environment()->length(); ++i) {
+  int first_expression_index = environment()->first_expression_index();
+  int length = environment()->length();
+  for (int i = 0; i < first_expression_index; ++i) {
     HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
     AddInstruction(osr_value);
     environment()->Bind(i, osr_value);
   }

+  if (first_expression_index != length) {
+    environment()->Drop(length - first_expression_index);
+    for (int i = first_expression_index; i < length; ++i) {
+      HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue;
+      AddInstruction(osr_value);
+      environment()->Push(osr_value);
+    }
+  }
+
+
   AddSimulate(osr_entry_id);
   AddInstruction(new(zone()) HOsrEntry(osr_entry_id));
   HContext* context = new(zone()) HContext;
@@ -3274,15 +3283,17 @@ void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   HForInCacheArray::cast(array)->set_index_cache(
       HForInCacheArray::cast(index_cache));

+  PreProcessOsrEntry(stmt);
   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   current_block()->Goto(loop_entry);
   set_current_block(loop_entry);

-  HValue* index = Top();
+  HValue* index = environment()->ExpressionStackAt(0);
+  HValue* limit = environment()->ExpressionStackAt(1);

   // Check that we still have more keys.
   HCompareIDAndBranch* compare_index =
-      new(zone()) HCompareIDAndBranch(index, array_length, Token::LT);
+      new(zone()) HCompareIDAndBranch(index, limit, Token::LT);
   compare_index->SetInputRepresentation(Representation::Integer32());

   HBasicBlock* loop_body = graph()->CreateBasicBlock();
@@ -3299,11 +3310,15 @@ void HGraphBuilder::VisitForInStatement(ForInStatement* stmt) {

   HValue* key = AddInstruction(
       new(zone()) HLoadKeyedFastElement(
-          array, index, HLoadKeyedFastElement::OMIT_HOLE_CHECK));
+          environment()->ExpressionStackAt(2),  // Enum cache.
+          environment()->ExpressionStackAt(0),  // Iteration 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));
+  AddInstruction(new(zone()) HCheckMapValue(
+      environment()->ExpressionStackAt(4),
+      environment()->ExpressionStackAt(3)));

   Bind(each_var, key);

@@ -7440,9 +7455,8 @@ bool HEnvironment::HasExpressionAt(int index) const {


 bool HEnvironment::ExpressionStackIsEmpty() const {
- int first_expression = parameter_count() + specials_count() + local_count();
-  ASSERT(length() >= first_expression);
-  return length() == first_expression;
+  ASSERT(length() >= first_expression_index());
+  return length() == first_expression_index();
 }


Index: src/hydrogen.h
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 1226656cb85ffb8a0fbd733a859b0ad088471243..65aa346cbe4366d79d40f64ccbf9c65effc86eda 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -399,6 +399,10 @@ class HEnvironment: public ZoneObject {
return i >= parameter_count() && i < parameter_count() + specials_count();
   }

+  int first_expression_index() const {
+    return parameter_count() + specials_count() + local_count();
+  }
+
   void Bind(Variable* variable, HValue* value) {
     Bind(IndexFor(variable), value);
   }
Index: test/mjsunit/compiler/optimized-for-in.js
diff --git a/test/mjsunit/compiler/optimized-for-in.js b/test/mjsunit/compiler/optimized-for-in.js index c8076ac73659301608a806a834cab8268e949690..4b841b20d40bff78c3068abe03d3733a43951e84 100644
--- a/test/mjsunit/compiler/optimized-for-in.js
+++ b/test/mjsunit/compiler/optimized-for-in.js
@@ -242,3 +242,23 @@ tryFunction("a1b2c3d4e5f6", function () {
   for (var i in t) r.push(i + t[i]);
   return r.join('');
 });
+
+// Test OSR inside for each.
+function osr (t) {
+  var sum = 0;
+  for (var x in t) {
+      for (var i = 0; i < t[x].length; i++) {
+       sum += t[x][i];
+      }
+  }
+  return sum;
+}
+
+function test_osr() {
+  with ({}) {}  // Disable optimizations of this function.
+  var arr = new Array(1000000);
+  for (var i = 0; i < arr.length; i++) arr[i] = i;
+  osr({x: arr});
+}
+
+test_osr();


--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev

Reply via email to