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