Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: src/ia32/stub-cache-ia32.cc

Issue 6546036: Combine typed and pixel arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: final version Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-ia32.cc ('k') | src/ic.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/lithium-ia32.cc ('k') | src/ic.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698