From e2b2fd620b5cdf90627672fd4a362e5a223755f6 Mon Sep 17 00:00:00 2001 From: "balazs.kilvady" Date: Thu, 5 Mar 2015 09:04:23 -0800 Subject: [PATCH] MIPS: Fix exception for assignment to uninitialised const. Port 2ecdf736cf0409b52832f78a4439ace855d6739b BUG= Review URL: https://codereview.chromium.org/983693003 Cr-Commit-Position: refs/heads/master@{#27023} --- src/mips/full-codegen-mips.cc | 61 ++++++++++++++++++++++++++------------- src/mips64/full-codegen-mips64.cc | 60 ++++++++++++++++++++++++++------------ 2 files changed, 82 insertions(+), 39 deletions(-) diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index bc13cc3..71f71cd 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -2707,24 +2707,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { __ lw(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); CallStoreIC(); - } else if (op == Token::INIT_CONST_LEGACY) { - // Const initializers need a write barrier. - DCHECK(!var->IsParameter()); // No const parameters. - if (var->IsLookupSlot()) { - __ li(a0, Operand(var->name())); - __ Push(v0, cp, a0); // Context and name. - __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); - } else { - DCHECK(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. DCHECK(!var->IsLookupSlot()); @@ -2740,6 +2722,22 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { // Perform the assignment. __ bind(&assign); EmitStoreToStackLocalOrContextSlot(var, location); + + } else if (var->mode() == CONST && op != Token::INIT_CONST) { + // Assignment to const variable needs a write barrier. + DCHECK(!var->IsLookupSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); + Label const_error; + MemOperand location = VarOperand(var, a1); + __ lw(a3, location); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&const_error, ne, a3, Operand(at)); + __ li(a3, Operand(var->name())); + __ push(a3); + __ CallRuntime(Runtime::kThrowReferenceError, 1); + __ bind(&const_error); + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } else if (!var->is_const_mode() || op == Token::INIT_CONST) { if (var->IsLookupSlot()) { // Assignment to var. @@ -2760,8 +2758,31 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { } EmitStoreToStackLocalOrContextSlot(var, location); } - } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError, 0); + + } else if (op == Token::INIT_CONST_LEGACY) { + // Const initializers need a write barrier. + DCHECK(!var->IsParameter()); // No const parameters. + if (var->IsLookupSlot()) { + __ li(a0, Operand(var->name())); + __ Push(v0, cp, a0); // Context and name. + __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); + } else { + DCHECK(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 { + DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY); + if (is_strict(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } + // Silently ignore store in sloppy mode. } } diff --git a/src/mips64/full-codegen-mips64.cc b/src/mips64/full-codegen-mips64.cc index e5b4d9d..c58788e 100644 --- a/src/mips64/full-codegen-mips64.cc +++ b/src/mips64/full-codegen-mips64.cc @@ -2704,23 +2704,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { __ li(StoreDescriptor::NameRegister(), Operand(var->name())); __ ld(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); CallStoreIC(); - } else if (op == Token::INIT_CONST_LEGACY) { - // Const initializers need a write barrier. - DCHECK(!var->IsParameter()); // No const parameters. - if (var->IsLookupSlot()) { - __ li(a0, Operand(var->name())); - __ Push(v0, cp, a0); // Context and name. - __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); - } else { - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label skip; - MemOperand location = VarOperand(var, a1); - __ ld(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. @@ -2737,6 +2720,22 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { // Perform the assignment. __ bind(&assign); EmitStoreToStackLocalOrContextSlot(var, location); + + } else if (var->mode() == CONST && op != Token::INIT_CONST) { + // Assignment to const variable needs a write barrier. + DCHECK(!var->IsLookupSlot()); + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); + Label const_error; + MemOperand location = VarOperand(var, a1); + __ ld(a3, location); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&const_error, ne, a3, Operand(at)); + __ li(a3, Operand(var->name())); + __ push(a3); + __ CallRuntime(Runtime::kThrowReferenceError, 1); + __ bind(&const_error); + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } else if (!var->is_const_mode() || op == Token::INIT_CONST) { if (var->IsLookupSlot()) { // Assignment to var. @@ -2761,8 +2760,31 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { } EmitStoreToStackLocalOrContextSlot(var, location); } - } else if (IsSignallingAssignmentToConst(var, op, language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError, 0); + + } else if (op == Token::INIT_CONST_LEGACY) { + // Const initializers need a write barrier. + DCHECK(!var->IsParameter()); // No const parameters. + if (var->IsLookupSlot()) { + __ li(a0, Operand(var->name())); + __ Push(v0, cp, a0); // Context and name. + __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); + } else { + DCHECK(var->IsStackAllocated() || var->IsContextSlot()); + Label skip; + MemOperand location = VarOperand(var, a1); + __ ld(a2, location); + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&skip, ne, a2, Operand(at)); + EmitStoreToStackLocalOrContextSlot(var, location); + __ bind(&skip); + } + + } else { + DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT_CONST_LEGACY); + if (is_strict(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError, 0); + } + // Silently ignore store in sloppy mode. } } -- 2.7.4