From: ager@chromium.org Date: Wed, 25 May 2011 06:04:01 +0000 (+0000) Subject: MIPS: port Fix calls of strict mode function with an implicit receiver. X-Git-Tag: upstream/4.7.83~19315 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b92ef0be3269f9a1dbf8cd4837daa52b42f75697;p=platform%2Fupstream%2Fv8.git MIPS: port Fix calls of strict mode function with an implicit receiver. Port of r8040 to mips. Original commit message: Strict mode functions are to get 'undefined' as the receiver when called with an implicit receiver. Modes are bad! It forces us to have checks on all function calls. This change attempts to limit the cost by passing information about whether or not a call is with an implicit or explicit receiver in ecx as part of the calling convention. The cost is setting ecx on all calls and checking ecx on entry to strict mode functions. Implicit/explicit receiver state has to be maintained by ICs. Various stubs have to not clobber ecx or save and restore it. CallFunction stub needs to check if the receiver is implicit when it doesn't know from the context. BUG= TEST= Review URL: http://codereview.chromium.org/6992051 Patch from Paul Lind . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8050 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index 732915f..e22259d 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -645,6 +645,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { // Set expected number of arguments to zero (not changing a0). __ mov(a2, zero_reg); __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); + __ SetCallKind(t1, CALL_AS_METHOD); __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET); } @@ -1102,6 +1103,8 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) { // Preserve the function. __ push(a1); + // Push call kind information. + __ push(t1); // Push the function on the stack as the argument to the runtime function. __ push(a1); @@ -1109,6 +1112,9 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) { __ CallRuntime(Runtime::kLazyCompile, 1); // Calculate the entry point. __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag); + + // Restore call kind information. + __ pop(t1); // Restore saved function. __ pop(a1); @@ -1126,12 +1132,17 @@ void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { // Preserve the function. __ push(a1); + // Push call kind information. + __ push(t1); // Push the function on the stack as the argument to the runtime function. __ push(a1); __ CallRuntime(Runtime::kLazyRecompile, 1); // Calculate the entry point. __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); + + // Restore call kind information. + __ pop(t1); // Restore saved function. __ pop(a1); @@ -1306,6 +1317,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { __ Branch(&function, ne, a1, Operand(zero_reg)); __ mov(a2, zero_reg); // expected arguments is 0 for CALL_NON_FUNCTION __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); + __ SetCallKind(t1, CALL_AS_METHOD); __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET); __ bind(&function); @@ -1321,6 +1333,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); __ sra(a2, a2, kSmiTagSize); __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); + __ SetCallKind(t1, CALL_AS_METHOD); // Check formal and actual parameter counts. __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); @@ -1500,6 +1513,7 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // -- a1: function (passed through to callee) // -- a2: expected arguments count // -- a3: callee code entry + // -- t1: call kind information // ----------------------------------- Label invoke, dont_adapt_arguments; diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index e9643ba..d470fea 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -4655,34 +4655,22 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) { void CallFunctionStub::Generate(MacroAssembler* masm) { Label slow; - // If the receiver might be a value (string, number or boolean) check - // for this and box it if it is. - if (ReceiverMightBeValue()) { + // 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()) { + Label call; // Get the receiver from the stack. // function, receiver [, arguments] - Label receiver_is_value, receiver_is_js_object; - __ lw(a1, MemOperand(sp, argc_ * kPointerSize)); - - // Check if receiver is a smi (which is a number value). - __ JumpIfSmi(a1, &receiver_is_value); - - // Check if the receiver is a valid JS object. - __ GetObjectType(a1, a2, a2); - __ Branch(&receiver_is_js_object, - ge, - a2, - Operand(FIRST_JS_OBJECT_TYPE)); - - // Call the runtime to box the value. - __ bind(&receiver_is_value); - // We need natives to execute this. - __ EnterInternalFrame(); - __ push(a1); - __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); - __ LeaveInternalFrame(); - __ sw(v0, MemOperand(sp, argc_ * kPointerSize)); - - __ bind(&receiver_is_js_object); + __ lw(t0, MemOperand(sp, argc_ * kPointerSize)); + // Call as function is indicated with the hole. + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&call, ne, t0, Operand(at)); + // Patch the receiver on the stack with the global receiver object. + __ lw(a1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); + __ lw(a1, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); + __ sw(a1, MemOperand(sp, argc_ * kPointerSize)); + __ bind(&call); } // Get the function to call from the stack. @@ -4699,7 +4687,19 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { // Fast-case: Invoke the function now. // a1: pushed function ParameterCount actual(argc_); - __ InvokeFunction(a1, actual, JUMP_FUNCTION); + + if (ReceiverMightBeImplicit()) { + Label call_as_function; + __ LoadRoot(at, Heap::kTheHoleValueRootIndex); + __ Branch(&call_as_function, eq, t0, Operand(at)); + __ InvokeFunction(a1, actual, JUMP_FUNCTION); + __ bind(&call_as_function); + } + __ InvokeFunction(a1, + actual, + JUMP_FUNCTION, + NullCallWrapper(), + CALL_AS_FUNCTION); // Slow-case: Non-function called. __ bind(&slow); diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc index 7d9d215..9c93c63 100644 --- a/src/mips/full-codegen-mips.cc +++ b/src/mips/full-codegen-mips.cc @@ -147,6 +147,19 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { } #endif + // Strict mode functions need to replace the receiver with undefined + // when called as functions (without an explicit receiver + // object). t1 is zero for method calls and non-zero for function + // calls. + if (info->is_strict_mode()) { + Label ok; + __ Branch(&ok, eq, t1, Operand(zero_reg)); + int receiver_offset = scope()->num_parameters() * kPointerSize; + __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); + __ sw(a2, MemOperand(sp, receiver_offset)); + __ bind(&ok); + } + int locals_count = scope()->num_stack_slots(); __ Push(ra, fp, cp, a1); @@ -2105,7 +2118,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, // Call the IC initialization code. InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop); + isolate()->stub_cache()->ComputeCallInitialize(arg_count, in_loop, mode); EmitCallIC(ic, mode, expr->id()); RecordJSReturnSite(expr); // Restore context register. @@ -2115,8 +2128,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, - Expression* key, - RelocInfo::Mode mode) { + Expression* key) { // Load the key. VisitForAccumulatorValue(key); @@ -2141,7 +2153,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, Handle ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. - EmitCallIC(ic, mode, expr->id()); + EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); RecordJSReturnSite(expr); // Restore context register. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); @@ -2255,7 +2267,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { // Record source position for debugger. SetSourcePosition(expr->position()); InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; - CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); + CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_IMPLICIT); __ CallStub(&stub); RecordJSReturnSite(expr); // Restore context register. @@ -2305,9 +2317,10 @@ void FullCodeGenerator::VisitCall(Call* expr) { __ bind(&call); } - // The receiver is either the global receiver or a JSObject found by - // LoadContextSlot. - EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); + // 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); } else if (fun->AsProperty() != NULL) { // Call to an object property. Property* prop = fun->AsProperty(); @@ -2348,7 +2361,7 @@ void FullCodeGenerator::VisitCall(Call* expr) { { PreservePositionScope scope(masm()->positions_recorder()); VisitForStackValue(prop->obj()); } - EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); + EmitKeyedCallWithIC(expr, prop->key()); } } } else { @@ -3663,9 +3676,12 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { // Call the JS runtime function. __ li(a2, Operand(expr->name())); + RelocInfo::Mode mode = RelocInfo::CODE_TARGET; Handle ic = - isolate()->stub_cache()->ComputeCallInitialize(arg_count, NOT_IN_LOOP); - EmitCallIC(ic, RelocInfo::CODE_TARGET, expr->id()); + isolate()->stub_cache()->ComputeCallInitialize(arg_count, + NOT_IN_LOOP, + mode); + EmitCallIC(ic, mode, expr->id()); // Restore context register. __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); } else { diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc index 1946bf1..12c81c2 100644 --- a/src/mips/ic-mips.cc +++ b/src/mips/ic-mips.cc @@ -494,7 +494,8 @@ Object* CallIC_Miss(Arguments args); // The generated code falls through if both probes miss. static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, int argc, - Code::Kind kind) { + Code::Kind kind, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- a1 : receiver // -- a2 : name @@ -505,7 +506,7 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, Code::Flags flags = Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, - Code::kNoExtraICState, + extra_ic_state, NORMAL, argc); Isolate::Current()->stub_cache()->GenerateProbe( @@ -593,7 +594,10 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) { } -static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { +static void GenerateCallMiss(MacroAssembler* masm, + int argc, + IC::UtilityId id, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -643,22 +647,33 @@ static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { __ bind(&invoke); } // Invoke the function. + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) + ? CALL_AS_FUNCTION + : CALL_AS_METHOD; ParameterCount actual(argc); - __ InvokeFunction(a1, actual, JUMP_FUNCTION); + __ InvokeFunction(a1, + actual, + JUMP_FUNCTION, + NullCallWrapper(), + call_kind); } -void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { +void CallIC::GenerateMiss(MacroAssembler* masm, + int argc, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address // ----------------------------------- - GenerateCallMiss(masm, argc, IC::kCallIC_Miss); + GenerateCallMiss(masm, argc, IC::kCallIC_Miss, extra_ic_state); } -void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { +void CallIC::GenerateMegamorphic(MacroAssembler* masm, + int argc, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -666,8 +681,8 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // Get the receiver of the function from the stack into a1. __ lw(a1, MemOperand(sp, argc * kPointerSize)); - GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC); - GenerateMiss(masm, argc); + GenerateMonomorphicCacheProbe(masm, argc, Code::CALL_IC, extra_ic_state); + GenerateMiss(masm, argc, extra_ic_state); } @@ -678,7 +693,7 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { // ----------------------------------- GenerateCallNormal(masm, argc); - GenerateMiss(masm, argc); + GenerateMiss(masm, argc, Code::kNoExtraICState); } @@ -688,7 +703,7 @@ void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { // -- ra : return address // ----------------------------------- - GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); + GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState); } @@ -773,7 +788,10 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { __ bind(&lookup_monomorphic_cache); __ IncrementCounter(counters->keyed_call_generic_lookup_cache(), 1, a0, a3); - GenerateMonomorphicCacheProbe(masm, argc, Code::KEYED_CALL_IC); + GenerateMonomorphicCacheProbe(masm, + argc, + Code::KEYED_CALL_IC, + Code::kNoExtraICState); // Fall through on miss. __ bind(&slow_call); diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 5d21683..36f0655 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -2699,6 +2699,21 @@ void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg, } } + +void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { + // This macro takes the dst register to make the code more readable + // at the call sites. However, the dst register has to be t1 to + // follow the calling convention which requires the call type to be + // in t1. + ASSERT(dst.is(t1)); + if (call_kind == CALL_AS_FUNCTION) { + li(dst, Operand(Smi::FromInt(1))); + } else { + li(dst, Operand(Smi::FromInt(0))); + } +} + + // ----------------------------------------------------------------------------- // JavaScript invokes. @@ -2708,7 +2723,8 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, Register code_reg, Label* done, InvokeFlag flag, - const CallWrapper& call_wrapper) { + const CallWrapper& call_wrapper, + CallKind call_kind) { bool definitely_matches = false; Label regular_invoke; @@ -2760,10 +2776,12 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, isolate()->builtins()->ArgumentsAdaptorTrampoline(); if (flag == CALL_FUNCTION) { call_wrapper.BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); + SetCallKind(t1, call_kind); Call(adaptor, RelocInfo::CODE_TARGET); call_wrapper.AfterCall(); jmp(done); } else { + SetCallKind(t1, call_kind); Jump(adaptor, RelocInfo::CODE_TARGET); } bind(®ular_invoke); @@ -2775,15 +2793,18 @@ void MacroAssembler::InvokeCode(Register code, const ParameterCount& expected, const ParameterCount& actual, InvokeFlag flag, - const CallWrapper& call_wrapper) { + const CallWrapper& call_wrapper, + CallKind call_kind) { Label done; InvokePrologue(expected, actual, Handle::null(), code, &done, flag, - call_wrapper); + call_wrapper, call_kind); if (flag == CALL_FUNCTION) { + SetCallKind(t1, call_kind); Call(code); } else { ASSERT(flag == JUMP_FUNCTION); + SetCallKind(t1, call_kind); Jump(code); } // Continue here if InvokePrologue does handle the invocation due to @@ -2796,13 +2817,17 @@ void MacroAssembler::InvokeCode(Handle code, const ParameterCount& expected, const ParameterCount& actual, RelocInfo::Mode rmode, - InvokeFlag flag) { + InvokeFlag flag, + CallKind call_kind) { Label done; - InvokePrologue(expected, actual, code, no_reg, &done, flag); + InvokePrologue(expected, actual, code, no_reg, &done, flag, + NullCallWrapper(), call_kind); if (flag == CALL_FUNCTION) { + SetCallKind(t1, call_kind); Call(code, rmode); } else { + SetCallKind(t1, call_kind); Jump(code, rmode); } // Continue here if InvokePrologue does handle the invocation due to @@ -2814,7 +2839,8 @@ void MacroAssembler::InvokeCode(Handle code, void MacroAssembler::InvokeFunction(Register function, const ParameterCount& actual, InvokeFlag flag, - const CallWrapper& call_wrapper) { + const CallWrapper& call_wrapper, + CallKind call_kind) { // Contract with called JS functions requires that function is passed in a1. ASSERT(function.is(a1)); Register expected_reg = a2; @@ -2829,7 +2855,7 @@ void MacroAssembler::InvokeFunction(Register function, lw(code_reg, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); ParameterCount expected(expected_reg); - InvokeCode(code_reg, expected, actual, flag, call_wrapper); + InvokeCode(code_reg, expected, actual, flag, call_wrapper, call_kind); } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 73ee047..bcb459e 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -614,25 +614,33 @@ DECLARE_NOTARGET_PROTOTYPE(Ret) // ------------------------------------------------------------------------- // JavaScript invokes. + // Setup call kind marking in t1. The method takes t1 as an + // explicit first parameter to make the code more readable at the + // call sites. + void SetCallKind(Register dst, CallKind kind); + // Invoke the JavaScript function code by either calling or jumping. void InvokeCode(Register code, const ParameterCount& expected, const ParameterCount& actual, InvokeFlag flag, - const CallWrapper& call_wrapper = NullCallWrapper()); + const CallWrapper& call_wrapper = NullCallWrapper(), + CallKind call_kind = CALL_AS_METHOD); void InvokeCode(Handle code, const ParameterCount& expected, const ParameterCount& actual, RelocInfo::Mode rmode, - InvokeFlag flag); + InvokeFlag flag, + CallKind call_kind = CALL_AS_METHOD); // Invoke the JavaScript function in the given register. Changes the // current context to the context in the function before invoking. void InvokeFunction(Register function, const ParameterCount& actual, InvokeFlag flag, - const CallWrapper& call_wrapper = NullCallWrapper()); + const CallWrapper& call_wrapper = NullCallWrapper(), + CallKind call_kind = CALL_AS_METHOD); void InvokeFunction(JSFunction* function, const ParameterCount& actual, @@ -1098,7 +1106,8 @@ DECLARE_NOTARGET_PROTOTYPE(Ret) Register code_reg, Label* done, InvokeFlag flag, - const CallWrapper& call_wrapper = NullCallWrapper()); + const CallWrapper& call_wrapper = NullCallWrapper(), + CallKind call_kind = CALL_AS_METHOD); // Get the code for the given builtin. Returns if able to resolve // the function in the 'resolved' flag. diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index c1ae567..47428a8 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -1469,8 +1469,10 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, MaybeObject* CallStubCompiler::GenerateMissBranch() { - MaybeObject* maybe_obj = masm()->isolate()->stub_cache()->ComputeCallMiss( - arguments().immediate(), kind_); + MaybeObject* maybe_obj = + isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), + kind_, + extra_ic_state_); Object* obj; if (!maybe_obj->ToObject(&obj)) return maybe_obj; __ Jump(Handle(Code::cast(obj)), RelocInfo::CODE_TARGET); @@ -1789,7 +1791,9 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( Label* index_out_of_range_label = &index_out_of_range; - if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { + if (kind_ == Code::CALL_IC && + (CallICBase::StringStubState::decode(extra_ic_state_) == + DEFAULT_STRING_STUB)) { index_out_of_range_label = &miss; } @@ -1873,7 +1877,9 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall( Label index_out_of_range; Label* index_out_of_range_label = &index_out_of_range; - if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) { + if (kind_ == Code::CALL_IC && + (CallICBase::StringStubState::decode(extra_ic_state_) == + DEFAULT_STRING_STUB)) { index_out_of_range_label = &miss; } @@ -2485,11 +2491,13 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, } -MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileCallGlobal( + JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name, + Code::ExtraICState extra_ic_state) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -2530,11 +2538,14 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, ASSERT(function->is_compiled()); Handle code(function->code()); ParameterCount expected(function->shared()->formal_parameter_count()); + CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) + ? CALL_AS_FUNCTION + : CALL_AS_METHOD; if (V8::UseCrankshaft()) { UNIMPLEMENTED_MIPS(); } else { - __ InvokeCode(code, expected, arguments(), - RelocInfo::CODE_TARGET, JUMP_FUNCTION); + __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET, + JUMP_FUNCTION, call_kind); } // Handle call cache miss.