Reapply "Fix receiver when calling eval() bound by with scope"
Originally applied in https://codereview.chromium.org/1202963005 BUG=v8:4214 CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_chromium_rel_ng;tryserver.blink:linux_blink_rel LOG=N R=arv@chromium.org, mstarzinger@chromium.org Review URL: https://codereview.chromium.org/1208873002 Cr-Commit-Position: refs/heads/master@{#29293}
This commit is contained in:
parent
876ae42598
commit
40b7d874b2
@ -3137,6 +3137,53 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in r0)
|
||||
// and the object holding it (returned in edx).
|
||||
DCHECK(!context_register().is(r2));
|
||||
__ mov(r2, Operand(callee->name()));
|
||||
__ Push(context_register(), r2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(r0, r1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ b(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(r0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r1);
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r2); // Reserved receiver slot.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3156,9 +3203,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r2); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -3174,7 +3219,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Record source position for debugger.
|
||||
@ -3191,43 +3236,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in r0)
|
||||
// and the object holding it (returned in edx).
|
||||
DCHECK(!context_register().is(r2));
|
||||
__ mov(r2, Operand(proxy->name()));
|
||||
__ Push(context_register(), r2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(r0, r1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ b(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(r0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r1);
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found
|
||||
// by LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -2829,6 +2829,51 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ Bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in x0)
|
||||
// and the object holding it (returned in x1).
|
||||
__ Mov(x10, Operand(callee->name()));
|
||||
__ Push(context_register(), x10);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(x0, x1); // Receiver, function.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ B(&call);
|
||||
__ Bind(&done);
|
||||
// Push function.
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the undefined to the call function stub.
|
||||
__ LoadRoot(x1, Heap::kUndefinedValueRootIndex);
|
||||
__ Push(x0, x1);
|
||||
__ Bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ LoadRoot(x10, Heap::kUndefinedValueRootIndex);
|
||||
__ Push(x10); // Reserved receiver slot.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -2849,9 +2894,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
{
|
||||
PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(x10, Heap::kUndefinedValueRootIndex);
|
||||
__ Push(x10); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -2867,7 +2910,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ Poke(x0, (arg_count + 1) * kPointerSize);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Record source position for debugger.
|
||||
@ -2887,41 +2930,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ Bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in x0)
|
||||
// and the object holding it (returned in x1).
|
||||
__ Mov(x10, Operand(proxy->name()));
|
||||
__ Push(context_register(), x10);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(x0, x1); // Receiver, function.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ B(&call);
|
||||
__ Bind(&done);
|
||||
// Push function.
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the undefined to the call function stub.
|
||||
__ LoadRoot(x1, Heap::kUndefinedValueRootIndex);
|
||||
__ Push(x0, x1);
|
||||
__ Bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found
|
||||
// by LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -1869,9 +1869,10 @@ class Call final : public Expression {
|
||||
allocation_site_ = site;
|
||||
}
|
||||
|
||||
static int num_ids() { return parent_num_ids() + 2; }
|
||||
static int num_ids() { return parent_num_ids() + 3; }
|
||||
BailoutId ReturnId() const { return BailoutId(local_id(0)); }
|
||||
BailoutId EvalOrLookupId() const { return BailoutId(local_id(1)); }
|
||||
BailoutId EvalId() const { return BailoutId(local_id(1)); }
|
||||
BailoutId LookupId() const { return BailoutId(local_id(2)); }
|
||||
|
||||
bool is_uninitialized() const {
|
||||
return IsUninitializedField::decode(bit_field_);
|
||||
|
@ -2356,7 +2356,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
callee_value = NewNode(common()->Projection(0), pair);
|
||||
receiver_value = NewNode(common()->Projection(1), pair);
|
||||
|
||||
PrepareFrameState(pair, expr->EvalOrLookupId(),
|
||||
PrepareFrameState(pair, expr->LookupId(),
|
||||
OutputFrameStateCombine::Push(2));
|
||||
break;
|
||||
}
|
||||
@ -2424,6 +2424,18 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
break;
|
||||
case Call::POSSIBLY_EVAL_CALL:
|
||||
possibly_eval = true;
|
||||
if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
|
||||
Variable* variable = callee->AsVariableProxy()->var();
|
||||
Node* name = jsgraph()->Constant(variable->name());
|
||||
const Operator* op =
|
||||
javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
Node* pair = NewNode(op, current_context(), name);
|
||||
callee_value = NewNode(common()->Projection(0), pair);
|
||||
receiver_value = NewNode(common()->Projection(1), pair);
|
||||
PrepareFrameState(pair, expr->LookupId(),
|
||||
OutputFrameStateCombine::Push(2));
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
case Call::OTHER_CALL:
|
||||
VisitForValue(callee);
|
||||
@ -2459,7 +2471,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
|
||||
Node* new_callee =
|
||||
NewNode(op, callee, source, function, language, position);
|
||||
PrepareFrameState(new_callee, expr->EvalOrLookupId(),
|
||||
PrepareFrameState(new_callee, expr->EvalId(),
|
||||
OutputFrameStateCombine::PokeAt(arg_count + 1));
|
||||
|
||||
// Patch callee on the environment.
|
||||
|
@ -736,6 +736,8 @@ class FullCodeGenerator: public AstVisitor {
|
||||
// and PushCatchContext.
|
||||
void PushFunctionArgumentForContextAllocation();
|
||||
|
||||
void PushCalleeAndWithBaseObject(Call* expr);
|
||||
|
||||
// AST node visit functions.
|
||||
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
|
@ -3036,6 +3036,49 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in eax) and
|
||||
// the object holding it (returned in edx).
|
||||
__ push(context_register());
|
||||
__ push(Immediate(callee->name()));
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ push(eax); // Function.
|
||||
__ push(edx); // Receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(eax);
|
||||
// The receiver is implicitly the global receiver. Indicate this by
|
||||
// passing the hole to the call function stub.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3054,9 +3097,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
// Reserved receiver slot.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
@ -3070,7 +3112,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
@ -3086,41 +3128,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in eax) and
|
||||
// the object holding it (returned in edx).
|
||||
__ push(context_register());
|
||||
__ push(Immediate(proxy->name()));
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ push(eax); // Function.
|
||||
__ push(edx); // Receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(eax);
|
||||
// The receiver is implicitly the global receiver. Indicate this by
|
||||
// passing the hole to the call function stub.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found by
|
||||
// LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
bool is_named_call = property->key()->IsPropertyName();
|
||||
|
@ -3121,6 +3121,53 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
// and the object holding it (returned in v1).
|
||||
DCHECK(!context_register().is(a2));
|
||||
__ li(a2, Operand(callee->name()));
|
||||
__ Push(context_register(), a2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(v0, v1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ Branch(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(v0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a2); // Reserved receiver slot.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3140,9 +3187,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a2); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -3158,7 +3203,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
@ -3173,43 +3218,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
// and the object holding it (returned in v1).
|
||||
DCHECK(!context_register().is(a2));
|
||||
__ li(a2, Operand(proxy->name()));
|
||||
__ Push(context_register(), a2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(v0, v1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ Branch(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(v0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found
|
||||
// by LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -3122,6 +3122,53 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
// and the object holding it (returned in v1).
|
||||
DCHECK(!context_register().is(a2));
|
||||
__ li(a2, Operand(callee->name()));
|
||||
__ Push(context_register(), a2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(v0, v1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ Branch(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(v0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a2); // Reserved receiver slot.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3141,9 +3188,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
int arg_count = args->length();
|
||||
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a2); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -3159,7 +3204,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
@ -3174,43 +3219,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in v0)
|
||||
// and the object holding it (returned in v1).
|
||||
DCHECK(!context_register().is(a2));
|
||||
__ li(a2, Operand(proxy->name()));
|
||||
__ Push(context_register(), a2);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(v0, v1); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ Branch(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(v0);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
|
||||
__ push(a1);
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found
|
||||
// by LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -3135,6 +3135,51 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in rax) and
|
||||
// the object holding it (returned in rdx).
|
||||
__ Push(context_register());
|
||||
__ Push(callee->name());
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(rax); // Function.
|
||||
__ Push(rdx); // Receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ Push(rax);
|
||||
// Pass undefined as the receiver, which is the WithBaseObject of a
|
||||
// non-object environment record. If the callee is sloppy, it will patch
|
||||
// it up to be the global receiver.
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex);
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3155,9 +3200,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
{
|
||||
PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r5); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -3173,7 +3216,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ StoreP(r3, MemOperand(sp, (arg_count + 1) * kPointerSize), r0);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
// Record source position for debugger.
|
||||
@ -3190,44 +3233,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed
|
||||
// by eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in r3)
|
||||
// and the object holding it (returned in edx).
|
||||
DCHECK(!context_register().is(r5));
|
||||
__ mov(r5, Operand(proxy->name()));
|
||||
__ Push(context_register(), r5);
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(r3, r4); // Function, receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the
|
||||
// function and receiver and have the slow path jump around this
|
||||
// code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ b(&call);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(r3);
|
||||
// The receiver is implicitly the global receiver. Indicate this
|
||||
// by passing the hole to the call function stub.
|
||||
__ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
|
||||
__ push(r4);
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found
|
||||
// by LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -3032,6 +3032,50 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in rax) and
|
||||
// the object holding it (returned in rdx).
|
||||
__ Push(context_register());
|
||||
__ Push(callee->name());
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(rax); // Function.
|
||||
__ Push(rdx); // Receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ Push(rax);
|
||||
// Pass undefined as the receiver, which is the WithBaseObject of a
|
||||
// non-object environment record. If the callee is sloppy, it will patch
|
||||
// it up to be the global receiver.
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex);
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3050,8 +3094,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
@ -3066,7 +3109,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the callee.
|
||||
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
@ -3082,40 +3125,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in rax) and
|
||||
// the object holding it (returned in rdx).
|
||||
__ Push(context_register());
|
||||
__ Push(proxy->name());
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ Push(rax); // Function.
|
||||
__ Push(rdx); // Receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ Push(rax);
|
||||
// The receiver is implicitly the global receiver. Indicate this by
|
||||
// passing the hole to the call function stub.
|
||||
__ PushRoot(Heap::kUndefinedValueRootIndex);
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found by
|
||||
// LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
|
@ -3017,6 +3017,49 @@ void FullCodeGenerator::EmitInitializeThisAfterSuper(
|
||||
}
|
||||
|
||||
|
||||
// See http://www.ecma-international.org/ecma-262/6.0/#sec-function-calls.
|
||||
void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
|
||||
VariableProxy* callee = expr->expression()->AsVariableProxy();
|
||||
if (callee->var()->IsLookupSlot()) {
|
||||
Label slow, done;
|
||||
SetSourcePosition(callee->position());
|
||||
{
|
||||
PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(callee, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in eax) and
|
||||
// the object holding it (returned in edx).
|
||||
__ push(context_register());
|
||||
__ push(Immediate(callee->name()));
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ push(eax); // Function.
|
||||
__ push(edx); // Receiver.
|
||||
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(eax);
|
||||
// The receiver is implicitly the global receiver. Indicate this by
|
||||
// passing the hole to the call function stub.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
__ bind(&call);
|
||||
}
|
||||
} else {
|
||||
VisitForStackValue(callee);
|
||||
// refEnv.WithBaseObject()
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
#ifdef DEBUG
|
||||
// We want to verify that RecordJSReturnSite gets called on all paths
|
||||
@ -3035,9 +3078,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
int arg_count = args->length();
|
||||
{ PreservePositionScope pos_scope(masm()->positions_recorder());
|
||||
VisitForStackValue(callee);
|
||||
// Reserved receiver slot.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
|
||||
// Push the arguments.
|
||||
for (int i = 0; i < arg_count; i++) {
|
||||
VisitForStackValue(args->at(i));
|
||||
@ -3051,7 +3093,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Touch up the stack with the resolved function.
|
||||
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
|
||||
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
|
||||
}
|
||||
// Record source position for debugger.
|
||||
SetSourcePosition(expr->position());
|
||||
@ -3067,41 +3109,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
EmitCallWithLoadIC(expr);
|
||||
} else if (call_type == Call::LOOKUP_SLOT_CALL) {
|
||||
// Call to a lookup slot (dynamically introduced variable).
|
||||
VariableProxy* proxy = callee->AsVariableProxy();
|
||||
Label slow, done;
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
// Generate code for loading from variables potentially shadowed by
|
||||
// eval-introduced variables.
|
||||
EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
|
||||
}
|
||||
__ bind(&slow);
|
||||
// Call the runtime to find the function to call (returned in eax) and
|
||||
// the object holding it (returned in edx).
|
||||
__ push(context_register());
|
||||
__ push(Immediate(proxy->name()));
|
||||
__ CallRuntime(Runtime::kLoadLookupSlot, 2);
|
||||
__ push(eax); // Function.
|
||||
__ push(edx); // Receiver.
|
||||
PrepareForBailoutForId(expr->EvalOrLookupId(), NO_REGISTERS);
|
||||
|
||||
// If fast case code has been generated, emit code to push the function
|
||||
// and receiver and have the slow path jump around this code.
|
||||
if (done.is_linked()) {
|
||||
Label call;
|
||||
__ jmp(&call, Label::kNear);
|
||||
__ bind(&done);
|
||||
// Push function.
|
||||
__ push(eax);
|
||||
// The receiver is implicitly the global receiver. Indicate this by
|
||||
// passing the hole to the call function stub.
|
||||
__ push(Immediate(isolate()->factory()->undefined_value()));
|
||||
__ bind(&call);
|
||||
}
|
||||
|
||||
// The receiver is either the global receiver or an object found by
|
||||
// LoadContextSlot.
|
||||
PushCalleeAndWithBaseObject(expr);
|
||||
EmitCall(expr);
|
||||
|
||||
} else if (call_type == Call::PROPERTY_CALL) {
|
||||
Property* property = callee->AsProperty();
|
||||
bool is_named_call = property->key()->IsPropertyName();
|
||||
|
6
test/mjsunit/regress/regress-4214.js
Normal file
6
test/mjsunit/regress/regress-4214.js
Normal file
@ -0,0 +1,6 @@
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
var o = { eval: function() { return this; } }
|
||||
with (o) assertSame(o, eval());
|
Loading…
Reference in New Issue
Block a user