Remove receiver conversion from function prologue
Depends on https://codereview.chromium.org/1407373007/ After that CL, all receiver conversion is handled by the call builtin. BUG= Review URL: https://codereview.chromium.org/1414883011 Cr-Commit-Position: refs/heads/master@{#31826}
This commit is contained in:
parent
faf0238b45
commit
4ab1b05d5e
@ -175,6 +175,8 @@ namespace internal {
|
||||
V(kRegisterWasClobbered, "Register was clobbered") \
|
||||
V(kRememberedSetPointerInNewSpace, "Remembered set pointer is in new space") \
|
||||
V(kReturnAddressNotFoundInFrame, "Return address not found in frame") \
|
||||
V(kSloppyFunctionExpectsJSReceiverReceiver, \
|
||||
"Sloppy function expects JSReceiver as receiver.") \
|
||||
V(kSmiAdditionOverflow, "Smi addition overflow") \
|
||||
V(kSmiSubtractionOverflow, "Smi subtraction overflow") \
|
||||
V(kSpread, "Spread in array literal") \
|
||||
|
@ -328,9 +328,8 @@ base::SmartArrayPointer<char> CompilationInfo::GetDebugName() const {
|
||||
}
|
||||
|
||||
|
||||
bool CompilationInfo::MustReplaceUndefinedReceiverWithGlobalProxy() {
|
||||
return is_sloppy(language_mode()) && !is_native() &&
|
||||
scope()->has_this_declaration() && scope()->receiver()->is_used();
|
||||
bool CompilationInfo::ExpectsJSReceiverAsReceiver() {
|
||||
return is_sloppy(language_mode()) && !is_native();
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,7 +326,7 @@ class CompilationInfo {
|
||||
}
|
||||
bool ShouldEnsureSpaceForLazyDeopt() { return !IsStub(); }
|
||||
|
||||
bool MustReplaceUndefinedReceiverWithGlobalProxy();
|
||||
bool ExpectsJSReceiverAsReceiver();
|
||||
|
||||
// Determines whether or not to insert a self-optimization header.
|
||||
bool ShouldSelfOptimize();
|
||||
|
@ -526,14 +526,6 @@ bool AstGraphBuilder::CreateGraph(bool stack_check) {
|
||||
env.RawParameterBind(0, jsgraph()->TheHoleConstant());
|
||||
}
|
||||
|
||||
// Build receiver check for sloppy mode if necessary.
|
||||
// TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
|
||||
if (scope->has_this_declaration()) {
|
||||
Node* original_receiver = env.RawParameterLookup(0);
|
||||
Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
|
||||
env.RawParameterBind(0, patched_receiver);
|
||||
}
|
||||
|
||||
// Build local context only if there are context allocated variables.
|
||||
if (info()->num_heap_slots() > 0) {
|
||||
// Push a new inner context scope for the current activation.
|
||||
@ -3112,28 +3104,6 @@ Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object). Otherwise there is nothing left to do here.
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
IfBuilder receiver_check(this);
|
||||
Node* undefined = jsgraph()->UndefinedConstant();
|
||||
Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
|
||||
receiver_check.If(check);
|
||||
receiver_check.Then();
|
||||
Node* proxy = BuildLoadGlobalProxy();
|
||||
environment()->Push(proxy);
|
||||
receiver_check.Else();
|
||||
environment()->Push(receiver);
|
||||
receiver_check.End();
|
||||
return environment()->Pop();
|
||||
} else {
|
||||
return receiver;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Node* AstGraphBuilder::BuildLocalActivationContext(Node* context) {
|
||||
Scope* scope = info()->scope();
|
||||
|
||||
|
@ -242,9 +242,6 @@ class AstGraphBuilder : public AstVisitor {
|
||||
// resulting node. The operand stack height remains the same, variables and
|
||||
// other dependencies tracked by the environment might be mutated though.
|
||||
|
||||
// Builder to create a receiver check for sloppy mode.
|
||||
Node* BuildPatchReceiverToGlobalProxy(Node* receiver);
|
||||
|
||||
// Builders to create local function, script and block contexts.
|
||||
Node* BuildLocalActivationContext(Node* context);
|
||||
Node* BuildLocalFunctionContext(Scope* scope);
|
||||
|
@ -115,24 +115,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
// pp: Callee's constant pool pointer (if enabled)
|
||||
// fp: Caller's frame pointer.
|
||||
// lr: Caller's pc.
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
|
||||
__ ldr(r2, MemOperand(sp, receiver_offset));
|
||||
__ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
|
||||
__ b(ne, &ok);
|
||||
|
||||
__ ldr(r2, GlobalObjectOperand());
|
||||
__ ldr(r2, FieldMemOperand(r2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ str(r2, MemOperand(sp, receiver_offset));
|
||||
|
||||
__ bind(&ok);
|
||||
}
|
||||
}
|
||||
|
||||
info()->set_prologue_offset(masm_->pc_offset());
|
||||
|
@ -628,22 +628,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
__ Debug("stop-at", __LINE__, BREAK);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
int receiver_offset = info_->scope()->num_parameters() * kXRegSize;
|
||||
__ Peek(x10, receiver_offset);
|
||||
__ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok);
|
||||
|
||||
__ Ldr(x10, GlobalObjectMemOperand());
|
||||
__ Ldr(x10, FieldMemOperand(x10, JSGlobalObject::kGlobalProxyOffset));
|
||||
__ Poke(x10, receiver_offset);
|
||||
|
||||
__ Bind(&ok);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(__ StackPointer().Is(jssp));
|
||||
|
@ -138,26 +138,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
// +1 for return address.
|
||||
int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
|
||||
__ mov(ecx, Operand(esp, receiver_offset));
|
||||
|
||||
__ cmp(ecx, isolate()->factory()->undefined_value());
|
||||
__ j(not_equal, &ok, Label::kNear);
|
||||
|
||||
__ mov(ecx, GlobalObjectOperand());
|
||||
__ mov(ecx, FieldOperand(ecx, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ mov(Operand(esp, receiver_offset), ecx);
|
||||
|
||||
__ bind(&ok);
|
||||
}
|
||||
|
||||
if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
|
||||
// Move state of dynamic frame alignment into edx.
|
||||
__ Move(edx, Immediate(kNoAlignmentPadding));
|
||||
|
@ -138,24 +138,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
// cp: Callee's context.
|
||||
// fp: Caller's frame pointer.
|
||||
// lr: Caller's pc.
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
|
||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||
__ lw(a2, MemOperand(sp, receiver_offset));
|
||||
__ Branch(&ok, ne, a2, Operand(at));
|
||||
|
||||
__ lw(a2, GlobalObjectOperand());
|
||||
__ lw(a2, FieldMemOperand(a2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ sw(a2, MemOperand(sp, receiver_offset));
|
||||
|
||||
__ bind(&ok);
|
||||
}
|
||||
}
|
||||
|
||||
info()->set_prologue_offset(masm_->pc_offset());
|
||||
|
@ -113,24 +113,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
// cp: Callee's context.
|
||||
// fp: Caller's frame pointer.
|
||||
// lr: Caller's pc.
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
|
||||
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
||||
__ ld(a2, MemOperand(sp, receiver_offset));
|
||||
__ Branch(&ok, ne, a2, Operand(at));
|
||||
|
||||
__ ld(a2, GlobalObjectOperand());
|
||||
__ ld(a2, FieldMemOperand(a2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ sd(a2, MemOperand(sp, receiver_offset));
|
||||
|
||||
__ bind(&ok);
|
||||
}
|
||||
}
|
||||
|
||||
info()->set_prologue_offset(masm_->pc_offset());
|
||||
|
@ -125,24 +125,6 @@ bool LCodeGen::GeneratePrologue() {
|
||||
__ int3();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions need to replace the receiver with the global proxy
|
||||
// when called as functions (without an explicit receiver object).
|
||||
if (info()->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
StackArgumentsAccessor args(rsp, scope()->num_parameters());
|
||||
__ movp(rcx, args.GetReceiverOperand());
|
||||
|
||||
__ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &ok, Label::kNear);
|
||||
|
||||
__ movp(rcx, GlobalObjectOperand());
|
||||
__ movp(rcx, FieldOperand(rcx, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ movp(args.GetReceiverOperand(), rcx);
|
||||
|
||||
__ bind(&ok);
|
||||
}
|
||||
}
|
||||
|
||||
info()->set_prologue_offset(masm_->pc_offset());
|
||||
|
@ -116,22 +116,12 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
|
||||
__ ldr(r2, MemOperand(sp, receiver_offset));
|
||||
__ CompareRoot(r2, Heap::kUndefinedValueRootIndex);
|
||||
__ b(ne, &ok);
|
||||
|
||||
__ ldr(r2, GlobalObjectOperand());
|
||||
__ ldr(r2, FieldMemOperand(r2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ str(r2, MemOperand(sp, receiver_offset));
|
||||
|
||||
__ bind(&ok);
|
||||
__ AssertNotSmi(r2);
|
||||
__ CompareObjectType(r2, r2, no_reg, FIRST_SPEC_OBJECT_TYPE);
|
||||
__ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver);
|
||||
}
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack. The
|
||||
|
@ -115,23 +115,14 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
int receiver_offset = info->scope()->num_parameters() * kXRegSize;
|
||||
__ Peek(x10, receiver_offset);
|
||||
__ JumpIfNotRoot(x10, Heap::kUndefinedValueRootIndex, &ok);
|
||||
|
||||
__ Ldr(x10, GlobalObjectMemOperand());
|
||||
__ Ldr(x10, FieldMemOperand(x10, JSGlobalObject::kGlobalProxyOffset));
|
||||
__ Poke(x10, receiver_offset);
|
||||
|
||||
__ Bind(&ok);
|
||||
__ AssertNotSmi(x10);
|
||||
__ CompareObjectType(x10, x10, x11, FIRST_SPEC_OBJECT_TYPE);
|
||||
__ Assert(ge, kSloppyFunctionExpectsJSReceiverReceiver);
|
||||
}
|
||||
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack.
|
||||
// The MANUAL indicates that the scope shouldn't actually generate code
|
||||
// to set up the frame because we do it manually below.
|
||||
|
@ -105,24 +105,12 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
// +1 for return address.
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
|
||||
__ mov(ecx, Operand(esp, receiver_offset));
|
||||
|
||||
__ cmp(ecx, isolate()->factory()->undefined_value());
|
||||
__ j(not_equal, &ok, Label::kNear);
|
||||
|
||||
__ mov(ecx, GlobalObjectOperand());
|
||||
__ mov(ecx, FieldOperand(ecx, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ mov(Operand(esp, receiver_offset), ecx);
|
||||
|
||||
__ bind(&ok);
|
||||
__ AssertNotSmi(ecx);
|
||||
__ CmpObjectType(ecx, FIRST_SPEC_OBJECT_TYPE, ecx);
|
||||
__ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
|
||||
}
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack. The
|
||||
|
@ -124,22 +124,13 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
|
||||
__ lw(at, MemOperand(sp, receiver_offset));
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&ok, ne, a2, Operand(at));
|
||||
|
||||
__ lw(a2, GlobalObjectOperand());
|
||||
__ lw(a2, FieldMemOperand(a2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ sw(a2, MemOperand(sp, receiver_offset));
|
||||
|
||||
__ bind(&ok);
|
||||
__ lw(a2, MemOperand(sp, receiver_offset));
|
||||
__ AssertNotSmi(a2);
|
||||
__ GetObjectType(a2, a2, a2);
|
||||
__ Check(ge, kSloppyFunctionExpectsJSReceiverReceiver, a2,
|
||||
Operand(FIRST_SPEC_OBJECT_TYPE));
|
||||
}
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack. The
|
||||
|
@ -124,22 +124,15 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
|
||||
__ ld(at, MemOperand(sp, receiver_offset));
|
||||
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
|
||||
__ Branch(&ok, ne, a2, Operand(at));
|
||||
|
||||
__ ld(a2, GlobalObjectOperand());
|
||||
__ ld(a2, FieldMemOperand(a2, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ sd(a2, MemOperand(sp, receiver_offset));
|
||||
__ bind(&ok);
|
||||
__ lw(a2, MemOperand(sp, receiver_offset));
|
||||
__ AssertNotSmi(a2);
|
||||
__ GetObjectType(a2, a2, a2);
|
||||
__ Check(ge, kSloppyFunctionExpectsJSReceiverReceiver, a2,
|
||||
Operand(FIRST_SPEC_OBJECT_TYPE));
|
||||
}
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack. The
|
||||
// MANUAL indicates that the scope shouldn't actually generate code to set up
|
||||
// the frame (that is done below).
|
||||
|
@ -104,24 +104,12 @@ void FullCodeGenerator::Generate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Sloppy mode functions and builtins need to replace the receiver with the
|
||||
// global proxy when called as functions (without an explicit receiver
|
||||
// object).
|
||||
if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
|
||||
Label ok;
|
||||
// +1 for return address.
|
||||
if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
|
||||
StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
|
||||
__ movp(rcx, args.GetReceiverOperand());
|
||||
|
||||
__ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
|
||||
__ j(not_equal, &ok, Label::kNear);
|
||||
|
||||
__ movp(rcx, GlobalObjectOperand());
|
||||
__ movp(rcx, FieldOperand(rcx, JSGlobalObject::kGlobalProxyOffset));
|
||||
|
||||
__ movp(args.GetReceiverOperand(), rcx);
|
||||
|
||||
__ bind(&ok);
|
||||
__ AssertNotSmi(rcx);
|
||||
__ CmpObjectType(rcx, FIRST_SPEC_OBJECT_TYPE, rcx);
|
||||
__ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
|
||||
}
|
||||
|
||||
// Open a frame scope to indicate that there is a frame on the stack. The
|
||||
|
Loading…
Reference in New Issue
Block a user