OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "factory.h" | 5 #include "factory.h" |
6 | 6 |
7 #include "macro-assembler.h" | 7 #include "macro-assembler.h" |
8 #include "isolate-inl.h" | 8 #include "isolate-inl.h" |
| 9 #include "v8conversions.h" |
9 | 10 |
10 namespace v8 { | 11 namespace v8 { |
11 namespace internal { | 12 namespace internal { |
12 | 13 |
13 | 14 |
14 template<typename T> | 15 template<typename T> |
15 Handle<T> Factory::New(Handle<Map> map, AllocationSpace space) { | 16 Handle<T> Factory::New(Handle<Map> map, AllocationSpace space) { |
16 CALL_HEAP_FUNCTION( | 17 CALL_HEAP_FUNCTION( |
17 isolate(), | 18 isolate(), |
18 isolate()->heap()->Allocate(*map, space), | 19 isolate()->heap()->Allocate(*map, space), |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 | 690 |
690 Handle<Struct> Factory::NewStruct(InstanceType type) { | 691 Handle<Struct> Factory::NewStruct(InstanceType type) { |
691 CALL_HEAP_FUNCTION( | 692 CALL_HEAP_FUNCTION( |
692 isolate(), | 693 isolate(), |
693 isolate()->heap()->AllocateStruct(type), | 694 isolate()->heap()->AllocateStruct(type), |
694 Struct); | 695 Struct); |
695 } | 696 } |
696 | 697 |
697 | 698 |
698 Handle<CodeCache> Factory::NewCodeCache() { | 699 Handle<CodeCache> Factory::NewCodeCache() { |
699 CALL_HEAP_FUNCTION( | 700 Handle<CodeCache> code_cache = |
700 isolate(), | 701 Handle<CodeCache>::cast(NewStruct(CODE_CACHE_TYPE)); |
701 isolate()->heap()->AllocateCodeCache(), | 702 code_cache->set_default_cache(*empty_fixed_array(), SKIP_WRITE_BARRIER); |
702 CodeCache); | 703 code_cache->set_normal_type_cache(*undefined_value(), SKIP_WRITE_BARRIER); |
| 704 return code_cache; |
703 } | 705 } |
704 | 706 |
705 | 707 |
706 Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry( | 708 Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry( |
707 int aliased_context_slot) { | 709 int aliased_context_slot) { |
708 Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast( | 710 Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast( |
709 NewStruct(ALIASED_ARGUMENTS_ENTRY_TYPE)); | 711 NewStruct(ALIASED_ARGUMENTS_ENTRY_TYPE)); |
710 entry->set_aliased_context_slot(aliased_context_slot); | 712 entry->set_aliased_context_slot(aliased_context_slot); |
711 return entry; | 713 return entry; |
712 } | 714 } |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 !function_info->optimization_disabled() && | 986 !function_info->optimization_disabled() && |
985 !isolate()->DebuggerHasBreakPoints()) { | 987 !isolate()->DebuggerHasBreakPoints()) { |
986 result->MarkForOptimization(); | 988 result->MarkForOptimization(); |
987 } | 989 } |
988 return result; | 990 return result; |
989 } | 991 } |
990 | 992 |
991 | 993 |
992 Handle<Object> Factory::NewNumber(double value, | 994 Handle<Object> Factory::NewNumber(double value, |
993 PretenureFlag pretenure) { | 995 PretenureFlag pretenure) { |
994 CALL_HEAP_FUNCTION( | 996 // We need to distinguish the minus zero value and this cannot be |
995 isolate(), | 997 // done after conversion to int. Doing this by comparing bit |
996 isolate()->heap()->NumberFromDouble(value, pretenure), Object); | 998 // patterns is faster than using fpclassify() et al. |
| 999 if (IsMinusZero(value)) return minus_zero_value(); |
| 1000 |
| 1001 int int_value = FastD2I(value); |
| 1002 if (value == int_value && Smi::IsValid(int_value)) { |
| 1003 return handle(Smi::FromInt(int_value), isolate()); |
| 1004 } |
| 1005 |
| 1006 // Materialize the value in the heap. |
| 1007 return NewHeapNumber(value, pretenure); |
997 } | 1008 } |
998 | 1009 |
999 | 1010 |
1000 Handle<Object> Factory::NewNumberFromInt(int32_t value, | 1011 Handle<Object> Factory::NewNumberFromInt(int32_t value, |
1001 PretenureFlag pretenure) { | 1012 PretenureFlag pretenure) { |
1002 CALL_HEAP_FUNCTION( | 1013 if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate()); |
1003 isolate(), | 1014 // Bypass NumberFromDouble to avoid various redundant checks. |
1004 isolate()->heap()->NumberFromInt32(value, pretenure), Object); | 1015 return NewHeapNumber(FastI2D(value), pretenure); |
1005 } | 1016 } |
1006 | 1017 |
1007 | 1018 |
1008 Handle<Object> Factory::NewNumberFromUint(uint32_t value, | 1019 Handle<Object> Factory::NewNumberFromUint(uint32_t value, |
1009 PretenureFlag pretenure) { | 1020 PretenureFlag pretenure) { |
1010 CALL_HEAP_FUNCTION( | 1021 CALL_HEAP_FUNCTION( |
1011 isolate(), | 1022 isolate(), |
1012 isolate()->heap()->NumberFromUint32(value, pretenure), Object); | 1023 isolate()->heap()->NumberFromUint32(value, pretenure), Object); |
1013 } | 1024 } |
1014 | 1025 |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 } | 1779 } |
1769 | 1780 |
1770 | 1781 |
1771 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) { | 1782 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) { |
1772 CALL_HEAP_FUNCTION(isolate(), | 1783 CALL_HEAP_FUNCTION(isolate(), |
1773 isolate()->heap()->AllocateSharedFunctionInfo(*name), | 1784 isolate()->heap()->AllocateSharedFunctionInfo(*name), |
1774 SharedFunctionInfo); | 1785 SharedFunctionInfo); |
1775 } | 1786 } |
1776 | 1787 |
1777 | 1788 |
| 1789 static inline int NumberCacheHash(Handle<FixedArray> cache, |
| 1790 Handle<Object> number) { |
| 1791 int mask = (cache->length() >> 1) - 1; |
| 1792 if (number->IsSmi()) { |
| 1793 return Handle<Smi>::cast(number)->value() & mask; |
| 1794 } else { |
| 1795 DoubleRepresentation rep(number->Number()); |
| 1796 return |
| 1797 (static_cast<int>(rep.bits) ^ static_cast<int>(rep.bits >> 32)) & mask; |
| 1798 } |
| 1799 } |
| 1800 |
| 1801 |
| 1802 Handle<Object> Factory::GetNumberStringCache(Handle<Object> number) { |
| 1803 DisallowHeapAllocation no_gc; |
| 1804 int hash = NumberCacheHash(number_string_cache(), number); |
| 1805 Object* key = number_string_cache()->get(hash * 2); |
| 1806 if (key == *number || (key->IsHeapNumber() && number->IsHeapNumber() && |
| 1807 key->Number() == number->Number())) { |
| 1808 return Handle<String>( |
| 1809 String::cast(number_string_cache()->get(hash * 2 + 1)), isolate()); |
| 1810 } |
| 1811 return undefined_value(); |
| 1812 } |
| 1813 |
| 1814 |
| 1815 void Factory::SetNumberStringCache(Handle<Object> number, |
| 1816 Handle<String> string) { |
| 1817 int hash = NumberCacheHash(number_string_cache(), number); |
| 1818 if (number_string_cache()->get(hash * 2) != *undefined_value()) { |
| 1819 int full_size = isolate()->heap()->FullSizeNumberStringCacheLength(); |
| 1820 if (number_string_cache()->length() != full_size) { |
| 1821 // The first time we have a hash collision, we move to the full sized |
| 1822 // number string cache. The idea is to have a small number string |
| 1823 // cache in the snapshot to keep boot-time memory usage down. |
| 1824 // If we expand the number string cache already while creating |
| 1825 // the snapshot then that didn't work out. |
| 1826 ASSERT(!Serializer::enabled() || FLAG_extra_code != NULL); |
| 1827 Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED); |
| 1828 isolate()->heap()->set_number_string_cache(*new_cache); |
| 1829 return; |
| 1830 } |
| 1831 } |
| 1832 number_string_cache()->set(hash * 2, *number); |
| 1833 number_string_cache()->set(hash * 2 + 1, *string); |
| 1834 } |
| 1835 |
| 1836 |
1778 Handle<String> Factory::NumberToString(Handle<Object> number, | 1837 Handle<String> Factory::NumberToString(Handle<Object> number, |
1779 bool check_number_string_cache) { | 1838 bool check_number_string_cache) { |
1780 CALL_HEAP_FUNCTION(isolate(), | 1839 isolate()->counters()->number_to_string_runtime()->Increment(); |
1781 isolate()->heap()->NumberToString( | 1840 if (check_number_string_cache) { |
1782 *number, check_number_string_cache), | 1841 Handle<Object> cached = GetNumberStringCache(number); |
1783 String); | 1842 if (!cached->IsUndefined()) return Handle<String>::cast(cached); |
| 1843 } |
| 1844 |
| 1845 char arr[100]; |
| 1846 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 1847 const char* str; |
| 1848 if (number->IsSmi()) { |
| 1849 int num = Handle<Smi>::cast(number)->value(); |
| 1850 str = IntToCString(num, buffer); |
| 1851 } else { |
| 1852 double num = Handle<HeapNumber>::cast(number)->value(); |
| 1853 str = DoubleToCString(num, buffer); |
| 1854 } |
| 1855 |
| 1856 // We tenure the allocated string since it is referenced from the |
| 1857 // number-string cache which lives in the old space. |
| 1858 Handle<String> js_string = NewStringFromOneByte(OneByteVector(str), TENURED); |
| 1859 SetNumberStringCache(number, js_string); |
| 1860 return js_string; |
1784 } | 1861 } |
1785 | 1862 |
1786 | 1863 |
1787 Handle<String> Factory::Uint32ToString(uint32_t value) { | |
1788 CALL_HEAP_FUNCTION(isolate(), | |
1789 isolate()->heap()->Uint32ToString(value), String); | |
1790 } | |
1791 | |
1792 | |
1793 Handle<SeededNumberDictionary> Factory::DictionaryAtNumberPut( | 1864 Handle<SeededNumberDictionary> Factory::DictionaryAtNumberPut( |
1794 Handle<SeededNumberDictionary> dictionary, | 1865 Handle<SeededNumberDictionary> dictionary, |
1795 uint32_t key, | 1866 uint32_t key, |
1796 Handle<Object> value) { | 1867 Handle<Object> value) { |
1797 CALL_HEAP_FUNCTION(isolate(), | 1868 CALL_HEAP_FUNCTION(isolate(), |
1798 dictionary->AtNumberPut(key, *value), | 1869 dictionary->AtNumberPut(key, *value), |
1799 SeededNumberDictionary); | 1870 SeededNumberDictionary); |
1800 } | 1871 } |
1801 | 1872 |
1802 | 1873 |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2170 if (String::Equals(name, infinity_string())) return infinity_value(); | 2241 if (String::Equals(name, infinity_string())) return infinity_value(); |
2171 return Handle<Object>::null(); | 2242 return Handle<Object>::null(); |
2172 } | 2243 } |
2173 | 2244 |
2174 | 2245 |
2175 Handle<Object> Factory::ToBoolean(bool value) { | 2246 Handle<Object> Factory::ToBoolean(bool value) { |
2176 return value ? true_value() : false_value(); | 2247 return value ? true_value() : false_value(); |
2177 } | 2248 } |
2178 | 2249 |
2179 } } // namespace v8::internal | 2250 } } // namespace v8::internal |
OLD | NEW |