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,
switch (slot->type()) {
case Slot::PARAMETER:
case Slot::LOCAL:
if (mode == Variable::CONST) {
__ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
__ sw(t0, MemOperand(fp, SlotOffset(slot)));
} else if (function != NULL) {
if (function != NULL) {
VisitForAccumulatorValue(function);
__ 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;
......@@ -726,17 +726,17 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ Check(ne, "Declaration in catch context.",
a1, Operand(t0));
}
if (mode == Variable::CONST) {
__ 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) {
if (function != NULL) {
VisitForAccumulatorValue(function);
__ sw(result_register(), ContextOperand(cp, slot->index()));
int offset = Context::SlotOffset(slot->index());
// We know that we have written a function, which is not a smi.
__ mov(a1, cp);
__ 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;
......@@ -752,13 +752,13 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
// must not destroy the current value.
if (mode == Variable::CONST) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
} else if (function != NULL) {
if (function != NULL) {
__ Push(cp, a2, a1);
// Push initial value for function declaration.
VisitForStackValue(function);
} else if (mode == Variable::CONST || mode == Variable::LET) {
__ LoadRoot(a0, Heap::kTheHoleValueRootIndex);
__ Push(cp, a2, a1, a0);
} else {
ASSERT(Smi::FromInt(0) == 0);
// No initial value!
......@@ -1279,9 +1279,22 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ movz(v0, a0, at); // Conditional move.
context()->Plug(v0);
} else {
context()->Plug(slot);
}
} else if (var->mode() == Variable::LET) {
// 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,
break;
}
__ 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) {
// 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