| Index: src/ia32/code-stubs-ia32.cc
|
| ===================================================================
|
| --- src/ia32/code-stubs-ia32.cc (revision 6110)
|
| +++ src/ia32/code-stubs-ia32.cc (working copy)
|
| @@ -2566,31 +2566,44 @@
|
| char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
|
| char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
|
| char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
|
| - CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
|
| + char* elem_uout = reinterpret_cast<char*>(&(test_elem[0].untagged_output));
|
| + CHECK_EQ(20, elem2_start - elem_start); // Two uint_32's and a pointer.
|
| CHECK_EQ(0, elem_in0 - elem_start);
|
| CHECK_EQ(kIntSize, elem_in1 - elem_start);
|
| CHECK_EQ(2 * kIntSize, elem_out - elem_start);
|
| + CHECK_EQ(3 * kIntSize, elem_uout - elem_start);
|
| }
|
| #endif
|
| - // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
|
| - __ lea(ecx, Operand(ecx, ecx, times_2, 0));
|
| + // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*20].
|
| + __ lea(ecx, Operand(ecx, ecx, times_4, 0));
|
| __ lea(ecx, Operand(eax, ecx, times_4, 0));
|
| // Check if cache matches: Double value is stored in uint32_t[2] array.
|
| - NearLabel cache_miss;
|
| + NearLabel cache_miss, allocate_cached_answer;
|
| __ cmp(ebx, Operand(ecx, 0));
|
| __ j(not_equal, &cache_miss);
|
| __ cmp(edx, Operand(ecx, kIntSize));
|
| __ j(not_equal, &cache_miss);
|
| // Cache hit!
|
| - __ mov(eax, Operand(ecx, 2 * kIntSize));
|
| if (tagged) {
|
| + __ mov(eax, Operand(ecx, 2 * kIntSize));
|
| __ fstp(0);
|
| + __ test(eax, Operand(eax));
|
| + __ j(zero, &allocate_cached_answer); // The answer is cached as untagged.
|
| __ ret(kPointerSize);
|
| } else { // UNTAGGED.
|
| - __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ movdbl(xmm1, Operand(ecx, 3 * kIntSize));
|
| __ Ret();
|
| }
|
|
|
| + __ bind(&allocate_cached_answer);
|
| + __ AllocateHeapNumber(eax, edi, edx, &runtime_call);
|
| + __ mov(ebx, Operand(ecx, 3 * kIntSize));
|
| + __ mov(FieldOperand(eax, HeapNumber::kValueOffset), ebx);
|
| + __ mov(ebx, Operand(ecx, 4 * kIntSize));
|
| + __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
|
| + __ mov(Operand(ecx, 2 * kIntSize), eax);
|
| + __ ret(kPointerSize);
|
| +
|
| __ bind(&cache_miss);
|
| // Update cache with new value.
|
| // We are short on registers, so use no_reg as scratch.
|
| @@ -2598,7 +2611,6 @@
|
| if (tagged) {
|
| __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
|
| } else { // UNTAGGED.
|
| - __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
|
| __ sub(Operand(esp), Immediate(kDoubleSize));
|
| __ movdbl(Operand(esp, 0), xmm1);
|
| __ fld_d(Operand(esp, 0));
|
| @@ -2607,12 +2619,14 @@
|
| GenerateOperation(masm);
|
| __ mov(Operand(ecx, 0), ebx);
|
| __ mov(Operand(ecx, kIntSize), edx);
|
| - __ mov(Operand(ecx, 2 * kIntSize), eax);
|
| - __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| if (tagged) {
|
| + __ fst_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ mov(Operand(ecx, 2 * kIntSize), eax);
|
| + __ fstp_d(Operand(ecx, 3 * kIntSize));
|
| __ ret(kPointerSize);
|
| } else { // UNTAGGED.
|
| - __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
|
| + __ fstp_d(Operand(ecx, 3 * kIntSize));
|
| + __ movdbl(xmm1, Operand(ecx, 3 * kIntSize));
|
| __ Ret();
|
|
|
| // Skip cache and return answer directly, only in untagged case.
|
|
|