Revision: 9541
Author: [email protected]
Date: Thu Oct 6 08:24:20 2011
Log: Fix load of potentially eval-shadowed let bindings.
BUG=
TEST=test/mjsunit/harmony/block-let-semantics.js
Review URL: http://codereview.chromium.org/8118032
http://code.google.com/p/v8/source/detail?r=9541
Modified:
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/test/mjsunit/harmony/block-let-semantics.js
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Sep 23 02:31:20
2011
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Oct 6 08:24:20
2011
@@ -1225,9 +1225,17 @@
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == Variable::CONST ||
+ local->mode() == Variable::LET) {
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+ if (local->mode() == Variable::CONST) {
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
+ } else { // Variable::LET
+ __ b(ne, done);
+ __ mov(r0, Operand(var->name()));
+ __ push(r0);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ }
}
__ jmp(done);
}
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Oct 3
04:44:39 2011
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Oct 6
08:24:20 2011
@@ -1207,10 +1207,16 @@
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == Variable::CONST ||
+ local->mode() == Variable::LET) {
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, done);
- __ mov(eax, isolate()->factory()->undefined_value());
+ if (local->mode() == Variable::CONST) {
+ __ mov(eax, isolate()->factory()->undefined_value());
+ } else { // Variable::LET
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ }
}
__ jmp(done);
}
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Sep 23 07:19:04
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Oct 6 08:24:20
2011
@@ -1184,10 +1184,16 @@
} else if (var->mode() == Variable::DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ movq(rax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == Variable::CONST) {
+ if (local->mode() == Variable::CONST ||
+ local->mode() == Variable::LET) {
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, done);
- __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+ if (local->mode() == Variable::CONST) {
+ __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
+ } else { // Variable::LET
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ }
}
__ jmp(done);
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/block-let-semantics.js Mon
Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/test/mjsunit/harmony/block-let-semantics.js Thu
Oct 6 08:24:20 2011
@@ -81,13 +81,20 @@
TestAll('f()(); let x; function f() { return function() { ++x; } }');
TestAll('f()(); let x; function f() { return function() { x++; } }');
-// Use in before initialization with a dynamic lookup.
+// Use before initialization with a dynamic lookup.
TestAll('eval("x + 1;"); let x;');
TestAll('eval("x = 1;"); let x;');
TestAll('eval("x += 1;"); let x;');
TestAll('eval("++x;"); let x;');
TestAll('eval("x++;"); let x;');
+// Use before initialization with check for eval-shadowed bindings.
+TestAll('function f() { eval("var y = 2;"); x + 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x = 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x += 1; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); ++x; }; f(); let x;');
+TestAll('function f() { eval("var y = 2;"); x++; }; f(); let x;');
+
// Test that variables introduced by function declarations are created and
// initialized upon entering a function / block scope.
function f() {
@@ -136,3 +143,19 @@
}
assertEquals(5, n());
}
+
+// Test that resolution of let bound variables works with scopes that call
eval.
+function outer() {
+ function middle() {
+ function inner() {
+ return x;
+ }
+ eval("1 + 1");
+ return x + inner();
+ }
+
+ let x = 1;
+ return middle();
+}
+
+assertEquals(2, outer());
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev