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