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 2861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2872 | 2872 |
2873 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 2873 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
2874 Handle<Map> receiver_map) { | 2874 Handle<Map> receiver_map) { |
2875 // ----------- S t a t e ------------- | 2875 // ----------- S t a t e ------------- |
2876 // -- eax : value | 2876 // -- eax : value |
2877 // -- ecx : key | 2877 // -- ecx : key |
2878 // -- edx : receiver | 2878 // -- edx : receiver |
2879 // -- esp[0] : return address | 2879 // -- esp[0] : return address |
2880 // ----------------------------------- | 2880 // ----------------------------------- |
2881 ElementsKind elements_kind = receiver_map->elements_kind(); | 2881 ElementsKind elements_kind = receiver_map->elements_kind(); |
2882 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2882 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
2883 Handle<Code> stub = | 2883 if ((receiver_map->has_fast_elements() || |
2884 KeyedStoreElementStub(is_jsarray, | 2884 receiver_map->has_external_array_elements())) { |
2885 elements_kind, | 2885 Handle<Code> stub = KeyedStoreFastElementStub( |
2886 store_mode_).GetCode(isolate()); | 2886 is_js_array, |
2887 | 2887 elements_kind, |
2888 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 2888 store_mode_).GetCode(isolate()); |
2889 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | |
2890 } else { | |
2891 Handle<Code> stub = | |
2892 KeyedStoreElementStub(is_js_array, elements_kind, | |
2893 store_mode_).GetCode(isolate()); | |
2894 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | |
2895 } | |
2889 | 2896 |
2890 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2897 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2891 __ jmp(ic, RelocInfo::CODE_TARGET); | 2898 __ jmp(ic, RelocInfo::CODE_TARGET); |
2892 | 2899 |
2893 // Return the generated code. | 2900 // Return the generated code. |
2894 return GetCode(Code::NORMAL, factory()->empty_string()); | 2901 return GetCode(Code::NORMAL, factory()->empty_string()); |
2895 } | 2902 } |
2896 | 2903 |
2897 | 2904 |
2898 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2905 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3328 __ j(sign, fail); | 3335 __ j(sign, fail); |
3329 __ SmiTag(scratch); | 3336 __ SmiTag(scratch); |
3330 __ mov(key, scratch); | 3337 __ mov(key, scratch); |
3331 __ bind(&key_ok); | 3338 __ bind(&key_ok); |
3332 } else { | 3339 } else { |
3333 __ JumpIfNotSmi(key, fail); | 3340 __ JumpIfNotSmi(key, fail); |
3334 } | 3341 } |
3335 } | 3342 } |
3336 | 3343 |
3337 | 3344 |
3338 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | |
Jakob Kummerow
2013/03/11 16:36:07
Love this change! :-)
| |
3339 MacroAssembler* masm, | |
3340 ElementsKind elements_kind) { | |
3341 // ----------- S t a t e ------------- | |
3342 // -- eax : value | |
3343 // -- ecx : key | |
3344 // -- edx : receiver | |
3345 // -- esp[0] : return address | |
3346 // ----------------------------------- | |
3347 Label miss_force_generic, slow, check_heap_number; | |
3348 | |
3349 // This stub is meant to be tail-jumped to, the receiver must already | |
3350 // have been verified by the caller to not be a smi. | |
3351 | |
3352 // Check that the key is a smi or a heap number convertible to a smi. | |
3353 GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); | |
3354 | |
3355 // Check that the index is in range. | |
3356 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
3357 __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); | |
3358 // Unsigned comparison catches both negative and too-large values. | |
3359 __ j(above_equal, &slow); | |
3360 | |
3361 // Handle both smis and HeapNumbers in the fast path. Go to the | |
3362 // runtime for all other kinds of values. | |
3363 // eax: value | |
3364 // edx: receiver | |
3365 // ecx: key | |
3366 // edi: elements array | |
3367 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { | |
3368 __ JumpIfNotSmi(eax, &slow); | |
3369 } else { | |
3370 __ JumpIfNotSmi(eax, &check_heap_number); | |
3371 } | |
3372 | |
3373 // smi case | |
3374 __ mov(ebx, eax); // Preserve the value in eax as the return value. | |
3375 __ SmiUntag(ebx); | |
3376 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | |
3377 // edi: base pointer of external storage | |
3378 switch (elements_kind) { | |
3379 case EXTERNAL_PIXEL_ELEMENTS: | |
3380 __ ClampUint8(ebx); | |
3381 __ SmiUntag(ecx); | |
3382 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
3383 break; | |
3384 case EXTERNAL_BYTE_ELEMENTS: | |
3385 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3386 __ SmiUntag(ecx); | |
3387 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
3388 break; | |
3389 case EXTERNAL_SHORT_ELEMENTS: | |
3390 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3391 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); | |
3392 break; | |
3393 case EXTERNAL_INT_ELEMENTS: | |
3394 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3395 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
3396 break; | |
3397 case EXTERNAL_FLOAT_ELEMENTS: | |
3398 case EXTERNAL_DOUBLE_ELEMENTS: | |
3399 // Need to perform int-to-float conversion. | |
3400 __ push(ebx); | |
3401 __ fild_s(Operand(esp, 0)); | |
3402 __ pop(ebx); | |
3403 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3404 __ fstp_s(Operand(edi, ecx, times_2, 0)); | |
3405 } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS. | |
3406 __ fstp_d(Operand(edi, ecx, times_4, 0)); | |
3407 } | |
3408 break; | |
3409 default: | |
3410 UNREACHABLE(); | |
3411 break; | |
3412 } | |
3413 __ ret(0); // Return the original value. | |
3414 | |
3415 // TODO(danno): handle heap number -> pixel array conversion | |
3416 if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { | |
3417 __ bind(&check_heap_number); | |
3418 // eax: value | |
3419 // edx: receiver | |
3420 // ecx: key | |
3421 // edi: elements array | |
3422 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | |
3423 Immediate(masm->isolate()->factory()->heap_number_map())); | |
3424 __ j(not_equal, &slow); | |
3425 | |
3426 // The WebGL specification leaves the behavior of storing NaN and | |
3427 // +/-Infinity into integer arrays basically undefined. For more | |
3428 // reproducible behavior, convert these to zero. | |
3429 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | |
3430 // edi: base pointer of external storage | |
3431 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
3432 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3433 __ fstp_s(Operand(edi, ecx, times_2, 0)); | |
3434 __ ret(0); | |
3435 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
3436 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3437 __ fstp_d(Operand(edi, ecx, times_4, 0)); | |
3438 __ ret(0); | |
3439 } else { | |
3440 // Perform float-to-int conversion with truncation (round-to-zero) | |
3441 // behavior. | |
3442 | |
3443 // For the moment we make the slow call to the runtime on | |
3444 // processors that don't support SSE2. The code in IntegerConvert | |
3445 // (code-stubs-ia32.cc) is roughly what is needed here though the | |
3446 // conversion failure case does not need to be handled. | |
3447 if (CpuFeatures::IsSupported(SSE2)) { | |
3448 if ((elements_kind == EXTERNAL_INT_ELEMENTS || | |
3449 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) && | |
3450 CpuFeatures::IsSupported(SSE3)) { | |
3451 CpuFeatureScope scope(masm, SSE3); | |
3452 // fisttp stores values as signed integers. To represent the | |
3453 // entire range of int and unsigned int arrays, store as a | |
3454 // 64-bit int and discard the high 32 bits. | |
3455 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3456 __ sub(esp, Immediate(2 * kPointerSize)); | |
3457 __ fisttp_d(Operand(esp, 0)); | |
3458 | |
3459 // If conversion failed (NaN, infinity, or a number outside | |
3460 // signed int64 range), the result is 0x8000000000000000, and | |
3461 // we must handle this case in the runtime. | |
3462 Label ok; | |
3463 __ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u)); | |
3464 __ j(not_equal, &ok); | |
3465 __ cmp(Operand(esp, 0), Immediate(0)); | |
3466 __ j(not_equal, &ok); | |
3467 __ add(esp, Immediate(2 * kPointerSize)); // Restore the stack. | |
3468 __ jmp(&slow); | |
3469 | |
3470 __ bind(&ok); | |
3471 __ pop(ebx); | |
3472 __ add(esp, Immediate(kPointerSize)); | |
3473 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
3474 } else { | |
3475 ASSERT(CpuFeatures::IsSupported(SSE2)); | |
3476 CpuFeatureScope scope(masm, SSE2); | |
3477 __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); | |
3478 __ cmp(ebx, 0x80000000u); | |
3479 __ j(equal, &slow); | |
3480 // ebx: untagged integer value | |
3481 switch (elements_kind) { | |
3482 case EXTERNAL_PIXEL_ELEMENTS: | |
3483 __ ClampUint8(ebx); | |
3484 // Fall through. | |
3485 case EXTERNAL_BYTE_ELEMENTS: | |
3486 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
3487 __ SmiUntag(ecx); | |
3488 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
3489 break; | |
3490 case EXTERNAL_SHORT_ELEMENTS: | |
3491 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
3492 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); | |
3493 break; | |
3494 case EXTERNAL_INT_ELEMENTS: | |
3495 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
3496 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
3497 break; | |
3498 default: | |
3499 UNREACHABLE(); | |
3500 break; | |
3501 } | |
3502 } | |
3503 __ ret(0); // Return original value. | |
3504 } | |
3505 } | |
3506 } | |
3507 | |
3508 // Slow case: call runtime. | |
3509 __ bind(&slow); | |
3510 Counters* counters = masm->isolate()->counters(); | |
3511 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); | |
3512 | |
3513 // ----------- S t a t e ------------- | |
3514 // -- eax : value | |
3515 // -- ecx : key | |
3516 // -- edx : receiver | |
3517 // -- esp[0] : return address | |
3518 // ----------------------------------- | |
3519 | |
3520 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
3521 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3522 | |
3523 // ----------- S t a t e ------------- | |
3524 // -- eax : value | |
3525 // -- ecx : key | |
3526 // -- edx : receiver | |
3527 // -- esp[0] : return address | |
3528 // ----------------------------------- | |
3529 | |
3530 __ bind(&miss_force_generic); | |
3531 Handle<Code> miss_ic = | |
3532 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
3533 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
3534 } | |
3535 | |
3536 | |
3537 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3345 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
3538 MacroAssembler* masm, | 3346 MacroAssembler* masm, |
3539 bool is_js_array, | 3347 bool is_js_array, |
3540 ElementsKind elements_kind, | 3348 ElementsKind elements_kind, |
3541 KeyedAccessStoreMode store_mode) { | 3349 KeyedAccessStoreMode store_mode) { |
3542 // ----------- S t a t e ------------- | 3350 // ----------- S t a t e ------------- |
3543 // -- eax : value | 3351 // -- eax : value |
3544 // -- ecx : key | 3352 // -- ecx : key |
3545 // -- edx : receiver | 3353 // -- edx : receiver |
3546 // -- esp[0] : return address | 3354 // -- esp[0] : return address |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3826 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3634 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
3827 } | 3635 } |
3828 } | 3636 } |
3829 | 3637 |
3830 | 3638 |
3831 #undef __ | 3639 #undef __ |
3832 | 3640 |
3833 } } // namespace v8::internal | 3641 } } // namespace v8::internal |
3834 | 3642 |
3835 #endif // V8_TARGET_ARCH_IA32 | 3643 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |