| Index: src/mips/code-stubs-mips.cc
|
| diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
|
| index 289e6b810769568551ebf243adfbaa9b95def883..7e0ab929c4a2832bb7125423a3f402bf96f91057 100644
|
| --- a/src/mips/code-stubs-mips.cc
|
| +++ b/src/mips/code-stubs-mips.cc
|
| @@ -5341,24 +5341,49 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -void CallFunctionStub::FinishCode(Handle<Code> code) {
|
| - code->set_has_function_cache(false);
|
| -}
|
| -
|
| +static void GenerateRecordCallTarget(MacroAssembler* masm) {
|
| + // Cache the called function in a global property cell. Cache states
|
| + // are uninitialized, monomorphic (indicated by a JSFunction), and
|
| + // megamorphic.
|
| + // a1 : the function to call
|
| + // a2 : cache cell for call target
|
| + Label done;
|
|
|
| -void CallFunctionStub::Clear(Heap* heap, Address address) {
|
| - UNREACHABLE();
|
| -}
|
| + ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
|
| + masm->isolate()->heap()->undefined_value());
|
| + ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()),
|
| + masm->isolate()->heap()->the_hole_value());
|
| +
|
| + // Load the cache state into a3.
|
| + __ lw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| +
|
| + // A monomorphic cache hit or an already megamorphic state: invoke the
|
| + // function without changing the state.
|
| + __ Branch(&done, eq, a3, Operand(a1));
|
| + __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
| + __ Branch(&done, eq, a3, Operand(at));
|
| +
|
| + // A monomorphic miss (i.e, here the cache is not uninitialized) goes
|
| + // megamorphic.
|
| + __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
| + __ Branch(&done, eq, a3, Operand(at));
|
| + // MegamorphicSentinel is an immortal immovable object (undefined) so no
|
| + // write-barrier is needed.
|
| + __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
| + __ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| + __ Branch(&done);
|
|
|
| + // An uninitialized cache is patched with the function.
|
| + __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| + // No need for a write barrier here - cells are rescanned.
|
|
|
| -Object* CallFunctionStub::GetCachedValue(Address address) {
|
| - UNREACHABLE();
|
| - return NULL;
|
| + __ bind(&done);
|
| }
|
|
|
|
|
| void CallFunctionStub::Generate(MacroAssembler* masm) {
|
| // a1 : the function to call
|
| + // a2 : cache cell for call target
|
| Label slow, non_function;
|
|
|
| // The receiver might implicitly be the global object. This is
|
| @@ -5435,6 +5460,48 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +void CallConstructStub::Generate(MacroAssembler* masm) {
|
| + // a0 : number of arguments
|
| + // a1 : the function to call
|
| + // a2 : cache cell for call target
|
| + Label slow, non_function_call;
|
| +
|
| + // Check that the function is not a smi.
|
| + __ JumpIfSmi(a1, &non_function_call);
|
| + // Check that the function is a JSFunction.
|
| + __ GetObjectType(a1, a3, a3);
|
| + __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
|
| +
|
| + if (RecordCallTarget()) {
|
| + GenerateRecordCallTarget(masm);
|
| + }
|
| +
|
| + // Jump to the function-specific construct stub.
|
| + __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
| + __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kConstructStubOffset));
|
| + __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| + __ Jump(at);
|
| +
|
| + // a0: number of arguments
|
| + // a1: called object
|
| + // a3: object type
|
| + Label do_call;
|
| + __ bind(&slow);
|
| + __ Branch(&non_function_call, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE));
|
| + __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
|
| + __ jmp(&do_call);
|
| +
|
| + __ bind(&non_function_call);
|
| + __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
|
| + __ bind(&do_call);
|
| + // Set expected number of arguments to zero (not changing r0).
|
| + __ li(a2, Operand(0, RelocInfo::NONE));
|
| + __ SetCallKind(t1, CALL_AS_METHOD);
|
| + __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
|
| + RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| // Unfortunately you have to run without snapshots to see most of these
|
| // names in the profile since most compare stubs end up in the snapshot.
|
| void CompareStub::PrintName(StringStream* stream) {
|
|
|