From: podivilov@chromium.org Date: Tue, 27 Apr 2010 14:56:56 +0000 (+0000) Subject: Port number string cache lookup for heap numbers in generatred code to x64 and ARM. X-Git-Tag: upstream/4.7.83~21932 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5a999d8b18b9bcbc7e1eec0cbe2298f5ef9137bd;p=platform%2Fupstream%2Fv8.git Port number string cache lookup for heap numbers in generatred code to x64 and ARM. Review URL: http://codereview.chromium.org/1575047 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4516 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index a1b8a1536..1c34f06a8 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -6241,20 +6241,12 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, Register result, Register scratch1, Register scratch2, + Register scratch3, bool object_is_smi, Label* not_found) { - // Currently only lookup for smis. Check for smi if object is not known to be - // a smi. - if (!object_is_smi) { - ASSERT(kSmiTag == 0); - __ tst(object, Operand(kSmiTagMask)); - __ b(ne, not_found); - } - // Use of registers. Register result is used as a temporary. Register number_string_cache = result; - Register mask = scratch1; - Register scratch = scratch2; + Register mask = scratch3; // Load the number string cache. __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); @@ -6267,9 +6259,55 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, __ sub(mask, mask, Operand(1)); // Make mask. // Calculate the entry in the number string cache. The hash value in the - // number string cache for smis is just the smi value. - __ and_(scratch, mask, Operand(object, ASR, 1)); + // number string cache for smis is just the smi value, and the hash for + // doubles is the xor of the upper and lower words. See + // Heap::GetNumberStringCache. + Label is_smi; + Label load_result_from_cache; + if (!object_is_smi) { + __ BranchOnSmi(object, &is_smi); + if (CpuFeatures::IsSupported(VFP3)) { + CpuFeatures::Scope scope(VFP3); + __ CheckMap(object, + scratch1, + Factory::heap_number_map(), + not_found, + true); + + ASSERT_EQ(8, kDoubleSize); + __ add(scratch1, + object, + Operand(HeapNumber::kValueOffset - kHeapObjectTag)); + __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); + __ eor(scratch1, scratch1, Operand(scratch2)); + __ and_(scratch1, scratch1, Operand(mask)); + + // Calculate address of entry in string cache: each entry consists + // of two pointer sized fields. + __ add(scratch1, + number_string_cache, + Operand(scratch1, LSL, kPointerSizeLog2 + 1)); + + Register probe = mask; + __ ldr(probe, + FieldMemOperand(scratch1, FixedArray::kHeaderSize)); + __ BranchOnSmi(probe, not_found); + __ sub(scratch2, object, Operand(kHeapObjectTag)); + __ vldr(d0, scratch2, HeapNumber::kValueOffset); + __ sub(probe, probe, Operand(kHeapObjectTag)); + __ vldr(d1, probe, HeapNumber::kValueOffset); + __ vcmp(d0, d1); + __ vmrs(pc); + __ b(ne, not_found); // The cache did not contain this value. + __ b(&load_result_from_cache); + } else { + __ b(not_found); + } + } + __ bind(&is_smi); + Register scratch = scratch1; + __ and_(scratch, mask, Operand(object, ASR, 1)); // Calculate address of entry in string cache: each entry consists // of two pointer sized fields. __ add(scratch, @@ -6277,15 +6315,15 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, Operand(scratch, LSL, kPointerSizeLog2 + 1)); // Check if the entry is the smi we are looking for. - Register object1 = scratch1; - __ ldr(object1, FieldMemOperand(scratch, FixedArray::kHeaderSize)); - __ cmp(object, object1); + Register probe = mask; + __ ldr(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize)); + __ cmp(object, probe); __ b(ne, not_found); // Get the result from the cache. + __ bind(&load_result_from_cache); __ ldr(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize)); - __ IncrementCounter(&Counters::number_to_string_native, 1, scratch1, @@ -6299,13 +6337,13 @@ void NumberToStringStub::Generate(MacroAssembler* masm) { __ ldr(r1, MemOperand(sp, 0)); // Generate code to lookup number in the number string cache. - GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, false, &runtime); + GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, false, &runtime); __ add(sp, sp, Operand(1 * kPointerSize)); __ Ret(); __ bind(&runtime); // Handle number to string in the runtime system if not found in the cache. - __ TailCallRuntime(Runtime::kNumberToString, 1, 1); + __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); } @@ -6718,7 +6756,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases( // First argument is a string, second is a smi. Try to lookup the number // string for the smi in the number string cache. NumberToStringStub::GenerateLookupNumberStringCache( - masm, r0, r2, r4, r5, true, &string1); + masm, r0, r2, r4, r5, r6, true, &string1); // Replace second argument on stack and tailcall string add stub to make // the result. diff --git a/src/arm/codegen-arm.h b/src/arm/codegen-arm.h index fdf9d655a..ea990caeb 100644 --- a/src/arm/codegen-arm.h +++ b/src/arm/codegen-arm.h @@ -839,6 +839,7 @@ class NumberToStringStub: public CodeStub { Register result, Register scratch1, Register scratch2, + Register scratch3, bool object_is_smi, Label* not_found); diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 9800283f8..dc1b2cb70 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -7770,6 +7770,18 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { } +void NumberToStringStub::GenerateConvertHashCodeToIndex(MacroAssembler* masm, + Register hash, + Register mask) { + __ and_(hash, mask); + // Each entry in string cache consists of two pointer sized fields, + // but times_twice_pointer_size (multiplication by 16) scale factor + // is not supported by addrmode on x64 platform. + // So we have to premultiply entry index before lookup. + __ shl(hash, Immediate(kPointerSizeLog2 + 1)); +} + + void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, Register object, Register result, @@ -7777,12 +7789,6 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, Register scratch2, bool object_is_smi, Label* not_found) { - // Currently only lookup for smis. Check for smi if object is not known to be - // a smi. - if (!object_is_smi) { - __ JumpIfNotSmi(object, not_found); - } - // Use of registers. Register result is used as a temporary. Register number_string_cache = result; Register mask = scratch1; @@ -7798,28 +7804,57 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, __ subl(mask, Immediate(1)); // Make mask. // Calculate the entry in the number string cache. The hash value in the - // number string cache for smis is just the smi value. + // number string cache for smis is just the smi value, and the hash for + // doubles is the xor of the upper and lower words. See + // Heap::GetNumberStringCache. + Label is_smi; + Label load_result_from_cache; + if (!object_is_smi) { + __ JumpIfSmi(object, &is_smi); + __ CheckMap(object, Factory::heap_number_map(), not_found, true); + + ASSERT_EQ(8, kDoubleSize); + __ movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4)); + __ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset)); + GenerateConvertHashCodeToIndex(masm, scratch, mask); + + Register index = scratch; + Register probe = mask; + __ movq(probe, + FieldOperand(number_string_cache, + index, + times_1, + FixedArray::kHeaderSize)); + __ JumpIfSmi(probe, not_found); + ASSERT(CpuFeatures::IsSupported(SSE2)); + CpuFeatures::Scope fscope(SSE2); + __ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset)); + __ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset)); + __ comisd(xmm0, xmm1); + __ j(parity_even, not_found); // Bail out if NaN is involved. + __ j(not_equal, not_found); // The cache did not contain this value. + __ jmp(&load_result_from_cache); + } + + __ bind(&is_smi); __ movq(scratch, object); __ SmiToInteger32(scratch, scratch); - __ andl(scratch, mask); + GenerateConvertHashCodeToIndex(masm, scratch, mask); - // Each entry in string cache consists of two pointer sized fields, - // but times_twice_pointer_size (multiplication by 16) scale factor - // is not supported by addrmode on x64 platform. - // So we have to premultiply entry index before lookup - __ shl(scratch, Immediate(kPointerSizeLog2 + 1)); + Register index = scratch; // Check if the entry is the smi we are looking for. __ cmpq(object, FieldOperand(number_string_cache, - scratch, + index, times_1, FixedArray::kHeaderSize)); __ j(not_equal, not_found); // Get the result from the cache. + __ bind(&load_result_from_cache); __ movq(result, FieldOperand(number_string_cache, - scratch, + index, times_1, FixedArray::kHeaderSize + kPointerSize)); __ IncrementCounter(&Counters::number_to_string_native, 1); @@ -7837,7 +7872,7 @@ void NumberToStringStub::Generate(MacroAssembler* masm) { __ bind(&runtime); // Handle number to string in the runtime system if not found in the cache. - __ TailCallRuntime(Runtime::kNumberToString, 1, 1); + __ TailCallRuntime(Runtime::kNumberToStringSkipCache, 1, 1); } diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 964e5382e..a894a5fdd 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -943,6 +943,10 @@ class NumberToStringStub: public CodeStub { Label* not_found); private: + static void GenerateConvertHashCodeToIndex(MacroAssembler* masm, + Register hash, + Register mask); + Major MajorKey() { return NumberToString; } int MinorKey() { return 0; }