| 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 |