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 |