Commit 04c51b21 authored by bjaideep's avatar bjaideep Committed by Commit bot

PPC/s390: Use Variable::binding_needs_init() to determine hole initialization

Port 6768456d

Original commit message:

    The old code was using VariableMode, but that signal is both
    over-pessimistic (some CONST and LET variables need no hole-initialization)
    and inconsistent with other uses of the InitializationFlag enum (such
    as %LoadLookupSlot).

    This changes no observable behavior, but removes unnecessary hole
    initialization and hole checks in a few places, including
    block-scoped function declarations, super property lookups,
    and new.target.

R=adamk@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com, mbrandy@us.ibm.com

BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2229383004
Cr-Commit-Position: refs/heads/master@{#38551}
parent d1ab9f12
......@@ -723,13 +723,8 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
void FullCodeGenerator::VisitVariableDeclaration(
VariableDeclaration* declaration) {
// If it was not possible to allocate the variable at compile time, we
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
bool hole_init = mode == LET || mode == CONST;
switch (variable->location()) {
case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
......@@ -742,7 +737,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
case VariableLocation::PARAMETER:
case VariableLocation::LOCAL:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ StoreP(ip, StackOperand(variable));
......@@ -750,7 +745,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
break;
case VariableLocation::CONTEXT:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
EmitDebugCheckDeclarationContext(variable);
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
......@@ -762,8 +757,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
case VariableLocation::LOOKUP: {
Comment cmnt(masm_, "[ VariableDeclaration");
DCHECK_EQ(VAR, mode);
DCHECK(!hole_init);
DCHECK_EQ(VAR, variable->mode());
DCHECK(!variable->binding_needs_init());
__ mov(r5, Operand(variable->name()));
__ Push(r5);
__ CallRuntime(Runtime::kDeclareEvalVar);
......@@ -1243,14 +1238,15 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ LoadP(r3, ContextSlotOperandCheckExtensions(local, slow));
if (local->mode() == LET || local->mode() == CONST) {
if (local->binding_needs_init()) {
__ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
__ bne(done);
__ mov(r3, Operand(var->name()));
__ push(r3);
__ CallRuntime(Runtime::kThrowReferenceError);
} else {
__ b(done);
}
__ b(done);
}
}
......@@ -1293,18 +1289,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
: "[ Stack variable");
if (NeedsHoleCheckForLoad(proxy)) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
Label done;
// Let and const need a read barrier.
GetVar(r3, var);
__ CompareRoot(r3, Heap::kTheHoleValueRootIndex);
__ bne(&done);
if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ mov(r3, Operand(var->name()));
__ push(r3);
__ CallRuntime(Runtime::kThrowReferenceError);
}
__ mov(r3, Operand(var->name()));
__ push(r3);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&done);
context()->Plug(r3);
break;
......@@ -2187,37 +2180,26 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT) {
// Non-initializing assignment to let variable needs a write barrier.
DCHECK(!var->IsLookupSlot());
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
MemOperand location = VarOperand(var, r4);
__ LoadP(r6, location);
__ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
__ bne(&assign);
__ mov(r6, Operand(var->name()));
__ push(r6);
__ CallRuntime(Runtime::kThrowReferenceError);
// Perform the assignment.
__ bind(&assign);
EmitStoreToStackLocalOrContextSlot(var, location);
} else if (var->mode() == CONST && op != Token::INIT) {
// Assignment to const variable needs a write barrier.
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot());
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
Label const_error;
MemOperand location = VarOperand(var, r4);
__ LoadP(r6, location);
__ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
__ bne(&const_error);
__ mov(r6, Operand(var->name()));
__ push(r6);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&const_error);
__ CallRuntime(Runtime::kThrowConstAssignError);
// Perform an initialization check for lexically declared variables.
if (var->binding_needs_init()) {
Label assign;
__ LoadP(r6, location);
__ CompareRoot(r6, Heap::kTheHoleValueRootIndex);
__ bne(&assign);
__ mov(r6, Operand(var->name()));
__ push(r6);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&assign);
}
if (var->mode() == CONST) {
__ CallRuntime(Runtime::kThrowConstAssignError);
} else {
EmitStoreToStackLocalOrContextSlot(var, location);
}
} else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
// Initializing assignment to const {this} needs a write barrier.
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
......
......@@ -699,13 +699,8 @@ void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
void FullCodeGenerator::VisitVariableDeclaration(
VariableDeclaration* declaration) {
// If it was not possible to allocate the variable at compile time, we
// need to "declare" it at runtime to make sure it actually exists in the
// local context.
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
bool hole_init = mode == LET || mode == CONST;
switch (variable->location()) {
case VariableLocation::GLOBAL:
case VariableLocation::UNALLOCATED: {
......@@ -718,7 +713,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
case VariableLocation::PARAMETER:
case VariableLocation::LOCAL:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ StoreP(ip, StackOperand(variable));
......@@ -726,7 +721,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
break;
case VariableLocation::CONTEXT:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
EmitDebugCheckDeclarationContext(variable);
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
......@@ -738,8 +733,8 @@ void FullCodeGenerator::VisitVariableDeclaration(
case VariableLocation::LOOKUP: {
Comment cmnt(masm_, "[ VariableDeclaration");
DCHECK_EQ(VAR, mode);
DCHECK(!hole_init);
DCHECK_EQ(VAR, variable->mode());
DCHECK(!variable->binding_needs_init());
__ mov(r4, Operand(variable->name()));
__ Push(r4);
__ CallRuntime(Runtime::kDeclareEvalVar);
......@@ -1207,14 +1202,15 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ LoadP(r2, ContextSlotOperandCheckExtensions(local, slow));
if (local->mode() == LET || local->mode() == CONST) {
if (local->binding_needs_init()) {
__ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
__ bne(done);
__ mov(r2, Operand(var->name()));
__ push(r2);
__ CallRuntime(Runtime::kThrowReferenceError);
} else {
__ b(done);
}
__ b(done);
}
}
......@@ -1255,18 +1251,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
: "[ Stack variable");
if (NeedsHoleCheckForLoad(proxy)) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
Label done;
// Let and const need a read barrier.
GetVar(r2, var);
__ CompareRoot(r2, Heap::kTheHoleValueRootIndex);
__ bne(&done);
if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ mov(r2, Operand(var->name()));
__ push(r2);
__ CallRuntime(Runtime::kThrowReferenceError);
}
__ mov(r2, Operand(var->name()));
__ push(r2);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&done);
context()->Plug(r2);
break;
......@@ -2141,37 +2134,27 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
EmitLoadStoreICSlot(slot);
CallStoreIC();
} else if (var->mode() == LET && op != Token::INIT) {
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
// Non-initializing assignment to let variable needs a write barrier.
DCHECK(!var->IsLookupSlot());
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
MemOperand location = VarOperand(var, r3);
__ LoadP(r5, location);
__ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
__ bne(&assign);
__ mov(r5, Operand(var->name()));
__ push(r5);
__ CallRuntime(Runtime::kThrowReferenceError);
// Perform the assignment.
__ bind(&assign);
EmitStoreToStackLocalOrContextSlot(var, location);
} else if (var->mode() == CONST && op != Token::INIT) {
// Assignment to const variable needs a write barrier.
DCHECK(!var->IsLookupSlot());
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
Label const_error;
MemOperand location = VarOperand(var, r3);
__ LoadP(r5, location);
__ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
__ bne(&const_error, Label::kNear);
__ mov(r5, Operand(var->name()));
__ push(r5);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&const_error);
__ CallRuntime(Runtime::kThrowConstAssignError);
// Perform an initialization check for lexically declared variables.
if (var->binding_needs_init()) {
Label assign;
__ LoadP(r5, location);
__ CompareRoot(r5, Heap::kTheHoleValueRootIndex);
__ bne(&assign);
__ mov(r5, Operand(var->name()));
__ push(r5);
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&assign);
}
if (var->mode() == CONST) {
__ CallRuntime(Runtime::kThrowConstAssignError);
} else {
EmitStoreToStackLocalOrContextSlot(var, location);
}
} else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
// Initializing assignment to const {this} needs a write barrier.
DCHECK(var->IsStackAllocated() || var->IsContextSlot());
......
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