| Index: src/mips/code-stubs-mips.cc | 
| diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc | 
| index 93a40be4752497f803f205b6c90d98949050727c..733c3694d205a0f20c1fb00fb5f7b1f6b9f7711c 100644 | 
| --- a/src/mips/code-stubs-mips.cc | 
| +++ b/src/mips/code-stubs-mips.cc | 
| @@ -110,16 +110,20 @@ void CompareNilICStub::InitializeInterfaceDescriptor( | 
| } | 
|  | 
|  | 
| -static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 
| -    CodeStubInterfaceDescriptor* descriptor) { | 
| +static void InitializeArrayConstructorDescriptor( | 
| +    Isolate* isolate, | 
| +    CodeStubInterfaceDescriptor* descriptor, | 
| +    int constant_stack_parameter_count) { | 
| // register state | 
| -  // a1 -- constructor function | 
| +  // a0 -- number of arguments | 
| // 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; | 
| +  static Register registers[] = { a2 }; | 
| +  descriptor->register_param_count_ = 1; | 
| +  if (constant_stack_parameter_count != 0) { | 
| +    // stack param count needs (constructor pointer, and single argument) | 
| +    descriptor->stack_parameter_count_ = &a0; | 
| +  } | 
| +  descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count; | 
| descriptor->register_params_ = registers; | 
| descriptor->function_mode_ = JS_FUNCTION_STUB_MODE; | 
| descriptor->deoptimization_handler_ = | 
| @@ -130,21 +134,21 @@ static void InitializeArrayConstructorDescriptor(Isolate* isolate, | 
| void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 
| Isolate* isolate, | 
| CodeStubInterfaceDescriptor* descriptor) { | 
| -  InitializeArrayConstructorDescriptor(isolate, descriptor); | 
| +  InitializeArrayConstructorDescriptor(isolate, descriptor, 0); | 
| } | 
|  | 
|  | 
| void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 
| Isolate* isolate, | 
| CodeStubInterfaceDescriptor* descriptor) { | 
| -  InitializeArrayConstructorDescriptor(isolate, descriptor); | 
| +  InitializeArrayConstructorDescriptor(isolate, descriptor, 1); | 
| } | 
|  | 
|  | 
| void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 
| Isolate* isolate, | 
| CodeStubInterfaceDescriptor* descriptor) { | 
| -  InitializeArrayConstructorDescriptor(isolate, descriptor); | 
| +  InitializeArrayConstructorDescriptor(isolate, descriptor, -1); | 
| } | 
|  | 
|  | 
| @@ -3342,6 +3346,9 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 
| StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 
| StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 
| RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 
| +  if (FLAG_optimize_constructed_arrays) { | 
| +    ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | 
| +  } | 
| } | 
|  | 
|  | 
| @@ -5096,7 +5103,7 @@ static void GenerateRecordCallTarget(MacroAssembler* masm) { | 
| Handle<Object> terminal_kind_sentinel = | 
| TypeFeedbackCells::MonomorphicArraySentinel(masm->isolate(), | 
| LAST_FAST_ELEMENTS_KIND); | 
| -  __ Branch(&miss, ne, a3, Operand(terminal_kind_sentinel)); | 
| +  __ Branch(&miss, gt, a3, Operand(terminal_kind_sentinel)); | 
| // Make sure the function is the Array() function | 
| __ LoadArrayFunction(a3); | 
| __ Branch(&megamorphic, ne, a1, Operand(a3)); | 
| @@ -7562,6 +7569,189 @@ void ProfileEntryHookStub::Generate(MacroAssembler* masm) { | 
| } | 
|  | 
|  | 
| +template<class T> | 
| +static void CreateArrayDispatch(MacroAssembler* masm) { | 
| +  int last_index = GetSequenceIndexFromFastElementsKind( | 
| +      TERMINAL_FAST_ELEMENTS_KIND); | 
| +  for (int i = 0; i <= last_index; ++i) { | 
| +    Label next; | 
| +    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 
| +    __ Branch(&next, ne, a3, Operand(kind)); | 
| +    T stub(kind); | 
| +    __ TailCallStub(&stub); | 
| +    __ bind(&next); | 
| +  } | 
| + | 
| +  // If we reached this point there is a problem. | 
| +  __ Abort("Unexpected ElementsKind in array constructor"); | 
| +} | 
| + | 
| + | 
| +static void CreateArrayDispatchOneArgument(MacroAssembler* masm) { | 
| +  // a2 - type info cell | 
| +  // a3 - kind | 
| +  // a0 - number of arguments | 
| +  // a1 - constructor? | 
| +  // sp[0] - last argument | 
| +  ASSERT(FAST_SMI_ELEMENTS == 0); | 
| +  ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | 
| +  ASSERT(FAST_ELEMENTS == 2); | 
| +  ASSERT(FAST_HOLEY_ELEMENTS == 3); | 
| +  ASSERT(FAST_DOUBLE_ELEMENTS == 4); | 
| +  ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == 5); | 
| + | 
| +  Handle<Object> undefined_sentinel( | 
| +      masm->isolate()->heap()->undefined_value(), | 
| +      masm->isolate()); | 
| + | 
| +  // is the low bit set? If so, we are holey and that is good. | 
| +  Label normal_sequence; | 
| +  __ And(at, a3, Operand(1)); | 
| +  __ Branch(&normal_sequence, ne, at, Operand(zero_reg)); | 
| + | 
| +  // look at the first argument | 
| +  __ lw(t1, MemOperand(sp, 0)); | 
| +  __ Branch(&normal_sequence, eq, t1, Operand(zero_reg)); | 
| + | 
| +  // We are going to create a holey array, but our kind is non-holey. | 
| +  // Fix kind and retry | 
| +  __ Addu(a3, a3, Operand(1)); | 
| +  __ Branch(&normal_sequence, eq, a2, Operand(undefined_sentinel)); | 
| + | 
| +  // Save the resulting elements kind in type info | 
| +  __ SmiTag(a3); | 
| +  __ sw(a3, FieldMemOperand(a2, kPointerSize)); | 
| +  __ SmiUntag(a3); | 
| + | 
| +  __ bind(&normal_sequence); | 
| +  int last_index = GetSequenceIndexFromFastElementsKind( | 
| +      TERMINAL_FAST_ELEMENTS_KIND); | 
| +  for (int i = 0; i <= last_index; ++i) { | 
| +    Label next; | 
| +    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 
| +    __ Branch(&next, ne, a3, Operand(kind)); | 
| +    ArraySingleArgumentConstructorStub stub(kind); | 
| +    __ TailCallStub(&stub); | 
| +    __ bind(&next); | 
| +  } | 
| + | 
| +  // If we reached this point there is a problem. | 
| +  __ Abort("Unexpected ElementsKind in array constructor"); | 
| +} | 
| + | 
| + | 
| +template<class T> | 
| +static void ArrayConstructorStubAheadOfTimeHelper(Isolate* isolate) { | 
| +  int to_index = GetSequenceIndexFromFastElementsKind( | 
| +      TERMINAL_FAST_ELEMENTS_KIND); | 
| +  for (int i = 0; i <= to_index; ++i) { | 
| +    ElementsKind kind = GetFastElementsKindFromSequenceIndex(i); | 
| +    T stub(kind); | 
| +    stub.GetCode(isolate)->set_is_pregenerated(true); | 
| +  } | 
| +} | 
| + | 
| + | 
| +void ArrayConstructorStubBase::GenerateStubsAheadOfTime(Isolate* isolate) { | 
| +  ArrayConstructorStubAheadOfTimeHelper<ArrayNoArgumentConstructorStub>( | 
| +      isolate); | 
| +  ArrayConstructorStubAheadOfTimeHelper<ArraySingleArgumentConstructorStub>( | 
| +      isolate); | 
| +  ArrayConstructorStubAheadOfTimeHelper<ArrayNArgumentsConstructorStub>( | 
| +      isolate); | 
| +} | 
| + | 
| + | 
| +void ArrayConstructorStub::Generate(MacroAssembler* masm) { | 
| +  // ----------- S t a t e ------------- | 
| +  //  -- a0 : argc (only if argument_count_ == ANY) | 
| +  //  -- a1 : constructor | 
| +  //  -- a2 : type info cell | 
| +  //  -- sp[0] : return address | 
| +  //  -- sp[4] : last argument | 
| +  // ----------------------------------- | 
| +  Handle<Object> undefined_sentinel( | 
| +      masm->isolate()->heap()->undefined_value(), | 
| +      masm->isolate()); | 
| + | 
| +  if (FLAG_debug_code) { | 
| +    // The array construct code is only set for the global and natives | 
| +    // builtin Array functions which always have maps. | 
| + | 
| +    // Initial map for the builtin Array function should be a map. | 
| +    __ lw(a3, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); | 
| +    // Will both indicate a NULL and a Smi. | 
| +    __ And(at, a3, Operand(kSmiTagMask)); | 
| +    __ Assert(ne, "Unexpected initial map for Array function", | 
| +        at, Operand(zero_reg)); | 
| +    __ GetObjectType(a3, a3, t0); | 
| +    __ Assert(eq, "Unexpected initial map for Array function", | 
| +        t0, Operand(MAP_TYPE)); | 
| + | 
| +    // We should either have undefined in ebx or a valid jsglobalpropertycell | 
| +    Label okay_here; | 
| +    Handle<Map> global_property_cell_map( | 
| +        masm->isolate()->heap()->global_property_cell_map()); | 
| +    __ Branch(&okay_here, eq, a2, Operand(undefined_sentinel)); | 
| +    __ lw(a3, FieldMemOperand(a2, 0)); | 
| +    __ Assert(eq, "Expected property cell in register ebx", | 
| +        a3, Operand(global_property_cell_map)); | 
| +    __ bind(&okay_here); | 
| +  } | 
| + | 
| +  if (FLAG_optimize_constructed_arrays) { | 
| +    Label no_info, switch_ready; | 
| +    // Get the elements kind and case on that. | 
| +    __ Branch(&no_info, eq, a2, Operand(undefined_sentinel)); | 
| +    __ lw(a3, FieldMemOperand(a2, kPointerSize)); | 
| + | 
| +    // There is no info if the call site went megamorphic either | 
| +    // TODO(mvstanton): Really? I thought if it was the array function that | 
| +    // the cell wouldn't get stamped as megamorphic. | 
| +    __ Branch(&no_info, eq, a3, | 
| +        Operand(TypeFeedbackCells::MegamorphicSentinel(masm->isolate()))); | 
| +    __ SmiUntag(a3); | 
| +    __ jmp(&switch_ready); | 
| +    __ bind(&no_info); | 
| +    __ li(a3, Operand(GetInitialFastElementsKind())); | 
| +    __ bind(&switch_ready); | 
| + | 
| +    if (argument_count_ == ANY) { | 
| +      Label not_zero_case, not_one_case; | 
| +      __ And(at, a0, a0); | 
| +      __ Branch(¬_zero_case, ne, at, Operand(zero_reg)); | 
| +      CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | 
| + | 
| +      __ bind(¬_zero_case); | 
| +      __ Branch(¬_one_case, gt, a0, Operand(1)); | 
| +      CreateArrayDispatchOneArgument(masm); | 
| + | 
| +      __ bind(¬_one_case); | 
| +      CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | 
| +    } else if (argument_count_ == NONE) { | 
| +      CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | 
| +    } else if (argument_count_ == ONE) { | 
| +      CreateArrayDispatchOneArgument(masm); | 
| +    } else if (argument_count_ == MORE_THAN_ONE) { | 
| +      CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | 
| +    } else { | 
| +     UNREACHABLE(); | 
| +    } | 
| +  } else { | 
| +     Label generic_constructor; | 
| +     // Run the native code for the Array function called as a constructor. | 
| +     ArrayNativeCode(masm, &generic_constructor); | 
| + | 
| +     // Jump to the generic construct code in case the specialized code cannot | 
| +     // handle the construction. | 
| +     __ bind(&generic_constructor); | 
| +     Handle<Code> generic_construct_stub = | 
| +         masm->isolate()->builtins()->JSConstructStubGeneric(); | 
| +     __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 
| +  } | 
| +} | 
| + | 
| + | 
| #undef __ | 
|  | 
| } }  // namespace v8::internal | 
|  |