X87: Use Variable::binding_needs_init() to determine hole initialization.
port 6768456db5
(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}
This commit is contained in:
parent
26e2d16b8f
commit
759a06fca3
@ -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.
|
||||
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
|
||||
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.
|
||||
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());
|
||||
|
Loading…
Reference in New Issue
Block a user