Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 2861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2872 | 2872 |
| 2873 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( | 2873 Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
| 2874 Handle<Map> receiver_map) { | 2874 Handle<Map> receiver_map) { |
| 2875 // ----------- S t a t e ------------- | 2875 // ----------- S t a t e ------------- |
| 2876 // -- eax : value | 2876 // -- eax : value |
| 2877 // -- ecx : key | 2877 // -- ecx : key |
| 2878 // -- edx : receiver | 2878 // -- edx : receiver |
| 2879 // -- esp[0] : return address | 2879 // -- esp[0] : return address |
| 2880 // ----------------------------------- | 2880 // ----------------------------------- |
| 2881 ElementsKind elements_kind = receiver_map->elements_kind(); | 2881 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 2882 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE; | 2882 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
| 2883 Handle<Code> stub = | 2883 if ((receiver_map->has_fast_elements() || |
| 2884 KeyedStoreElementStub(is_jsarray, | 2884 receiver_map->has_external_array_elements())) { |
| 2885 elements_kind, | 2885 Handle<Code> stub = KeyedStoreFastElementStub( |
| 2886 store_mode_).GetCode(isolate()); | 2886 is_js_array, |
| 2887 | 2887 elements_kind, |
| 2888 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | 2888 store_mode_).GetCode(isolate()); |
| 2889 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | |
| 2890 } else { | |
| 2891 Handle<Code> stub = | |
| 2892 KeyedStoreElementStub(is_js_array, elements_kind, | |
| 2893 store_mode_).GetCode(isolate()); | |
| 2894 __ DispatchMap(edx, receiver_map, stub, DO_SMI_CHECK); | |
| 2895 } | |
| 2889 | 2896 |
| 2890 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2897 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2891 __ jmp(ic, RelocInfo::CODE_TARGET); | 2898 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2892 | 2899 |
| 2893 // Return the generated code. | 2900 // Return the generated code. |
| 2894 return GetCode(Code::NORMAL, factory()->empty_string()); | 2901 return GetCode(Code::NORMAL, factory()->empty_string()); |
| 2895 } | 2902 } |
| 2896 | 2903 |
| 2897 | 2904 |
| 2898 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 2905 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3328 __ j(sign, fail); | 3335 __ j(sign, fail); |
| 3329 __ SmiTag(scratch); | 3336 __ SmiTag(scratch); |
| 3330 __ mov(key, scratch); | 3337 __ mov(key, scratch); |
| 3331 __ bind(&key_ok); | 3338 __ bind(&key_ok); |
| 3332 } else { | 3339 } else { |
| 3333 __ JumpIfNotSmi(key, fail); | 3340 __ JumpIfNotSmi(key, fail); |
| 3334 } | 3341 } |
| 3335 } | 3342 } |
| 3336 | 3343 |
| 3337 | 3344 |
| 3338 void KeyedStoreStubCompiler::GenerateStoreExternalArray( | |
|
Jakob Kummerow
2013/03/11 16:36:07
Love this change! :-)
| |
| 3339 MacroAssembler* masm, | |
| 3340 ElementsKind elements_kind) { | |
| 3341 // ----------- S t a t e ------------- | |
| 3342 // -- eax : value | |
| 3343 // -- ecx : key | |
| 3344 // -- edx : receiver | |
| 3345 // -- esp[0] : return address | |
| 3346 // ----------------------------------- | |
| 3347 Label miss_force_generic, slow, check_heap_number; | |
| 3348 | |
| 3349 // This stub is meant to be tail-jumped to, the receiver must already | |
| 3350 // have been verified by the caller to not be a smi. | |
| 3351 | |
| 3352 // Check that the key is a smi or a heap number convertible to a smi. | |
| 3353 GenerateSmiKeyCheck(masm, ecx, ebx, xmm0, xmm1, &miss_force_generic); | |
| 3354 | |
| 3355 // Check that the index is in range. | |
| 3356 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
| 3357 __ cmp(ecx, FieldOperand(edi, ExternalArray::kLengthOffset)); | |
| 3358 // Unsigned comparison catches both negative and too-large values. | |
| 3359 __ j(above_equal, &slow); | |
| 3360 | |
| 3361 // Handle both smis and HeapNumbers in the fast path. Go to the | |
| 3362 // runtime for all other kinds of values. | |
| 3363 // eax: value | |
| 3364 // edx: receiver | |
| 3365 // ecx: key | |
| 3366 // edi: elements array | |
| 3367 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { | |
| 3368 __ JumpIfNotSmi(eax, &slow); | |
| 3369 } else { | |
| 3370 __ JumpIfNotSmi(eax, &check_heap_number); | |
| 3371 } | |
| 3372 | |
| 3373 // smi case | |
| 3374 __ mov(ebx, eax); // Preserve the value in eax as the return value. | |
| 3375 __ SmiUntag(ebx); | |
| 3376 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | |
| 3377 // edi: base pointer of external storage | |
| 3378 switch (elements_kind) { | |
| 3379 case EXTERNAL_PIXEL_ELEMENTS: | |
| 3380 __ ClampUint8(ebx); | |
| 3381 __ SmiUntag(ecx); | |
| 3382 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
| 3383 break; | |
| 3384 case EXTERNAL_BYTE_ELEMENTS: | |
| 3385 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 3386 __ SmiUntag(ecx); | |
| 3387 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
| 3388 break; | |
| 3389 case EXTERNAL_SHORT_ELEMENTS: | |
| 3390 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 3391 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); | |
| 3392 break; | |
| 3393 case EXTERNAL_INT_ELEMENTS: | |
| 3394 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 3395 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
| 3396 break; | |
| 3397 case EXTERNAL_FLOAT_ELEMENTS: | |
| 3398 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 3399 // Need to perform int-to-float conversion. | |
| 3400 __ push(ebx); | |
| 3401 __ fild_s(Operand(esp, 0)); | |
| 3402 __ pop(ebx); | |
| 3403 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
| 3404 __ fstp_s(Operand(edi, ecx, times_2, 0)); | |
| 3405 } else { // elements_kind == EXTERNAL_DOUBLE_ELEMENTS. | |
| 3406 __ fstp_d(Operand(edi, ecx, times_4, 0)); | |
| 3407 } | |
| 3408 break; | |
| 3409 default: | |
| 3410 UNREACHABLE(); | |
| 3411 break; | |
| 3412 } | |
| 3413 __ ret(0); // Return the original value. | |
| 3414 | |
| 3415 // TODO(danno): handle heap number -> pixel array conversion | |
| 3416 if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { | |
| 3417 __ bind(&check_heap_number); | |
| 3418 // eax: value | |
| 3419 // edx: receiver | |
| 3420 // ecx: key | |
| 3421 // edi: elements array | |
| 3422 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | |
| 3423 Immediate(masm->isolate()->factory()->heap_number_map())); | |
| 3424 __ j(not_equal, &slow); | |
| 3425 | |
| 3426 // The WebGL specification leaves the behavior of storing NaN and | |
| 3427 // +/-Infinity into integer arrays basically undefined. For more | |
| 3428 // reproducible behavior, convert these to zero. | |
| 3429 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); | |
| 3430 // edi: base pointer of external storage | |
| 3431 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { | |
| 3432 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 3433 __ fstp_s(Operand(edi, ecx, times_2, 0)); | |
| 3434 __ ret(0); | |
| 3435 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { | |
| 3436 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 3437 __ fstp_d(Operand(edi, ecx, times_4, 0)); | |
| 3438 __ ret(0); | |
| 3439 } else { | |
| 3440 // Perform float-to-int conversion with truncation (round-to-zero) | |
| 3441 // behavior. | |
| 3442 | |
| 3443 // For the moment we make the slow call to the runtime on | |
| 3444 // processors that don't support SSE2. The code in IntegerConvert | |
| 3445 // (code-stubs-ia32.cc) is roughly what is needed here though the | |
| 3446 // conversion failure case does not need to be handled. | |
| 3447 if (CpuFeatures::IsSupported(SSE2)) { | |
| 3448 if ((elements_kind == EXTERNAL_INT_ELEMENTS || | |
| 3449 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) && | |
| 3450 CpuFeatures::IsSupported(SSE3)) { | |
| 3451 CpuFeatureScope scope(masm, SSE3); | |
| 3452 // fisttp stores values as signed integers. To represent the | |
| 3453 // entire range of int and unsigned int arrays, store as a | |
| 3454 // 64-bit int and discard the high 32 bits. | |
| 3455 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 3456 __ sub(esp, Immediate(2 * kPointerSize)); | |
| 3457 __ fisttp_d(Operand(esp, 0)); | |
| 3458 | |
| 3459 // If conversion failed (NaN, infinity, or a number outside | |
| 3460 // signed int64 range), the result is 0x8000000000000000, and | |
| 3461 // we must handle this case in the runtime. | |
| 3462 Label ok; | |
| 3463 __ cmp(Operand(esp, kPointerSize), Immediate(0x80000000u)); | |
| 3464 __ j(not_equal, &ok); | |
| 3465 __ cmp(Operand(esp, 0), Immediate(0)); | |
| 3466 __ j(not_equal, &ok); | |
| 3467 __ add(esp, Immediate(2 * kPointerSize)); // Restore the stack. | |
| 3468 __ jmp(&slow); | |
| 3469 | |
| 3470 __ bind(&ok); | |
| 3471 __ pop(ebx); | |
| 3472 __ add(esp, Immediate(kPointerSize)); | |
| 3473 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
| 3474 } else { | |
| 3475 ASSERT(CpuFeatures::IsSupported(SSE2)); | |
| 3476 CpuFeatureScope scope(masm, SSE2); | |
| 3477 __ cvttsd2si(ebx, FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 3478 __ cmp(ebx, 0x80000000u); | |
| 3479 __ j(equal, &slow); | |
| 3480 // ebx: untagged integer value | |
| 3481 switch (elements_kind) { | |
| 3482 case EXTERNAL_PIXEL_ELEMENTS: | |
| 3483 __ ClampUint8(ebx); | |
| 3484 // Fall through. | |
| 3485 case EXTERNAL_BYTE_ELEMENTS: | |
| 3486 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
| 3487 __ SmiUntag(ecx); | |
| 3488 __ mov_b(Operand(edi, ecx, times_1, 0), ebx); | |
| 3489 break; | |
| 3490 case EXTERNAL_SHORT_ELEMENTS: | |
| 3491 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 3492 __ mov_w(Operand(edi, ecx, times_1, 0), ebx); | |
| 3493 break; | |
| 3494 case EXTERNAL_INT_ELEMENTS: | |
| 3495 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 3496 __ mov(Operand(edi, ecx, times_2, 0), ebx); | |
| 3497 break; | |
| 3498 default: | |
| 3499 UNREACHABLE(); | |
| 3500 break; | |
| 3501 } | |
| 3502 } | |
| 3503 __ ret(0); // Return original value. | |
| 3504 } | |
| 3505 } | |
| 3506 } | |
| 3507 | |
| 3508 // Slow case: call runtime. | |
| 3509 __ bind(&slow); | |
| 3510 Counters* counters = masm->isolate()->counters(); | |
| 3511 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1); | |
| 3512 | |
| 3513 // ----------- S t a t e ------------- | |
| 3514 // -- eax : value | |
| 3515 // -- ecx : key | |
| 3516 // -- edx : receiver | |
| 3517 // -- esp[0] : return address | |
| 3518 // ----------------------------------- | |
| 3519 | |
| 3520 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); | |
| 3521 __ jmp(ic, RelocInfo::CODE_TARGET); | |
| 3522 | |
| 3523 // ----------- S t a t e ------------- | |
| 3524 // -- eax : value | |
| 3525 // -- ecx : key | |
| 3526 // -- edx : receiver | |
| 3527 // -- esp[0] : return address | |
| 3528 // ----------------------------------- | |
| 3529 | |
| 3530 __ bind(&miss_force_generic); | |
| 3531 Handle<Code> miss_ic = | |
| 3532 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | |
| 3533 __ jmp(miss_ic, RelocInfo::CODE_TARGET); | |
| 3534 } | |
| 3535 | |
| 3536 | |
| 3537 void KeyedStoreStubCompiler::GenerateStoreFastElement( | 3345 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
| 3538 MacroAssembler* masm, | 3346 MacroAssembler* masm, |
| 3539 bool is_js_array, | 3347 bool is_js_array, |
| 3540 ElementsKind elements_kind, | 3348 ElementsKind elements_kind, |
| 3541 KeyedAccessStoreMode store_mode) { | 3349 KeyedAccessStoreMode store_mode) { |
| 3542 // ----------- S t a t e ------------- | 3350 // ----------- S t a t e ------------- |
| 3543 // -- eax : value | 3351 // -- eax : value |
| 3544 // -- ecx : key | 3352 // -- ecx : key |
| 3545 // -- edx : receiver | 3353 // -- edx : receiver |
| 3546 // -- esp[0] : return address | 3354 // -- esp[0] : return address |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3826 __ jmp(ic_slow, RelocInfo::CODE_TARGET); | 3634 __ jmp(ic_slow, RelocInfo::CODE_TARGET); |
| 3827 } | 3635 } |
| 3828 } | 3636 } |
| 3829 | 3637 |
| 3830 | 3638 |
| 3831 #undef __ | 3639 #undef __ |
| 3832 | 3640 |
| 3833 } } // namespace v8::internal | 3641 } } // namespace v8::internal |
| 3834 | 3642 |
| 3835 #endif // V8_TARGET_ARCH_IA32 | 3643 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |