| Index: src/mips/stub-cache-mips.cc
|
| diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
|
| index 427022250edb282df8ff51b64d0d6343e89842e1..4bad0a2ccda04930c7fc5c3bcb748c93f93f449d 100644
|
| --- a/src/mips/stub-cache-mips.cc
|
| +++ b/src/mips/stub-cache-mips.cc
|
| @@ -1601,7 +1601,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| DONT_DO_SMI_CHECK);
|
|
|
| if (argc == 1) { // Otherwise fall through to call the builtin.
|
| - Label exit, attempt_to_grow_elements;
|
| + Label attempt_to_grow_elements;
|
|
|
| // Get the array's length into v0 and calculate new length.
|
| __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| @@ -1615,11 +1615,15 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| // Check if we could survive without allocation.
|
| __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0));
|
|
|
| + // Check if value is a smi.
|
| + Label with_write_barrier;
|
| + __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
|
| + __ JumpIfNotSmi(t0, &with_write_barrier);
|
| +
|
| // Save new length.
|
| __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
|
|
| // Push the element.
|
| - __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize));
|
| // We may need a register containing the address end_elements below,
|
| // so write back the value in end_elements.
|
| __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
|
| @@ -1630,13 +1634,25 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| __ sw(t0, MemOperand(end_elements));
|
|
|
| // Check for a smi.
|
| - Label with_write_barrier;
|
| - __ JumpIfNotSmi(t0, &with_write_barrier);
|
| - __ bind(&exit);
|
| __ Drop(argc + 1);
|
| __ Ret();
|
|
|
| __ bind(&with_write_barrier);
|
| +
|
| + __ lw(t2, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| + __ CheckFastSmiOnlyElements(t2, t2, &call_builtin);
|
| +
|
| + // Save new length.
|
| + __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| +
|
| + // Push the element.
|
| + // We may need a register containing the address end_elements below,
|
| + // so write back the value in end_elements.
|
| + __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize);
|
| + __ Addu(end_elements, elements, end_elements);
|
| + __ Addu(end_elements, end_elements, kEndElementsOffset);
|
| + __ sw(t0, MemOperand(end_elements));
|
| +
|
| __ RecordWrite(elements,
|
| end_elements,
|
| t0,
|
| @@ -1655,6 +1671,15 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| __ Branch(&call_builtin);
|
| }
|
|
|
| + __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize));
|
| + // Growing elements that are SMI-only requires special handling in case
|
| + // the new element is non-Smi. For now, delegate to the builtin.
|
| + Label no_fast_elements_check;
|
| + __ JumpIfSmi(a2, &no_fast_elements_check);
|
| + __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| + __ CheckFastObjectElements(t3, t3, &call_builtin);
|
| + __ bind(&no_fast_elements_check);
|
| +
|
| ExternalReference new_space_allocation_top =
|
| ExternalReference::new_space_allocation_top_address(
|
| masm()->isolate());
|
| @@ -1680,8 +1705,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| // Update new_space_allocation_top.
|
| __ sw(t2, MemOperand(t3));
|
| // Push the argument.
|
| - __ lw(t2, MemOperand(sp, (argc - 1) * kPointerSize));
|
| - __ sw(t2, MemOperand(end_elements));
|
| + __ sw(a2, MemOperand(end_elements));
|
| // Fill the rest with holes.
|
| __ LoadRoot(t2, Heap::kTheHoleValueRootIndex);
|
| for (int i = 1; i < kAllocationDelta; i++) {
|
| @@ -3252,9 +3276,10 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) {
|
| }
|
|
|
|
|
| -MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
|
| MapList* receiver_maps,
|
| - CodeList* handler_ics) {
|
| + CodeList* handler_stubs,
|
| + MapList* transitioned_maps) {
|
| // ----------- S t a t e -------------
|
| // -- a0 : value
|
| // -- a1 : key
|
| @@ -3267,10 +3292,18 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
|
|
|
| int receiver_count = receiver_maps->length();
|
| __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset));
|
| - for (int current = 0; current < receiver_count; ++current) {
|
| - Handle<Map> map(receiver_maps->at(current));
|
| - Handle<Code> code(handler_ics->at(current));
|
| - __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map));
|
| + for (int i = 0; i < receiver_count; ++i) {
|
| + Handle<Map> map(receiver_maps->at(i));
|
| + Handle<Code> code(handler_stubs->at(i));
|
| + if (transitioned_maps->at(i) == NULL) {
|
| + __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map));
|
| + } else {
|
| + Label next_map;
|
| + __ Branch(&next_map, eq, a3, Operand(map));
|
| + __ li(t0, Operand(Handle<Map>(transitioned_maps->at(i))));
|
| + __ Jump(code, RelocInfo::CODE_TARGET);
|
| + __ bind(&next_map);
|
| + }
|
| }
|
|
|
| __ bind(&miss);
|
| @@ -3499,7 +3532,7 @@ static bool IsElementTypeSigned(ElementsKind elements_kind) {
|
|
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| - case FAST_SMI_ELEMENTS:
|
| + case FAST_SMI_ONLY_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| @@ -3596,6 +3629,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
| }
|
| break;
|
| case FAST_ELEMENTS:
|
| + case FAST_SMI_ONLY_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| @@ -3956,6 +3990,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| }
|
| break;
|
| case FAST_ELEMENTS:
|
| + case FAST_SMI_ONLY_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| @@ -4020,6 +4055,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| + case FAST_SMI_ONLY_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| @@ -4191,6 +4227,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| + case FAST_SMI_ONLY_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| case NON_STRICT_ARGUMENTS_ELEMENTS:
|
| @@ -4340,8 +4377,10 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
|
| }
|
|
|
|
|
| -void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
|
| - bool is_js_array) {
|
| +void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
| + MacroAssembler* masm,
|
| + bool is_js_array,
|
| + ElementsKind elements_kind) {
|
| // ----------- S t a t e -------------
|
| // -- a0 : value
|
| // -- a1 : key
|
| @@ -4350,7 +4389,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
|
| // -- a3 : scratch
|
| // -- a4 : scratch (elements)
|
| // -----------------------------------
|
| - Label miss_force_generic;
|
| + Label miss_force_generic, transition_elements_kind;
|
|
|
| Register value_reg = a0;
|
| Register key_reg = a1;
|
| @@ -4384,19 +4423,32 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
|
| // Compare smis.
|
| __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
|
|
|
| - __ Addu(scratch,
|
| - elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| - STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| - __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
|
| - __ Addu(scratch, scratch, scratch2);
|
| - __ sw(value_reg, MemOperand(scratch));
|
| - __ mov(receiver_reg, value_reg);
|
| - __ RecordWrite(elements_reg, // Object.
|
| - scratch, // Address.
|
| - receiver_reg, // Value.
|
| - kRAHasNotBeenSaved,
|
| - kDontSaveFPRegs);
|
| -
|
| + if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
|
| + __ JumpIfNotSmi(value_reg, &transition_elements_kind);
|
| + __ Addu(scratch,
|
| + elements_reg,
|
| + Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| + __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
|
| + __ Addu(scratch, scratch, scratch2);
|
| + __ sw(value_reg, MemOperand(scratch));
|
| + } else {
|
| + ASSERT(elements_kind == FAST_ELEMENTS);
|
| + __ Addu(scratch,
|
| + elements_reg,
|
| + Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| + __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize);
|
| + __ Addu(scratch, scratch, scratch2);
|
| + __ sw(value_reg, MemOperand(scratch));
|
| + __ mov(receiver_reg, value_reg);
|
| + ASSERT(elements_kind == FAST_ELEMENTS);
|
| + __ RecordWrite(elements_reg, // Object.
|
| + scratch, // Address.
|
| + receiver_reg, // Value.
|
| + kRAHasNotBeenSaved,
|
| + kDontSaveFPRegs);
|
| + }
|
| // value_reg (a0) is preserved.
|
| // Done.
|
| __ Ret();
|
| @@ -4405,6 +4457,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
|
| Handle<Code> ic =
|
| masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
| __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + __ bind(&transition_elements_kind);
|
| + Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ Jump(ic_miss, RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
| @@ -4422,15 +4478,15 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
| // -- t2 : scratch (exponent_reg)
|
| // -- t3 : scratch4
|
| // -----------------------------------
|
| - Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
|
| + Label miss_force_generic, transition_elements_kind;
|
|
|
| Register value_reg = a0;
|
| Register key_reg = a1;
|
| Register receiver_reg = a2;
|
| - Register scratch = a3;
|
| - Register elements_reg = t0;
|
| - Register mantissa_reg = t1;
|
| - Register exponent_reg = t2;
|
| + Register elements_reg = a3;
|
| + Register scratch1 = t0;
|
| + Register scratch2 = t1;
|
| + Register scratch3 = t2;
|
| Register scratch4 = t3;
|
|
|
| // This stub is meant to be tail-jumped to, the receiver must already
|
| @@ -4442,90 +4498,25 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
|
|
| // Check that the key is within bounds.
|
| if (is_js_array) {
|
| - __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
| + __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
| } else {
|
| - __ lw(scratch,
|
| + __ lw(scratch1,
|
| FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
|
| }
|
| // Compare smis, unsigned compare catches both negative and out-of-bound
|
| // indexes.
|
| - __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
|
| -
|
| - // Handle smi values specially.
|
| - __ JumpIfSmi(value_reg, &smi_value);
|
| -
|
| - // Ensure that the object is a heap number
|
| - __ CheckMap(value_reg,
|
| - scratch,
|
| - masm->isolate()->factory()->heap_number_map(),
|
| - &miss_force_generic,
|
| - DONT_DO_SMI_CHECK);
|
| -
|
| - // Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
|
| - // in the exponent.
|
| - __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
|
| - __ lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
|
| - __ Branch(&maybe_nan, ge, exponent_reg, Operand(scratch));
|
| + __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1));
|
| +
|
| + __ StoreNumberToDoubleElements(value_reg,
|
| + key_reg,
|
| + receiver_reg,
|
| + elements_reg,
|
| + scratch1,
|
| + scratch2,
|
| + scratch3,
|
| + scratch4,
|
| + &transition_elements_kind);
|
|
|
| - __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
| -
|
| - __ bind(&have_double_value);
|
| - __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
|
| - __ Addu(scratch, elements_reg, Operand(scratch4));
|
| - __ sw(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
|
| - uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
| - __ sw(exponent_reg, FieldMemOperand(scratch, offset));
|
| - __ Ret(USE_DELAY_SLOT);
|
| - __ mov(v0, value_reg); // In delay slot.
|
| -
|
| - __ bind(&maybe_nan);
|
| - // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
|
| - // it's an Infinity, and the non-NaN code path applies.
|
| - __ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
|
| - __ Branch(&is_nan, gt, exponent_reg, Operand(scratch));
|
| - __ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
|
| - __ Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
|
| -
|
| - __ bind(&is_nan);
|
| - // Load canonical NaN for storing into the double array.
|
| - uint64_t nan_int64 = BitCast<uint64_t>(
|
| - FixedDoubleArray::canonical_not_the_hole_nan_as_double());
|
| - __ li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
|
| - __ li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
|
| - __ jmp(&have_double_value);
|
| -
|
| - __ bind(&smi_value);
|
| - __ Addu(scratch, elements_reg,
|
| - Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
|
| - __ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
|
| - __ Addu(scratch, scratch, scratch4);
|
| - // scratch is now effective address of the double element
|
| -
|
| - FloatingPointHelper::Destination destination;
|
| - if (CpuFeatures::IsSupported(FPU)) {
|
| - destination = FloatingPointHelper::kFPURegisters;
|
| - } else {
|
| - destination = FloatingPointHelper::kCoreRegisters;
|
| - }
|
| -
|
| - Register untagged_value = receiver_reg;
|
| - __ SmiUntag(untagged_value, value_reg);
|
| - FloatingPointHelper::ConvertIntToDouble(
|
| - masm,
|
| - untagged_value,
|
| - destination,
|
| - f0,
|
| - mantissa_reg,
|
| - exponent_reg,
|
| - scratch4,
|
| - f2);
|
| - if (destination == FloatingPointHelper::kFPURegisters) {
|
| - CpuFeatures::Scope scope(FPU);
|
| - __ sdc1(f0, MemOperand(scratch, 0));
|
| - } else {
|
| - __ sw(mantissa_reg, MemOperand(scratch, 0));
|
| - __ sw(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
|
| - }
|
| __ Ret(USE_DELAY_SLOT);
|
| __ mov(v0, value_reg); // In delay slot.
|
|
|
| @@ -4534,6 +4525,10 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
| Handle<Code> ic =
|
| masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
| __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + __ bind(&transition_elements_kind);
|
| + Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ Jump(ic_miss, RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
|
|