| 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 |