Commit 759a06fc authored by zhengxing.li's avatar zhengxing.li Committed by Commit bot

X87: Use Variable::binding_needs_init() to determine hole initialization.

  port 6768456d (r38395)

  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.

BUG=

Review-Url: https://codereview.chromium.org/2223803002
Cr-Commit-Position: refs/heads/master@{#38468}
parent 26e2d16b
......@@ -706,13 +706,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: {
......@@ -725,7 +720,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
case VariableLocation::PARAMETER:
case VariableLocation::LOCAL:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
__ mov(StackOperand(variable),
Immediate(isolate()->factory()->the_hole_value()));
......@@ -733,7 +728,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
break;
case VariableLocation::CONTEXT:
if (hole_init) {
if (variable->binding_needs_init()) {
Comment cmnt(masm_, "[ VariableDeclaration");
EmitDebugCheckDeclarationContext(variable);
__ mov(ContextOperand(esi, variable->index()),
......@@ -745,8 +740,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());
__ push(Immediate(variable->name()));
__ CallRuntime(Runtime::kDeclareEvalVar);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
......@@ -1195,13 +1190,14 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
if (local->mode() == LET || local->mode() == CONST) {
if (local->binding_needs_init()) {
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, done);
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError);
} else {
__ jmp(done);
}
__ jmp(done);
}
}
......@@ -1244,17 +1240,14 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
: "[ Stack variable");
if (NeedsHoleCheckForLoad(proxy)) {
// Let and const need a read barrier.
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
Label done;
GetVar(eax, var);
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, &done, Label::kNear);
if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError);
}
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&done);
context()->Plug(eax);
break;
......@@ -2082,34 +2075,25 @@ 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, ecx);
__ mov(edx, location);
__ cmp(edx, isolate()->factory()->the_hole_value());
__ j(not_equal, &assign, Label::kNear);
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError);
__ 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, ecx);
__ mov(edx, location);
__ cmp(edx, isolate()->factory()->the_hole_value());
__ j(not_equal, &const_error, Label::kNear);
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError);
__ bind(&const_error);
__ CallRuntime(Runtime::kThrowConstAssignError);
// Perform an initialization check for lexically declared variables.
if (var->binding_needs_init()) {
Label assign;
__ mov(edx, location);
__ cmp(edx, isolate()->factory()->the_hole_value());
__ j(not_equal, &assign, Label::kNear);
__ push(Immediate(var->name()));
__ 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