| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2695 Handle<Map> receiver_map) { | 2695 Handle<Map> receiver_map) { |
| 2696 // ----------- S t a t e ------------- | 2696 // ----------- S t a t e ------------- |
| 2697 // -- rax : value | 2697 // -- rax : value |
| 2698 // -- rcx : key | 2698 // -- rcx : key |
| 2699 // -- rdx : receiver | 2699 // -- rdx : receiver |
| 2700 // -- rsp[0] : return address | 2700 // -- rsp[0] : return address |
| 2701 // ----------------------------------- | 2701 // ----------------------------------- |
| 2702 | 2702 |
| 2703 ElementsKind elements_kind = receiver_map->elements_kind(); | 2703 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2704 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2704 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2705 Handle<Code> stub = | 2705 if (receiver_map->has_fast_elements() || |
| 2706 KeyedStoreElementStub(is_js_array, | 2706 receiver_map->has_external_array_elements()) { |
| 2707 elements_kind, | 2707 Handle<Code> stub = KeyedStoreFastElementStub( |
| 2708 store_mode_).GetCode(isolate()); | 2708 is_js_array, |
| 2709 | 2709 elements_kind, |
| 2710 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); | 2710 store_mode_).GetCode(isolate()); |
| 2711 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 2712 } else { |
| 2713 Handle<Code> stub = |
| 2714 KeyedStoreElementStub(is_js_array, elements_kind, |
| 2715 store_mode_).GetCode(isolate()); |
| 2716 __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
| 2717 } |
| 2711 | 2718 |
| 2712 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2719 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2713 __ jmp(ic, RelocInfo::CODE_TARGET); | 2720 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2714 | 2721 |
| 2715 // Return the generated code. | 2722 // Return the generated code. |
| 2716 return GetCode(Code::NORMAL, factory()->empty_string()); | 2723 return GetCode(Code::NORMAL, factory()->empty_string()); |
| 2717 } | 2724 } |
| 2718 | 2725 |
| 2719 | 2726 |
| 2720 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2727 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3135 __ cvttsd2si(scratch, xmm_scratch0); | 3142 __ cvttsd2si(scratch, xmm_scratch0); |
| 3136 __ cvtlsi2sd(xmm_scratch1, scratch); | 3143 __ cvtlsi2sd(xmm_scratch1, scratch); |
| 3137 __ ucomisd(xmm_scratch1, xmm_scratch0); | 3144 __ ucomisd(xmm_scratch1, xmm_scratch0); |
| 3138 __ j(not_equal, fail); | 3145 __ j(not_equal, fail); |
| 3139 __ j(parity_even, fail); // NaN. | 3146 __ j(parity_even, fail); // NaN. |
| 3140 __ Integer32ToSmi(key, scratch); | 3147 __ Integer32ToSmi(key, scratch); |
| 3141 __ bind(&key_ok); | 3148 __ bind(&key_ok); |
| 3142 } | 3149 } |
| 3143 | 3150 |
| 3144 | 3151 |
| 3145 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | |
| 3146 MacroAssembler* masm, | |
| 3147 ElementsKind elements_kind) { | |
| 3148 // ----------- S t a t e ------------- | |
| 3149 // -- rax : value | |
| 3150 // -- rcx : key | |
| 3151 // -- rdx : receiver | |
| 3152 // -- rsp[0] : return address | |
| 3153 // ----------------------------------- | |
| 3154 Label slow, miss_force_generic; | |
| 3155 | |
| 3156 // This stub is meant to be tail-jumped to, the receiver must already | |
| 3157 // have been verified by the caller to not be a smi. | |
| 3158 | |
| 3159 // Check that the key is a smi or a heap number convertible to a smi. | |
| 3160 GenerateSmiKeyCheck(masm, rcx, rbx, xmm0, xmm1, &miss_force_generic); | |
| 3161 | |
| 3162 // Check that the index is in range. | |
| 3163 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | |
| 3164 __ SmiToInteger32(rdi, rcx); // Untag the index. | |
| 3165 __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); | |
| 3166 // Unsigned comparison catches both negative and too-large values. | |
| 3167 __ j(above_equal, &miss_force_generic); | |
| 3168 | |
| 3169 // Handle both smis and HeapNumbers in the fast path. Go to the | |
| 3170 // runtime for all other kinds of values. | |
| 3171 // rax: value | |
| 3172 // rcx: key (a smi) | |
| 3173 // rdx: receiver (a JSObject) | |
| 3174 // rbx: elements array | |
| 3175 // rdi: untagged key | |
| 3176 Label check_heap_number; | |
| 3177 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { | |
| 3178 // Float to pixel conversion is only implemented in the runtime for now. | |
| 3179 __ JumpIfNotSmi(rax, &slow); | |
| 3180 } else { | |
| 3181 __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); | |
| 3182 } | |
| 3183 // No more branches to slow case on this path. Key and receiver not needed. | |
| 3184 __ SmiToInteger32(rdx, rax); | |
| 3185 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | |
| 3186 // rbx: base pointer of external storage | |
| 3187 switch (elements_kind) { | |
| 3188 case EXTERNAL_PIXEL_ELEMENTS: | |
| 3189 { // Clamp the value to [0..255]. | |
| 3190 Label done; | |
| 3191 __ testl(rdx, Immediate(0xFFFFFF00)); | |
| 3192 __ j(zero, &done, Label::kNear); | |
| 3193 __ setcc(negative, rdx); // 1 if negative, 0 if positive. | |
| 3194 __ decb(rdx); // 0 if negative, 255 if positive. | |
| 3195 __ bind(&done); | |
| 3196 } | |
| 3197 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | |
| 3198 break; | |
| 3199 case EXTERNAL_BYTE_ELEMENTS: | |
| 3200 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 3201 __ movb(Operand(rbx, rdi, times_1, 0), rdx); | |
| 3202 break; | |
| 3203 case EXTERNAL_SHORT_ELEMENTS: | |
| 3204 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 3205 __ movw(Operand(rbx, rdi, times_2, 0), rdx); | |
| 3206 break; | |
| 3207 case EXTERNAL_INT_ELEMENTS: | |
| 3208 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 3209 __ movl(Operand(rbx, rdi, times_4, 0), rdx); | |
| 3210 break; | |
| 3211 case EXTERNAL_FLOAT_ELEMENTS: | |
| 3212 // Need to perform int-to-float conversion. | |
| 3213 __ cvtlsi2ss(xmm0, rdx); | |
| 3214 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); | |
| 3215 break; | |
| 3216 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 3217 // Need to perform int-to-float conversion. | |
| 3218 __ cvtlsi2sd(xmm0, rdx); | |
| 3219 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); | |
| 3220 break; | |
| 3221 case FAST_ELEMENTS: | |
| 3222 case FAST_SMI_ELEMENTS: | |
| 3223 case FAST_DOUBLE_ELEMENTS: | |
| 3224 case FAST_HOLEY_ELEMENTS: | |
| 3225 case FAST_HOLEY_SMI_ELEMENTS: | |
| 3226 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 3227 case DICTIONARY_ELEMENTS: | |
| 3228 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 3229 UNREACHABLE(); | |
| 3230 break; | |
| 3231 } | |
| 3232 __ ret(0); | |
| 3233 | |
| 3234 // TODO(danno): handle heap number -> pixel array conversion | |
| 3235 if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { | |
| 3236 __ bind(&check_heap_number); | |
| 3237 // rax: value | |
| 3238 // rcx: key (a smi) | |
| 3239 // rdx: receiver (a JSObject) | |
| 3240 // rbx: elements array | |
| 3241 // rdi: untagged key | |
| 3242 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); | |
| 3243 __ j(not_equal, &slow); | |
| 3244 // No more branches to slow case on this path. | |
| 3245 | |
| 3246 // The WebGL specification leaves the behavior of storing NaN and | |
| 3247 // +/-Infinity into integer arrays basically undefined. For more | |
| 3248 // reproducible behavior, convert these to zero. | |
| 3249 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); | |
| 3250 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | |
| 3251 // rdi: untagged index | |
| 3252 // rbx: base pointer of external storage | |
| 3253 // top of FPU stack: value | |
| 3254 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
| 3255 __ cvtsd2ss(xmm0, xmm0); | |
| 3256 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); | |
| 3257 __ ret(0); | |
| 3258 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
| 3259 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); | |
| 3260 __ ret(0); | |
| 3261 } else { | |
| 3262 // Perform float-to-int conversion with truncation (round-to-zero) | |
| 3263 // behavior. | |
| 3264 // Fast path: use machine instruction to convert to int64. If that | |
| 3265 // fails (out-of-range), go into the runtime. | |
| 3266 __ cvttsd2siq(r8, xmm0); | |
| 3267 __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); | |
| 3268 __ cmpq(r8, kScratchRegister); | |
| 3269 __ j(equal, &slow); | |
| 3270 | |
| 3271 // rdx: value (converted to an untagged integer) | |
| 3272 // rdi: untagged index | |
| 3273 // rbx: base pointer of external storage | |
| 3274 switch (elements_kind) { | |
| 3275 case EXTERNAL_BYTE_ELEMENTS: | |
| 3276 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 3277 __ movb(Operand(rbx, rdi, times_1, 0), r8); | |
| 3278 break; | |
| 3279 case EXTERNAL_SHORT_ELEMENTS: | |
| 3280 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 3281 __ movw(Operand(rbx, rdi, times_2, 0), r8); | |
| 3282 break; | |
| 3283 case EXTERNAL_INT_ELEMENTS: | |
| 3284 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 3285 __ movl(Operand(rbx, rdi, times_4, 0), r8); | |
| 3286 break; | |
| 3287 case EXTERNAL_PIXEL_ELEMENTS: | |
| 3288 case EXTERNAL_FLOAT_ELEMENTS: | |
| 3289 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 3290 case FAST_ELEMENTS: | |
| 3291 case FAST_SMI_ELEMENTS: | |
| 3292 case FAST_DOUBLE_ELEMENTS: | |
| 3293 case FAST_HOLEY_ELEMENTS: | |
| 3294 case FAST_HOLEY_SMI_ELEMENTS: | |
| 3295 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
| 3296 case DICTIONARY_ELEMENTS: | |
| 3297 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
| 3298 UNREACHABLE(); | |
| 3299 break; | |
| 3300 } | |
| 3301 __ ret(0); | |
| 3302 } | |
| 3303 } | |
| 3304 | |
| 3305 // Slow case: call runtime. | |
| 3306 __ bind(&slow); | |
| 3307 | |
| 3308 // ----------- S t a t e ------------- | |
| 3309 // -- rax : value | |
| 3310 // -- rcx : key | |
| 3311 // -- rdx : receiver | |
| 3312 // -- rsp[0] : return address | |
| 3313 // ----------------------------------- | |
| 3314 | |
| 3315 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
| 3316 __ jmp(ic, RelocInfo::CODE_TARGET); | |
| 3317 | |
| 3318 // Miss case: call runtime. | |
| 3319 __ bind(&miss_force_generic); | |
| 3320 | |
| 3321 // ----------- S t a t e ------------- | |
| 3322 // -- rax : value | |
| 3323 // -- rcx : key | |
| 3324 // -- rdx : receiver | |
| 3325 // -- rsp[0] : return address | |
| 3326 // ----------------------------------- | |
| 3327 | |
| 3328 Handle<Code> miss_ic = | |
| 3329 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
| 3330 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
| 3331 } | |
| 3332 | |
| 3333 | |
| 3334 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3152 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
| 3335 MacroAssembler* masm, | 3153 MacroAssembler* masm, |
| 3336 bool is_js_array, | 3154 bool is_js_array, |
| 3337 ElementsKind elements_kind, | 3155 ElementsKind elements_kind, |
| 3338 KeyedAccessStoreMode store_mode) { | 3156 KeyedAccessStoreMode store_mode) { |
| 3339 // ----------- S t a t e ------------- | 3157 // ----------- S t a t e ------------- |
| 3340 // -- rax : value | 3158 // -- rax : value |
| 3341 // -- rcx : key | 3159 // -- rcx : key |
| 3342 // -- rdx : receiver | 3160 // -- rdx : receiver |
| 3343 // -- rsp[0] : return address | 3161 // -- rsp[0] : return address |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3606 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3424 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 3607 } | 3425 } |
| 3608 } | 3426 } |
| 3609 | 3427 |
| 3610 | 3428 |
| 3611 #undef __ | 3429 #undef __ |
| 3612 | 3430 |
| 3613 } } // namespace v8::internal | 3431 } } // namespace v8::internal |
| 3614 | 3432 |
| 3615 #endif // V8_TARGET_ARCH_X64 | 3433 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |