OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 2695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2706 // Handle store cache miss. | 2706 // Handle store cache miss. |
2707 __ bind(&miss); | 2707 __ bind(&miss); |
2708 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | 2708 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); |
2709 __ jmp(ic, RelocInfo::CODE_TARGET); | 2709 __ jmp(ic, RelocInfo::CODE_TARGET); |
2710 | 2710 |
2711 // Return the generated code. | 2711 // Return the generated code. |
2712 return GetCode(NORMAL, NULL); | 2712 return GetCode(NORMAL, NULL); |
2713 } | 2713 } |
2714 | 2714 |
2715 | 2715 |
2716 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray( | |
2717 JSObject* receiver) { | |
2718 // ----------- S t a t e ------------- | |
2719 // -- eax : value | |
2720 // -- ecx : key | |
2721 // -- edx : receiver | |
2722 // -- esp[0] : return address | |
2723 // ----------------------------------- | |
2724 Label miss; | |
2725 | |
2726 // Check that the map matches. | |
2727 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false); | |
2728 | |
2729 // Do the load. | |
2730 GenerateFastPixelArrayStore(masm(), | |
2731 edx, | |
2732 ecx, | |
2733 eax, | |
2734 edi, | |
2735 ebx, | |
2736 true, | |
2737 &miss, | |
2738 &miss, | |
2739 NULL, | |
2740 &miss); | |
2741 | |
2742 // Handle store cache miss. | |
2743 __ bind(&miss); | |
2744 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); | |
2745 __ jmp(ic, RelocInfo::CODE_TARGET); | |
2746 | |
2747 // Return the generated code. | |
2748 return GetCode(NORMAL, NULL); | |
2749 } | |
2750 | |
2751 | |
2752 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2716 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
2753 JSObject* object, | 2717 JSObject* object, |
2754 JSObject* last) { | 2718 JSObject* last) { |
2755 // ----------- S t a t e ------------- | 2719 // ----------- S t a t e ------------- |
2756 // -- eax : receiver | 2720 // -- eax : receiver |
2757 // -- ecx : name | 2721 // -- ecx : name |
2758 // -- esp[0] : return address | 2722 // -- esp[0] : return address |
2759 // ----------------------------------- | 2723 // ----------------------------------- |
2760 Label miss; | 2724 Label miss; |
2761 | 2725 |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3188 __ ret(0); | 3152 __ ret(0); |
3189 | 3153 |
3190 __ bind(&miss); | 3154 __ bind(&miss); |
3191 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3155 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3192 | 3156 |
3193 // Return the generated code. | 3157 // Return the generated code. |
3194 return GetCode(NORMAL, NULL); | 3158 return GetCode(NORMAL, NULL); |
3195 } | 3159 } |
3196 | 3160 |
3197 | 3161 |
3198 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) { | |
3199 // ----------- S t a t e ------------- | |
3200 // -- eax : key | |
3201 // -- edx : receiver | |
3202 // -- esp[0] : return address | |
3203 // ----------------------------------- | |
3204 Label miss; | |
3205 | |
3206 // Check that the map matches. | |
3207 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false); | |
3208 | |
3209 GenerateFastPixelArrayLoad(masm(), | |
3210 edx, | |
3211 eax, | |
3212 ecx, | |
3213 ebx, | |
3214 eax, | |
3215 &miss, | |
3216 &miss, | |
3217 &miss); | |
3218 | |
3219 // Handle load cache miss. | |
3220 __ bind(&miss); | |
3221 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss)); | |
3222 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3223 | |
3224 // Return the generated code. | |
3225 return GetCode(NORMAL, NULL); | |
3226 } | |
3227 | |
3228 | |
3229 // Specialized stub for constructing objects from functions which only have only | 3162 // Specialized stub for constructing objects from functions which only have only |
3230 // simple assignments of the form this.x = ...; in their body. | 3163 // simple assignments of the form this.x = ...; in their body. |
3231 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3164 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3232 // ----------- S t a t e ------------- | 3165 // ----------- S t a t e ------------- |
3233 // -- eax : argc | 3166 // -- eax : argc |
3234 // -- edi : constructor | 3167 // -- edi : constructor |
3235 // -- esp[0] : return address | 3168 // -- esp[0] : return address |
3236 // -- esp[4] : last argument | 3169 // -- esp[4] : last argument |
3237 // ----------------------------------- | 3170 // ----------------------------------- |
3238 Label generic_stub_call; | 3171 Label generic_stub_call; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3358 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); | 3291 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); |
3359 Handle<Code> generic_construct_stub(code); | 3292 Handle<Code> generic_construct_stub(code); |
3360 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3293 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
3361 | 3294 |
3362 // Return the generated code. | 3295 // Return the generated code. |
3363 return GetCode(); | 3296 return GetCode(); |
3364 } | 3297 } |
3365 | 3298 |
3366 | 3299 |
3367 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3300 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3368 ExternalArrayType array_type, Code::Flags flags) { | 3301 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { |
3369 // ----------- S t a t e ------------- | 3302 // ----------- S t a t e ------------- |
3370 // -- eax : key | 3303 // -- eax : key |
3371 // -- edx : receiver | 3304 // -- edx : receiver |
3372 // -- esp[0] : return address | 3305 // -- esp[0] : return address |
3373 // ----------------------------------- | 3306 // ----------------------------------- |
3374 Label slow, failed_allocation; | 3307 Label slow, failed_allocation; |
3375 | 3308 |
3376 // Check that the object isn't a smi. | 3309 // Check that the object isn't a smi. |
3377 __ test(edx, Immediate(kSmiTagMask)); | 3310 __ test(edx, Immediate(kSmiTagMask)); |
3378 __ j(zero, &slow, not_taken); | 3311 __ j(zero, &slow, not_taken); |
3379 | 3312 |
3380 // Check that the key is a smi. | 3313 // Check that the key is a smi. |
3381 __ test(eax, Immediate(kSmiTagMask)); | 3314 __ test(eax, Immediate(kSmiTagMask)); |
3382 __ j(not_zero, &slow, not_taken); | 3315 __ j(not_zero, &slow, not_taken); |
3383 | 3316 |
3384 // Get the map of the receiver. | 3317 // Check that the map matches. |
3385 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 3318 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
3386 // Check that the receiver does not require access checks. We need | |
3387 // to check this explicitly since this generic stub does not perform | |
3388 // map checks. | |
3389 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | |
3390 1 << Map::kIsAccessCheckNeeded); | |
3391 __ j(not_zero, &slow, not_taken); | |
3392 | |
3393 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); | |
3394 __ j(not_equal, &slow, not_taken); | |
3395 | |
3396 // Check that the elements array is the appropriate type of | |
3397 // ExternalArray. | |
3398 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3319 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3399 Handle<Map> map(Heap::MapForExternalArrayType(array_type)); | |
3400 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), | |
3401 Immediate(map)); | |
3402 __ j(not_equal, &slow, not_taken); | |
3403 | 3320 |
3404 // eax: key, known to be a smi. | 3321 // eax: key, known to be a smi. |
3405 // edx: receiver, known to be a JSObject. | 3322 // edx: receiver, known to be a JSObject. |
3406 // ebx: elements object, known to be an external array. | 3323 // ebx: elements object, known to be an external array. |
3407 // Check that the index is in range. | 3324 // Check that the index is in range. |
3408 __ mov(ecx, eax); | 3325 __ mov(ecx, eax); |
3409 __ SmiUntag(ecx); // Untag the index. | 3326 __ SmiUntag(ecx); // Untag the index. |
3410 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); | 3327 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
3411 // Unsigned comparison catches both negative and too-large values. | 3328 // Unsigned comparison catches both negative and too-large values. |
3412 __ j(above_equal, &slow); | 3329 __ j(above_equal, &slow); |
3413 | |
3414 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | 3330 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
3415 // ebx: base pointer of external storage | 3331 // ebx: base pointer of external storage |
3416 switch (array_type) { | 3332 switch (array_type) { |
3417 case kExternalByteArray: | 3333 case kExternalByteArray: |
3418 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); | 3334 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); |
3419 break; | 3335 break; |
3420 case kExternalUnsignedByteArray: | 3336 case kExternalUnsignedByteArray: |
3421 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); | 3337 case kExternalPixelArray: |
| 3338 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); |
3422 break; | 3339 break; |
3423 case kExternalShortArray: | 3340 case kExternalShortArray: |
3424 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); | 3341 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0)); |
3425 break; | 3342 break; |
3426 case kExternalUnsignedShortArray: | 3343 case kExternalUnsignedShortArray: |
3427 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); | 3344 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0)); |
3428 break; | 3345 break; |
3429 case kExternalIntArray: | 3346 case kExternalIntArray: |
3430 case kExternalUnsignedIntArray: | 3347 case kExternalUnsignedIntArray: |
3431 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); | 3348 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); |
3432 break; | 3349 break; |
3433 case kExternalFloatArray: | 3350 case kExternalFloatArray: |
3434 __ fld_s(Operand(ebx, ecx, times_4, 0)); | 3351 __ fld_s(Operand(ebx, ecx, times_4, 0)); |
3435 break; | 3352 break; |
3436 default: | 3353 default: |
3437 UNREACHABLE(); | 3354 UNREACHABLE(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3492 __ ret(0); | 3409 __ ret(0); |
3493 } else if (array_type == kExternalFloatArray) { | 3410 } else if (array_type == kExternalFloatArray) { |
3494 // For the floating-point array type, we need to always allocate a | 3411 // For the floating-point array type, we need to always allocate a |
3495 // HeapNumber. | 3412 // HeapNumber. |
3496 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); | 3413 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
3497 // Set the value. | 3414 // Set the value. |
3498 __ mov(eax, ecx); | 3415 __ mov(eax, ecx); |
3499 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3416 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3500 __ ret(0); | 3417 __ ret(0); |
3501 } else { | 3418 } else { |
3502 __ mov(eax, ecx); | |
3503 __ SmiTag(eax); | 3419 __ SmiTag(eax); |
3504 __ ret(0); | 3420 __ ret(0); |
3505 } | 3421 } |
3506 | 3422 |
3507 // If we fail allocation of the HeapNumber, we still have a value on | 3423 // If we fail allocation of the HeapNumber, we still have a value on |
3508 // top of the FPU stack. Remove it. | 3424 // top of the FPU stack. Remove it. |
3509 __ bind(&failed_allocation); | 3425 __ bind(&failed_allocation); |
3510 __ ffree(); | 3426 __ ffree(); |
3511 __ fincstp(); | 3427 __ fincstp(); |
3512 // Fall through to slow case. | 3428 // Fall through to slow case. |
(...skipping 14 matching lines...) Expand all Loading... |
3527 | 3443 |
3528 // Perform tail call to the entry. | 3444 // Perform tail call to the entry. |
3529 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3445 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
3530 | 3446 |
3531 // Return the generated code. | 3447 // Return the generated code. |
3532 return GetCode(flags); | 3448 return GetCode(flags); |
3533 } | 3449 } |
3534 | 3450 |
3535 | 3451 |
3536 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( | 3452 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
3537 ExternalArrayType array_type, Code::Flags flags) { | 3453 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { |
3538 // ----------- S t a t e ------------- | 3454 // ----------- S t a t e ------------- |
3539 // -- eax : value | 3455 // -- eax : value |
3540 // -- ecx : key | 3456 // -- ecx : key |
3541 // -- edx : receiver | 3457 // -- edx : receiver |
3542 // -- esp[0] : return address | 3458 // -- esp[0] : return address |
3543 // ----------------------------------- | 3459 // ----------------------------------- |
3544 Label slow, check_heap_number; | 3460 Label slow, check_heap_number; |
3545 | 3461 |
3546 // Check that the object isn't a smi. | 3462 // Check that the object isn't a smi. |
3547 __ test(edx, Immediate(kSmiTagMask)); | 3463 __ test(edx, Immediate(kSmiTagMask)); |
3548 __ j(zero, &slow); | 3464 __ j(zero, &slow); |
3549 // Get the map from the receiver. | 3465 |
3550 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 3466 // Check that the map matches. |
3551 // Check that the receiver does not require access checks. We need | 3467 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false); |
3552 // to do this because this generic stub does not perform map checks. | 3468 |
3553 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), | |
3554 1 << Map::kIsAccessCheckNeeded); | |
3555 __ j(not_zero, &slow); | |
3556 // Check that the key is a smi. | 3469 // Check that the key is a smi. |
3557 __ test(ecx, Immediate(kSmiTagMask)); | 3470 __ test(ecx, Immediate(kSmiTagMask)); |
3558 __ j(not_zero, &slow); | 3471 __ j(not_zero, &slow); |
3559 // Get the instance type from the map of the receiver. | |
3560 __ CmpInstanceType(edi, JS_OBJECT_TYPE); | |
3561 __ j(not_equal, &slow); | |
3562 | |
3563 // Check that the elements array is the appropriate type of | |
3564 // ExternalArray. | |
3565 // eax: value | |
3566 // edx: receiver, a JSObject | |
3567 // ecx: key, a smi | |
3568 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
3569 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)), | |
3570 &slow, true); | |
3571 | 3472 |
3572 // Check that the index is in range. | 3473 // Check that the index is in range. |
| 3474 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
3573 __ mov(ebx, ecx); | 3475 __ mov(ebx, ecx); |
3574 __ SmiUntag(ebx); | 3476 __ SmiUntag(ebx); |
3575 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); | 3477 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); |
3576 // Unsigned comparison catches both negative and too-large values. | 3478 // Unsigned comparison catches both negative and too-large values. |
3577 __ j(above_equal, &slow); | 3479 __ j(above_equal, &slow); |
3578 | 3480 |
3579 // Handle both smis and HeapNumbers in the fast path. Go to the | 3481 // Handle both smis and HeapNumbers in the fast path. Go to the |
3580 // runtime for all other kinds of values. | 3482 // runtime for all other kinds of values. |
3581 // eax: value | 3483 // eax: value |
3582 // edx: receiver | 3484 // edx: receiver |
3583 // ecx: key | 3485 // ecx: key |
3584 // edi: elements array | 3486 // edi: elements array |
3585 // ebx: untagged index | 3487 // ebx: untagged index |
3586 __ test(eax, Immediate(kSmiTagMask)); | 3488 __ test(eax, Immediate(kSmiTagMask)); |
3587 __ j(not_equal, &check_heap_number); | 3489 if (array_type == kExternalPixelArray) |
| 3490 __ j(not_equal, &slow); |
| 3491 else |
| 3492 __ j(not_equal, &check_heap_number); |
| 3493 |
3588 // smi case | 3494 // smi case |
3589 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. | 3495 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
3590 __ SmiUntag(ecx); | 3496 __ SmiUntag(ecx); |
3591 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3497 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3592 // ecx: base pointer of external storage | 3498 // ecx: base pointer of external storage |
3593 switch (array_type) { | 3499 switch (array_type) { |
| 3500 case kExternalPixelArray: |
| 3501 { // Clamp the value to [0..255]. |
| 3502 NearLabel done; |
| 3503 __ test(ecx, Immediate(0xFFFFFF00)); |
| 3504 __ j(zero, &done); |
| 3505 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
| 3506 __ dec_b(ecx); // 0 if negative, 255 if positive. |
| 3507 __ bind(&done); |
| 3508 } |
| 3509 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3510 break; |
3594 case kExternalByteArray: | 3511 case kExternalByteArray: |
3595 case kExternalUnsignedByteArray: | 3512 case kExternalUnsignedByteArray: |
3596 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3513 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3597 break; | 3514 break; |
3598 case kExternalShortArray: | 3515 case kExternalShortArray: |
3599 case kExternalUnsignedShortArray: | 3516 case kExternalUnsignedShortArray: |
3600 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3517 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3601 break; | 3518 break; |
3602 case kExternalIntArray: | 3519 case kExternalIntArray: |
3603 case kExternalUnsignedIntArray: | 3520 case kExternalUnsignedIntArray: |
3604 __ mov(Operand(edi, ebx, times_4, 0), ecx); | 3521 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
3605 break; | 3522 break; |
3606 case kExternalFloatArray: | 3523 case kExternalFloatArray: |
3607 // Need to perform int-to-float conversion. | 3524 // Need to perform int-to-float conversion. |
3608 __ push(ecx); | 3525 __ push(ecx); |
3609 __ fild_s(Operand(esp, 0)); | 3526 __ fild_s(Operand(esp, 0)); |
3610 __ pop(ecx); | 3527 __ pop(ecx); |
3611 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3528 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3612 break; | 3529 break; |
3613 default: | 3530 default: |
3614 UNREACHABLE(); | 3531 UNREACHABLE(); |
3615 break; | 3532 break; |
3616 } | 3533 } |
3617 __ ret(0); // Return the original value. | 3534 __ ret(0); // Return the original value. |
3618 | 3535 |
3619 __ bind(&check_heap_number); | 3536 // TODO(danno): handle heap number -> pixel array conversion |
3620 // eax: value | 3537 if (array_type != kExternalPixelArray) { |
3621 // edx: receiver | 3538 __ bind(&check_heap_number); |
3622 // ecx: key | 3539 // eax: value |
3623 // edi: elements array | 3540 // edx: receiver |
3624 // ebx: untagged index | 3541 // ecx: key |
3625 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3542 // edi: elements array |
3626 Immediate(Factory::heap_number_map())); | 3543 // ebx: untagged index |
3627 __ j(not_equal, &slow); | 3544 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
| 3545 Immediate(Factory::heap_number_map())); |
| 3546 __ j(not_equal, &slow); |
3628 | 3547 |
3629 // The WebGL specification leaves the behavior of storing NaN and | 3548 // The WebGL specification leaves the behavior of storing NaN and |
3630 // +/-Infinity into integer arrays basically undefined. For more | 3549 // +/-Infinity into integer arrays basically undefined. For more |
3631 // reproducible behavior, convert these to zero. | 3550 // reproducible behavior, convert these to zero. |
3632 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3551 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3633 // ebx: untagged index | 3552 // ebx: untagged index |
3634 // edi: base pointer of external storage | 3553 // edi: base pointer of external storage |
3635 if (array_type == kExternalFloatArray) { | 3554 if (array_type == kExternalFloatArray) { |
3636 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3555 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3637 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3556 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3638 __ ret(0); | 3557 __ ret(0); |
3639 } else { | 3558 } else { |
3640 // Perform float-to-int conversion with truncation (round-to-zero) | 3559 // Perform float-to-int conversion with truncation (round-to-zero) |
3641 // behavior. | 3560 // behavior. |
3642 | 3561 |
3643 // For the moment we make the slow call to the runtime on | 3562 // For the moment we make the slow call to the runtime on |
3644 // processors that don't support SSE2. The code in IntegerConvert | 3563 // processors that don't support SSE2. The code in IntegerConvert |
3645 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3564 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3646 // conversion failure case does not need to be handled. | 3565 // conversion failure case does not need to be handled. |
3647 if (CpuFeatures::IsSupported(SSE2)) { | 3566 if (CpuFeatures::IsSupported(SSE2)) { |
3648 if (array_type != kExternalIntArray && | 3567 if (array_type != kExternalIntArray && |
3649 array_type != kExternalUnsignedIntArray) { | 3568 array_type != kExternalUnsignedIntArray) { |
3650 ASSERT(CpuFeatures::IsSupported(SSE2)); | |
3651 CpuFeatures::Scope scope(SSE2); | |
3652 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | |
3653 // ecx: untagged integer value | |
3654 switch (array_type) { | |
3655 case kExternalByteArray: | |
3656 case kExternalUnsignedByteArray: | |
3657 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | |
3658 break; | |
3659 case kExternalShortArray: | |
3660 case kExternalUnsignedShortArray: | |
3661 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | |
3662 break; | |
3663 default: | |
3664 UNREACHABLE(); | |
3665 break; | |
3666 } | |
3667 } else { | |
3668 if (CpuFeatures::IsSupported(SSE3)) { | |
3669 CpuFeatures::Scope scope(SSE3); | |
3670 // fisttp stores values as signed integers. To represent the | |
3671 // entire range of int and unsigned int arrays, store as a | |
3672 // 64-bit int and discard the high 32 bits. | |
3673 // If the value is NaN or +/-infinity, the result is 0x80000000, | |
3674 // which is automatically zero when taken mod 2^n, n < 32. | |
3675 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
3676 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | |
3677 __ fisttp_d(Operand(esp, 0)); | |
3678 __ pop(ecx); | |
3679 __ add(Operand(esp), Immediate(kPointerSize)); | |
3680 } else { | |
3681 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3569 ASSERT(CpuFeatures::IsSupported(SSE2)); |
3682 CpuFeatures::Scope scope(SSE2); | 3570 CpuFeatures::Scope scope(SSE2); |
3683 // We can easily implement the correct rounding behavior for the | 3571 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3684 // range [0, 2^31-1]. For the time being, to keep this code simple, | 3572 // ecx: untagged integer value |
3685 // make the slow runtime call for values outside this range. | 3573 switch (array_type) { |
3686 // Note: we could do better for signed int arrays. | 3574 case kExternalPixelArray: |
3687 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); | 3575 { // Clamp the value to [0..255]. |
3688 // We will need the key if we have to make the slow runtime call. | 3576 NearLabel done; |
3689 __ push(ecx); | 3577 __ test(ecx, Immediate(0xFFFFFF00)); |
3690 __ LoadPowerOf2(xmm1, ecx, 31); | 3578 __ j(zero, &done); |
3691 __ pop(ecx); | 3579 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3692 __ ucomisd(xmm1, xmm0); | 3580 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3693 __ j(above_equal, &slow); | 3581 __ bind(&done); |
3694 __ cvttsd2si(ecx, Operand(xmm0)); | 3582 } |
| 3583 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3584 case kExternalByteArray: |
| 3585 case kExternalUnsignedByteArray: |
| 3586 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
| 3587 break; |
| 3588 case kExternalShortArray: |
| 3589 case kExternalUnsignedShortArray: |
| 3590 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
| 3591 break; |
| 3592 default: |
| 3593 UNREACHABLE(); |
| 3594 break; |
| 3595 } |
| 3596 } else { |
| 3597 if (CpuFeatures::IsSupported(SSE3)) { |
| 3598 CpuFeatures::Scope scope(SSE3); |
| 3599 // fisttp stores values as signed integers. To represent the |
| 3600 // entire range of int and unsigned int arrays, store as a |
| 3601 // 64-bit int and discard the high 32 bits. |
| 3602 // If the value is NaN or +/-infinity, the result is 0x80000000, |
| 3603 // which is automatically zero when taken mod 2^n, n < 32. |
| 3604 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3605 __ sub(Operand(esp), Immediate(2 * kPointerSize)); |
| 3606 __ fisttp_d(Operand(esp, 0)); |
| 3607 __ pop(ecx); |
| 3608 __ add(Operand(esp), Immediate(kPointerSize)); |
| 3609 } else { |
| 3610 ASSERT(CpuFeatures::IsSupported(SSE2)); |
| 3611 CpuFeatures::Scope scope(SSE2); |
| 3612 // We can easily implement the correct rounding behavior for the |
| 3613 // range [0, 2^31-1]. For the time being, to keep this code simple, |
| 3614 // make the slow runtime call for values outside this range. |
| 3615 // Note: we could do better for signed int arrays. |
| 3616 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 3617 // We will need the key if we have to make the slow runtime call. |
| 3618 __ push(ecx); |
| 3619 __ LoadPowerOf2(xmm1, ecx, 31); |
| 3620 __ pop(ecx); |
| 3621 __ ucomisd(xmm1, xmm0); |
| 3622 __ j(above_equal, &slow); |
| 3623 __ cvttsd2si(ecx, Operand(xmm0)); |
| 3624 } |
| 3625 // ecx: untagged integer value |
| 3626 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
3695 } | 3627 } |
3696 // ecx: untagged integer value | 3628 __ ret(0); // Return original value. |
3697 __ mov(Operand(edi, ebx, times_4, 0), ecx); | |
3698 } | 3629 } |
3699 __ ret(0); // Return original value. | |
3700 } | 3630 } |
3701 } | 3631 } |
3702 | 3632 |
3703 // Slow case: call runtime. | 3633 // Slow case: call runtime. |
3704 __ bind(&slow); | 3634 __ bind(&slow); |
3705 // ----------- S t a t e ------------- | 3635 // ----------- S t a t e ------------- |
3706 // -- eax : value | 3636 // -- eax : value |
3707 // -- ecx : key | 3637 // -- ecx : key |
3708 // -- edx : receiver | 3638 // -- edx : receiver |
3709 // -- esp[0] : return address | 3639 // -- esp[0] : return address |
(...skipping 13 matching lines...) Expand all Loading... |
3723 | 3653 |
3724 return GetCode(flags); | 3654 return GetCode(flags); |
3725 } | 3655 } |
3726 | 3656 |
3727 | 3657 |
3728 #undef __ | 3658 #undef __ |
3729 | 3659 |
3730 } } // namespace v8::internal | 3660 } } // namespace v8::internal |
3731 | 3661 |
3732 #endif // V8_TARGET_ARCH_IA32 | 3662 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |