Add number string cache lookup for heap numbers to generatred code (on top of the already existing smi lookup)
Added a number to string runtime function which does not try to do a cache lookup as the number is known to not be in the cahce. Review URL: http://codereview.chromium.org/1602010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4355 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c33886c9b7
commit
c0976e9276
10
src/heap.cc
10
src/heap.cc
@ -1808,11 +1808,13 @@ Object* Heap::SmiOrNumberFromDouble(double value,
|
||||
}
|
||||
|
||||
|
||||
Object* Heap::NumberToString(Object* number) {
|
||||
Object* Heap::NumberToString(Object* number, bool check_number_string_cache) {
|
||||
Counters::number_to_string_runtime.Increment();
|
||||
Object* cached = GetNumberStringCache(number);
|
||||
if (cached != undefined_value()) {
|
||||
return cached;
|
||||
if (check_number_string_cache) {
|
||||
Object* cached = GetNumberStringCache(number);
|
||||
if (cached != undefined_value()) {
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
char arr[100];
|
||||
|
@ -938,7 +938,8 @@ class Heap : public AllStatic {
|
||||
kRootListLength
|
||||
};
|
||||
|
||||
static Object* NumberToString(Object* number);
|
||||
static Object* NumberToString(Object* number,
|
||||
bool check_number_string_cache = true);
|
||||
|
||||
static Map* MapForExternalArrayType(ExternalArrayType array_type);
|
||||
static RootListIndex RootIndexForExternalArrayType(
|
||||
|
@ -10938,14 +10938,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) {
|
||||
ASSERT(kSmiTag == 0);
|
||||
__ test(object, Immediate(kSmiTagMask));
|
||||
__ j(not_zero, not_found);
|
||||
}
|
||||
|
||||
// Use of registers. Register result is used as a temporary.
|
||||
Register number_string_cache = result;
|
||||
Register mask = scratch1;
|
||||
@ -10961,23 +10953,74 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm,
|
||||
__ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
|
||||
__ shr(mask, 1); // Divide length by two (length is not a smi).
|
||||
__ sub(Operand(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.
|
||||
__ mov(scratch, object);
|
||||
__ SmiUntag(scratch);
|
||||
// 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;
|
||||
if (object_is_smi) {
|
||||
__ mov(scratch, object);
|
||||
__ SmiUntag(scratch);
|
||||
} else {
|
||||
Label not_smi, hash_calculated;
|
||||
ASSERT(kSmiTag == 0);
|
||||
__ test(object, Immediate(kSmiTagMask));
|
||||
__ j(not_zero, ¬_smi);
|
||||
__ mov(scratch, object);
|
||||
__ SmiUntag(scratch);
|
||||
__ jmp(&smi_hash_calculated);
|
||||
__ bind(¬_smi);
|
||||
__ cmp(FieldOperand(object, HeapObject::kMapOffset),
|
||||
Factory::heap_number_map());
|
||||
__ j(not_equal, not_found);
|
||||
ASSERT_EQ(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, Operand(mask));
|
||||
Register index = scratch;
|
||||
Register probe = mask;
|
||||
__ mov(probe,
|
||||
FieldOperand(number_string_cache,
|
||||
index,
|
||||
times_twice_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
__ test(probe, Immediate(kSmiTagMask));
|
||||
__ j(zero, not_found);
|
||||
if (CpuFeatures::IsSupported(SSE2)) {
|
||||
CpuFeatures::Scope fscope(SSE2);
|
||||
__ movdbl(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
|
||||
__ movdbl(xmm1, FieldOperand(probe, HeapNumber::kValueOffset));
|
||||
__ comisd(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);
|
||||
}
|
||||
|
||||
__ bind(&smi_hash_calculated);
|
||||
// Object is smi and hash is now in scratch. Calculate cache index.
|
||||
__ and_(scratch, Operand(mask));
|
||||
Register index = scratch;
|
||||
// Check if the entry is the smi we are looking for.
|
||||
__ cmp(object,
|
||||
FieldOperand(number_string_cache,
|
||||
scratch,
|
||||
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,
|
||||
scratch,
|
||||
index,
|
||||
times_twice_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize));
|
||||
__ IncrementCounter(&Counters::number_to_string_native, 1);
|
||||
@ -10995,7 +11038,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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -5249,6 +5249,17 @@ static Object* Runtime_NumberToString(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_NumberToStringSkipCache(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
|
||||
Object* number = args[0];
|
||||
RUNTIME_ASSERT(number->IsNumber());
|
||||
|
||||
return Heap::NumberToString(number, false);
|
||||
}
|
||||
|
||||
|
||||
static Object* Runtime_NumberToInteger(Arguments args) {
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 1);
|
||||
|
@ -99,6 +99,7 @@ namespace internal {
|
||||
F(URIUnescape, 1, 1) \
|
||||
\
|
||||
F(NumberToString, 1, 1) \
|
||||
F(NumberToStringSkipCache, 1, 1) \
|
||||
F(NumberToInteger, 1, 1) \
|
||||
F(NumberToJSUint32, 1, 1) \
|
||||
F(NumberToJSInt32, 1, 1) \
|
||||
|
@ -530,7 +530,7 @@ function ToString(x) {
|
||||
}
|
||||
|
||||
function NonStringToString(x) {
|
||||
if (IS_NUMBER(x)) return %NumberToString(x);
|
||||
if (IS_NUMBER(x)) return %_NumberToString(x);
|
||||
if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
|
||||
if (IS_UNDEFINED(x)) return 'undefined';
|
||||
return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
|
||||
|
Loading…
Reference in New Issue
Block a user