Commit 45bd2f50 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Move NumberToStringStub::GenerateLookupNumberStringCache to the MacroAssembler.

This renames the method to LookupNumberStringCache() and puts it into
the MacroAssembler in preparation of the NumberToStringStub Hydrogen
conversion.

R=mvstanton@chromium.org

Review URL: https://codereview.chromium.org/23618056

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16806 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 31813439
......@@ -193,14 +193,12 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
Register argument = r2;
Label not_cached, argument_is_string;
NumberToStringStub::GenerateLookupNumberStringCache(
masm,
r0, // Input.
argument, // Result.
r3, // Scratch.
r4, // Scratch.
r5, // Scratch.
&not_cached);
__ LookupNumberStringCache(r0, // Input.
argument, // Result.
r3, // Scratch.
r4, // Scratch.
r5, // Scratch.
&not_cached);
__ IncrementCounter(counters->string_ctor_cached_number(), 1, r3, r4);
__ bind(&argument_is_string);
......
......@@ -972,99 +972,13 @@ static void EmitCheckForInternalizedStringsOrObjects(MacroAssembler* masm,
}
void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Register scratch3,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch3;
// Load the number string cache.
__ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
__ ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
// Divide length by two (length is a smi).
__ mov(mask, Operand(mask, ASR, kSmiTagSize + 1));
__ 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 the hash for
// doubles is the xor of the upper and lower words. See
// Heap::GetNumberStringCache.
Isolate* isolate = masm->isolate();
Label is_smi;
Label load_result_from_cache;
__ JumpIfSmi(object, &is_smi);
__ CheckMap(object,
scratch1,
Heap::kHeapNumberMapRootIndex,
not_found,
DONT_DO_SMI_CHECK);
STATIC_ASSERT(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));
__ JumpIfSmi(probe, not_found);
__ sub(scratch2, object, Operand(kHeapObjectTag));
__ vldr(d0, scratch2, HeapNumber::kValueOffset);
__ sub(probe, probe, Operand(kHeapObjectTag));
__ vldr(d1, probe, HeapNumber::kValueOffset);
__ VFPCompareAndSetFlags(d0, d1);
__ b(ne, not_found); // The cache did not contain this value.
__ b(&load_result_from_cache);
__ 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,
number_string_cache,
Operand(scratch, LSL, kPointerSizeLog2 + 1));
// Check if the entry is the smi we are looking for.
__ 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(isolate->counters()->number_to_string_native(),
1,
scratch1,
scratch2);
}
void NumberToStringStub::Generate(MacroAssembler* masm) {
Label runtime;
__ ldr(r1, MemOperand(sp, 0));
// Generate code to lookup number in the number string cache.
GenerateLookupNumberStringCache(masm, r1, r0, r2, r3, r4, &runtime);
__ LookupNumberStringCache(r1, r0, r2, r3, r4, &runtime);
__ add(sp, sp, Operand(1 * kPointerSize));
__ Ret();
......@@ -5792,13 +5706,7 @@ void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
// Check the number to string cache.
__ bind(&not_string);
// Puts the cached result into scratch1.
NumberToStringStub::GenerateLookupNumberStringCache(masm,
arg,
scratch1,
scratch2,
scratch3,
scratch4,
slow);
__ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, scratch4, slow);
__ mov(arg, scratch1);
__ str(arg, MemOperand(sp, stack_offset));
__ bind(&done);
......
......@@ -261,19 +261,6 @@ class NumberToStringStub: public PlatformCodeStub {
public:
NumberToStringStub() { }
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
static void GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Register scratch3,
Label* not_found);
private:
Major MajorKey() { return NumberToString; }
int MinorKey() { return 0; }
......
......@@ -3097,6 +3097,88 @@ void MacroAssembler::JumpIfNotHeapNumber(Register object,
}
void MacroAssembler::LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Register scratch3,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch3;
// Load the number string cache.
LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
ldr(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
// Divide length by two (length is a smi).
mov(mask, Operand(mask, ASR, kSmiTagSize + 1));
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 the hash for
// doubles is the xor of the upper and lower words. See
// Heap::GetNumberStringCache.
Label is_smi;
Label load_result_from_cache;
JumpIfSmi(object, &is_smi);
CheckMap(object,
scratch1,
Heap::kHeapNumberMapRootIndex,
not_found,
DONT_DO_SMI_CHECK);
STATIC_ASSERT(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));
JumpIfSmi(probe, not_found);
sub(scratch2, object, Operand(kHeapObjectTag));
vldr(d0, scratch2, HeapNumber::kValueOffset);
sub(probe, probe, Operand(kHeapObjectTag));
vldr(d1, probe, HeapNumber::kValueOffset);
VFPCompareAndSetFlags(d0, d1);
b(ne, not_found); // The cache did not contain this value.
b(&load_result_from_cache);
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,
number_string_cache,
Operand(scratch, LSL, kPointerSizeLog2 + 1));
// Check if the entry is the smi we are looking for.
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(isolate()->counters()->number_to_string_native(),
1,
scratch1,
scratch2);
}
void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
Register first,
Register second,
......
......@@ -1294,6 +1294,18 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// String utilities
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
void LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Register scratch3,
Label* not_found);
// Checks if both objects are sequential ASCII strings and jumps to label
// if either is not. Assumes that neither object is a smi.
void JumpIfNonSmisNotBothSequentialAsciiStrings(Register object1,
......
......@@ -1065,13 +1065,11 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// Lookup the argument in the number to string cache.
Label not_cached, argument_is_string;
NumberToStringStub::GenerateLookupNumberStringCache(
masm,
eax, // Input.
ebx, // Result.
ecx, // Scratch 1.
edx, // Scratch 2.
&not_cached);
__ LookupNumberStringCache(eax, // Input.
ebx, // Result.
ecx, // Scratch 1.
edx, // Scratch 2.
&not_cached);
__ IncrementCounter(counters->string_ctor_cached_number(), 1);
__ bind(&argument_is_string);
// ----------- S t a t e -------------
......
......@@ -3767,98 +3767,13 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
}
void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch1;
Register scratch = scratch2;
// Load the number string cache.
__ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
__ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
__ shr(mask, kSmiTagSize + 1); // Untag length and divide it by two.
__ sub(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, and the hash for
// doubles is the xor of the upper and lower words. See
// Heap::GetNumberStringCache.
Label smi_hash_calculated;
Label load_result_from_cache;
Label not_smi;
STATIC_ASSERT(kSmiTag == 0);
__ JumpIfNotSmi(object, &not_smi, Label::kNear);
__ mov(scratch, object);
__ SmiUntag(scratch);
__ jmp(&smi_hash_calculated, Label::kNear);
__ bind(&not_smi);
__ cmp(FieldOperand(object, HeapObject::kMapOffset),
masm->isolate()->factory()->heap_number_map());
__ j(not_equal, not_found);
STATIC_ASSERT(8 == kDoubleSize);
__ mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
__ xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
// Object is heap number and hash is now in scratch. Calculate cache index.
__ and_(scratch, mask);
Register index = scratch;
Register probe = mask;
__ mov(probe,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
__ JumpIfSmi(probe, not_found);
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope fscope(masm, SSE2);
__ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
__ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
__ ucomisd(xmm0, xmm1);
} else {
__ fld_d(FieldOperand(object, HeapNumber::kValueOffset));
__ fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
__ FCmp();
}
__ 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, Label::kNear);
__ bind(&smi_hash_calculated);
// Object is smi and hash is now in scratch. Calculate cache index.
__ and_(scratch, mask);
// Check if the entry is the smi we are looking for.
__ cmp(object,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
__ j(not_equal, not_found);
// Get the result from the cache.
__ bind(&load_result_from_cache);
__ mov(result,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize + kPointerSize));
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->number_to_string_native(), 1);
}
void NumberToStringStub::Generate(MacroAssembler* masm) {
Label runtime;
__ mov(ebx, Operand(esp, kPointerSize));
// Generate code to lookup number in the number string cache.
GenerateLookupNumberStringCache(masm, ebx, eax, ecx, edx, &runtime);
__ LookupNumberStringCache(ebx, eax, ecx, edx, &runtime);
__ ret(1 * kPointerSize);
__ bind(&runtime);
......@@ -5518,12 +5433,7 @@ void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
// Check the number to string cache.
__ bind(&not_string);
// Puts the cached result into scratch1.
NumberToStringStub::GenerateLookupNumberStringCache(masm,
arg,
scratch1,
scratch2,
scratch3,
slow);
__ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
__ mov(arg, scratch1);
__ mov(Operand(esp, stack_offset), arg);
__ bind(&done);
......
......@@ -221,18 +221,6 @@ class NumberToStringStub: public PlatformCodeStub {
public:
NumberToStringStub() { }
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
static void GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found);
private:
Major MajorKey() { return NumberToString; }
int MinorKey() { return 0; }
......
......@@ -3023,6 +3023,88 @@ void MacroAssembler::LoadPowerOf2(XMMRegister dst,
}
void MacroAssembler::LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch1;
Register scratch = scratch2;
// Load the number string cache.
LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
shr(mask, kSmiTagSize + 1); // Untag length and divide it by two.
sub(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, and the hash for
// doubles is the xor of the upper and lower words. See
// Heap::GetNumberStringCache.
Label smi_hash_calculated;
Label load_result_from_cache;
Label not_smi;
STATIC_ASSERT(kSmiTag == 0);
JumpIfNotSmi(object, &not_smi, Label::kNear);
mov(scratch, object);
SmiUntag(scratch);
jmp(&smi_hash_calculated, Label::kNear);
bind(&not_smi);
cmp(FieldOperand(object, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
j(not_equal, not_found);
STATIC_ASSERT(8 == kDoubleSize);
mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
// Object is heap number and hash is now in scratch. Calculate cache index.
and_(scratch, mask);
Register index = scratch;
Register probe = mask;
mov(probe,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
JumpIfSmi(probe, not_found);
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatureScope fscope(this, SSE2);
movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
} else {
fld_d(FieldOperand(object, HeapNumber::kValueOffset));
fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
FCmp();
}
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, Label::kNear);
bind(&smi_hash_calculated);
// Object is smi and hash is now in scratch. Calculate cache index.
and_(scratch, mask);
// Check if the entry is the smi we are looking for.
cmp(object,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize));
j(not_equal, not_found);
// Get the result from the cache.
bind(&load_result_from_cache);
mov(result,
FieldOperand(number_string_cache,
index,
times_twice_pointer_size,
FixedArray::kHeaderSize + kPointerSize));
IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
}
void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
Register instance_type,
Register scratch,
......
......@@ -897,6 +897,17 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// String utilities.
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
void LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found);
// Check whether the instance type represents a flat ASCII string. Jump to the
// label if not. If the instance type can be scratched specify same register
// for both instance type and scratch.
......
......@@ -1142,13 +1142,11 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// Lookup the argument in the number to string cache.
Label not_cached, argument_is_string;
NumberToStringStub::GenerateLookupNumberStringCache(
masm,
rax, // Input.
rbx, // Result.
rcx, // Scratch 1.
rdx, // Scratch 2.
&not_cached);
__ LookupNumberStringCache(rax, // Input.
rbx, // Result.
rcx, // Scratch 1.
rdx, // Scratch 2.
&not_cached);
__ IncrementCounter(counters->string_ctor_cached_number(), 1);
__ bind(&argument_is_string);
......
......@@ -2909,96 +2909,6 @@ void RegExpConstructResultStub::Generate(MacroAssembler* masm) {
}
void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch1;
Register scratch = scratch2;
// Load the number string cache.
__ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
__ SmiToInteger32(
mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
__ shrl(mask, Immediate(1));
__ subq(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, 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;
Factory* factory = masm->isolate()->factory();
__ JumpIfSmi(object, &is_smi);
__ CheckMap(object,
factory->heap_number_map(),
not_found,
DONT_DO_SMI_CHECK);
STATIC_ASSERT(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);
__ movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
__ movsd(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
__ ucomisd(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);
__ SmiToInteger32(scratch, object);
GenerateConvertHashCodeToIndex(masm, scratch, mask);
// Check if the entry is the smi we are looking for.
__ cmpq(object,
FieldOperand(number_string_cache,
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,
index,
times_1,
FixedArray::kHeaderSize + kPointerSize));
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->number_to_string_native(), 1);
}
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::Generate(MacroAssembler* masm) {
Label runtime;
......@@ -3006,7 +2916,7 @@ void NumberToStringStub::Generate(MacroAssembler* masm) {
__ movq(rbx, args.GetArgumentOperand(0));
// Generate code to lookup number in the number string cache.
GenerateLookupNumberStringCache(masm, rbx, rax, r8, r9, &runtime);
__ LookupNumberStringCache(rbx, rax, r8, r9, &runtime);
__ ret(1 * kPointerSize);
__ bind(&runtime);
......@@ -4646,12 +4556,7 @@ void StringAddStub::GenerateConvertArgument(MacroAssembler* masm,
// Check the number to string cache.
__ bind(&not_string);
// Puts the cached result into scratch1.
NumberToStringStub::GenerateLookupNumberStringCache(masm,
arg,
scratch1,
scratch2,
scratch3,
slow);
__ LookupNumberStringCache(arg, scratch1, scratch2, scratch3, slow);
__ movq(arg, scratch1);
__ movq(Operand(rsp, stack_offset), arg);
__ bind(&done);
......
......@@ -212,23 +212,7 @@ class NumberToStringStub: public PlatformCodeStub {
public:
NumberToStringStub() { }
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
static void GenerateLookupNumberStringCache(MacroAssembler* masm,
Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found);
private:
static void GenerateConvertHashCodeToIndex(MacroAssembler* masm,
Register hash,
Register mask);
Major MajorKey() { return NumberToString; }
int MinorKey() { return 0; }
......
......@@ -2264,6 +2264,90 @@ void MacroAssembler::Test(const Operand& src, Smi* source) {
// ----------------------------------------------------------------------------
void MacroAssembler::LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found) {
// Use of registers. Register result is used as a temporary.
Register number_string_cache = result;
Register mask = scratch1;
Register scratch = scratch2;
// Load the number string cache.
LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
// Make the hash mask from the length of the number string cache. It
// contains two elements (number and string) for each cache entry.
SmiToInteger32(
mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
shrl(mask, Immediate(1));
subq(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, 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;
JumpIfSmi(object, &is_smi);
CheckMap(object,
isolate()->factory()->heap_number_map(),
not_found,
DONT_DO_SMI_CHECK);
STATIC_ASSERT(8 == kDoubleSize);
movl(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset));
and_(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;
Register probe = mask;
movq(probe,
FieldOperand(number_string_cache,
index,
times_1,
FixedArray::kHeaderSize));
JumpIfSmi(probe, not_found);
movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
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);
SmiToInteger32(scratch, object);
and_(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));
// Check if the entry is the smi we are looking for.
cmpq(object,
FieldOperand(number_string_cache,
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,
index,
times_1,
FixedArray::kHeaderSize + kPointerSize));
IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
}
void MacroAssembler::JumpIfNotString(Register object,
Register object_map,
Label* not_string,
......
......@@ -739,6 +739,17 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// String macros.
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
// can be the same. If the number is not found in the cache the code jumps to
// the label not_found with only the content of register object unchanged.
void LookupNumberStringCache(Register object,
Register result,
Register scratch1,
Register scratch2,
Label* not_found);
// If object is a string, its map is loaded into object_map.
void JumpIfNotString(Register object,
Register object_map,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment