}
+// 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;
+
+ {
+ 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
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++) {
// 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.
} 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();
}
+// 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;
+
+ {
+ 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
{
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++) {
// 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.
} 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();
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_);
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;
}
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);
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.
// 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)
}
+// 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;
+ {
+ 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
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));
// 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());
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();
}
+// 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;
+
+ {
+ 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
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++) {
// 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());
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();
}
+// 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;
+
+ {
+ 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
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++) {
// 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());
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();
}
+// 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;
+
+ {
+ 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
{
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++) {
// 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.
} 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();
}
+// 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;
+
+ {
+ 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
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++) {
// 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());
} 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();
}
+// 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;
+ {
+ 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
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));
// 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());
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();
--- /dev/null
+// 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());