OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1554 } else { | 1554 } else { |
1555 Label call_builtin; | 1555 Label call_builtin; |
1556 | 1556 |
1557 Register elements = a3; | 1557 Register elements = a3; |
1558 Register end_elements = t1; | 1558 Register end_elements = t1; |
1559 | 1559 |
1560 // Get the elements array of the object. | 1560 // Get the elements array of the object. |
1561 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1561 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1562 | 1562 |
1563 // Check that the elements are in fast mode and writable. | 1563 // Check that the elements are in fast mode and writable. |
1564 __ CheckMap(elements, v0, | 1564 __ CheckMap(elements, |
1565 Heap::kFixedArrayMapRootIndex, &call_builtin, true); | 1565 v0, |
| 1566 Heap::kFixedArrayMapRootIndex, |
| 1567 &call_builtin, |
| 1568 DONT_DO_SMI_CHECK); |
1566 | 1569 |
1567 if (argc == 1) { // Otherwise fall through to call the builtin. | 1570 if (argc == 1) { // Otherwise fall through to call the builtin. |
1568 Label exit, with_write_barrier, attempt_to_grow_elements; | 1571 Label exit, with_write_barrier, attempt_to_grow_elements; |
1569 | 1572 |
1570 // Get the array's length into v0 and calculate new length. | 1573 // Get the array's length into v0 and calculate new length. |
1571 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1574 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1572 STATIC_ASSERT(kSmiTagSize == 1); | 1575 STATIC_ASSERT(kSmiTagSize == 1); |
1573 STATIC_ASSERT(kSmiTag == 0); | 1576 STATIC_ASSERT(kSmiTag == 0); |
1574 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1577 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); |
1575 | 1578 |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1703 __ JumpIfSmi(receiver, &miss); | 1706 __ JumpIfSmi(receiver, &miss); |
1704 | 1707 |
1705 // Check that the maps haven't changed. | 1708 // Check that the maps haven't changed. |
1706 CheckPrototypes(JSObject::cast(object), | 1709 CheckPrototypes(JSObject::cast(object), |
1707 receiver, holder, elements, t0, v0, name, &miss); | 1710 receiver, holder, elements, t0, v0, name, &miss); |
1708 | 1711 |
1709 // Get the elements array of the object. | 1712 // Get the elements array of the object. |
1710 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1713 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1711 | 1714 |
1712 // Check that the elements are in fast mode and writable. | 1715 // Check that the elements are in fast mode and writable. |
1713 __ CheckMap(elements, v0, Heap::kFixedArrayMapRootIndex, &call_builtin, true); | 1716 __ CheckMap(elements, |
| 1717 v0, |
| 1718 Heap::kFixedArrayMapRootIndex, |
| 1719 &call_builtin, |
| 1720 DONT_DO_SMI_CHECK); |
1714 | 1721 |
1715 // Get the array's length into t0 and calculate new length. | 1722 // Get the array's length into t0 and calculate new length. |
1716 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1723 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1717 __ Subu(t0, t0, Operand(Smi::FromInt(1))); | 1724 __ Subu(t0, t0, Operand(Smi::FromInt(1))); |
1718 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); | 1725 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); |
1719 | 1726 |
1720 // Get the last element. | 1727 // Get the last element. |
1721 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | 1728 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); |
1722 STATIC_ASSERT(kSmiTagSize == 1); | 1729 STATIC_ASSERT(kSmiTagSize == 1); |
1723 STATIC_ASSERT(kSmiTag == 0); | 1730 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 | 2049 |
2043 // Load the (only) argument into v0. | 2050 // Load the (only) argument into v0. |
2044 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2051 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
2045 | 2052 |
2046 // If the argument is a smi, just return. | 2053 // If the argument is a smi, just return. |
2047 STATIC_ASSERT(kSmiTag == 0); | 2054 STATIC_ASSERT(kSmiTag == 0); |
2048 __ And(t0, v0, Operand(kSmiTagMask)); | 2055 __ And(t0, v0, Operand(kSmiTagMask)); |
2049 __ Drop(argc + 1, eq, t0, Operand(zero_reg)); | 2056 __ Drop(argc + 1, eq, t0, Operand(zero_reg)); |
2050 __ Ret(eq, t0, Operand(zero_reg)); | 2057 __ Ret(eq, t0, Operand(zero_reg)); |
2051 | 2058 |
2052 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, true); | 2059 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); |
2053 | 2060 |
2054 Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return; | 2061 Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return; |
2055 | 2062 |
2056 // If fpu is enabled, we use the floor instruction. | 2063 // If fpu is enabled, we use the floor instruction. |
2057 | 2064 |
2058 // Load the HeapNumber value. | 2065 // Load the HeapNumber value. |
2059 __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); | 2066 __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); |
2060 | 2067 |
2061 // Backup FCSR. | 2068 // Backup FCSR. |
2062 __ cfc1(a3, FCSR); | 2069 __ cfc1(a3, FCSR); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2193 Label slow; | 2200 Label slow; |
2194 __ Branch(&slow, lt, v0, Operand(zero_reg)); | 2201 __ Branch(&slow, lt, v0, Operand(zero_reg)); |
2195 | 2202 |
2196 // Smi case done. | 2203 // Smi case done. |
2197 __ Drop(argc + 1); | 2204 __ Drop(argc + 1); |
2198 __ Ret(); | 2205 __ Ret(); |
2199 | 2206 |
2200 // Check if the argument is a heap number and load its exponent and | 2207 // Check if the argument is a heap number and load its exponent and |
2201 // sign. | 2208 // sign. |
2202 __ bind(¬_smi); | 2209 __ bind(¬_smi); |
2203 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, true); | 2210 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); |
2204 __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 2211 __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
2205 | 2212 |
2206 // Check the sign of the argument. If the argument is positive, | 2213 // Check the sign of the argument. If the argument is positive, |
2207 // just return it. | 2214 // just return it. |
2208 Label negative_sign; | 2215 Label negative_sign; |
2209 __ And(t0, a1, Operand(HeapNumber::kSignMask)); | 2216 __ And(t0, a1, Operand(HeapNumber::kSignMask)); |
2210 __ Branch(&negative_sign, ne, t0, Operand(zero_reg)); | 2217 __ Branch(&negative_sign, ne, t0, Operand(zero_reg)); |
2211 __ Drop(argc + 1); | 2218 __ Drop(argc + 1); |
2212 __ Ret(); | 2219 __ Ret(); |
2213 | 2220 |
(...skipping 25 matching lines...) Expand all Loading... |
2239 | 2246 |
2240 | 2247 |
2241 MaybeObject* CallStubCompiler::CompileFastApiCall( | 2248 MaybeObject* CallStubCompiler::CompileFastApiCall( |
2242 const CallOptimization& optimization, | 2249 const CallOptimization& optimization, |
2243 Object* object, | 2250 Object* object, |
2244 JSObject* holder, | 2251 JSObject* holder, |
2245 JSGlobalPropertyCell* cell, | 2252 JSGlobalPropertyCell* cell, |
2246 JSFunction* function, | 2253 JSFunction* function, |
2247 String* name) { | 2254 String* name) { |
2248 | 2255 |
2249 Isolate* isolate = masm()->isolate(); | 2256 Counters* counters = isolate()->counters(); |
2250 Heap* heap = isolate->heap(); | |
2251 Counters* counters = isolate->counters(); | |
2252 | 2257 |
2253 ASSERT(optimization.is_simple_api_call()); | 2258 ASSERT(optimization.is_simple_api_call()); |
2254 // Bail out if object is a global object as we don't want to | 2259 // Bail out if object is a global object as we don't want to |
2255 // repatch it to global receiver. | 2260 // repatch it to global receiver. |
2256 if (object->IsGlobalObject()) return heap->undefined_value(); | 2261 if (object->IsGlobalObject()) return heap()->undefined_value(); |
2257 if (cell != NULL) return heap->undefined_value(); | 2262 if (cell != NULL) return heap()->undefined_value(); |
2258 if (!object->IsJSObject()) return heap()->undefined_value(); | 2263 if (!object->IsJSObject()) return heap()->undefined_value(); |
2259 int depth = optimization.GetPrototypeDepthOfExpectedType( | 2264 int depth = optimization.GetPrototypeDepthOfExpectedType( |
2260 JSObject::cast(object), holder); | 2265 JSObject::cast(object), holder); |
2261 if (depth == kInvalidProtoDepth) return heap->undefined_value(); | 2266 if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
2262 | 2267 |
2263 Label miss, miss_before_stack_reserved; | 2268 Label miss, miss_before_stack_reserved; |
2264 | 2269 |
2265 GenerateNameCheck(name, &miss_before_stack_reserved); | 2270 GenerateNameCheck(name, &miss_before_stack_reserved); |
2266 | 2271 |
2267 // Get the receiver from the stack. | 2272 // Get the receiver from the stack. |
2268 const int argc = arguments().immediate(); | 2273 const int argc = arguments().immediate(); |
2269 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2274 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
2270 | 2275 |
2271 // Check that the receiver isn't a smi. | 2276 // Check that the receiver isn't a smi. |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3060 | 3065 |
3061 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); | 3066 GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); |
3062 __ bind(&miss); | 3067 __ bind(&miss); |
3063 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); | 3068 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); |
3064 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3069 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3065 | 3070 |
3066 return GetCode(CALLBACKS, name); | 3071 return GetCode(CALLBACKS, name); |
3067 } | 3072 } |
3068 | 3073 |
3069 | 3074 |
3070 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3075 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { |
| 3076 // ----------- S t a t e ------------- |
| 3077 // -- ra : return address |
| 3078 // -- a0 : key |
| 3079 // -- a1 : receiver |
| 3080 // ----------------------------------- |
| 3081 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); |
| 3082 Code* stub; |
| 3083 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3084 __ DispatchMap(a1, |
| 3085 a2, |
| 3086 Handle<Map>(receiver_map), |
| 3087 Handle<Code>(stub), |
| 3088 DO_SMI_CHECK); |
| 3089 |
| 3090 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3091 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3092 |
| 3093 // Return the generated code. |
| 3094 return GetCode(NORMAL, NULL); |
| 3095 } |
| 3096 |
| 3097 |
| 3098 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic( |
| 3099 MapList* receiver_maps, |
| 3100 CodeList* handler_ics) { |
3071 // ----------- S t a t e ------------- | 3101 // ----------- S t a t e ------------- |
3072 // -- ra : return address | 3102 // -- ra : return address |
3073 // -- a0 : key | 3103 // -- a0 : key |
3074 // -- a1 : receiver | 3104 // -- a1 : receiver |
3075 // ----------------------------------- | 3105 // ----------------------------------- |
3076 Label miss; | 3106 Label miss; |
3077 | |
3078 // Check that the receiver isn't a smi. | |
3079 __ JumpIfSmi(a1, &miss); | 3107 __ JumpIfSmi(a1, &miss); |
3080 | 3108 |
3081 // Check that the map matches. | 3109 int receiver_count = receiver_maps->length(); |
3082 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); | 3110 __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); |
3083 __ Branch(&miss, ne, a2, Operand(Handle<Map>(receiver->map()))); | 3111 for (int current = 0; current < receiver_count; ++current) { |
3084 | 3112 Handle<Map> map(receiver_maps->at(current)); |
3085 // Check that the key is a smi. | 3113 Handle<Code> code(handler_ics->at(current)); |
3086 __ JumpIfNotSmi(a0, &miss); | 3114 __ Jump(code, RelocInfo::CODE_TARGET, eq, a2, Operand(map)); |
3087 | 3115 } |
3088 // Get the elements array. | |
3089 __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); | |
3090 __ AssertFastElements(a2); | |
3091 | |
3092 // Check that the key is within bounds. | |
3093 __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset)); | |
3094 __ Branch(&miss, hs, a0, Operand(a3)); | |
3095 | |
3096 // Load the result and make sure it's not the hole. | |
3097 __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | |
3098 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | |
3099 __ sll(t1, a0, kPointerSizeLog2 - kSmiTagSize); | |
3100 __ Addu(t1, t1, a3); | |
3101 __ lw(t0, MemOperand(t1)); | |
3102 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); | |
3103 __ Branch(&miss, eq, t0, Operand(t1)); | |
3104 __ mov(v0, t0); | |
3105 __ Ret(); | |
3106 | 3116 |
3107 __ bind(&miss); | 3117 __ bind(&miss); |
3108 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3118 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3119 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
3109 | 3120 |
3110 // Return the generated code. | 3121 // Return the generated code. |
3111 return GetCode(NORMAL, NULL); | 3122 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
3112 } | 3123 } |
3113 | 3124 |
3114 | 3125 |
3115 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, | 3126 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
3116 int index, | 3127 int index, |
3117 Map* transition, | 3128 Map* transition, |
3118 String* name) { | 3129 String* name) { |
3119 // ----------- S t a t e ------------- | 3130 // ----------- S t a t e ------------- |
3120 // -- a0 : value | 3131 // -- a0 : value |
3121 // -- a1 : key | 3132 // -- a1 : key |
(...skipping 21 matching lines...) Expand all Loading... |
3143 | 3154 |
3144 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); | 3155 __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); |
3145 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | 3156 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); |
3146 __ Jump(ic, RelocInfo::CODE_TARGET); | 3157 __ Jump(ic, RelocInfo::CODE_TARGET); |
3147 | 3158 |
3148 // Return the generated code. | 3159 // Return the generated code. |
3149 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 3160 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
3150 } | 3161 } |
3151 | 3162 |
3152 | 3163 |
3153 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 3164 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( |
3154 JSObject* receiver) { | 3165 Map* receiver_map) { |
3155 // ----------- S t a t e ------------- | 3166 // ----------- S t a t e ------------- |
3156 // -- a0 : value | 3167 // -- a0 : value |
3157 // -- a1 : key | 3168 // -- a1 : key |
3158 // -- a2 : receiver | 3169 // -- a2 : receiver |
3159 // -- ra : return address | 3170 // -- ra : return address |
3160 // -- a3 : scratch | 3171 // -- a3 : scratch |
3161 // -- t0 : scratch (elements) | |
3162 // ----------------------------------- | 3172 // ----------------------------------- |
3163 Label miss; | 3173 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
3164 Register value_reg = a0; | 3174 MaybeObject* maybe_stub = |
3165 Register key_reg = a1; | 3175 KeyedStoreFastElementStub(is_js_array).TryGetCode(); |
3166 Register receiver_reg = a2; | 3176 Code* stub; |
3167 Register scratch = a3; | 3177 if (!maybe_stub->To(&stub)) return maybe_stub; |
3168 Register elements_reg = t0; | 3178 __ DispatchMap(a2, |
| 3179 a3, |
| 3180 Handle<Map>(receiver_map), |
| 3181 Handle<Code>(stub), |
| 3182 DO_SMI_CHECK); |
3169 | 3183 |
3170 // Check that the receiver isn't a smi. | 3184 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
3171 __ JumpIfSmi(receiver_reg, &miss); | |
3172 | |
3173 // Check that the map matches. | |
3174 __ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); | |
3175 __ Branch(&miss, ne, scratch, Operand(Handle<Map>(receiver->map()))); | |
3176 | |
3177 // Check that the key is a smi. | |
3178 __ JumpIfNotSmi(key_reg, &miss); | |
3179 | |
3180 // Get the elements array and make sure it is a fast element array, not 'cow'. | |
3181 __ lw(elements_reg, | |
3182 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); | |
3183 __ lw(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset)); | |
3184 __ Branch(&miss, ne, scratch, | |
3185 Operand(Handle<Map>(FACTORY->fixed_array_map()))); | |
3186 | |
3187 // Check that the key is within bounds. | |
3188 if (receiver->IsJSArray()) { | |
3189 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | |
3190 } else { | |
3191 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); | |
3192 } | |
3193 // Compare smis. | |
3194 __ Branch(&miss, hs, key_reg, Operand(scratch)); | |
3195 __ Addu(scratch, | |
3196 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | |
3197 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | |
3198 __ sll(key_reg, key_reg, kPointerSizeLog2 - kSmiTagSize); | |
3199 __ Addu(v0, scratch, key_reg); | |
3200 __ sw(value_reg, MemOperand(v0)); | |
3201 __ RecordWrite(scratch, Operand(key_reg), receiver_reg , elements_reg); | |
3202 | |
3203 // value_reg (a0) is preserved. | |
3204 // Done. | |
3205 __ mov(v0, value_reg); | |
3206 __ Ret(); | |
3207 | |
3208 __ bind(&miss); | |
3209 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); | |
3210 __ Jump(ic, RelocInfo::CODE_TARGET); | 3185 __ Jump(ic, RelocInfo::CODE_TARGET); |
3211 | 3186 |
3212 // Return the generated code. | 3187 // Return the generated code. |
3213 return GetCode(NORMAL, NULL); | 3188 return GetCode(NORMAL, NULL); |
3214 } | 3189 } |
3215 | 3190 |
3216 | 3191 |
| 3192 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
| 3193 MapList* receiver_maps, |
| 3194 CodeList* handler_ics) { |
| 3195 // ----------- S t a t e ------------- |
| 3196 // -- a0 : value |
| 3197 // -- a1 : key |
| 3198 // -- a2 : receiver |
| 3199 // -- ra : return address |
| 3200 // -- a3 : scratch |
| 3201 // ----------------------------------- |
| 3202 Label miss; |
| 3203 __ JumpIfSmi(a2, &miss); |
| 3204 |
| 3205 int receiver_count = receiver_maps->length(); |
| 3206 __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 3207 for (int current = 0; current < receiver_count; ++current) { |
| 3208 Handle<Map> map(receiver_maps->at(current)); |
| 3209 Handle<Code> code(handler_ics->at(current)); |
| 3210 __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); |
| 3211 } |
| 3212 |
| 3213 __ bind(&miss); |
| 3214 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3215 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
| 3216 |
| 3217 // Return the generated code. |
| 3218 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 3219 } |
| 3220 |
| 3221 |
3217 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3222 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3218 // a0 : argc | 3223 // a0 : argc |
3219 // a1 : constructor | 3224 // a1 : constructor |
3220 // ra : return address | 3225 // ra : return address |
3221 // [sp] : last argument | 3226 // [sp] : last argument |
3222 Label generic_stub_call; | 3227 Label generic_stub_call; |
3223 | 3228 |
3224 // Use t7 for holding undefined which is used in several places below. | 3229 // Use t7 for holding undefined which is used in several places below. |
3225 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); | 3230 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); |
3226 | 3231 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3357 __ bind(&generic_stub_call); | 3362 __ bind(&generic_stub_call); |
3358 Handle<Code> generic_construct_stub = | 3363 Handle<Code> generic_construct_stub = |
3359 masm()->isolate()->builtins()->JSConstructStubGeneric(); | 3364 masm()->isolate()->builtins()->JSConstructStubGeneric(); |
3360 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | 3365 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); |
3361 | 3366 |
3362 // Return the generated code. | 3367 // Return the generated code. |
3363 return GetCode(); | 3368 return GetCode(); |
3364 } | 3369 } |
3365 | 3370 |
3366 | 3371 |
| 3372 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( |
| 3373 JSObject*receiver, ExternalArrayType array_type) { |
| 3374 // ----------- S t a t e ------------- |
| 3375 // -- ra : return address |
| 3376 // -- a0 : key |
| 3377 // -- a1 : receiver |
| 3378 // ----------------------------------- |
| 3379 MaybeObject* maybe_stub = |
| 3380 KeyedLoadExternalArrayStub(array_type).TryGetCode(); |
| 3381 Code* stub; |
| 3382 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3383 __ DispatchMap(a1, |
| 3384 a2, |
| 3385 Handle<Map>(receiver->map()), |
| 3386 Handle<Code>(stub), |
| 3387 DO_SMI_CHECK); |
| 3388 |
| 3389 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3390 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3391 |
| 3392 // Return the generated code. |
| 3393 return GetCode(); |
| 3394 } |
| 3395 |
| 3396 |
| 3397 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore( |
| 3398 JSObject* receiver, ExternalArrayType array_type) { |
| 3399 // ----------- S t a t e ------------- |
| 3400 // -- a0 : value |
| 3401 // -- a1 : name |
| 3402 // -- a2 : receiver |
| 3403 // -- ra : return address |
| 3404 // ----------------------------------- |
| 3405 MaybeObject* maybe_stub = |
| 3406 KeyedStoreExternalArrayStub(array_type).TryGetCode(); |
| 3407 Code* stub; |
| 3408 if (!maybe_stub->To(&stub)) return maybe_stub; |
| 3409 __ DispatchMap(a2, |
| 3410 a3, |
| 3411 Handle<Map>(receiver->map()), |
| 3412 Handle<Code>(stub), |
| 3413 DONT_DO_SMI_CHECK); |
| 3414 |
| 3415 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3416 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 3417 |
| 3418 return GetCode(); |
| 3419 } |
| 3420 |
| 3421 |
| 3422 #undef __ |
| 3423 #define __ ACCESS_MASM(masm) |
| 3424 |
| 3425 |
3367 static bool IsElementTypeSigned(ExternalArrayType array_type) { | 3426 static bool IsElementTypeSigned(ExternalArrayType array_type) { |
3368 switch (array_type) { | 3427 switch (array_type) { |
3369 case kExternalByteArray: | 3428 case kExternalByteArray: |
3370 case kExternalShortArray: | 3429 case kExternalShortArray: |
3371 case kExternalIntArray: | 3430 case kExternalIntArray: |
3372 return true; | 3431 return true; |
3373 | 3432 |
3374 case kExternalUnsignedByteArray: | 3433 case kExternalUnsignedByteArray: |
3375 case kExternalUnsignedShortArray: | 3434 case kExternalUnsignedShortArray: |
3376 case kExternalUnsignedIntArray: | 3435 case kExternalUnsignedIntArray: |
3377 return false; | 3436 return false; |
3378 | 3437 |
3379 default: | 3438 default: |
3380 UNREACHABLE(); | 3439 UNREACHABLE(); |
3381 return false; | 3440 return false; |
3382 } | 3441 } |
3383 } | 3442 } |
3384 | 3443 |
3385 | 3444 |
3386 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3445 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
3387 JSObject* receiver_object, | 3446 MacroAssembler* masm, |
3388 ExternalArrayType array_type, | 3447 ExternalArrayType array_type) { |
3389 Code::Flags flags) { | |
3390 // ---------- S t a t e -------------- | 3448 // ---------- S t a t e -------------- |
3391 // -- ra : return address | 3449 // -- ra : return address |
3392 // -- a0 : key | 3450 // -- a0 : key |
3393 // -- a1 : receiver | 3451 // -- a1 : receiver |
3394 // ----------------------------------- | 3452 // ----------------------------------- |
3395 Label slow, failed_allocation; | 3453 Label miss_force_generic, slow, failed_allocation; |
3396 | 3454 |
3397 Register key = a0; | 3455 Register key = a0; |
3398 Register receiver = a1; | 3456 Register receiver = a1; |
3399 | 3457 |
3400 // Check that the object isn't a smi. | 3458 // This stub is meant to be tail-jumped to, the receiver must already |
3401 __ JumpIfSmi(receiver, &slow); | 3459 // have been verified by the caller to not be a smi. |
3402 | 3460 |
3403 // Check that the key is a smi. | 3461 // Check that the key is a smi. |
3404 __ JumpIfNotSmi(key, &slow); | 3462 __ JumpIfNotSmi(key, &miss_force_generic); |
3405 | |
3406 // Make sure that we've got the right map. | |
3407 __ lw(a2, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
3408 __ Branch(&slow, ne, a2, Operand(Handle<Map>(receiver_object->map()))); | |
3409 | 3463 |
3410 __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 3464 __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
3411 // a3: elements array | 3465 // a3: elements array |
3412 | 3466 |
3413 // Check that the index is in range. | 3467 // Check that the index is in range. |
3414 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); | 3468 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); |
3415 __ sra(t2, key, kSmiTagSize); | 3469 __ sra(t2, key, kSmiTagSize); |
3416 // Unsigned comparison catches both negative and too-large values. | 3470 // Unsigned comparison catches both negative and too-large values. |
3417 __ Branch(&slow, Uless, t1, Operand(t2)); | 3471 __ Branch(&miss_force_generic, Uless, t1, Operand(t2)); |
3418 | |
3419 | 3472 |
3420 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); | 3473 __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
3421 // a3: base pointer of external storage | 3474 // a3: base pointer of external storage |
3422 | 3475 |
3423 // We are not untagging smi key and instead work with it | 3476 // We are not untagging smi key and instead work with it |
3424 // as if it was premultiplied by 2. | 3477 // as if it was premultiplied by 2. |
3425 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); | 3478 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); |
3426 | 3479 |
3427 Register value = a2; | 3480 Register value = a2; |
3428 switch (array_type) { | 3481 switch (array_type) { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3558 | 3611 |
3559 // Tag integer as smi and return it. | 3612 // Tag integer as smi and return it. |
3560 __ sll(v0, value, kSmiTagSize); | 3613 __ sll(v0, value, kSmiTagSize); |
3561 __ Ret(); | 3614 __ Ret(); |
3562 | 3615 |
3563 Register hiword = value; // a2. | 3616 Register hiword = value; // a2. |
3564 Register loword = a3; | 3617 Register loword = a3; |
3565 | 3618 |
3566 __ bind(&box_int_0); | 3619 __ bind(&box_int_0); |
3567 // Integer does not have leading zeros. | 3620 // Integer does not have leading zeros. |
3568 GenerateUInt2Double(masm(), hiword, loword, t0, 0); | 3621 GenerateUInt2Double(masm, hiword, loword, t0, 0); |
3569 __ Branch(&done); | 3622 __ Branch(&done); |
3570 | 3623 |
3571 __ bind(&box_int_1); | 3624 __ bind(&box_int_1); |
3572 // Integer has one leading zero. | 3625 // Integer has one leading zero. |
3573 GenerateUInt2Double(masm(), hiword, loword, t0, 1); | 3626 GenerateUInt2Double(masm, hiword, loword, t0, 1); |
3574 | 3627 |
3575 | 3628 |
3576 __ bind(&done); | 3629 __ bind(&done); |
3577 // Integer was converted to double in registers hiword:loword. | 3630 // Integer was converted to double in registers hiword:loword. |
3578 // Wrap it into a HeapNumber. Don't use a0 and a1 as AllocateHeapNumber | 3631 // Wrap it into a HeapNumber. Don't use a0 and a1 as AllocateHeapNumber |
3579 // clobbers all registers - also when jumping due to exhausted young | 3632 // clobbers all registers - also when jumping due to exhausted young |
3580 // space. | 3633 // space. |
3581 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); | 3634 __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); |
3582 __ AllocateHeapNumber(t2, t3, t5, t6, &slow); | 3635 __ AllocateHeapNumber(t2, t3, t5, t6, &slow); |
3583 | 3636 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3679 | 3732 |
3680 } else { | 3733 } else { |
3681 // Tag integer as smi and return it. | 3734 // Tag integer as smi and return it. |
3682 __ sll(v0, value, kSmiTagSize); | 3735 __ sll(v0, value, kSmiTagSize); |
3683 __ Ret(); | 3736 __ Ret(); |
3684 } | 3737 } |
3685 | 3738 |
3686 // Slow case, key and receiver still in a0 and a1. | 3739 // Slow case, key and receiver still in a0 and a1. |
3687 __ bind(&slow); | 3740 __ bind(&slow); |
3688 __ IncrementCounter( | 3741 __ IncrementCounter( |
3689 masm()->isolate()->counters()->keyed_load_external_array_slow(), | 3742 masm->isolate()->counters()->keyed_load_external_array_slow(), |
3690 1, a2, a3); | 3743 1, a2, a3); |
3691 | 3744 |
3692 // ---------- S t a t e -------------- | 3745 // ---------- S t a t e -------------- |
3693 // -- ra : return address | 3746 // -- ra : return address |
3694 // -- a0 : key | 3747 // -- a0 : key |
3695 // -- a1 : receiver | 3748 // -- a1 : receiver |
3696 // ----------------------------------- | 3749 // ----------------------------------- |
3697 | 3750 |
3698 __ Push(a1, a0); | 3751 __ Push(a1, a0); |
3699 | 3752 |
3700 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3753 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
3701 | 3754 |
3702 return GetCode(flags); | 3755 __ bind(&miss_force_generic); |
| 3756 Code* stub = masm->isolate()->builtins()->builtin( |
| 3757 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 3758 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); |
3703 } | 3759 } |
3704 | 3760 |
3705 | 3761 |
3706 | 3762 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3707 | 3763 MacroAssembler* masm, |
3708 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( | 3764 ExternalArrayType array_type) { |
3709 JSObject* receiver_object, | |
3710 ExternalArrayType array_type, | |
3711 Code::Flags flags) { | |
3712 // ---------- S t a t e -------------- | 3765 // ---------- S t a t e -------------- |
3713 // -- a0 : value | 3766 // -- a0 : value |
3714 // -- a1 : key | 3767 // -- a1 : key |
3715 // -- a2 : receiver | 3768 // -- a2 : receiver |
3716 // -- ra : return address | 3769 // -- ra : return address |
3717 // ----------------------------------- | 3770 // ----------------------------------- |
3718 | 3771 |
3719 Label slow, check_heap_number; | 3772 Label slow, check_heap_number, miss_force_generic; |
3720 | 3773 |
3721 // Register usage. | 3774 // Register usage. |
3722 Register value = a0; | 3775 Register value = a0; |
3723 Register key = a1; | 3776 Register key = a1; |
3724 Register receiver = a2; | 3777 Register receiver = a2; |
3725 // a3 mostly holds the elements array or the destination external array. | 3778 // a3 mostly holds the elements array or the destination external array. |
3726 | 3779 |
3727 // Check that the object isn't a smi. | 3780 // This stub is meant to be tail-jumped to, the receiver must already |
3728 __ JumpIfSmi(receiver, &slow); | 3781 // have been verified by the caller to not be a smi. |
3729 | |
3730 // Make sure that we've got the right map. | |
3731 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | |
3732 __ Branch(&slow, ne, a3, Operand(Handle<Map>(receiver_object->map()))); | |
3733 | 3782 |
3734 __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); | 3783 __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
3735 | 3784 |
3736 // Check that the key is a smi. | 3785 // Check that the key is a smi. |
3737 __ JumpIfNotSmi(key, &slow); | 3786 __ JumpIfNotSmi(key, &miss_force_generic); |
3738 | 3787 |
3739 // Check that the index is in range. | 3788 // Check that the index is in range. |
3740 __ SmiUntag(t0, key); | 3789 __ SmiUntag(t0, key); |
3741 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); | 3790 __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); |
3742 // Unsigned comparison catches both negative and too-large values. | 3791 // Unsigned comparison catches both negative and too-large values. |
3743 __ Branch(&slow, Ugreater_equal, t0, Operand(t1)); | 3792 __ Branch(&miss_force_generic, Ugreater_equal, t0, Operand(t1)); |
3744 | 3793 |
3745 // Handle both smis and HeapNumbers in the fast path. Go to the | 3794 // Handle both smis and HeapNumbers in the fast path. Go to the |
3746 // runtime for all other kinds of values. | 3795 // runtime for all other kinds of values. |
3747 // a3: external array. | 3796 // a3: external array. |
3748 // t0: key (integer). | 3797 // t0: key (integer). |
3749 | 3798 |
3750 if (array_type == kExternalPixelArray) { | 3799 if (array_type == kExternalPixelArray) { |
3751 // Double to pixel conversion is only implemented in the runtime for now. | 3800 // Double to pixel conversion is only implemented in the runtime for now. |
3752 __ JumpIfNotSmi(value, &slow); | 3801 __ JumpIfNotSmi(value, &slow); |
3753 } else { | 3802 } else { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3790 __ sh(t1, MemOperand(t8, 0)); | 3839 __ sh(t1, MemOperand(t8, 0)); |
3791 break; | 3840 break; |
3792 case kExternalIntArray: | 3841 case kExternalIntArray: |
3793 case kExternalUnsignedIntArray: | 3842 case kExternalUnsignedIntArray: |
3794 __ sll(t8, t0, 2); | 3843 __ sll(t8, t0, 2); |
3795 __ addu(t8, a3, t8); | 3844 __ addu(t8, a3, t8); |
3796 __ sw(t1, MemOperand(t8, 0)); | 3845 __ sw(t1, MemOperand(t8, 0)); |
3797 break; | 3846 break; |
3798 case kExternalFloatArray: | 3847 case kExternalFloatArray: |
3799 // Perform int-to-float conversion and store to memory. | 3848 // Perform int-to-float conversion and store to memory. |
3800 StoreIntAsFloat(masm(), a3, t0, t1, t2, t3, t4); | 3849 StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); |
3801 break; | 3850 break; |
3802 case kExternalDoubleArray: | 3851 case kExternalDoubleArray: |
3803 __ sll(t8, t0, 3); | 3852 __ sll(t8, t0, 3); |
3804 __ addu(a3, a3, t8); | 3853 __ addu(a3, a3, t8); |
3805 // a3: effective address of the double element | 3854 // a3: effective address of the double element |
3806 FloatingPointHelper::Destination destination; | 3855 FloatingPointHelper::Destination destination; |
3807 if (CpuFeatures::IsSupported(FPU)) { | 3856 if (CpuFeatures::IsSupported(FPU)) { |
3808 destination = FloatingPointHelper::kFPURegisters; | 3857 destination = FloatingPointHelper::kFPURegisters; |
3809 } else { | 3858 } else { |
3810 destination = FloatingPointHelper::kCoreRegisters; | 3859 destination = FloatingPointHelper::kCoreRegisters; |
3811 } | 3860 } |
3812 FloatingPointHelper::ConvertIntToDouble( | 3861 FloatingPointHelper::ConvertIntToDouble( |
3813 masm(), t1, destination, | 3862 masm, t1, destination, |
3814 f0, t2, t3, // These are: double_dst, dst1, dst2. | 3863 f0, t2, t3, // These are: double_dst, dst1, dst2. |
3815 t0, f2); // These are: scratch2, single_scratch. | 3864 t0, f2); // These are: scratch2, single_scratch. |
3816 if (destination == FloatingPointHelper::kFPURegisters) { | 3865 if (destination == FloatingPointHelper::kFPURegisters) { |
3817 CpuFeatures::Scope scope(FPU); | 3866 CpuFeatures::Scope scope(FPU); |
3818 __ sdc1(f0, MemOperand(a3, 0)); | 3867 __ sdc1(f0, MemOperand(a3, 0)); |
3819 } else { | 3868 } else { |
3820 __ sw(t2, MemOperand(a3, 0)); | 3869 __ sw(t2, MemOperand(a3, 0)); |
3821 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); | 3870 __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); |
3822 } | 3871 } |
3823 break; | 3872 break; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4065 __ sw(t3, MemOperand(t8, 0)); | 4114 __ sw(t3, MemOperand(t8, 0)); |
4066 break; | 4115 break; |
4067 default: | 4116 default: |
4068 UNREACHABLE(); | 4117 UNREACHABLE(); |
4069 break; | 4118 break; |
4070 } | 4119 } |
4071 } | 4120 } |
4072 } | 4121 } |
4073 } | 4122 } |
4074 | 4123 |
4075 // Slow case: call runtime. | 4124 // Slow case, key and receiver still in a0 and a1. |
4076 __ bind(&slow); | 4125 __ bind(&slow); |
| 4126 __ IncrementCounter( |
| 4127 masm->isolate()->counters()->keyed_load_external_array_slow(), |
| 4128 1, a2, a3); |
4077 // Entry registers are intact. | 4129 // Entry registers are intact. |
4078 // ---------- S t a t e -------------- | 4130 // ---------- S t a t e -------------- |
4079 // -- a0 : value | |
4080 // -- a1 : key | |
4081 // -- a2 : receiver | |
4082 // -- ra : return address | 4131 // -- ra : return address |
| 4132 // -- a0 : key |
| 4133 // -- a1 : receiver |
| 4134 // ----------------------------------- |
| 4135 Handle<Code> slow_ic = |
| 4136 masm->isolate()->builtins()->KeyedStoreIC_Slow(); |
| 4137 __ Jump(slow_ic, RelocInfo::CODE_TARGET); |
| 4138 |
| 4139 // Miss case, call the runtime. |
| 4140 __ bind(&miss_force_generic); |
| 4141 |
| 4142 // ---------- S t a t e -------------- |
| 4143 // -- ra : return address |
| 4144 // -- a0 : key |
| 4145 // -- a1 : receiver |
4083 // ----------------------------------- | 4146 // ----------------------------------- |
4084 | 4147 |
4085 // Push receiver, key and value for runtime call. | 4148 Handle<Code> miss_ic = |
4086 __ Push(a2, a1, a0); | 4149 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
4087 | 4150 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
4088 __ li(a1, Operand(Smi::FromInt(NONE))); // PropertyAttributes. | |
4089 __ li(a0, Operand(Smi::FromInt( | |
4090 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode))); | |
4091 __ Push(a1, a0); | |
4092 | |
4093 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); | |
4094 | |
4095 return GetCode(flags); | |
4096 } | 4151 } |
4097 | 4152 |
4098 | 4153 |
| 4154 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
| 4155 // ----------- S t a t e ------------- |
| 4156 // -- ra : return address |
| 4157 // -- a0 : key |
| 4158 // -- a1 : receiver |
| 4159 // ----------------------------------- |
| 4160 Label miss_force_generic; |
| 4161 |
| 4162 // This stub is meant to be tail-jumped to, the receiver must already |
| 4163 // have been verified by the caller to not be a smi. |
| 4164 |
| 4165 // Check that the key is a smi. |
| 4166 __ JumpIfNotSmi(a0, &miss_force_generic); |
| 4167 |
| 4168 // Get the elements array. |
| 4169 __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); |
| 4170 __ AssertFastElements(a2); |
| 4171 |
| 4172 // Check that the key is within bounds. |
| 4173 __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset)); |
| 4174 __ Branch(&miss_force_generic, hs, a0, Operand(a3)); |
| 4175 |
| 4176 // Load the result and make sure it's not the hole. |
| 4177 __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4178 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4179 __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); |
| 4180 __ Addu(t0, t0, a3); |
| 4181 __ lw(t0, MemOperand(t0)); |
| 4182 __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
| 4183 __ Branch(&miss_force_generic, eq, t0, Operand(t1)); |
| 4184 __ mov(v0, t0); |
| 4185 __ Ret(); |
| 4186 |
| 4187 __ bind(&miss_force_generic); |
| 4188 Code* stub = masm->isolate()->builtins()->builtin( |
| 4189 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 4190 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); |
| 4191 } |
| 4192 |
| 4193 |
| 4194 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm, |
| 4195 bool is_js_array) { |
| 4196 // ----------- S t a t e ------------- |
| 4197 // -- a0 : value |
| 4198 // -- a1 : key |
| 4199 // -- a2 : receiver |
| 4200 // -- ra : return address |
| 4201 // -- a3 : scratch |
| 4202 // -- a4 : scratch (elements) |
| 4203 // ----------------------------------- |
| 4204 Label miss_force_generic; |
| 4205 |
| 4206 Register value_reg = a0; |
| 4207 Register key_reg = a1; |
| 4208 Register receiver_reg = a2; |
| 4209 Register scratch = a3; |
| 4210 Register elements_reg = t0; |
| 4211 Register scratch2 = t1; |
| 4212 Register scratch3 = t2; |
| 4213 |
| 4214 // This stub is meant to be tail-jumped to, the receiver must already |
| 4215 // have been verified by the caller to not be a smi. |
| 4216 |
| 4217 // Check that the key is a smi. |
| 4218 __ JumpIfNotSmi(a0, &miss_force_generic); |
| 4219 |
| 4220 // Get the elements array and make sure it is a fast element array, not 'cow'. |
| 4221 __ lw(elements_reg, |
| 4222 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); |
| 4223 __ CheckMap(elements_reg, |
| 4224 scratch, |
| 4225 Heap::kFixedArrayMapRootIndex, |
| 4226 &miss_force_generic, |
| 4227 DONT_DO_SMI_CHECK); |
| 4228 |
| 4229 // Check that the key is within bounds. |
| 4230 if (is_js_array) { |
| 4231 __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
| 4232 } else { |
| 4233 __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
| 4234 } |
| 4235 // Compare smis. |
| 4236 __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); |
| 4237 |
| 4238 __ Addu(scratch, |
| 4239 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4240 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4241 __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); |
| 4242 __ Addu(scratch3, scratch2, scratch); |
| 4243 __ sw(value_reg, MemOperand(scratch3)); |
| 4244 __ RecordWrite(scratch, Operand(scratch2), receiver_reg , elements_reg); |
| 4245 |
| 4246 // value_reg (a0) is preserved. |
| 4247 // Done. |
| 4248 __ Ret(); |
| 4249 |
| 4250 __ bind(&miss_force_generic); |
| 4251 Handle<Code> ic = |
| 4252 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 4253 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 4254 } |
| 4255 |
| 4256 |
4099 #undef __ | 4257 #undef __ |
4100 | 4258 |
4101 } } // namespace v8::internal | 4259 } } // namespace v8::internal |
4102 | 4260 |
4103 #endif // V8_TARGET_ARCH_MIPS | 4261 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |