Use FullCodeGenerator::EmitGlobalVariableLoad() where possible to avoid code duplication.
Review URL: https://codereview.chromium.org/1222203007 Cr-Commit-Position: refs/heads/master@{#29520}
This commit is contained in:
parent
ea560a9be9
commit
f043ab8618
@ -1416,15 +1416,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
// load machinery.
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1493,7 +1487,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||||
|
__ mov(LoadDescriptor::SlotRegister(),
|
||||||
|
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1505,11 +1515,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(r0);
|
context()->Plug(r0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1517,6 +1523,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1590,11 +1597,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ mov(r1, Operand(var->name()));
|
__ mov(r1, Operand(var->name()));
|
||||||
__ Push(cp, r1); // Context and name.
|
__ Push(cp, r1); // Context and name.
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(r0);
|
context()->Plug(r0);
|
||||||
}
|
}
|
||||||
@ -5154,44 +5165,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(r0);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ mov(r0, Operand(proxy->name()));
|
|
||||||
__ Push(cp, r0);
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(r0);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1399,14 +1399,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ Bind(&fast);
|
__ Bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
__ Mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
// load machinery.
|
||||||
__ Mov(LoadDescriptor::SlotRegister(),
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1472,7 +1467,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
||||||
|
__ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||||
|
__ Mov(LoadDescriptor::SlotRegister(),
|
||||||
|
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1484,11 +1495,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "Global variable");
|
Comment cmnt(masm_, "Global variable");
|
||||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
|
||||||
__ Mov(LoadDescriptor::SlotRegister(),
|
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(x0);
|
context()->Plug(x0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1496,6 +1503,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot()
|
Comment cmnt(masm_, var->IsContextSlot()
|
||||||
? "Context variable"
|
? "Context variable"
|
||||||
: "Stack variable");
|
: "Stack variable");
|
||||||
@ -1569,12 +1577,16 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed by
|
// Generate code for loading from variables potentially shadowed by
|
||||||
// eval-introduced variables.
|
// eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ Bind(&slow);
|
__ Bind(&slow);
|
||||||
Comment cmnt(masm_, "Lookup variable");
|
Comment cmnt(masm_, "Lookup variable");
|
||||||
__ Mov(x1, Operand(var->name()));
|
__ Mov(x1, Operand(var->name()));
|
||||||
__ Push(cp, x1); // Context and name.
|
__ Push(cp, x1); // Context and name.
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ Bind(&done);
|
__ Bind(&done);
|
||||||
context()->Plug(x0);
|
context()->Plug(x0);
|
||||||
break;
|
break;
|
||||||
@ -4841,43 +4853,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "Global variable");
|
|
||||||
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
|
|
||||||
__ Mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
|
||||||
__ Mov(LoadDescriptor::SlotRegister(),
|
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(x0);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ Bind(&slow);
|
|
||||||
__ Mov(x0, Operand(proxy->name()));
|
|
||||||
__ Push(cp, x0);
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ Bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(x0);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -214,11 +214,6 @@ void FullCodeGenerator::CallLoadIC(ContextualMode contextual_mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::CallGlobalLoadIC(Handle<String> name) {
|
|
||||||
return CallLoadIC(CONTEXTUAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
|
void FullCodeGenerator::CallStoreIC(TypeFeedbackId id) {
|
||||||
Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
|
Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
|
||||||
CallIC(ic, id);
|
CallIC(ic, id);
|
||||||
@ -612,6 +607,22 @@ void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
||||||
|
VariableProxy* proxy = expr->AsVariableProxy();
|
||||||
|
DCHECK(!context()->IsEffect());
|
||||||
|
DCHECK(!context()->IsTest());
|
||||||
|
|
||||||
|
if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
proxy->var()->IsLookupSlot())) {
|
||||||
|
EmitVariableLoad(proxy, INSIDE_TYPEOF);
|
||||||
|
PrepareForBailout(proxy, TOS_REG);
|
||||||
|
} else {
|
||||||
|
// This expression cannot throw a reference error at the top level.
|
||||||
|
VisitInDuplicateContext(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitBlock(Block* stmt) {
|
void FullCodeGenerator::VisitBlock(Block* stmt) {
|
||||||
Comment cmnt(masm_, "[ Block");
|
Comment cmnt(masm_, "[ Block");
|
||||||
NestedBlock nested_block(this, stmt);
|
NestedBlock nested_block(this, stmt);
|
||||||
|
@ -552,7 +552,9 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
TypeofState typeof_state,
|
TypeofState typeof_state,
|
||||||
Label* slow,
|
Label* slow,
|
||||||
Label* done);
|
Label* done);
|
||||||
void EmitVariableLoad(VariableProxy* proxy);
|
void EmitGlobalVariableLoad(VariableProxy* proxy, TypeofState typeof_state);
|
||||||
|
void EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state = NOT_INSIDE_TYPEOF);
|
||||||
|
|
||||||
void EmitAccessor(Expression* expression);
|
void EmitAccessor(Expression* expression);
|
||||||
|
|
||||||
@ -654,7 +656,6 @@ class FullCodeGenerator: public AstVisitor {
|
|||||||
|
|
||||||
void CallLoadIC(ContextualMode mode, LanguageMode language_mode = SLOPPY,
|
void CallLoadIC(ContextualMode mode, LanguageMode language_mode = SLOPPY,
|
||||||
TypeFeedbackId id = TypeFeedbackId::None());
|
TypeFeedbackId id = TypeFeedbackId::None());
|
||||||
void CallGlobalLoadIC(Handle<String> name);
|
|
||||||
void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
|
void CallStoreIC(TypeFeedbackId id = TypeFeedbackId::None());
|
||||||
|
|
||||||
void SetFunctionPosition(FunctionLiteral* fun);
|
void SetFunctionPosition(FunctionLiteral* fun);
|
||||||
|
@ -1344,18 +1344,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All extension objects were empty and it is safe to use a global
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
// load IC call.
|
// load machinery.
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1421,7 +1412,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ mov(LoadDescriptor::NameRegister(), var->name());
|
||||||
|
__ mov(LoadDescriptor::SlotRegister(),
|
||||||
|
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
Variable* var = proxy->var();
|
Variable* var = proxy->var();
|
||||||
@ -1432,11 +1439,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), var->name());
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1444,6 +1447,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1516,11 +1520,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ push(esi); // Context.
|
__ push(esi); // Context.
|
||||||
__ push(Immediate(var->name()));
|
__ push(Immediate(var->name()));
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
break;
|
break;
|
||||||
@ -5092,45 +5100,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(eax);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ push(esi);
|
|
||||||
__ push(Immediate(proxy->name()));
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(eax);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1408,15 +1408,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
// load machinery.
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1485,7 +1479,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||||
|
__ li(LoadDescriptor::SlotRegister(),
|
||||||
|
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1497,11 +1507,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1509,6 +1515,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1584,11 +1591,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ li(a1, Operand(var->name()));
|
__ li(a1, Operand(var->name()));
|
||||||
__ Push(cp, a1); // Context and name.
|
__ Push(cp, a1); // Context and name.
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
}
|
}
|
||||||
@ -5177,43 +5188,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ lw(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(v0);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ li(a0, Operand(proxy->name()));
|
|
||||||
__ Push(cp, a0);
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(v0);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1405,15 +1405,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
// load machinery.
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1482,7 +1476,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||||
|
__ li(LoadDescriptor::SlotRegister(),
|
||||||
|
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1494,13 +1504,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
// Use inline caching. Variable name is passed in a2 and the global
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
// object (receiver) in a0.
|
|
||||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(var->name()));
|
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1508,6 +1512,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1583,11 +1588,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ li(a1, Operand(var->name()));
|
__ li(a1, Operand(var->name()));
|
||||||
__ Push(cp, a1); // Context and name.
|
__ Push(cp, a1); // Context and name.
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(v0);
|
context()->Plug(v0);
|
||||||
}
|
}
|
||||||
@ -5181,43 +5190,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ ld(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ li(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
|
||||||
__ li(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(v0);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ li(a0, Operand(proxy->name()));
|
|
||||||
__ Push(cp, a0);
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(v0);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1387,14 +1387,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->var()->name()));
|
// load machinery.
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode =
|
|
||||||
(typeof_state == INSIDE_TYPEOF) ? NOT_CONTEXTUAL : CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1462,7 +1457,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
||||||
|
__ mov(LoadDescriptor::SlotRegister(),
|
||||||
|
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1474,11 +1485,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(r3);
|
context()->Plug(r3);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1486,6 +1493,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1559,11 +1567,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ mov(r4, Operand(var->name()));
|
__ mov(r4, Operand(var->name()));
|
||||||
__ Push(cp, r4); // Context and name.
|
__ Push(cp, r4); // Context and name.
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(r3);
|
context()->Plug(r3);
|
||||||
}
|
}
|
||||||
@ -5178,44 +5190,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ LoadP(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ mov(LoadDescriptor::NameRegister(), Operand(proxy->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(r3);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ mov(r3, Operand(proxy->name()));
|
|
||||||
__ Push(cp, r3);
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(r3);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1381,17 +1381,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All extension objects were empty and it is safe to use a global
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
// load IC call.
|
// load machinery.
|
||||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ Move(LoadDescriptor::NameRegister(), proxy->var()->name());
|
|
||||||
__ Move(LoadDescriptor::SlotRegister(),
|
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1457,7 +1449,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ Move(LoadDescriptor::NameRegister(), var->name());
|
||||||
|
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ Move(LoadDescriptor::SlotRegister(),
|
||||||
|
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
// Record position before possible IC call.
|
// Record position before possible IC call.
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
@ -1469,11 +1477,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ Move(LoadDescriptor::NameRegister(), var->name());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ Move(LoadDescriptor::SlotRegister(),
|
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(rax);
|
context()->Plug(rax);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1481,6 +1485,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
|
||||||
: "[ Stack slot");
|
: "[ Stack slot");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1553,11 +1558,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ Push(rsi); // Context.
|
__ Push(rsi); // Context.
|
||||||
__ Push(var->name());
|
__ Push(var->name());
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(rax);
|
context()->Plug(rax);
|
||||||
break;
|
break;
|
||||||
@ -5112,45 +5121,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ Move(LoadDescriptor::NameRegister(), proxy->name());
|
|
||||||
__ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ Move(LoadDescriptor::SlotRegister(),
|
|
||||||
SmiFromSlot(proxy->VariableFeedbackSlot()));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(rax);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ Push(rsi);
|
|
||||||
__ Push(proxy->name());
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(rax);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
@ -1337,18 +1337,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
|
|||||||
__ bind(&fast);
|
__ bind(&fast);
|
||||||
}
|
}
|
||||||
|
|
||||||
// All extension objects were empty and it is safe to use a global
|
// All extension objects were empty and it is safe to use a normal global
|
||||||
// load IC call.
|
// load machinery.
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
|
|
||||||
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
|
|
||||||
? NOT_CONTEXTUAL
|
|
||||||
: CONTEXTUAL;
|
|
||||||
|
|
||||||
CallLoadIC(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1414,7 +1405,23 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
|
Variable* var = proxy->var();
|
||||||
|
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
|
||||||
|
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
|
||||||
|
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
||||||
|
__ mov(LoadDescriptor::NameRegister(), var->name());
|
||||||
|
__ mov(LoadDescriptor::SlotRegister(),
|
||||||
|
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
||||||
|
// Inside typeof use a regular load, not a contextual load, to avoid
|
||||||
|
// a reference error.
|
||||||
|
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
||||||
|
TypeofState typeof_state) {
|
||||||
SetExpressionPosition(proxy);
|
SetExpressionPosition(proxy);
|
||||||
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
|
||||||
Variable* var = proxy->var();
|
Variable* var = proxy->var();
|
||||||
@ -1425,11 +1432,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::GLOBAL:
|
case VariableLocation::GLOBAL:
|
||||||
case VariableLocation::UNALLOCATED: {
|
case VariableLocation::UNALLOCATED: {
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
Comment cmnt(masm_, "[ Global variable");
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
EmitGlobalVariableLoad(proxy, typeof_state);
|
||||||
__ mov(LoadDescriptor::NameRegister(), var->name());
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
CallGlobalLoadIC(var->name());
|
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1437,6 +1440,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
case VariableLocation::PARAMETER:
|
case VariableLocation::PARAMETER:
|
||||||
case VariableLocation::LOCAL:
|
case VariableLocation::LOCAL:
|
||||||
case VariableLocation::CONTEXT: {
|
case VariableLocation::CONTEXT: {
|
||||||
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_state);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
if (var->binding_needs_init()) {
|
if (var->binding_needs_init()) {
|
||||||
@ -1509,11 +1513,15 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
|
|||||||
Label done, slow;
|
Label done, slow;
|
||||||
// Generate code for loading from variables potentially shadowed
|
// Generate code for loading from variables potentially shadowed
|
||||||
// by eval-introduced variables.
|
// by eval-introduced variables.
|
||||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
EmitDynamicLookupFastCase(proxy, typeof_state, &slow, &done);
|
||||||
__ bind(&slow);
|
__ bind(&slow);
|
||||||
__ push(esi); // Context.
|
__ push(esi); // Context.
|
||||||
__ push(Immediate(var->name()));
|
__ push(Immediate(var->name()));
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
Runtime::FunctionId function_id =
|
||||||
|
typeof_state == NOT_INSIDE_TYPEOF
|
||||||
|
? Runtime::kLoadLookupSlot
|
||||||
|
: Runtime::kLoadLookupSlotNoReferenceError;
|
||||||
|
__ CallRuntime(function_id, 2);
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
break;
|
break;
|
||||||
@ -5082,45 +5090,6 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
|
|
||||||
VariableProxy* proxy = expr->AsVariableProxy();
|
|
||||||
DCHECK(!context()->IsEffect());
|
|
||||||
DCHECK(!context()->IsTest());
|
|
||||||
|
|
||||||
if (proxy != NULL && proxy->var()->IsUnallocatedOrGlobalSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Global variable");
|
|
||||||
__ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
|
|
||||||
__ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
|
|
||||||
__ mov(LoadDescriptor::SlotRegister(),
|
|
||||||
Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
|
|
||||||
// Use a regular load, not a contextual load, to avoid a reference
|
|
||||||
// error.
|
|
||||||
CallLoadIC(NOT_CONTEXTUAL);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
context()->Plug(eax);
|
|
||||||
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
|
|
||||||
Comment cmnt(masm_, "[ Lookup slot");
|
|
||||||
Label done, slow;
|
|
||||||
|
|
||||||
// Generate code for loading from variables potentially shadowed
|
|
||||||
// by eval-introduced variables.
|
|
||||||
EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
|
|
||||||
|
|
||||||
__ bind(&slow);
|
|
||||||
__ push(esi);
|
|
||||||
__ push(Immediate(proxy->name()));
|
|
||||||
__ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
|
|
||||||
PrepareForBailout(expr, TOS_REG);
|
|
||||||
__ bind(&done);
|
|
||||||
|
|
||||||
context()->Plug(eax);
|
|
||||||
} else {
|
|
||||||
// This expression cannot throw a reference error at the top level.
|
|
||||||
VisitInDuplicateContext(expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
|
||||||
Expression* sub_expr,
|
Expression* sub_expr,
|
||||||
Handle<String> check) {
|
Handle<String> check) {
|
||||||
|
Loading…
Reference in New Issue
Block a user