Index: src/factory.cc |
diff --git a/src/factory.cc b/src/factory.cc |
index 3865aa851aa6400aa9403512423ca5ff3b32e9b6..bc25f451263bf36d0bbf139379919b819418cbda 100644 |
--- a/src/factory.cc |
+++ b/src/factory.cc |
@@ -6,6 +6,7 @@ |
#include "macro-assembler.h" |
#include "isolate-inl.h" |
+#include "v8conversions.h" |
namespace v8 { |
namespace internal { |
@@ -696,10 +697,11 @@ Handle<Struct> Factory::NewStruct(InstanceType type) { |
Handle<CodeCache> Factory::NewCodeCache() { |
- CALL_HEAP_FUNCTION( |
- isolate(), |
- isolate()->heap()->AllocateCodeCache(), |
- CodeCache); |
+ Handle<CodeCache> code_cache = |
+ Handle<CodeCache>::cast(NewStruct(CODE_CACHE_TYPE)); |
+ code_cache->set_default_cache(*empty_fixed_array(), SKIP_WRITE_BARRIER); |
+ code_cache->set_normal_type_cache(*undefined_value(), SKIP_WRITE_BARRIER); |
+ return code_cache; |
} |
@@ -991,17 +993,26 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo( |
Handle<Object> Factory::NewNumber(double value, |
PretenureFlag pretenure) { |
- CALL_HEAP_FUNCTION( |
- isolate(), |
- isolate()->heap()->NumberFromDouble(value, pretenure), Object); |
+ // We need to distinguish the minus zero value and this cannot be |
+ // done after conversion to int. Doing this by comparing bit |
+ // patterns is faster than using fpclassify() et al. |
+ if (IsMinusZero(value)) return minus_zero_value(); |
+ |
+ int int_value = FastD2I(value); |
+ if (value == int_value && Smi::IsValid(int_value)) { |
+ return handle(Smi::FromInt(int_value), isolate()); |
+ } |
+ |
+ // Materialize the value in the heap. |
+ return NewHeapNumber(value, pretenure); |
} |
Handle<Object> Factory::NewNumberFromInt(int32_t value, |
PretenureFlag pretenure) { |
- CALL_HEAP_FUNCTION( |
- isolate(), |
- isolate()->heap()->NumberFromInt32(value, pretenure), Object); |
+ if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate()); |
+ // Bypass NumberFromDouble to avoid various redundant checks. |
+ return NewHeapNumber(FastI2D(value), pretenure); |
} |
@@ -1775,18 +1786,78 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) { |
} |
+static inline int NumberCacheHash(Handle<FixedArray> cache, |
+ Handle<Object> number) { |
+ int mask = (cache->length() >> 1) - 1; |
+ if (number->IsSmi()) { |
+ return Handle<Smi>::cast(number)->value() & mask; |
+ } else { |
+ DoubleRepresentation rep(number->Number()); |
+ return |
+ (static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32)) & mask; |
+ } |
+} |
+ |
+ |
+Handle<Object> Factory::GetNumberStringCache(Handle<Object> number) { |
+ DisallowHeapAllocation no_gc; |
+ int hash = NumberCacheHash(number_string_cache(), number); |
+ Object* key = number_string_cache()->get(hash * 2); |
+ if (key == *number || (key->IsHeapNumber() && number->IsHeapNumber() && |
+ key->Number() == number->Number())) { |
+ return Handle<String>( |
+ String::cast(number_string_cache()->get(hash * 2 + 1)), isolate()); |
+ } |
+ return undefined_value(); |
+} |
+ |
+ |
+void Factory::SetNumberStringCache(Handle<Object> number, |
+ Handle<String> string) { |
+ int hash = NumberCacheHash(number_string_cache(), number); |
+ if (number_string_cache()->get(hash * 2) != *undefined_value()) { |
+ int full_size = isolate()->heap()->FullSizeNumberStringCacheLength(); |
+ if (number_string_cache()->length() != full_size) { |
+ // The first time we have a hash collision, we move to the full sized |
+ // number string cache. The idea is to have a small number string |
+ // cache in the snapshot to keep boot-time memory usage down. |
+ // If we expand the number string cache already while creating |
+ // the snapshot then that didn't work out. |
+ ASSERT(!Serializer::enabled() || FLAG_extra_code != NULL); |
+ Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED); |
+ isolate()->heap()->set_number_string_cache(*new_cache); |
+ return; |
+ } |
+ } |
+ number_string_cache()->set(hash * 2, *number); |
+ number_string_cache()->set(hash * 2 + 1, *string); |
+} |
+ |
+ |
Handle<String> Factory::NumberToString(Handle<Object> number, |
bool check_number_string_cache) { |
- CALL_HEAP_FUNCTION(isolate(), |
- isolate()->heap()->NumberToString( |
- *number, check_number_string_cache), |
- String); |
-} |
+ isolate()->counters()->number_to_string_runtime()->Increment(); |
+ if (check_number_string_cache) { |
+ Handle<Object> cached = GetNumberStringCache(number); |
+ if (!cached->IsUndefined()) return Handle<String>::cast(cached); |
+ } |
+ char arr[100]; |
+ Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
+ const char* str; |
+ if (number->IsSmi()) { |
+ int num = Handle<Smi>::cast(number)->value(); |
+ str = IntToCString(num, buffer); |
+ } else { |
+ double num = Handle<HeapNumber>::cast(number)->value(); |
+ str = DoubleToCString(num, buffer); |
+ } |
-Handle<String> Factory::Uint32ToString(uint32_t value) { |
- CALL_HEAP_FUNCTION(isolate(), |
- isolate()->heap()->Uint32ToString(value), String); |
+ // We tenure the allocated string since it is referenced from the |
+ // number-string cache which lives in the old space. |
+ Handle<String> js_string = NewStringFromOneByte(OneByteVector(str), TENURED); |
+ SetNumberStringCache(number, js_string); |
+ return js_string; |
} |