}
+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();
}
}
%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();
+})();