| Index: src/mips/code-stubs-mips.cc
|
| diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
|
| index 91203c6b65ad7dd0ff0fc5164b7d8398faaaf955..81ad1efafed1c4f34162a60e1388c6b1b3c44087 100644
|
| --- a/src/mips/code-stubs-mips.cc
|
| +++ b/src/mips/code-stubs-mips.cc
|
| @@ -74,6 +74,44 @@ void TransitionElementsKindStub::InitializeInterfaceDescriptor(
|
| }
|
|
|
|
|
| +static void InitializeArrayConstructorDescriptor(Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + // register state
|
| + // a1 -- constructor function
|
| + // a2 -- type info cell with elements kind
|
| + // a0 -- number of arguments to the constructor function
|
| + static Register registers[] = { a1, a2 };
|
| + descriptor->register_param_count_ = 2;
|
| + // stack param count needs (constructor pointer, and single argument)
|
| + descriptor->stack_parameter_count_ = &a0;
|
| + descriptor->register_params_ = registers;
|
| + descriptor->extra_expression_stack_count_ = 1;
|
| + descriptor->deoptimization_handler_ =
|
| + FUNCTION_ADDR(ArrayConstructor_StubFailure);
|
| +}
|
| +
|
| +
|
| +void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + InitializeArrayConstructorDescriptor(isolate, descriptor);
|
| +}
|
| +
|
| +
|
| +void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + InitializeArrayConstructorDescriptor(isolate, descriptor);
|
| +}
|
| +
|
| +
|
| +void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
|
| + Isolate* isolate,
|
| + CodeStubInterfaceDescriptor* descriptor) {
|
| + InitializeArrayConstructorDescriptor(isolate, descriptor);
|
| +}
|
| +
|
| +
|
| #define __ ACCESS_MASM(masm)
|
|
|
| static void EmitIdenticalObjectComparison(MacroAssembler* masm,
|
| @@ -5618,12 +5656,13 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -static void GenerateRecordCallTarget(MacroAssembler* masm) {
|
| +static void GenerateRecordCallTargetNoArray(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
|
| + ASSERT(!FLAG_optimize_constructed_arrays);
|
| Label done;
|
|
|
| ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()),
|
| @@ -5660,6 +5699,78 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +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
|
| + ASSERT(FLAG_optimize_constructed_arrays);
|
| + Label initialize, done, miss, megamorphic, not_array_function;
|
| +
|
| + 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));
|
| +
|
| + // Special handling of the Array() function, which caches not only the
|
| + // monomorphic Array function but the initial ElementsKind with special
|
| + // sentinels
|
| + Handle<Object> terminal_kind_sentinel =
|
| + TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
|
| + LAST_FAST_ELEMENTS_KIND);
|
| + __ Branch(&miss, ne, a3, Operand(terminal_kind_sentinel));
|
| + // Make sure the function is the Array() function
|
| + __ LoadArrayFunction(a3);
|
| + __ Branch(&megamorphic, ne, a1, Operand(a3));
|
| + __ jmp(&done);
|
| +
|
| + __ bind(&miss);
|
| +
|
| + // A monomorphic miss (i.e, here the cache is not uninitialized) goes
|
| + // megamorphic.
|
| + __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
| + __ Branch(&initialize, eq, a3, Operand(at));
|
| + // MegamorphicSentinel is an immortal immovable object (undefined) so no
|
| + // write-barrier is needed.
|
| + __ bind(&megamorphic);
|
| + __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
|
| + __ sw(at, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| +
|
| + // An uninitialized cache is patched with the function or sentinel to
|
| + // indicate the ElementsKind if function is the Array constructor.
|
| + __ bind(&initialize);
|
| + // Make sure the function is the Array() function
|
| + __ LoadArrayFunction(a3);
|
| + __ Branch(¬_array_function, ne, a1, Operand(a3));
|
| +
|
| + // The target function is the Array constructor, install a sentinel value in
|
| + // the constructor's type info cell that will track the initial ElementsKind
|
| + // that should be used for the array when its constructed.
|
| + Handle<Object> initial_kind_sentinel =
|
| + TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(),
|
| + GetInitialFastElementsKind());
|
| + __ li(a3, Operand(initial_kind_sentinel));
|
| + __ sw(a3, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| + __ Branch(&done);
|
| +
|
| + __ bind(¬_array_function);
|
| + __ sw(a1, FieldMemOperand(a2, JSGlobalPropertyCell::kValueOffset));
|
| + // No need for a write barrier here - cells are rescanned.
|
| +
|
| + __ bind(&done);
|
| +}
|
| +
|
| +
|
| void CallFunctionStub::Generate(MacroAssembler* masm) {
|
| // a1 : the function to call
|
| // a2 : cache cell for call target
|
| @@ -5692,7 +5803,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
|
| __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
|
|
|
| if (RecordCallTarget()) {
|
| - GenerateRecordCallTarget(masm);
|
| + if (FLAG_optimize_constructed_arrays) {
|
| + GenerateRecordCallTarget(masm);
|
| + } else {
|
| + GenerateRecordCallTargetNoArray(masm);
|
| + }
|
| }
|
|
|
| // Fast-case: Invoke the function now.
|
| @@ -5766,13 +5881,19 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
|
| __ Branch(&slow, ne, a3, Operand(JS_FUNCTION_TYPE));
|
|
|
| if (RecordCallTarget()) {
|
| - GenerateRecordCallTarget(masm);
|
| + if (FLAG_optimize_constructed_arrays) {
|
| + GenerateRecordCallTarget(masm);
|
| + } else {
|
| + GenerateRecordCallTargetNoArray(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));
|
| + Register jmp_reg = FLAG_optimize_constructed_arrays ? a3 : a2;
|
| + __ lw(jmp_reg, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
| + __ lw(jmp_reg, FieldMemOperand(jmp_reg,
|
| + SharedFunctionInfo::kConstructStubOffset));
|
| + __ Addu(at, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
|
| __ Jump(at);
|
|
|
| // a0: number of arguments
|
|
|