Commit 08202053 authored by keuchel@chromium.org's avatar keuchel@chromium.org

Avoid dynamic lookup when initializing let declared variables.

'Let's inside a 'with' would initialize the variable
using the StoreContextSlot runtime function which
would fail because it checks that the variable does
not hold the hole value.

Review URL: http://codereview.chromium.org/7792098

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9156 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8b82ad27
......@@ -1936,12 +1936,26 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ ldr(r1, MemOperand(fp, SlotOffset(slot)));
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(r1, ip);
__ Check(eq, "Let binding re-initialization.");
}
// Perform the assignment.
__ str(result_register(), MemOperand(fp, SlotOffset(slot)));
break;
case Slot::CONTEXT: {
MemOperand target = EmitSlotSearch(slot, r1);
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ ldr(r3, target);
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ cmp(r3, ip);
__ Check(eq, "Let binding re-initialization.");
}
// Perform the assignment and issue the write barrier.
__ str(result_register(), target);
// RecordWrite may destroy all its register arguments.
......@@ -1952,6 +1966,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
}
case Slot::LOOKUP:
ASSERT(op != Token::INIT_LET);
// Call the runtime for the assignment.
__ push(r0); // Value.
__ mov(r1, Operand(slot->var()->name()));
......
......@@ -1928,12 +1928,24 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ mov(edx, Operand(ebp, SlotOffset(slot)));
__ cmp(edx, isolate()->factory()->the_hole_value());
__ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment.
__ mov(Operand(ebp, SlotOffset(slot)), eax);
break;
case Slot::CONTEXT: {
MemOperand target = EmitSlotSearch(slot, ecx);
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ mov(edx, target);
__ cmp(edx, isolate()->factory()->the_hole_value());
__ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment and issue the write barrier.
__ mov(target, eax);
// The value of the assignment is in eax. RecordWrite clobbers its
......@@ -1945,6 +1957,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
}
case Slot::LOOKUP:
ASSERT(op != Token::INIT_LET);
// Call the runtime for the assignment.
__ push(eax); // Value.
__ push(esi); // Context.
......
......@@ -1850,18 +1850,21 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
block->AddStatement(new(zone()) ExpressionStatement(initialize));
}
// Add an assignment node to the initialization statement block if
// we still have a pending initialization value. We must distinguish
// between variables and constants: Variable initializations are simply
// Add an assignment node to the initialization statement block if we still
// have a pending initialization value. We must distinguish between
// different kinds of declarations: 'var' initializations are simply
// assignments (with all the consequences if they are inside a 'with'
// statement - they may change a 'with' object property). Constant
// initializations always assign to the declared constant which is
// always at the function scope level. This is only relevant for
// dynamically looked-up variables and constants (the start context
// for constant lookups is always the function context, while it is
// the top context for variables). Sigh...
// the top context for var declared variables). Sigh...
// For 'let' declared variables the initialization is in the same scope
// as the declaration. Thus dynamic lookups are unnecessary even if the
// block scope is inside a with.
if (value != NULL) {
bool in_with = is_const ? false : inside_with();
bool in_with = mode == Variable::VAR ? inside_with() : false;
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
......
......@@ -1848,12 +1848,24 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ movq(rdx, Operand(rbp, SlotOffset(slot)));
__ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
__ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment.
__ movq(Operand(rbp, SlotOffset(slot)), rax);
break;
case Slot::CONTEXT: {
MemOperand target = EmitSlotSearch(slot, rcx);
if (FLAG_debug_code && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
__ movq(rdx, target);
__ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
__ Check(equal, "Let binding re-initialization.");
}
// Perform the assignment and issue the write barrier.
__ movq(target, rax);
// The value of the assignment is in rax. RecordWrite clobbers its
......@@ -1865,6 +1877,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
}
case Slot::LOOKUP:
ASSERT(op != Token::INIT_LET);
// Call the runtime for the assignment.
__ push(rax); // Value.
__ push(rsi); // Context.
......
......@@ -415,6 +415,28 @@ with_block_4();
EndTest();
// With block and a block local variable.
BeginTest("With block 5");
function with_block_5() {
with({a:1}) {
let a = 2;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({a:2}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
with_block_5();
EndTest();
// Simple closure formed by returning an inner function referering to an outer
// block local variable and an outer function's parameter.
BeginTest("Closure 1");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment