OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2692 __ bind(&miss); | 2692 __ bind(&miss); |
2693 __ DecrementCounter(counters->keyed_store_field(), 1); | 2693 __ DecrementCounter(counters->keyed_store_field(), 1); |
2694 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2694 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2695 __ jmp(ic, RelocInfo::CODE_TARGET); | 2695 __ jmp(ic, RelocInfo::CODE_TARGET); |
2696 | 2696 |
2697 // Return the generated code. | 2697 // Return the generated code. |
2698 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2698 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2699 } | 2699 } |
2700 | 2700 |
2701 | 2701 |
2702 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( | 2702 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement( |
2703 Map* receiver_map) { | 2703 Map* receiver_map) { |
2704 // ----------- S t a t e ------------- | 2704 // ----------- S t a t e ------------- |
2705 // -- eax : value | 2705 // -- eax : value |
2706 // -- ecx : key | 2706 // -- ecx : key |
2707 // -- edx : receiver | 2707 // -- edx : receiver |
2708 // -- esp[0] : return address | 2708 // -- esp[0] : return address |
2709 // ----------------------------------- | 2709 // ----------------------------------- |
2710 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2710 MaybeObject* maybe_stub; |
2711 MaybeObject* maybe_stub = | 2711 if (receiver_map->has_fast_elements()) { |
2712 KeyedStoreFastElementStub(is_js_array).TryGetCode(); | 2712 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2713 maybe_stub = KeyedStoreFastElementStub(is_js_array).TryGetCode(); |
| 2714 } else { |
| 2715 ASSERT(receiver_map->has_external_array_elements()); |
| 2716 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2717 maybe_stub = KeyedStoreExternalArrayStub(elements_kind).TryGetCode(); |
| 2718 } |
2713 Code* stub; | 2719 Code* stub; |
2714 if (!maybe_stub->To(&stub)) return maybe_stub; | 2720 if (!maybe_stub->To(&stub)) return maybe_stub; |
2715 __ DispatchMap(edx, | 2721 __ DispatchMap(edx, |
2716 Handle<Map>(receiver_map), | 2722 Handle<Map>(receiver_map), |
2717 Handle<Code>(stub), | 2723 Handle<Code>(stub), |
2718 DO_SMI_CHECK); | 2724 DO_SMI_CHECK); |
2719 | 2725 |
2720 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2726 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2721 __ jmp(ic, RelocInfo::CODE_TARGET); | 2727 __ jmp(ic, RelocInfo::CODE_TARGET); |
2722 | 2728 |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3156 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); | 3162 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); |
3157 __ bind(&miss); | 3163 __ bind(&miss); |
3158 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3164 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
3159 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3165 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3160 | 3166 |
3161 // Return the generated code. | 3167 // Return the generated code. |
3162 return GetCode(CALLBACKS, name); | 3168 return GetCode(CALLBACKS, name); |
3163 } | 3169 } |
3164 | 3170 |
3165 | 3171 |
3166 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { | 3172 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) { |
3167 // ----------- S t a t e ------------- | 3173 // ----------- S t a t e ------------- |
3168 // -- eax : key | 3174 // -- eax : key |
3169 // -- edx : receiver | 3175 // -- edx : receiver |
3170 // -- esp[0] : return address | 3176 // -- esp[0] : return address |
3171 // ----------------------------------- | 3177 // ----------------------------------- |
3172 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); | 3178 MaybeObject* maybe_stub; |
| 3179 if (receiver_map->has_fast_elements()) { |
| 3180 maybe_stub = KeyedLoadFastElementStub().TryGetCode(); |
| 3181 } else { |
| 3182 ASSERT(receiver_map->has_external_array_elements()); |
| 3183 JSObject::ElementsKind elements_kind = receiver_map->elements_kind(); |
| 3184 maybe_stub = KeyedLoadExternalArrayStub(elements_kind).TryGetCode(); |
| 3185 } |
3173 Code* stub; | 3186 Code* stub; |
3174 if (!maybe_stub->To(&stub)) return maybe_stub; | 3187 if (!maybe_stub->To(&stub)) return maybe_stub; |
3175 __ DispatchMap(edx, | 3188 __ DispatchMap(edx, |
3176 Handle<Map>(receiver_map), | 3189 Handle<Map>(receiver_map), |
3177 Handle<Code>(stub), | 3190 Handle<Code>(stub), |
3178 DO_SMI_CHECK); | 3191 DO_SMI_CHECK); |
3179 | 3192 |
3180 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3193 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3181 | 3194 |
3182 // Return the generated code. | 3195 // Return the generated code. |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3344 __ bind(&generic_stub_call); | 3357 __ bind(&generic_stub_call); |
3345 Handle<Code> generic_construct_stub = | 3358 Handle<Code> generic_construct_stub = |
3346 isolate()->builtins()->JSConstructStubGeneric(); | 3359 isolate()->builtins()->JSConstructStubGeneric(); |
3347 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 3360 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
3348 | 3361 |
3349 // Return the generated code. | 3362 // Return the generated code. |
3350 return GetCode(); | 3363 return GetCode(); |
3351 } | 3364 } |
3352 | 3365 |
3353 | 3366 |
3354 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( | |
3355 JSObject*receiver, ExternalArrayType array_type) { | |
3356 // ----------- S t a t e ------------- | |
3357 // -- eax : key | |
3358 // -- edx : receiver | |
3359 // -- esp[0] : return address | |
3360 // ----------------------------------- | |
3361 MaybeObject* maybe_stub = | |
3362 KeyedLoadExternalArrayStub(array_type).TryGetCode(); | |
3363 Code* stub; | |
3364 if (!maybe_stub->To(&stub)) return maybe_stub; | |
3365 __ DispatchMap(edx, | |
3366 Handle<Map>(receiver->map()), | |
3367 Handle<Code>(stub), | |
3368 DO_SMI_CHECK); | |
3369 | |
3370 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); | |
3371 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3372 | |
3373 // Return the generated code. | |
3374 return GetCode(); | |
3375 } | |
3376 | |
3377 | |
3378 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore( | |
3379 JSObject* receiver, ExternalArrayType array_type) { | |
3380 // ----------- S t a t e ------------- | |
3381 // -- eax : value | |
3382 // -- ecx : key | |
3383 // -- edx : receiver | |
3384 // -- esp[0] : return address | |
3385 // ----------------------------------- | |
3386 MaybeObject* maybe_stub = | |
3387 KeyedStoreExternalArrayStub(array_type).TryGetCode(); | |
3388 Code* stub; | |
3389 if (!maybe_stub->To(&stub)) return maybe_stub; | |
3390 __ DispatchMap(edx, | |
3391 Handle<Map>(receiver->map()), | |
3392 Handle<Code>(stub), | |
3393 DO_SMI_CHECK); | |
3394 | |
3395 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | |
3396 __ jmp(ic, RelocInfo::CODE_TARGET); | |
3397 | |
3398 return GetCode(); | |
3399 } | |
3400 | |
3401 | |
3402 #undef __ | 3367 #undef __ |
3403 #define __ ACCESS_MASM(masm) | 3368 #define __ ACCESS_MASM(masm) |
3404 | 3369 |
3405 | 3370 |
3406 void KeyedLoadStubCompiler::GenerateLoadExternalArray( | 3371 void KeyedLoadStubCompiler::GenerateLoadExternalArray( |
3407 MacroAssembler* masm, | 3372 MacroAssembler* masm, |
3408 ExternalArrayType array_type) { | 3373 JSObject::ElementsKind elements_kind) { |
3409 // ----------- S t a t e ------------- | 3374 // ----------- S t a t e ------------- |
3410 // -- eax : key | 3375 // -- eax : key |
3411 // -- edx : receiver | 3376 // -- edx : receiver |
3412 // -- esp[0] : return address | 3377 // -- esp[0] : return address |
3413 // ----------------------------------- | 3378 // ----------------------------------- |
3414 Label miss_force_generic, failed_allocation, slow; | 3379 Label miss_force_generic, failed_allocation, slow; |
3415 | 3380 |
3416 // This stub is meant to be tail-jumped to, the receiver must already | 3381 // This stub is meant to be tail-jumped to, the receiver must already |
3417 // have been verified by the caller to not be a smi. | 3382 // have been verified by the caller to not be a smi. |
3418 | 3383 |
3419 // Check that the key is a smi. | 3384 // Check that the key is a smi. |
3420 __ test(eax, Immediate(kSmiTagMask)); | 3385 __ test(eax, Immediate(kSmiTagMask)); |
3421 __ j(not_zero, &miss_force_generic); | 3386 __ j(not_zero, &miss_force_generic); |
3422 | 3387 |
3423 // Check that the index is in range. | 3388 // Check that the index is in range. |
3424 __ mov(ecx, eax); | 3389 __ mov(ecx, eax); |
3425 __ SmiUntag(ecx); // Untag the index. | 3390 __ SmiUntag(ecx); // Untag the index. |
3426 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); | 3391 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
3427 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); | 3392 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); |
3428 // Unsigned comparison catches both negative and too-large values. | 3393 // Unsigned comparison catches both negative and too-large values. |
3429 __ j(above_equal, &miss_force_generic); | 3394 __ j(above_equal, &miss_force_generic); |
3430 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); | 3395 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); |
3431 // ebx: base pointer of external storage | 3396 // ebx: base pointer of external storage |
3432 switch (array_type) { | 3397 switch (elements_kind) { |
3433 case kExternalByteArray: | 3398 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
3434 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); | 3399 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); |
3435 break; | 3400 break; |
3436 case kExternalUnsignedByteArray: | 3401 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3437 case kExternalPixelArray: | 3402 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
3438 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); | 3403 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); |
3439 break; | 3404 break; |
3440 case kExternalShortArray: | 3405 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
3441 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0)); | 3406 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0)); |
3442 break; | 3407 break; |
3443 case kExternalUnsignedShortArray: | 3408 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3444 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0)); | 3409 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0)); |
3445 break; | 3410 break; |
3446 case kExternalIntArray: | 3411 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3447 case kExternalUnsignedIntArray: | 3412 case JSObject::EXTERNAL_INT_ELEMENTS: |
3448 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); | 3413 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); |
3449 break; | 3414 break; |
3450 case kExternalFloatArray: | 3415 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
3451 __ fld_s(Operand(ebx, ecx, times_4, 0)); | 3416 __ fld_s(Operand(ebx, ecx, times_4, 0)); |
3452 break; | 3417 break; |
3453 case kExternalDoubleArray: | 3418 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
3454 __ fld_d(Operand(ebx, ecx, times_8, 0)); | 3419 __ fld_d(Operand(ebx, ecx, times_8, 0)); |
3455 break; | 3420 break; |
3456 default: | 3421 default: |
3457 UNREACHABLE(); | 3422 UNREACHABLE(); |
3458 break; | 3423 break; |
3459 } | 3424 } |
3460 | 3425 |
3461 // For integer array types: | 3426 // For integer array types: |
3462 // ecx: value | 3427 // ecx: value |
3463 // For floating-point array type: | 3428 // For floating-point array type: |
3464 // FP(0): value | 3429 // FP(0): value |
3465 | 3430 |
3466 if (array_type == kExternalIntArray || | 3431 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS || |
3467 array_type == kExternalUnsignedIntArray) { | 3432 elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
3468 // For the Int and UnsignedInt array types, we need to see whether | 3433 // For the Int and UnsignedInt array types, we need to see whether |
3469 // the value can be represented in a Smi. If not, we need to convert | 3434 // the value can be represented in a Smi. If not, we need to convert |
3470 // it to a HeapNumber. | 3435 // it to a HeapNumber. |
3471 Label box_int; | 3436 Label box_int; |
3472 if (array_type == kExternalIntArray) { | 3437 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) { |
3473 __ cmp(ecx, 0xC0000000); | 3438 __ cmp(ecx, 0xC0000000); |
3474 __ j(sign, &box_int); | 3439 __ j(sign, &box_int); |
3475 } else { | 3440 } else { |
3476 ASSERT_EQ(array_type, kExternalUnsignedIntArray); | 3441 ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
3477 // The test is different for unsigned int values. Since we need | 3442 // The test is different for unsigned int values. Since we need |
3478 // the value to be in the range of a positive smi, we can't | 3443 // the value to be in the range of a positive smi, we can't |
3479 // handle either of the top two bits being set in the value. | 3444 // handle either of the top two bits being set in the value. |
3480 __ test(ecx, Immediate(0xC0000000)); | 3445 __ test(ecx, Immediate(0xC0000000)); |
3481 __ j(not_zero, &box_int); | 3446 __ j(not_zero, &box_int); |
3482 } | 3447 } |
3483 | 3448 |
3484 __ mov(eax, ecx); | 3449 __ mov(eax, ecx); |
3485 __ SmiTag(eax); | 3450 __ SmiTag(eax); |
3486 __ ret(0); | 3451 __ ret(0); |
3487 | 3452 |
3488 __ bind(&box_int); | 3453 __ bind(&box_int); |
3489 | 3454 |
3490 // Allocate a HeapNumber for the int and perform int-to-double | 3455 // Allocate a HeapNumber for the int and perform int-to-double |
3491 // conversion. | 3456 // conversion. |
3492 if (array_type == kExternalIntArray) { | 3457 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) { |
3493 __ push(ecx); | 3458 __ push(ecx); |
3494 __ fild_s(Operand(esp, 0)); | 3459 __ fild_s(Operand(esp, 0)); |
3495 __ pop(ecx); | 3460 __ pop(ecx); |
3496 } else { | 3461 } else { |
3497 ASSERT(array_type == kExternalUnsignedIntArray); | 3462 ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind); |
3498 // Need to zero-extend the value. | 3463 // Need to zero-extend the value. |
3499 // There's no fild variant for unsigned values, so zero-extend | 3464 // There's no fild variant for unsigned values, so zero-extend |
3500 // to a 64-bit int manually. | 3465 // to a 64-bit int manually. |
3501 __ push(Immediate(0)); | 3466 __ push(Immediate(0)); |
3502 __ push(ecx); | 3467 __ push(ecx); |
3503 __ fild_d(Operand(esp, 0)); | 3468 __ fild_d(Operand(esp, 0)); |
3504 __ pop(ecx); | 3469 __ pop(ecx); |
3505 __ pop(ecx); | 3470 __ pop(ecx); |
3506 } | 3471 } |
3507 // FP(0): value | 3472 // FP(0): value |
3508 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); | 3473 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
3509 // Set the value. | 3474 // Set the value. |
3510 __ mov(eax, ecx); | 3475 __ mov(eax, ecx); |
3511 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3476 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3512 __ ret(0); | 3477 __ ret(0); |
3513 } else if (array_type == kExternalFloatArray || | 3478 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS || |
3514 array_type == kExternalDoubleArray) { | 3479 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
3515 // For the floating-point array type, we need to always allocate a | 3480 // For the floating-point array type, we need to always allocate a |
3516 // HeapNumber. | 3481 // HeapNumber. |
3517 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); | 3482 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); |
3518 // Set the value. | 3483 // Set the value. |
3519 __ mov(eax, ecx); | 3484 __ mov(eax, ecx); |
3520 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3485 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3521 __ ret(0); | 3486 __ ret(0); |
3522 } else { | 3487 } else { |
3523 __ SmiTag(eax); | 3488 __ SmiTag(eax); |
3524 __ ret(0); | 3489 __ ret(0); |
(...skipping 29 matching lines...) Expand all Loading... |
3554 // Miss case: Jump to runtime. | 3519 // Miss case: Jump to runtime. |
3555 __ bind(&miss_force_generic); | 3520 __ bind(&miss_force_generic); |
3556 Handle<Code> miss_ic = | 3521 Handle<Code> miss_ic = |
3557 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 3522 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
3558 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3523 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3559 } | 3524 } |
3560 | 3525 |
3561 | 3526 |
3562 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | 3527 void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
3563 MacroAssembler* masm, | 3528 MacroAssembler* masm, |
3564 ExternalArrayType array_type) { | 3529 JSObject::ElementsKind elements_kind) { |
3565 // ----------- S t a t e ------------- | 3530 // ----------- S t a t e ------------- |
3566 // -- eax : key | 3531 // -- eax : key |
3567 // -- edx : receiver | 3532 // -- edx : receiver |
3568 // -- esp[0] : return address | 3533 // -- esp[0] : return address |
3569 // ----------------------------------- | 3534 // ----------------------------------- |
3570 Label miss_force_generic, slow, check_heap_number; | 3535 Label miss_force_generic, slow, check_heap_number; |
3571 | 3536 |
3572 // This stub is meant to be tail-jumped to, the receiver must already | 3537 // This stub is meant to be tail-jumped to, the receiver must already |
3573 // have been verified by the caller to not be a smi. | 3538 // have been verified by the caller to not be a smi. |
3574 | 3539 |
(...skipping 10 matching lines...) Expand all Loading... |
3585 __ j(above_equal, &slow); | 3550 __ j(above_equal, &slow); |
3586 | 3551 |
3587 // Handle both smis and HeapNumbers in the fast path. Go to the | 3552 // Handle both smis and HeapNumbers in the fast path. Go to the |
3588 // runtime for all other kinds of values. | 3553 // runtime for all other kinds of values. |
3589 // eax: value | 3554 // eax: value |
3590 // edx: receiver | 3555 // edx: receiver |
3591 // ecx: key | 3556 // ecx: key |
3592 // edi: elements array | 3557 // edi: elements array |
3593 // ebx: untagged index | 3558 // ebx: untagged index |
3594 __ test(eax, Immediate(kSmiTagMask)); | 3559 __ test(eax, Immediate(kSmiTagMask)); |
3595 if (array_type == kExternalPixelArray) | 3560 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) |
3596 __ j(not_equal, &slow); | 3561 __ j(not_equal, &slow); |
3597 else | 3562 else |
3598 __ j(not_equal, &check_heap_number); | 3563 __ j(not_equal, &check_heap_number); |
3599 | 3564 |
3600 // smi case | 3565 // smi case |
3601 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. | 3566 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. |
3602 __ SmiUntag(ecx); | 3567 __ SmiUntag(ecx); |
3603 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3568 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3604 // ecx: base pointer of external storage | 3569 // ecx: base pointer of external storage |
3605 switch (array_type) { | 3570 switch (elements_kind) { |
3606 case kExternalPixelArray: | 3571 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
3607 { // Clamp the value to [0..255]. | 3572 { // Clamp the value to [0..255]. |
3608 Label done; | 3573 Label done; |
3609 __ test(ecx, Immediate(0xFFFFFF00)); | 3574 __ test(ecx, Immediate(0xFFFFFF00)); |
3610 __ j(zero, &done, Label::kNear); | 3575 __ j(zero, &done, Label::kNear); |
3611 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3576 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3612 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3577 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3613 __ bind(&done); | 3578 __ bind(&done); |
3614 } | 3579 } |
3615 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3580 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3616 break; | 3581 break; |
3617 case kExternalByteArray: | 3582 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
3618 case kExternalUnsignedByteArray: | 3583 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3619 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3584 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3620 break; | 3585 break; |
3621 case kExternalShortArray: | 3586 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
3622 case kExternalUnsignedShortArray: | 3587 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3623 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3588 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3624 break; | 3589 break; |
3625 case kExternalIntArray: | 3590 case JSObject::EXTERNAL_INT_ELEMENTS: |
3626 case kExternalUnsignedIntArray: | 3591 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3627 __ mov(Operand(edi, ebx, times_4, 0), ecx); | 3592 __ mov(Operand(edi, ebx, times_4, 0), ecx); |
3628 break; | 3593 break; |
3629 case kExternalFloatArray: | 3594 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
3630 case kExternalDoubleArray: | 3595 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
3631 // Need to perform int-to-float conversion. | 3596 // Need to perform int-to-float conversion. |
3632 __ push(ecx); | 3597 __ push(ecx); |
3633 __ fild_s(Operand(esp, 0)); | 3598 __ fild_s(Operand(esp, 0)); |
3634 __ pop(ecx); | 3599 __ pop(ecx); |
3635 if (array_type == kExternalFloatArray) { | 3600 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
3636 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3601 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3637 } else { // array_type == kExternalDoubleArray. | 3602 } else { // elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS. |
3638 __ fstp_d(Operand(edi, ebx, times_8, 0)); | 3603 __ fstp_d(Operand(edi, ebx, times_8, 0)); |
3639 } | 3604 } |
3640 break; | 3605 break; |
3641 default: | 3606 default: |
3642 UNREACHABLE(); | 3607 UNREACHABLE(); |
3643 break; | 3608 break; |
3644 } | 3609 } |
3645 __ ret(0); // Return the original value. | 3610 __ ret(0); // Return the original value. |
3646 | 3611 |
3647 // TODO(danno): handle heap number -> pixel array conversion | 3612 // TODO(danno): handle heap number -> pixel array conversion |
3648 if (array_type != kExternalPixelArray) { | 3613 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) { |
3649 __ bind(&check_heap_number); | 3614 __ bind(&check_heap_number); |
3650 // eax: value | 3615 // eax: value |
3651 // edx: receiver | 3616 // edx: receiver |
3652 // ecx: key | 3617 // ecx: key |
3653 // edi: elements array | 3618 // edi: elements array |
3654 // ebx: untagged index | 3619 // ebx: untagged index |
3655 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 3620 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
3656 Immediate(masm->isolate()->factory()->heap_number_map())); | 3621 Immediate(masm->isolate()->factory()->heap_number_map())); |
3657 __ j(not_equal, &slow); | 3622 __ j(not_equal, &slow); |
3658 | 3623 |
3659 // The WebGL specification leaves the behavior of storing NaN and | 3624 // The WebGL specification leaves the behavior of storing NaN and |
3660 // +/-Infinity into integer arrays basically undefined. For more | 3625 // +/-Infinity into integer arrays basically undefined. For more |
3661 // reproducible behavior, convert these to zero. | 3626 // reproducible behavior, convert these to zero. |
3662 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | 3627 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); |
3663 // ebx: untagged index | 3628 // ebx: untagged index |
3664 // edi: base pointer of external storage | 3629 // edi: base pointer of external storage |
3665 if (array_type == kExternalFloatArray) { | 3630 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) { |
3666 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3631 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3667 __ fstp_s(Operand(edi, ebx, times_4, 0)); | 3632 __ fstp_s(Operand(edi, ebx, times_4, 0)); |
3668 __ ret(0); | 3633 __ ret(0); |
3669 } else if (array_type == kExternalDoubleArray) { | 3634 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) { |
3670 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 3635 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
3671 __ fstp_d(Operand(edi, ebx, times_8, 0)); | 3636 __ fstp_d(Operand(edi, ebx, times_8, 0)); |
3672 __ ret(0); | 3637 __ ret(0); |
3673 } else { | 3638 } else { |
3674 // Perform float-to-int conversion with truncation (round-to-zero) | 3639 // Perform float-to-int conversion with truncation (round-to-zero) |
3675 // behavior. | 3640 // behavior. |
3676 | 3641 |
3677 // For the moment we make the slow call to the runtime on | 3642 // For the moment we make the slow call to the runtime on |
3678 // processors that don't support SSE2. The code in IntegerConvert | 3643 // processors that don't support SSE2. The code in IntegerConvert |
3679 // (code-stubs-ia32.cc) is roughly what is needed here though the | 3644 // (code-stubs-ia32.cc) is roughly what is needed here though the |
3680 // conversion failure case does not need to be handled. | 3645 // conversion failure case does not need to be handled. |
3681 if (CpuFeatures::IsSupported(SSE2)) { | 3646 if (CpuFeatures::IsSupported(SSE2)) { |
3682 if (array_type != kExternalIntArray && | 3647 if (elements_kind != JSObject::EXTERNAL_INT_ELEMENTS && |
3683 array_type != kExternalUnsignedIntArray) { | 3648 elements_kind != JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) { |
3684 ASSERT(CpuFeatures::IsSupported(SSE2)); | 3649 ASSERT(CpuFeatures::IsSupported(SSE2)); |
3685 CpuFeatures::Scope scope(SSE2); | 3650 CpuFeatures::Scope scope(SSE2); |
3686 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); | 3651 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); |
3687 // ecx: untagged integer value | 3652 // ecx: untagged integer value |
3688 switch (array_type) { | 3653 switch (elements_kind) { |
3689 case kExternalPixelArray: | 3654 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
3690 { // Clamp the value to [0..255]. | 3655 { // Clamp the value to [0..255]. |
3691 Label done; | 3656 Label done; |
3692 __ test(ecx, Immediate(0xFFFFFF00)); | 3657 __ test(ecx, Immediate(0xFFFFFF00)); |
3693 __ j(zero, &done, Label::kNear); | 3658 __ j(zero, &done, Label::kNear); |
3694 __ setcc(negative, ecx); // 1 if negative, 0 if positive. | 3659 __ setcc(negative, ecx); // 1 if negative, 0 if positive. |
3695 __ dec_b(ecx); // 0 if negative, 255 if positive. | 3660 __ dec_b(ecx); // 0 if negative, 255 if positive. |
3696 __ bind(&done); | 3661 __ bind(&done); |
3697 } | 3662 } |
3698 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3663 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3699 break; | 3664 break; |
3700 case kExternalByteArray: | 3665 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
3701 case kExternalUnsignedByteArray: | 3666 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3702 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); | 3667 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); |
3703 break; | 3668 break; |
3704 case kExternalShortArray: | 3669 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
3705 case kExternalUnsignedShortArray: | 3670 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3706 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); | 3671 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); |
3707 break; | 3672 break; |
3708 default: | 3673 default: |
3709 UNREACHABLE(); | 3674 UNREACHABLE(); |
3710 break; | 3675 break; |
3711 } | 3676 } |
3712 } else { | 3677 } else { |
3713 if (CpuFeatures::IsSupported(SSE3)) { | 3678 if (CpuFeatures::IsSupported(SSE3)) { |
3714 CpuFeatures::Scope scope(SSE3); | 3679 CpuFeatures::Scope scope(SSE3); |
3715 // fisttp stores values as signed integers. To represent the | 3680 // fisttp stores values as signed integers. To represent the |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3768 // -- esp[0] : return address | 3733 // -- esp[0] : return address |
3769 // ----------------------------------- | 3734 // ----------------------------------- |
3770 | 3735 |
3771 __ bind(&miss_force_generic); | 3736 __ bind(&miss_force_generic); |
3772 Handle<Code> miss_ic = | 3737 Handle<Code> miss_ic = |
3773 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3738 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3774 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | 3739 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3775 } | 3740 } |
3776 | 3741 |
3777 | 3742 |
3778 | |
3779 | |
3780 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { | 3743 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { |
3781 // ----------- S t a t e ------------- | 3744 // ----------- S t a t e ------------- |
3782 // -- eax : key | 3745 // -- eax : key |
3783 // -- edx : receiver | 3746 // -- edx : receiver |
3784 // -- esp[0] : return address | 3747 // -- esp[0] : return address |
3785 // ----------------------------------- | 3748 // ----------------------------------- |
3786 Label miss_force_generic; | 3749 Label miss_force_generic; |
3787 | 3750 |
3788 // This stub is meant to be tail-jumped to, the receiver must already | 3751 // This stub is meant to be tail-jumped to, the receiver must already |
3789 // have been verified by the caller to not be a smi. | 3752 // have been verified by the caller to not be a smi. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3862 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 3825 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
3863 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); | 3826 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
3864 } | 3827 } |
3865 | 3828 |
3866 | 3829 |
3867 #undef __ | 3830 #undef __ |
3868 | 3831 |
3869 } } // namespace v8::internal | 3832 } } // namespace v8::internal |
3870 | 3833 |
3871 #endif // V8_TARGET_ARCH_IA32 | 3834 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |