From 857a4834087e6d74eb54be132a3a18fff3ecd80b Mon Sep 17 00:00:00 2001 From: "plind44@gmail.com" Date: Fri, 14 Feb 2014 17:37:45 +0000 Subject: [PATCH] MIPS: Fix assignment of function name constant. Port r19379 (622d830) Original commit message: If it's shadowed by a variable of the same name and both are forcibly context-allocated, the function is assigned to the wrong context slot. BUG=v8:3138 LOG=Y R=plind44@gmail.com Review URL: https://codereview.chromium.org/166813002 Patch from Balazs Kilvady . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19391 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/full-codegen-mips.cc | 83 +++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index b9c9ea0..41bc68e 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -2477,6 +2477,28 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) { } +void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( + Variable* var, MemOperand location) { + __ sw(result_register(), location); + if (var->IsContextSlot()) { + // RecordWrite may destroy all its register arguments. + __ Move(a3, result_register()); + int offset = Context::SlotOffset(var->index()); + __ RecordWriteContextSlot( + a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); + } +} + + +void FullCodeGenerator::EmitCallStoreContextSlot( + Handle name, LanguageMode mode) { + __ li(a1, Operand(name)); + __ li(a0, Operand(Smi::FromInt(mode))); + __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. + __ CallRuntime(Runtime::kStoreContextSlot, 4); +} + + void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { if (var->IsUnallocated()) { @@ -2485,35 +2507,29 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ li(a2, Operand(var->name())); __ lw(a1, GlobalObjectOperand()); CallStoreIC(); + } else if (op == Token::INIT_CONST) { // Const initializers need a write barrier. ASSERT(!var->IsParameter()); // No const parameters. - if (var->IsStackLocal()) { - Label skip; - __ lw(a1, StackOperand(var)); - __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); - __ Branch(&skip, ne, a1, Operand(t0)); - __ sw(result_register(), StackOperand(var)); - __ bind(&skip); - } else { - ASSERT(var->IsContextSlot() || var->IsLookupSlot()); - // Like var declarations, const declarations are hoisted to function - // scope. However, unlike var initializers, const initializers are - // able to drill a hole to that function context, even from inside a - // 'with' context. We thus bypass the normal static scope lookup for - // var->IsContextSlot(). + if (var->IsLookupSlot()) { __ li(a0, Operand(var->name())); __ Push(v0, cp, a0); // Context and name. __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); + } else { + ASSERT(var->IsStackAllocated() || var->IsContextSlot()); + Label skip; + MemOperand location = VarOperand(var, a1); + __ lw(a2, location); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&skip, ne, a2, Operand(at)); + EmitStoreToStackLocalOrContextSlot(var, location); + __ bind(&skip); } } else if (var->mode() == LET && op != Token::INIT_LET) { // Non-initializing assignment to let variable needs a write barrier. if (var->IsLookupSlot()) { - __ li(a1, Operand(var->name())); - __ li(a0, Operand(Smi::FromInt(language_mode()))); - __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. - __ CallRuntime(Runtime::kStoreContextSlot, 4); + EmitCallStoreContextSlot(var->name(), language_mode()); } else { ASSERT(var->IsStackAllocated() || var->IsContextSlot()); Label assign; @@ -2526,20 +2542,16 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ CallRuntime(Runtime::kThrowReferenceError, 1); // Perform the assignment. __ bind(&assign); - __ sw(result_register(), location); - if (var->IsContextSlot()) { - // RecordWrite may destroy all its register arguments. - __ mov(a3, result_register()); - int offset = Context::SlotOffset(var->index()); - __ RecordWriteContextSlot( - a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); - } + EmitStoreToStackLocalOrContextSlot(var, location); } } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { // Assignment to var or initializing assignment to let/const // in harmony mode. - if (var->IsStackAllocated() || var->IsContextSlot()) { + if (var->IsLookupSlot()) { + EmitCallStoreContextSlot(var->name(), language_mode()); + } else { + ASSERT((var->IsStackAllocated() || var->IsContextSlot())); MemOperand location = VarOperand(var, a1); if (generate_debug_code_ && op == Token::INIT_LET) { // Check for an uninitialized let binding. @@ -2547,23 +2559,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); } - // Perform the assignment. - __ sw(v0, location); - if (var->IsContextSlot()) { - __ mov(a3, v0); - int offset = Context::SlotOffset(var->index()); - __ RecordWriteContextSlot( - a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); - } - } else { - ASSERT(var->IsLookupSlot()); - __ li(a1, Operand(var->name())); - __ li(a0, Operand(Smi::FromInt(language_mode()))); - __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. - __ CallRuntime(Runtime::kStoreContextSlot, 4); + EmitStoreToStackLocalOrContextSlot(var, location); } } - // Non-initializing assignments to consts are ignored. + // Non-initializing assignments to consts are ignored. } -- 2.7.4