Fix replaying of HCapturedObject for nested objects.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 Sep 2013 15:28:46 +0000 (15:28 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 26 Sep 2013 15:28:46 +0000 (15:28 +0000)
R=titzer@chromium.org
TEST=mjsunit/compiler/property-refs,mjsunit/compiler/escape-analysis

Review URL: https://codereview.chromium.org/24561002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16969 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/hydrogen-instructions.cc
test/mjsunit/compiler/escape-analysis.js

index 6125ca2..a66b6ab 100644 (file)
@@ -2341,18 +2341,27 @@ void HSimulate::ReplayEnvironment(HEnvironment* env) {
 }
 
 
+static void ReplayEnvironmentNested(const ZoneList<HValue*>* values,
+                                    HCapturedObject* other) {
+  for (int i = 0; i < values->length(); ++i) {
+    HValue* value = values->at(i);
+    if (value->IsCapturedObject()) {
+      if (HCapturedObject::cast(value)->capture_id() == other->capture_id()) {
+        values->at(i) = other;
+      } else {
+        ReplayEnvironmentNested(HCapturedObject::cast(value)->values(), other);
+      }
+    }
+  }
+}
+
+
 // Replay captured objects by replacing all captured objects with the
 // same capture id in the current and all outer environments.
 void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
   ASSERT(env != NULL);
   while (env != NULL) {
-    for (int i = 0; i < env->length(); ++i) {
-      HValue* value = env->values()->at(i);
-      if (value->IsCapturedObject() &&
-          HCapturedObject::cast(value)->capture_id() == this->capture_id()) {
-        env->SetValueAt(i, this);
-      }
-    }
+    ReplayEnvironmentNested(env->values(), this);
     env = env->outer();
   }
 }
index 74e638a..21ebcbb 100644 (file)
   %OptimizeFunctionOnNextCall(oob);
   assertEquals(7, oob(cons2, true));
 })();
+
+
+// Test non-shallow nested graph of captured objects.
+(function testDeep() {
+  var deopt = { deopt:false };
+  function constructor1() {
+    this.x = 23;
+  }
+  function constructor2(nested) {
+    this.a = 17;
+    this.b = nested;
+    this.c = 42;
+  }
+  function deep() {
+    var o1 = new constructor1();
+    var o2 = new constructor2(o1);
+    assertEquals(17, o2.a);
+    assertEquals(23, o2.b.x);
+    assertEquals(42, o2.c);
+    o1.x = 99;
+    deopt.deopt;
+    assertEquals(99, o1.x);
+    assertEquals(99, o2.b.x);
+  }
+  deep(); deep();
+  %OptimizeFunctionOnNextCall(deep);
+  deep(); deep();
+  delete deopt.deopt;
+  deep(); deep();
+})();