diff options
Diffstat (limited to 'deps/v8/src/mips/ic-mips.cc')
-rw-r--r-- | deps/v8/src/mips/ic-mips.cc | 405 |
1 files changed, 264 insertions, 141 deletions
diff --git a/deps/v8/src/mips/ic-mips.cc b/deps/v8/src/mips/ic-mips.cc index a76c215a48..c3cdb4cd38 100644 --- a/deps/v8/src/mips/ic-mips.cc +++ b/deps/v8/src/mips/ic-mips.cc @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -210,7 +210,8 @@ static void GenerateDictionaryStore(MacroAssembler* masm, // Update the write barrier. Make sure not to clobber the value. __ mov(scratch1, value); - __ RecordWrite(elements, scratch2, scratch1); + __ RecordWrite( + elements, scratch2, scratch1, kRAHasNotBeenSaved, kDontSaveFPRegs); } @@ -383,10 +384,10 @@ Object* CallIC_Miss(Arguments args); // The generated code does not accept smi keys. // The generated code falls through if both probes miss. -static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, - int argc, - Code::Kind kind, - Code::ExtraICState extra_ic_state) { +void CallICBase::GenerateMonomorphicCacheProbe(MacroAssembler* masm, + int argc, + Code::Kind kind, + Code::ExtraICState extra_state) { // ----------- S t a t e ------------- // -- a1 : receiver // -- a2 : name @@ -396,7 +397,7 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, // Probe the stub cache. Code::Flags flags = Code::ComputeFlags(kind, MONOMORPHIC, - extra_ic_state, + extra_state, NORMAL, argc); Isolate::Current()->stub_cache()->GenerateProbe( @@ -462,7 +463,7 @@ static void GenerateFunctionTailCall(MacroAssembler* masm, } -static void GenerateCallNormal(MacroAssembler* masm, int argc) { +void CallICBase::GenerateNormal(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -485,10 +486,10 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) { } -static void GenerateCallMiss(MacroAssembler* masm, - int argc, - IC::UtilityId id, - Code::ExtraICState extra_ic_state) { +void CallICBase::GenerateMiss(MacroAssembler* masm, + int argc, + IC::UtilityId id, + Code::ExtraICState extra_state) { // ----------- S t a t e ------------- // -- a2 : name // -- ra : return address @@ -504,29 +505,29 @@ static void GenerateCallMiss(MacroAssembler* masm, // Get the receiver of the function from the stack. __ lw(a3, MemOperand(sp, argc*kPointerSize)); - __ EnterInternalFrame(); + { + FrameScope scope(masm, StackFrame::INTERNAL); - // Push the receiver and the name of the function. - __ Push(a3, a2); + // Push the receiver and the name of the function. + __ Push(a3, a2); - // Call the entry. - __ li(a0, Operand(2)); - __ li(a1, Operand(ExternalReference(IC_Utility(id), isolate))); + // Call the entry. + __ li(a0, Operand(2)); + __ li(a1, Operand(ExternalReference(IC_Utility(id), isolate))); - CEntryStub stub(1); - __ CallStub(&stub); + CEntryStub stub(1); + __ CallStub(&stub); - // Move result to a1 and leave the internal frame. - __ mov(a1, v0); - __ LeaveInternalFrame(); + // Move result to a1 and leave the internal frame. + __ mov(a1, v0); + } // Check if the receiver is a global object of some sort. // This can happen only for regular CallIC but not KeyedCallIC. if (id == IC::kCallIC_Miss) { Label invoke, global; __ lw(a2, MemOperand(sp, argc * kPointerSize)); - __ andi(t0, a2, kSmiTagMask); - __ Branch(&invoke, eq, t0, Operand(zero_reg)); + __ JumpIfSmi(a2, &invoke); __ GetObjectType(a2, a3, a3); __ Branch(&global, eq, a3, Operand(JS_GLOBAL_OBJECT_TYPE)); __ Branch(&invoke, ne, a3, Operand(JS_BUILTINS_OBJECT_TYPE)); @@ -538,7 +539,7 @@ static void GenerateCallMiss(MacroAssembler* masm, __ bind(&invoke); } // Invoke the function. - CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) + CallKind call_kind = CallICBase::Contextual::decode(extra_state) ? CALL_AS_FUNCTION : CALL_AS_METHOD; ParameterCount actual(argc); @@ -550,18 +551,6 @@ static void GenerateCallMiss(MacroAssembler* masm, } -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, extra_ic_state); -} - - void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc, Code::ExtraICState extra_ic_state) { @@ -577,27 +566,6 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, } -void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { - // ----------- S t a t e ------------- - // -- a2 : name - // -- ra : return address - // ----------------------------------- - - GenerateCallNormal(masm, argc); - GenerateMiss(masm, argc, Code::kNoExtraICState); -} - - -void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { - // ----------- S t a t e ------------- - // -- a2 : name - // -- ra : return address - // ----------------------------------- - - GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss, Code::kNoExtraICState); -} - - void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // ----------- S t a t e ------------- // -- a2 : name @@ -649,12 +617,13 @@ void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { // This branch is taken when calling KeyedCallIC_Miss is neither required // nor beneficial. __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1, a0, a3); - __ EnterInternalFrame(); - __ push(a2); // Save the key. - __ Push(a1, a2); // Pass the receiver and the key. - __ CallRuntime(Runtime::kKeyedGetProperty, 2); - __ pop(a2); // Restore the key. - __ LeaveInternalFrame(); + { + FrameScope scope(masm, StackFrame::INTERNAL); + __ push(a2); // Save the key. + __ Push(a1, a2); // Pass the receiver and the key. + __ CallRuntime(Runtime::kKeyedGetProperty, 2); + __ pop(a2); // Restore the key. + } __ mov(a1, v0); __ jmp(&do_call); @@ -713,7 +682,7 @@ void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { __ JumpIfSmi(a2, &miss); __ IsObjectJSStringType(a2, a0, &miss); - GenerateCallNormal(masm, argc); + CallICBase::GenerateNormal(masm, argc); __ bind(&miss); GenerateMiss(masm, argc); } @@ -899,21 +868,26 @@ void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) { // -- lr : return address // ----------------------------------- Label slow, notin; + // Store address is returned in register (of MemOperand) mapped_location. MemOperand mapped_location = GenerateMappedArgumentsLookup(masm, a2, a1, a3, t0, t1, ¬in, &slow); __ sw(a0, mapped_location); - // Verify mapped_location MemOperand is register, with no offset. + __ mov(t5, a0); ASSERT_EQ(mapped_location.offset(), 0); - __ RecordWrite(a3, mapped_location.rm(), t5); + __ RecordWrite(a3, mapped_location.rm(), t5, + kRAHasNotBeenSaved, kDontSaveFPRegs); __ Ret(USE_DELAY_SLOT); __ mov(v0, a0); // (In delay slot) return the value stored in v0. __ bind(¬in); // The unmapped lookup expects that the parameter map is in a3. + // Store address is returned in register (of MemOperand) unmapped_location. MemOperand unmapped_location = GenerateUnmappedArgumentsLookup(masm, a1, a3, t0, &slow); __ sw(a0, unmapped_location); + __ mov(t5, a0); ASSERT_EQ(unmapped_location.offset(), 0); - __ RecordWrite(a3, unmapped_location.rm(), t5); + __ RecordWrite(a3, unmapped_location.rm(), t5, + kRAHasNotBeenSaved, kDontSaveFPRegs); __ Ret(USE_DELAY_SLOT); __ mov(v0, a0); // (In delay slot) return the value stored in v0. __ bind(&slow); @@ -1059,19 +1033,32 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { __ lw(t0, FieldMemOperand(a0, String::kHashFieldOffset)); __ sra(at, t0, String::kHashShift); __ xor_(a3, a3, at); - __ And(a3, a3, Operand(KeyedLookupCache::kCapacityMask)); + int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; + __ And(a3, a3, Operand(mask)); // Load the key (consisting of map and symbol) from the cache and // check for match. + Label load_in_object_property; + static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; + Label hit_on_nth_entry[kEntriesPerBucket]; ExternalReference cache_keys = ExternalReference::keyed_lookup_cache_keys(isolate); __ li(t0, Operand(cache_keys)); __ sll(at, a3, kPointerSizeLog2 + 1); __ addu(t0, t0, at); - __ lw(t1, MemOperand(t0)); // Move t0 to symbol. - __ Addu(t0, t0, Operand(kPointerSize)); + + for (int i = 0; i < kEntriesPerBucket - 1; i++) { + Label try_next_entry; + __ lw(t1, MemOperand(t0, kPointerSize * i * 2)); + __ Branch(&try_next_entry, ne, a2, Operand(t1)); + __ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1))); + __ Branch(&hit_on_nth_entry[i], eq, a0, Operand(t1)); + __ bind(&try_next_entry); + } + + __ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2)); __ Branch(&slow, ne, a2, Operand(t1)); - __ lw(t1, MemOperand(t0)); + __ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1))); __ Branch(&slow, ne, a0, Operand(t1)); // Get field offset. @@ -1081,15 +1068,24 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { // a3 : lookup cache index ExternalReference cache_field_offsets = ExternalReference::keyed_lookup_cache_field_offsets(isolate); - __ li(t0, Operand(cache_field_offsets)); - __ sll(at, a3, kPointerSizeLog2); - __ addu(at, t0, at); - __ lw(t1, MemOperand(at)); - __ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset)); - __ Subu(t1, t1, t2); - __ Branch(&property_array_property, ge, t1, Operand(zero_reg)); + + // Hit on nth entry. + for (int i = kEntriesPerBucket - 1; i >= 0; i--) { + __ bind(&hit_on_nth_entry[i]); + __ li(t0, Operand(cache_field_offsets)); + __ sll(at, a3, kPointerSizeLog2); + __ addu(at, t0, at); + __ lw(t1, MemOperand(at, kPointerSize * i)); + __ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset)); + __ Subu(t1, t1, t2); + __ Branch(&property_array_property, ge, t1, Operand(zero_reg)); + if (i != 0) { + __ Branch(&load_in_object_property); + } + } // Load in-object property. + __ bind(&load_in_object_property); __ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset)); __ addu(t2, t2, t1); // Index from start of object. __ Subu(a1, a1, Operand(kHeapObjectTag)); // Remove the heap tag. @@ -1150,14 +1146,12 @@ void KeyedLoadIC::GenerateString(MacroAssembler* masm) { Register receiver = a1; Register index = a0; - Register scratch1 = a2; - Register scratch2 = a3; + Register scratch = a3; Register result = v0; StringCharAtGenerator char_at_generator(receiver, index, - scratch1, - scratch2, + scratch, result, &miss, // When not a string. &miss, // When not a number. @@ -1201,109 +1195,192 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, // -- a2 : receiver // -- ra : return address // ----------------------------------- - - Label slow, fast, array, extra, exit; + Label slow, array, extra, check_if_double_array; + Label fast_object_with_map_check, fast_object_without_map_check; + Label fast_double_with_map_check, fast_double_without_map_check; + Label transition_smi_elements, finish_object_store, non_double_value; + Label transition_double_elements; // Register usage. Register value = a0; Register key = a1; Register receiver = a2; - Register elements = a3; // Elements array of the receiver. - // t0 is used as ip in the arm version. - // t3-t4 are used as temporaries. + Register receiver_map = a3; + Register elements_map = t2; + Register elements = t3; // Elements array of the receiver. + // t0 and t1 are used as general scratch registers. // Check that the key is a smi. __ JumpIfNotSmi(key, &slow); // Check that the object isn't a smi. __ JumpIfSmi(receiver, &slow); - // Get the map of the object. - __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); + __ lw(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); // Check that the receiver does not require access checks. We need // to do this because this generic stub does not perform map checks. - __ lbu(t0, FieldMemOperand(t3, Map::kBitFieldOffset)); + __ lbu(t0, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); __ And(t0, t0, Operand(1 << Map::kIsAccessCheckNeeded)); __ Branch(&slow, ne, t0, Operand(zero_reg)); // Check if the object is a JS array or not. - __ lbu(t3, FieldMemOperand(t3, Map::kInstanceTypeOffset)); - - __ Branch(&array, eq, t3, Operand(JS_ARRAY_TYPE)); + __ lbu(t0, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); + __ Branch(&array, eq, t0, Operand(JS_ARRAY_TYPE)); // Check that the object is some kind of JSObject. - __ Branch(&slow, lt, t3, Operand(FIRST_JS_RECEIVER_TYPE)); - __ Branch(&slow, eq, t3, Operand(JS_PROXY_TYPE)); - __ Branch(&slow, eq, t3, Operand(JS_FUNCTION_PROXY_TYPE)); + __ Branch(&slow, lt, t0, Operand(FIRST_JS_OBJECT_TYPE)); // Object case: Check key against length in the elements array. __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); - // Check that the object is in fast mode and writable. - __ lw(t3, FieldMemOperand(elements, HeapObject::kMapOffset)); - __ LoadRoot(t0, Heap::kFixedArrayMapRootIndex); - __ Branch(&slow, ne, t3, Operand(t0)); // Check array bounds. Both the key and the length of FixedArray are smis. __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); - __ Branch(&fast, lo, key, Operand(t0)); - // Fall thru to slow if un-tagged index >= length. + __ Branch(&fast_object_with_map_check, lo, key, Operand(t0)); // Slow case, handle jump to runtime. __ bind(&slow); - // Entry registers are intact. // a0: value. // a1: key. // a2: receiver. - GenerateRuntimeSetProperty(masm, strict_mode); // Extra capacity case: Check if there is extra capacity to // perform the store and update the length. Used for adding one // element to the array by writing to array[array.length]. - __ bind(&extra); + // Condition code from comparing key and array length is still available. // Only support writing to array[array.length]. __ Branch(&slow, ne, key, Operand(t0)); // Check for room in the elements backing store. // Both the key and the length of FixedArray are smis. __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); __ Branch(&slow, hs, key, Operand(t0)); + __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); + __ Branch(&check_if_double_array, ne, elements_map, + Operand(masm->isolate()->factory()->fixed_array_map())); // Calculate key + 1 as smi. - STATIC_ASSERT(0 == kSmiTag); - __ Addu(t3, key, Operand(Smi::FromInt(1))); - __ sw(t3, FieldMemOperand(receiver, JSArray::kLengthOffset)); - __ Branch(&fast); - + STATIC_ASSERT(kSmiTag == 0); + __ Addu(t0, key, Operand(Smi::FromInt(1))); + __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); + __ Branch(&fast_object_without_map_check); + + __ bind(&check_if_double_array); + __ Branch(&slow, ne, elements_map, + Operand(masm->isolate()->factory()->fixed_double_array_map())); + // Add 1 to key, and go to common element store code for doubles. + STATIC_ASSERT(kSmiTag == 0); + __ Addu(t0, key, Operand(Smi::FromInt(1))); + __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); + __ jmp(&fast_double_without_map_check); // Array case: Get the length and the elements array from the JS // array. Check that the array is in fast mode (and writable); if it // is the length is always a smi. - __ bind(&array); __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); - __ lw(t3, FieldMemOperand(elements, HeapObject::kMapOffset)); - __ LoadRoot(t0, Heap::kFixedArrayMapRootIndex); - __ Branch(&slow, ne, t3, Operand(t0)); // Check the key against the length in the array. __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); __ Branch(&extra, hs, key, Operand(t0)); // Fall through to fast case. - __ bind(&fast); - // Fast case, store the value to the elements backing store. - __ Addu(t4, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); - __ sll(t1, key, kPointerSizeLog2 - kSmiTagSize); - __ Addu(t4, t4, Operand(t1)); - __ sw(value, MemOperand(t4)); - // Skip write barrier if the written value is a smi. - __ JumpIfSmi(value, &exit); - + __ bind(&fast_object_with_map_check); + Register scratch_value = t0; + Register address = t1; + __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); + __ Branch(&fast_double_with_map_check, ne, elements_map, + Operand(masm->isolate()->factory()->fixed_array_map())); + __ bind(&fast_object_without_map_check); + // Smi stores don't require further checks. + Label non_smi_value; + __ JumpIfNotSmi(value, &non_smi_value); + // It's irrelevant whether array is smi-only or not when writing a smi. + __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); + __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); + __ Addu(address, address, scratch_value); + __ sw(value, MemOperand(address)); + __ Ret(USE_DELAY_SLOT); + __ mov(v0, value); + + __ bind(&non_smi_value); + // Escape to elements kind transition case. + __ CheckFastObjectElements(receiver_map, scratch_value, + &transition_smi_elements); + // Fast elements array, store the value to the elements backing store. + __ bind(&finish_object_store); + __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); + __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); + __ Addu(address, address, scratch_value); + __ sw(value, MemOperand(address)); // Update write barrier for the elements array address. - __ Subu(t3, t4, Operand(elements)); - - __ RecordWrite(elements, Operand(t3), t4, t5); - __ bind(&exit); - - __ mov(v0, a0); // Return the value written. + __ mov(v0, value); // Preserve the value which is returned. + __ RecordWrite(elements, + address, + value, + kRAHasNotBeenSaved, + kDontSaveFPRegs, + EMIT_REMEMBERED_SET, + OMIT_SMI_CHECK); __ Ret(); + + __ bind(&fast_double_with_map_check); + // Check for fast double array case. If this fails, call through to the + // runtime. + __ Branch(&slow, ne, elements_map, + Operand(masm->isolate()->factory()->fixed_double_array_map())); + __ bind(&fast_double_without_map_check); + __ StoreNumberToDoubleElements(value, + key, + receiver, + elements, + a3, + t0, + t1, + t2, + &transition_double_elements); + __ Ret(USE_DELAY_SLOT); + __ mov(v0, value); + + __ bind(&transition_smi_elements); + // Transition the array appropriately depending on the value type. + __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset)); + __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); + __ Branch(&non_double_value, ne, t0, Operand(at)); + + // Value is a double. Transition FAST_SMI_ONLY_ELEMENTS -> + // FAST_DOUBLE_ELEMENTS and complete the store. + __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, + FAST_DOUBLE_ELEMENTS, + receiver_map, + t0, + &slow); + ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 + ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &slow); + __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); + __ jmp(&fast_double_without_map_check); + + __ bind(&non_double_value); + // Value is not a double, FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS + __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, + FAST_ELEMENTS, + receiver_map, + t0, + &slow); + ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 + ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm); + __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); + __ jmp(&finish_object_store); + + __ bind(&transition_double_elements); + // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a + // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and + // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS + __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, + FAST_ELEMENTS, + receiver_map, + t0, + &slow); + ASSERT(receiver_map.is(a3)); // Transition code expects map in a3 + ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow); + __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); + __ jmp(&finish_object_store); } @@ -1382,6 +1459,47 @@ void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { } +void KeyedStoreIC::GenerateTransitionElementsSmiToDouble(MacroAssembler* masm) { + // ---------- S t a t e -------------- + // -- a2 : receiver + // -- a3 : target map + // -- ra : return address + // ----------------------------------- + // Must return the modified receiver in v0. + if (!FLAG_trace_elements_transitions) { + Label fail; + ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &fail); + __ Ret(USE_DELAY_SLOT); + __ mov(v0, a2); + __ bind(&fail); + } + + __ push(a2); + __ TailCallRuntime(Runtime::kTransitionElementsSmiToDouble, 1, 1); +} + + +void KeyedStoreIC::GenerateTransitionElementsDoubleToObject( + MacroAssembler* masm) { + // ---------- S t a t e -------------- + // -- a2 : receiver + // -- a3 : target map + // -- ra : return address + // ----------------------------------- + // Must return the modified receiver in v0. + if (!FLAG_trace_elements_transitions) { + Label fail; + ElementsTransitionGenerator::GenerateDoubleToObject(masm, &fail); + __ Ret(USE_DELAY_SLOT); + __ mov(v0, a2); + __ bind(&fail); + } + + __ push(a2); + __ TailCallRuntime(Runtime::kTransitionElementsDoubleToObject, 1, 1); +} + + void StoreIC::GenerateMegamorphic(MacroAssembler* masm, StrictModeFlag strict_mode) { // ----------- S t a t e ------------- @@ -1426,11 +1544,10 @@ void StoreIC::GenerateArrayLength(MacroAssembler* masm) { // -- ra : return address // ----------------------------------- // - // This accepts as a receiver anything JSObject::SetElementsLength accepts - // (currently anything except for external and pixel arrays which means - // anything with elements of FixedArray type.), but currently is restricted - // to JSArray. - // Value must be a number, but only smis are accepted as the most common case. + // This accepts as a receiver anything JSArray::SetElementsLength accepts + // (currently anything except for external arrays which means anything with + // elements of FixedArray type). Value must be a number, but only smis are + // accepted as the most common case. Label miss; @@ -1452,6 +1569,10 @@ void StoreIC::GenerateArrayLength(MacroAssembler* masm) { __ GetObjectType(scratch, scratch, scratch); __ Branch(&miss, ne, scratch, Operand(FIXED_ARRAY_TYPE)); + // Check that the array has fast properties, otherwise the length + // property might have been redefined. + // TODO(mstarzinger): Port this check to MIPS. + // Check that value is a smi. __ JumpIfNotSmi(value, &miss); @@ -1521,11 +1642,9 @@ Condition CompareIC::ComputeCondition(Token::Value op) { case Token::LT: return lt; case Token::GT: - // Reverse left and right operands to obtain ECMA-262 conversion order. - return lt; + return gt; case Token::LTE: - // Reverse left and right operands to obtain ECMA-262 conversion order. - return ge; + return le; case Token::GTE: return ge; default: @@ -1545,6 +1664,9 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) { rewritten = stub.GetCode(); } else { ICCompareStub stub(op_, state); + if (state == KNOWN_OBJECTS) { + stub.set_known_map(Handle<Map>(Handle<JSObject>::cast(x)->map())); + } rewritten = stub.GetCode(); } set_target(*rewritten); @@ -1572,7 +1694,8 @@ void PatchInlinedSmiCode(Address address) { // If the instruction following the call is not a andi at, rx, #yyy, nothing // was inlined. Instr instr = Assembler::instr_at(andi_instruction_address); - if (!Assembler::IsAndImmediate(instr)) { + if (!(Assembler::IsAndImmediate(instr) && + Assembler::GetRt(instr) == (uint32_t)zero_reg.code())) { return; } |