Commit 227e679c authored by keuchel@chromium.org's avatar keuchel@chromium.org

MIPS: port Temporal dead zone behaviour for let bindings.

Ported r9070 (1cfdac01)

BUG=
TEST=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9080 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 07c1c9eb
...@@ -700,12 +700,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -700,12 +700,12 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
switch (slot->type()) { switch (slot->type()) {
case Slot::PARAMETER: case Slot::PARAMETER:
case Slot::LOCAL: case Slot::LOCAL:
if (mode == Variable::CONST) { if (function != NULL) {
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, MemOperand(fp, SlotOffset(slot)));
} else if (function != NULL) {
VisitForAccumulatorValue(function); VisitForAccumulatorValue(function);
__ sw(result_register(), MemOperand(fp, SlotOffset(slot))); __ sw(result_register(), MemOperand(fp, SlotOffset(slot)));
} else if (mode == Variable::CONST || mode == Variable::LET) {
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, MemOperand(fp, SlotOffset(slot)));
} }
break; break;
...@@ -726,17 +726,17 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -726,17 +726,17 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ Check(ne, "Declaration in catch context.", __ Check(ne, "Declaration in catch context.",
a1, Operand(t0)); a1, Operand(t0));
} }
if (mode == Variable::CONST) { if (function != NULL) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sw(at, ContextOperand(cp, slot->index()));
// No write barrier since the_hole_value is in old space.
} else if (function != NULL) {
VisitForAccumulatorValue(function); VisitForAccumulatorValue(function);
__ sw(result_register(), ContextOperand(cp, slot->index())); __ sw(result_register(), ContextOperand(cp, slot->index()));
int offset = Context::SlotOffset(slot->index()); int offset = Context::SlotOffset(slot->index());
// We know that we have written a function, which is not a smi. // We know that we have written a function, which is not a smi.
__ mov(a1, cp); __ mov(a1, cp);
__ RecordWrite(a1, Operand(offset), a2, result_register()); __ RecordWrite(a1, Operand(offset), a2, result_register());
} else if (mode == Variable::CONST || mode == Variable::LET) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sw(at, ContextOperand(cp, slot->index()));
// No write barrier since the_hole_value is in old space.
} }
break; break;
...@@ -752,13 +752,13 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -752,13 +752,13 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// Note: For variables we must not push an initial value (such as // Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we // 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value. // must not destroy the current value.
if (mode == Variable::CONST) { if (function != NULL) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
} else if (function != NULL) {
__ Push(cp, a2, a1); __ Push(cp, a2, a1);
// Push initial value for function declaration. // Push initial value for function declaration.
VisitForStackValue(function); VisitForStackValue(function);
} else if (mode == Variable::CONST || mode == Variable::LET) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
} else { } else {
ASSERT(Smi::FromInt(0) == 0); ASSERT(Smi::FromInt(0) == 0);
// No initial value! // No initial value!
...@@ -1279,9 +1279,22 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { ...@@ -1279,9 +1279,22 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex); __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ movz(v0, a0, at); // Conditional move. __ movz(v0, a0, at); // Conditional move.
context()->Plug(v0); context()->Plug(v0);
} else { } else if (var->mode() == Variable::LET) {
context()->Plug(slot); // Let bindings may be the hole value if they have not been initialized.
} // Throw a type error in this case.
Label done;
MemOperand slot_operand = EmitSlotSearch(slot, a0);
__ lw(v0, slot_operand);
__ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
__ Branch(&done, ne, v0, Operand(a1));
__ li(v0, Operand(var->name()));
__ push(v0);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&done);
context()->Plug(v0);
} else {
context()->Plug(slot);
}
} }
} }
...@@ -1863,6 +1876,56 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1863,6 +1876,56 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
break; break;
} }
__ bind(&skip); __ bind(&skip);
} else if (var->mode() == Variable::LET && op != Token::INIT_LET) {
// Perform the assignment for non-const variables. Const assignments
// are simply skipped.
Slot* slot = var->AsSlot();
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL: {
Label assign;
// Check for an initialized let binding.
__ lw(a1, MemOperand(fp, SlotOffset(slot)));
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ Branch(&assign, ne, a1, Operand(t0));
__ li(a1, Operand(var->name()));
__ push(a1);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
// Perform the assignment.
__ bind(&assign);
__ sw(result_register(), MemOperand(fp, SlotOffset(slot)));
break;
}
case Slot::CONTEXT: {
// Let variables may be the hole value if they have not been
// initialized. Throw a type error in this case.
Label assign;
MemOperand target = EmitSlotSearch(slot, a1);
// Check for an initialized let binding.
__ lw(a3, target);
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ Branch(&assign, ne, a3, Operand(t0));
__ li(a3, Operand(var->name()));
__ push(a3);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
// Perform the assignment.
__ bind(&assign);
__ sw(result_register(), target);
// RecordWrite may destroy all its register arguments.
__ mov(a3, result_register());
int offset = Context::SlotOffset(slot->index());
__ RecordWrite(a1, Operand(offset), a2, a3);
break;
}
case Slot::LOOKUP:
// Call the runtime for the assignment.
__ push(v0); // Value.
__ li(a1, Operand(slot->var()->name()));
__ li(a0, Operand(Smi::FromInt(strict_mode_flag())));
__ Push(cp, a1, a0); // Context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
break;
}
} else if (var->mode() != Variable::CONST) { } else if (var->mode() != Variable::CONST) {
// Perform the assignment for non-const variables. Const assignments // Perform the assignment for non-const variables. Const assignments
......
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