diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc index 6c374b3914..ca3c8ea210 100644 --- a/src/arm/builtins-arm.cc +++ b/src/arm/builtins-arm.cc @@ -1089,8 +1089,6 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ mov(r4, Operand::Zero()); __ jmp(&patch_receiver); - // Use the global receiver object from the called function as the - // receiver. __ bind(&use_global_receiver); __ ldr(r2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); @@ -1180,7 +1178,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); __ SmiUntag(r2); __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); - __ SetCallKind(r5, CALL_AS_METHOD); + __ SetCallKind(r5, CALL_AS_FUNCTION); __ cmp(r2, r0); // Check formal and actual parameter counts. __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET, @@ -1188,7 +1186,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ParameterCount expected(0); __ InvokeCode(r3, expected, expected, JUMP_FUNCTION, - NullCallWrapper(), CALL_AS_METHOD); + NullCallWrapper(), CALL_AS_FUNCTION); } @@ -1282,7 +1280,6 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); __ b(&push_receiver); - // Use the current global receiver object as the receiver. __ bind(&use_global_receiver); __ ldr(r0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); @@ -1320,7 +1317,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { __ cmp(r0, r1); __ b(ne, &loop); - // Invoke the function. + // Call the function. Label call_proxy; ParameterCount actual(r0); __ SmiUntag(r0); @@ -1328,18 +1325,18 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); __ b(ne, &call_proxy); __ InvokeFunction(r1, actual, CALL_FUNCTION, - NullCallWrapper(), CALL_AS_METHOD); + NullCallWrapper(), CALL_AS_FUNCTION); frame_scope.GenerateLeaveFrame(); __ add(sp, sp, Operand(3 * kPointerSize)); __ Jump(lr); - // Invoke the function proxy. + // Call the function proxy. __ bind(&call_proxy); __ push(r1); // add function proxy as last argument __ add(r0, r0, Operand(1)); __ mov(r2, Operand::Zero()); - __ SetCallKind(r5, CALL_AS_METHOD); + __ SetCallKind(r5, CALL_AS_FUNCTION); __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET); diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index d9449d5543..8a744ae6c5 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -3186,43 +3186,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // r1: pushed function (to be verified) __ JumpIfSmi(r1, &non_function); - // The receiver might implicitly be the global object. This is - // indicated by passing the hole as the receiver to the call - // function stub. - if (ReceiverMightBeImplicit() || ReceiverIsImplicit()) { - Label try_call, call, patch_current_context; - if (ReceiverMightBeImplicit()) { - // Get the receiver from the stack. - // function, receiver [, arguments] - __ ldr(r4, MemOperand(sp, argc_ * kPointerSize)); - // Call as function is indicated with the hole. - __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); - __ b(ne, &try_call); - } - // Patch the receiver on the stack with the global receiver object. - // Goto slow case if we do not have a function. - __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); - __ b(ne, &patch_current_context); - CallStubCompiler::FetchGlobalProxy(masm, r3, r1); - __ str(r3, MemOperand(sp, argc_ * kPointerSize)); - __ jmp(&call); - - __ bind(&patch_current_context); - __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); - __ str(r4, MemOperand(sp, argc_ * kPointerSize)); - __ jmp(&slow); - - __ bind(&try_call); - // Get the map of the function object. - __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); - __ b(ne, &slow); - - __ bind(&call); - } else { - // Get the map of the function object. - __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); - __ b(ne, &slow); - } + // Goto slow case if we do not have a function. + __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); + __ b(ne, &slow); if (RecordCallTarget()) { GenerateRecordCallTarget(masm); @@ -3232,17 +3198,6 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // r1: pushed function ParameterCount actual(argc_); - if (ReceiverMightBeImplicit()) { - Label call_as_function; - __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); - __ b(eq, &call_as_function); - __ InvokeFunction(r1, - actual, - JUMP_FUNCTION, - NullCallWrapper(), - CALL_AS_METHOD); - __ bind(&call_as_function); - } __ InvokeFunction(r1, actual, JUMP_FUNCTION, @@ -3281,7 +3236,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { __ mov(r0, Operand(argc_)); // Set up the number of arguments. __ mov(r2, Operand::Zero()); __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); - __ SetCallKind(r5, CALL_AS_METHOD); + __ SetCallKind(r5, CALL_AS_FUNCTION); __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET); } diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 06514910ac..8a500e2035 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -144,15 +144,25 @@ void FullCodeGenerator::Generate() { } #endif - // Strict mode functions and builtins need to replace the receiver - // with undefined when called as functions (without an explicit - // receiver object). r5 is zero for method calls and non-zero for - // function calls. - if (!info->is_classic_mode() || info->is_native()) { + // Classic mode functions and builtins need to replace the receiver with the + // global proxy when called as functions (without an explicit receiver + // object). + if (info->is_classic_mode() && !info->is_native()) { + Label ok; __ cmp(r5, Operand::Zero()); + __ b(eq, &ok); + int receiver_offset = info->scope()->num_parameters() * kPointerSize; - __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); - __ str(r2, MemOperand(sp, receiver_offset), ne); + __ ldr(r2, MemOperand(sp, receiver_offset)); + __ CompareRoot(r2, Heap::kUndefinedValueRootIndex); + __ b(ne, &ok); + + __ ldr(r2, GlobalObjectOperand()); + __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); + + __ str(r2, MemOperand(sp, receiver_offset)); + + __ bind(&ok); } // Open a frame scope to indicate that there is a frame on the stack. The @@ -2734,7 +2744,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Record source position for debugger. SetSourcePosition(expr->position()); - CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); + CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); __ CallStub(&stub); RecordJSReturnSite(expr); @@ -2776,15 +2786,14 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ push(r0); // The receiver is implicitly the global receiver. Indicate this // by passing the hole to the call function stub. - __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); + __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); __ push(r1); __ bind(&call); } // The receiver is either the global receiver or an object found - // by LoadContextSlot. That object could be the hole if the - // receiver is implicitly the global object. - EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT); + // by LoadContextSlot. + EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); } else if (property != NULL) { { PreservePositionScope scope(masm()->positions_recorder()); VisitForStackValue(property->obj()); @@ -2801,12 +2810,10 @@ void FullCodeGenerator::VisitCall(Call* expr) { { PreservePositionScope scope(masm()->positions_recorder()); VisitForStackValue(callee); } - // Push the hole as receiver. - // It will be correctly replaced in the call stub. - __ LoadRoot(r1, Heap::kTheHoleValueRootIndex); + __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); __ push(r1); // Emit function call. - EmitCallWithStub(expr, RECEIVER_IS_IMPLICIT); + EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); } #ifdef DEBUG @@ -3723,7 +3730,7 @@ void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { __ mov(r1, result_register()); ParameterCount count(arg_count); __ InvokeFunction(r1, count, CALL_FUNCTION, - NullCallWrapper(), CALL_AS_METHOD); + NullCallWrapper(), CALL_AS_FUNCTION); __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); __ jmp(&done); diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index 7b3ba36689..adfef24d09 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -491,7 +491,7 @@ void CallICBase::GenerateMiss(MacroAssembler* masm, // Patch the receiver on the stack. __ bind(&global); - CallStubCompiler::FetchGlobalProxy(masm, r2, r1); + __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); __ str(r2, MemOperand(sp, argc * kPointerSize)); __ bind(&invoke); } diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index da90a6705c..b72417e8c8 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2511,8 +2511,7 @@ LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { instr->arguments_count(), instr->function(), undefined, - instr->inlining_kind(), - instr->undefined_receiver()); + instr->inlining_kind()); // Only replay binding of arguments object if it wasn't removed from graph. if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) { inner->Bind(instr->arguments_var(), instr->arguments_object()); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index d2c9a2515f..47376d113c 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -147,15 +147,27 @@ bool LCodeGen::GeneratePrologue() { // fp: Caller's frame pointer. // lr: Caller's pc. - // Strict mode functions and builtins need to replace the receiver - // with undefined when called as functions (without an explicit - // receiver object). r5 is zero for method calls and non-zero for - // function calls. - if (!info_->is_classic_mode() || info_->is_native()) { + // Classic mode functions and builtins need to replace the receiver with the + // global proxy when called as functions (without an explicit receiver + // object). + if (info_->this_has_uses() && + info_->is_classic_mode() && + !info_->is_native()) { + Label ok; __ cmp(r5, Operand::Zero()); - int receiver_offset = scope()->num_parameters() * kPointerSize; - __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); - __ str(r2, MemOperand(sp, receiver_offset), ne); + __ b(eq, &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, GlobalObject::kGlobalReceiverOffset)); + + __ str(r2, MemOperand(sp, receiver_offset)); + + __ bind(&ok); } } @@ -3494,7 +3506,12 @@ void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { __ b(&result_in_receiver); __ bind(&global_object); - CallStubCompiler::FetchGlobalProxy(masm(), receiver, function); + __ ldr(receiver, FieldMemOperand(function, JSFunction::kContextOffset)); + __ ldr(receiver, + ContextOperand(receiver, + Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); + __ ldr(receiver, + FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset)); if (result.is(receiver)) { __ bind(&result_in_receiver); @@ -3552,7 +3569,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { // by InvokeFunction. ParameterCount actual(receiver); __ InvokeFunction(function, actual, CALL_FUNCTION, - safepoint_generator, CALL_AS_METHOD); + safepoint_generator, CALL_AS_FUNCTION); } @@ -3673,7 +3690,7 @@ void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { instr->hydrogen()->formal_parameter_count(), instr->arity(), instr, - CALL_AS_METHOD, + CALL_AS_FUNCTION, R1_UNINITIALIZED); } @@ -3951,13 +3968,13 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { LPointerMap* pointers = instr->pointer_map(); SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); ParameterCount count(instr->arity()); - __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); + __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_FUNCTION); } else { CallKnownFunction(known_function, instr->hydrogen()->formal_parameter_count(), instr->arity(), instr, - CALL_AS_METHOD, + CALL_AS_FUNCTION, R1_CONTAINS_TARGET); } } @@ -3992,10 +4009,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { ASSERT(ToRegister(instr->result()).is(r0)); int arity = instr->arity(); - CallFunctionFlags flags = - instr->hydrogen()->IsContextualCall() ? - RECEIVER_IS_IMPLICIT : NO_CALL_FUNCTION_FLAGS; - CallFunctionStub stub(arity, flags); + CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); if (instr->hydrogen()->IsTailCall()) { if (NeedsEagerFrame()) __ mov(sp, fp); __ Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 5350b6bb4e..f26f834e59 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -2341,23 +2341,11 @@ void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { } -void CallStubCompiler::PatchGlobalProxy(Handle object, - Handle function) { +void CallStubCompiler::PatchImplicitReceiver(Handle object) { if (object->IsGlobalObject()) { const int argc = arguments().immediate(); const int receiver_offset = argc * kPointerSize; - __ Move(r3, handle(function->context()->global_proxy())); - __ str(r3, MemOperand(sp, receiver_offset)); - } -} - - -void CallStubCompiler::PatchGlobalProxy(Handle object, - Register function) { - if (object->IsGlobalObject()) { - FetchGlobalProxy(masm(), r3, function); - const int argc = arguments().immediate(); - const int receiver_offset = argc * kPointerSize; + __ LoadRoot(r3, Heap::kUndefinedValueRootIndex); __ str(r3, MemOperand(sp, receiver_offset)); } } @@ -2456,7 +2444,7 @@ void CallStubCompiler::GenerateJumpFunction(Handle object, ASSERT(function.is(r1)); // Check that the function really is a function. GenerateFunctionCheck(function, r3, miss); - PatchGlobalProxy(object, function); + PatchImplicitReceiver(object); // Invoke the function. __ InvokeFunction(r1, arguments(), JUMP_FUNCTION, @@ -2574,15 +2562,6 @@ Handle StoreStubCompiler::CompileStoreCallback( #define __ ACCESS_MASM(masm) -void CallStubCompiler::FetchGlobalProxy(MacroAssembler* masm, - Register target, - Register function) { - __ ldr(target, FieldMemOperand(function, JSFunction::kContextOffset)); - __ ldr(target, ContextOperand(target, Context::GLOBAL_OBJECT_INDEX)); - __ ldr(target, FieldMemOperand(target, GlobalObject::kGlobalReceiverOffset)); -} - - void StoreStubCompiler::GenerateStoreViaSetter( MacroAssembler* masm, Handle setter) { diff --git a/src/builtins.cc b/src/builtins.cc index 9191263630..a690b31b29 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -1173,6 +1173,15 @@ MUST_USE_RESULT static MaybeObject* HandleApiCallHelper( fun_data = *desc; } + SharedFunctionInfo* shared = function->shared(); + if (shared->is_classic_mode() && !shared->native()) { + Object* recv = args[0]; + ASSERT(!recv->IsNull()); + if (recv->IsUndefined()) { + args[0] = function->context()->global_object()->global_receiver(); + } + } + Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data); if (raw_holder->IsNull()) { diff --git a/src/code-stubs.cc b/src/code-stubs.cc index f524bb6bfb..76af3f775e 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -595,7 +595,6 @@ void ArgumentsAccessStub::PrintName(StringStream* stream) { void CallFunctionStub::PrintName(StringStream* stream) { stream->Add("CallFunctionStub_Args%d", argc_); - if (ReceiverMightBeImplicit()) stream->Add("_Implicit"); if (RecordCallTarget()) stream->Add("_Recording"); } diff --git a/src/code-stubs.h b/src/code-stubs.h index 090483bb38..f4a52480eb 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -1553,8 +1553,8 @@ class CallFunctionStub: public PlatformCodeStub { virtual void PrintName(StringStream* stream); // Minor key encoding in 32 bits with Bitfield . - class FlagBits: public BitField {}; - class ArgcBits: public BitField {}; + class FlagBits: public BitField {}; + class ArgcBits: public BitField {}; Major MajorKey() { return CallFunction; } int MinorKey() { @@ -1562,14 +1562,6 @@ class CallFunctionStub: public PlatformCodeStub { return FlagBits::encode(flags_) | ArgcBits::encode(argc_); } - bool ReceiverMightBeImplicit() { - return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0; - } - - bool ReceiverIsImplicit() { - return (flags_ & RECEIVER_IS_IMPLICIT) != 0; - } - bool RecordCallTarget() { return (flags_ & RECORD_CALL_TARGET) != 0; } diff --git a/src/compiler.cc b/src/compiler.cc index 276b9d8fe3..b9e13c1661 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -59,7 +59,8 @@ CompilationInfo::CompilationInfo(Handle