Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 2524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2535 __ test(eax, Operand(eax)); | 2535 __ test(eax, Operand(eax)); |
| 2536 __ j(zero, &runtime_call_clear_stack); | 2536 __ j(zero, &runtime_call_clear_stack); |
| 2537 #ifdef DEBUG | 2537 #ifdef DEBUG |
| 2538 // Check that the layout of cache elements match expectations. | 2538 // Check that the layout of cache elements match expectations. |
| 2539 { TranscendentalCache::Element test_elem[2]; | 2539 { TranscendentalCache::Element test_elem[2]; |
| 2540 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 2540 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
| 2541 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); | 2541 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); |
| 2542 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); | 2542 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); |
| 2543 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); | 2543 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); |
| 2544 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); | 2544 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); |
| 2545 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. | 2545 char* elem_uout = reinterpret_cast<char*>(&(test_elem[0].untagged_output)); |
| 2546 CHECK_EQ(20, elem2_start - elem_start); // Two uint_32's and a pointer. | |
| 2546 CHECK_EQ(0, elem_in0 - elem_start); | 2547 CHECK_EQ(0, elem_in0 - elem_start); |
| 2547 CHECK_EQ(kIntSize, elem_in1 - elem_start); | 2548 CHECK_EQ(kIntSize, elem_in1 - elem_start); |
| 2548 CHECK_EQ(2 * kIntSize, elem_out - elem_start); | 2549 CHECK_EQ(2 * kIntSize, elem_out - elem_start); |
| 2550 CHECK_EQ(3 * kIntSize, elem_uout - elem_start); | |
| 2549 } | 2551 } |
| 2550 #endif | 2552 #endif |
| 2551 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. | 2553 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*20]. |
| 2552 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); | 2554 __ lea(ecx, Operand(ecx, ecx, times_4, 0)); |
| 2553 __ lea(ecx, Operand(eax, ecx, times_4, 0)); | 2555 __ lea(ecx, Operand(eax, ecx, times_4, 0)); |
| 2554 // Check if cache matches: Double value is stored in uint32_t[2] array. | 2556 // Check if cache matches: Double value is stored in uint32_t[2] array. |
| 2555 NearLabel cache_miss; | 2557 NearLabel cache_miss, allocate_cached_answer; |
| 2556 __ cmp(ebx, Operand(ecx, 0)); | 2558 __ cmp(ebx, Operand(ecx, 0)); |
| 2557 __ j(not_equal, &cache_miss); | 2559 __ j(not_equal, &cache_miss); |
| 2558 __ cmp(edx, Operand(ecx, kIntSize)); | 2560 __ cmp(edx, Operand(ecx, kIntSize)); |
| 2559 __ j(not_equal, &cache_miss); | 2561 __ j(not_equal, &cache_miss); |
| 2560 // Cache hit! | 2562 // Cache hit! |
| 2561 __ mov(eax, Operand(ecx, 2 * kIntSize)); | 2563 __ mov(eax, Operand(ecx, 2 * kIntSize)); |
| 2562 __ fstp(0); | 2564 __ fstp(0); |
| 2565 __ test(eax, Operand(eax)); | |
| 2566 __ j(zero, &allocate_cached_answer); // The answer is cached as untagged. | |
|
Erik Corry
2010/12/13 20:26:13
"is cached, but only as untagged".
| |
| 2567 __ ret(kPointerSize); | |
| 2568 | |
| 2569 __ bind(&allocate_cached_answer); | |
| 2570 __ AllocateHeapNumber(eax, edi, edx, &runtime_call); | |
| 2571 __ mov(ebx, Operand(ecx, 3 * kIntSize)); | |
| 2572 __ mov(FieldOperand(eax, HeapNumber::kValueOffset), ebx); | |
| 2573 __ mov(ebx, Operand(ecx, 4 * kIntSize)); | |
| 2574 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); | |
| 2575 __ mov(Operand(ecx, 2 * kIntSize), eax); | |
| 2563 __ ret(kPointerSize); | 2576 __ ret(kPointerSize); |
| 2564 | 2577 |
| 2565 __ bind(&cache_miss); | 2578 __ bind(&cache_miss); |
| 2566 // Update cache with new value. | 2579 // Update cache with new value. |
| 2567 // We are short on registers, so use no_reg as scratch. | 2580 // We are short on registers, so use no_reg as scratch. |
| 2568 // This gives slightly larger code. | 2581 // This gives slightly larger code. |
| 2569 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); | 2582 __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); |
| 2570 GenerateOperation(masm); | 2583 GenerateOperation(masm); |
| 2571 __ mov(Operand(ecx, 0), ebx); | 2584 __ mov(Operand(ecx, 0), ebx); |
| 2572 __ mov(Operand(ecx, kIntSize), edx); | 2585 __ mov(Operand(ecx, kIntSize), edx); |
| 2573 __ mov(Operand(ecx, 2 * kIntSize), eax); | 2586 __ mov(Operand(ecx, 2 * kIntSize), eax); |
| 2587 __ fst_d(Operand(ecx, 3 * kIntSize)); | |
| 2574 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2588 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2575 __ ret(kPointerSize); | 2589 __ ret(kPointerSize); |
| 2576 | 2590 |
| 2577 __ bind(&runtime_call_clear_stack); | 2591 __ bind(&runtime_call_clear_stack); |
| 2578 __ fstp(0); | 2592 __ fstp(0); |
| 2579 __ bind(&runtime_call); | 2593 __ bind(&runtime_call); |
| 2580 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); | 2594 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); |
| 2581 } | 2595 } |
| 2582 | 2596 |
| 2583 | 2597 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2728 __ test(eax, Operand(eax)); | 2742 __ test(eax, Operand(eax)); |
| 2729 __ j(zero, &call_runtime); | 2743 __ j(zero, &call_runtime); |
| 2730 #ifdef DEBUG | 2744 #ifdef DEBUG |
| 2731 // Check that the layout of cache elements match expectations. | 2745 // Check that the layout of cache elements match expectations. |
| 2732 { TranscendentalCache::Element test_elem[2]; | 2746 { TranscendentalCache::Element test_elem[2]; |
| 2733 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); | 2747 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); |
| 2734 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); | 2748 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); |
| 2735 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); | 2749 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); |
| 2736 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); | 2750 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); |
| 2737 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); | 2751 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); |
| 2738 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. | 2752 char* elem_uout = reinterpret_cast<char*>(&(test_elem[0].untagged_output)); |
| 2753 CHECK_EQ(20, elem2_start - elem_start); // Two uint_32's and a pointer. | |
|
Erik Corry
2010/12/13 20:26:13
Comment is now wrong and type has wrong name.
| |
| 2739 CHECK_EQ(0, elem_in0 - elem_start); | 2754 CHECK_EQ(0, elem_in0 - elem_start); |
| 2740 CHECK_EQ(kIntSize, elem_in1 - elem_start); | 2755 CHECK_EQ(kIntSize, elem_in1 - elem_start); |
| 2741 CHECK_EQ(2 * kIntSize, elem_out - elem_start); | 2756 CHECK_EQ(2 * kIntSize, elem_out - elem_start); |
| 2757 CHECK_EQ(3 * kIntSize, elem_uout - elem_start); | |
| 2742 } | 2758 } |
| 2743 #endif | 2759 #endif |
| 2744 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. | 2760 // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12]. |
| 2745 __ lea(ecx, Operand(ecx, ecx, times_2, 0)); | 2761 __ lea(ecx, Operand(ecx, ecx, times_4, 0)); |
| 2746 __ lea(ecx, Operand(eax, ecx, times_4, 0)); | 2762 __ lea(ecx, Operand(eax, ecx, times_4, 0)); |
| 2747 // Check if cache matches: Double value is stored in uint32_t[2] array. | 2763 // Check if cache matches: Double value is stored in uint32_t[2] array. |
| 2748 NearLabel cache_miss; | 2764 NearLabel cache_miss; |
| 2749 __ cmp(ebx, Operand(ecx, 0)); | 2765 __ cmp(ebx, Operand(ecx, 0)); |
| 2750 __ j(not_equal, &cache_miss); | 2766 __ j(not_equal, &cache_miss); |
| 2751 __ cmp(edx, Operand(ecx, kIntSize)); | 2767 __ cmp(edx, Operand(ecx, kIntSize)); |
| 2752 __ j(not_equal, &cache_miss); | 2768 __ j(not_equal, &cache_miss); |
| 2753 // Cache hit! | 2769 // Cache hit! |
| 2754 __ mov(eax, Operand(ecx, 2 * kIntSize)); | 2770 __ movdbl(xmm1, Operand(ecx, 3 * kIntSize)); |
| 2755 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | |
| 2756 __ Ret(); | 2771 __ Ret(); |
| 2757 | 2772 |
| 2758 __ bind(&cache_miss); | 2773 __ bind(&cache_miss); |
| 2759 // Update cache with new value. | 2774 // Update cache with new value. |
| 2760 // We are short on registers, so use no_reg as scratch. | 2775 // We are short on registers, so use no_reg as scratch. |
| 2761 // This gives slightly larger code. | 2776 // This gives slightly larger code. |
| 2762 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 2777 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2763 __ sub(Operand(esp), Immediate(sizeof(double))); | |
| 2764 __ movdbl(Operand(esp, 0), xmm1); | 2778 __ movdbl(Operand(esp, 0), xmm1); |
| 2765 __ fld_d(Operand(esp, 0)); | 2779 __ fld_d(Operand(esp, 0)); |
| 2766 __ add(Operand(esp), Immediate(sizeof(double))); | 2780 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2767 GenerateOperation(masm); | 2781 GenerateOperation(masm); |
| 2768 __ mov(Operand(ecx, 0), ebx); | 2782 __ mov(Operand(ecx, 0), ebx); |
| 2769 __ mov(Operand(ecx, kIntSize), edx); | 2783 __ mov(Operand(ecx, kIntSize), edx); |
| 2770 __ mov(Operand(ecx, 2 * kIntSize), eax); | 2784 __ mov(Operand(ecx, 2 * kIntSize), Immediate(0)); // No tagged cached value. |
| 2771 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 2785 __ fst_d(Operand(ecx, 3 * kIntSize)); |
| 2772 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2786 __ movdbl(xmm1, Operand(ecx, 3 * kIntSize)); |
| 2773 __ Ret(); | 2787 __ Ret(); |
| 2774 | 2788 |
| 2775 __ bind(&skip_cache); | 2789 __ bind(&skip_cache); |
| 2776 __ sub(Operand(esp), Immediate(2 * kPointerSize)); | 2790 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2777 __ movdbl(Operand(esp, 0), xmm1); | 2791 __ movdbl(Operand(esp, 0), xmm1); |
| 2778 __ fld_d(Operand(esp, 0)); | 2792 __ fld_d(Operand(esp, 0)); |
| 2779 GenerateOperation(masm); | 2793 GenerateOperation(masm); |
| 2780 __ fstp_d(Operand(esp, 0)); | 2794 __ fstp_d(Operand(esp, 0)); |
| 2781 __ movdbl(xmm1, Operand(esp, 0)); | 2795 __ movdbl(xmm1, Operand(esp, 0)); |
| 2782 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 2796 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2783 __ Ret(); | 2797 __ Ret(); |
| 2784 | 2798 |
| 2785 __ bind(&call_runtime); | 2799 __ bind(&call_runtime); |
| 2786 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); | 2800 __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache); |
| 2787 __ push(eax); | 2801 __ push(eax); |
| 2788 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); | 2802 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1); |
| 2789 __ CallRuntime(RuntimeFunction(), 1); | 2803 __ CallRuntime(RuntimeFunction(), 1); |
| 2790 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 2804 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 2791 __ Ret(); | 2805 __ Ret(); |
| 2792 } | 2806 } |
| (...skipping 3621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6414 // Do a tail call to the rewritten stub. | 6428 // Do a tail call to the rewritten stub. |
| 6415 __ jmp(Operand(edi)); | 6429 __ jmp(Operand(edi)); |
| 6416 } | 6430 } |
| 6417 | 6431 |
| 6418 | 6432 |
| 6419 #undef __ | 6433 #undef __ |
| 6420 | 6434 |
| 6421 } } // namespace v8::internal | 6435 } } // namespace v8::internal |
| 6422 | 6436 |
| 6423 #endif // V8_TARGET_ARCH_IA32 | 6437 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |