| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| 11 #include "src/code-stubs.h" |
| 11 #include "src/deoptimizer.h" | 12 #include "src/deoptimizer.h" |
| 12 #include "src/execution.h" | 13 #include "src/execution.h" |
| 13 #include "src/global-handles.h" | 14 #include "src/global-handles.h" |
| 14 #include "src/ic/ic.h" | 15 #include "src/ic/ic.h" |
| 15 #include "src/ic/stub-cache.h" | 16 #include "src/ic/stub-cache.h" |
| 16 #include "src/natives.h" | 17 #include "src/natives.h" |
| 17 #include "src/objects.h" | 18 #include "src/objects.h" |
| 18 #include "src/runtime.h" | 19 #include "src/runtime.h" |
| 19 #include "src/serialize.h" | 20 #include "src/serialize.h" |
| 20 #include "src/snapshot.h" | 21 #include "src/snapshot.h" |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 DCHECK(deserializing_user_code()); \ | 866 DCHECK(deserializing_user_code()); \ |
| 866 int builtin_id = source_->GetInt(); \ | 867 int builtin_id = source_->GetInt(); \ |
| 867 DCHECK_LE(0, builtin_id); \ | 868 DCHECK_LE(0, builtin_id); \ |
| 868 DCHECK_LT(builtin_id, Builtins::builtin_count); \ | 869 DCHECK_LT(builtin_id, Builtins::builtin_count); \ |
| 869 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 870 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
| 870 new_object = isolate->builtins()->builtin(name); \ | 871 new_object = isolate->builtins()->builtin(name); \ |
| 871 emit_write_barrier = false; \ | 872 emit_write_barrier = false; \ |
| 872 } else if (where == kAttachedReference) { \ | 873 } else if (where == kAttachedReference) { \ |
| 873 DCHECK(deserializing_user_code()); \ | 874 DCHECK(deserializing_user_code()); \ |
| 874 int index = source_->GetInt(); \ | 875 int index = source_->GetInt(); \ |
| 875 new_object = attached_objects_->at(index); \ | 876 new_object = *attached_objects_->at(index); \ |
| 876 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 877 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
| 877 } else { \ | 878 } else { \ |
| 878 DCHECK(where == kBackrefWithSkip); \ | 879 DCHECK(where == kBackrefWithSkip); \ |
| 879 int skip = source_->GetInt(); \ | 880 int skip = source_->GetInt(); \ |
| 880 current = reinterpret_cast<Object**>( \ | 881 current = reinterpret_cast<Object**>( \ |
| 881 reinterpret_cast<Address>(current) + skip); \ | 882 reinterpret_cast<Address>(current) + skip); \ |
| 882 emit_write_barrier = (space_number == NEW_SPACE); \ | 883 emit_write_barrier = (space_number == NEW_SPACE); \ |
| 883 new_object = GetAddressFromEnd(data & kSpaceMask); \ | 884 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 884 if (deserializing_user_code()) { \ | 885 if (deserializing_user_code()) { \ |
| 885 new_object = ProcessBackRefInSerializedCode(new_object); \ | 886 new_object = ProcessBackRefInSerializedCode(new_object); \ |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1130 CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0) | 1131 CASE_STATEMENT(kBuiltin, kPlain, kInnerPointer, 0) |
| 1131 CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0) | 1132 CASE_BODY(kBuiltin, kPlain, kInnerPointer, 0) |
| 1132 #endif | 1133 #endif |
| 1133 // Find a builtin and write a pointer to it in the current code object. | 1134 // Find a builtin and write a pointer to it in the current code object. |
| 1134 CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0) | 1135 CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0) |
| 1135 CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0) | 1136 CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0) |
| 1136 // Find an object in the attached references and write a pointer to it to | 1137 // Find an object in the attached references and write a pointer to it to |
| 1137 // the current object. | 1138 // the current object. |
| 1138 CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0) | 1139 CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0) |
| 1139 CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0) | 1140 CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0) |
| 1141 CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0) |
| 1142 CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0) |
| 1143 CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0) |
| 1144 CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0) |
| 1140 | 1145 |
| 1141 #undef CASE_STATEMENT | 1146 #undef CASE_STATEMENT |
| 1142 #undef CASE_BODY | 1147 #undef CASE_BODY |
| 1143 #undef ALL_SPACES | 1148 #undef ALL_SPACES |
| 1144 | 1149 |
| 1145 case kSkip: { | 1150 case kSkip: { |
| 1146 int size = source_->GetInt(); | 1151 int size = source_->GetInt(); |
| 1147 current = reinterpret_cast<Object**>( | 1152 current = reinterpret_cast<Object**>( |
| 1148 reinterpret_cast<intptr_t>(current) + size); | 1153 reinterpret_cast<intptr_t>(current) + size); |
| 1149 break; | 1154 break; |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1307 } | 1312 } |
| 1308 } | 1313 } |
| 1309 return kInvalidRootIndex; | 1314 return kInvalidRootIndex; |
| 1310 } | 1315 } |
| 1311 | 1316 |
| 1312 | 1317 |
| 1313 // Encode the location of an already deserialized object in order to write its | 1318 // Encode the location of an already deserialized object in order to write its |
| 1314 // location into a later object. We can encode the location as an offset from | 1319 // location into a later object. We can encode the location as an offset from |
| 1315 // the start of the deserialized objects or as an offset backwards from the | 1320 // the start of the deserialized objects or as an offset backwards from the |
| 1316 // current allocation pointer. | 1321 // current allocation pointer. |
| 1317 void Serializer::SerializeReferenceToPreviousObject( | 1322 void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object, |
| 1318 int space, | 1323 HowToCode how_to_code, |
| 1319 int address, | 1324 WhereToPoint where_to_point, |
| 1320 HowToCode how_to_code, | 1325 int skip) { |
| 1321 WhereToPoint where_to_point, | 1326 int space = SpaceOfObject(heap_object); |
| 1322 int skip) { | 1327 int address = address_mapper_.MappedTo(heap_object); |
| 1323 int offset = CurrentAllocationAddress(space) - address; | 1328 int offset = CurrentAllocationAddress(space) - address; |
| 1324 // Shift out the bits that are always 0. | 1329 // Shift out the bits that are always 0. |
| 1325 offset >>= kObjectAlignmentBits; | 1330 offset >>= kObjectAlignmentBits; |
| 1326 if (skip == 0) { | 1331 if (skip == 0) { |
| 1327 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); | 1332 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); |
| 1328 } else { | 1333 } else { |
| 1329 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, | 1334 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, |
| 1330 "BackRefSerWithSkip"); | 1335 "BackRefSerWithSkip"); |
| 1331 sink_->PutInt(skip, "BackRefSkipDistance"); | 1336 sink_->PutInt(skip, "BackRefSkipDistance"); |
| 1332 } | 1337 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1343 HeapObject* heap_object = HeapObject::cast(o); | 1348 HeapObject* heap_object = HeapObject::cast(o); |
| 1344 DCHECK(!heap_object->IsJSFunction()); | 1349 DCHECK(!heap_object->IsJSFunction()); |
| 1345 | 1350 |
| 1346 int root_index; | 1351 int root_index; |
| 1347 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { | 1352 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { |
| 1348 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); | 1353 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); |
| 1349 return; | 1354 return; |
| 1350 } | 1355 } |
| 1351 | 1356 |
| 1352 if (address_mapper_.IsMapped(heap_object)) { | 1357 if (address_mapper_.IsMapped(heap_object)) { |
| 1353 int space = SpaceOfObject(heap_object); | 1358 SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, |
| 1354 int address = address_mapper_.MappedTo(heap_object); | |
| 1355 SerializeReferenceToPreviousObject(space, | |
| 1356 address, | |
| 1357 how_to_code, | |
| 1358 where_to_point, | |
| 1359 skip); | 1359 skip); |
| 1360 } else { | 1360 } else { |
| 1361 if (skip != 0) { | 1361 if (skip != 0) { |
| 1362 sink_->Put(kSkip, "FlushPendingSkip"); | 1362 sink_->Put(kSkip, "FlushPendingSkip"); |
| 1363 sink_->PutInt(skip, "SkipDistance"); | 1363 sink_->PutInt(skip, "SkipDistance"); |
| 1364 } | 1364 } |
| 1365 | 1365 |
| 1366 // Object has not yet been serialized. Serialize it here. | 1366 // Object has not yet been serialized. Serialize it here. |
| 1367 ObjectSerializer object_serializer(this, | 1367 ObjectSerializer object_serializer(this, |
| 1368 heap_object, | 1368 heap_object, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1451 | 1451 |
| 1452 // Pointers from the partial snapshot to the objects in the startup snapshot | 1452 // Pointers from the partial snapshot to the objects in the startup snapshot |
| 1453 // should go through the root array or through the partial snapshot cache. | 1453 // should go through the root array or through the partial snapshot cache. |
| 1454 // If this is not the case you may have to add something to the root array. | 1454 // If this is not the case you may have to add something to the root array. |
| 1455 DCHECK(!startup_serializer_->address_mapper()->IsMapped(heap_object)); | 1455 DCHECK(!startup_serializer_->address_mapper()->IsMapped(heap_object)); |
| 1456 // All the internalized strings that the partial snapshot needs should be | 1456 // All the internalized strings that the partial snapshot needs should be |
| 1457 // either in the root table or in the partial snapshot cache. | 1457 // either in the root table or in the partial snapshot cache. |
| 1458 DCHECK(!heap_object->IsInternalizedString()); | 1458 DCHECK(!heap_object->IsInternalizedString()); |
| 1459 | 1459 |
| 1460 if (address_mapper_.IsMapped(heap_object)) { | 1460 if (address_mapper_.IsMapped(heap_object)) { |
| 1461 int space = SpaceOfObject(heap_object); | 1461 SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, |
| 1462 int address = address_mapper_.MappedTo(heap_object); | |
| 1463 SerializeReferenceToPreviousObject(space, | |
| 1464 address, | |
| 1465 how_to_code, | |
| 1466 where_to_point, | |
| 1467 skip); | 1462 skip); |
| 1468 } else { | 1463 } else { |
| 1469 if (skip != 0) { | 1464 if (skip != 0) { |
| 1470 sink_->Put(kSkip, "SkipFromSerializeObject"); | 1465 sink_->Put(kSkip, "SkipFromSerializeObject"); |
| 1471 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | 1466 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); |
| 1472 } | 1467 } |
| 1473 // Object has not yet been serialized. Serialize it here. | 1468 // Object has not yet been serialized. Serialize it here. |
| 1474 ObjectSerializer serializer(this, | 1469 ObjectSerializer serializer(this, |
| 1475 heap_object, | 1470 heap_object, |
| 1476 sink_, | 1471 sink_, |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 | 1775 |
| 1781 void Serializer::InitializeCodeAddressMap() { | 1776 void Serializer::InitializeCodeAddressMap() { |
| 1782 isolate_->InitializeLoggingAndCounters(); | 1777 isolate_->InitializeLoggingAndCounters(); |
| 1783 code_address_map_ = new CodeAddressMap(isolate_); | 1778 code_address_map_ = new CodeAddressMap(isolate_); |
| 1784 } | 1779 } |
| 1785 | 1780 |
| 1786 | 1781 |
| 1787 ScriptData* CodeSerializer::Serialize(Isolate* isolate, | 1782 ScriptData* CodeSerializer::Serialize(Isolate* isolate, |
| 1788 Handle<SharedFunctionInfo> info, | 1783 Handle<SharedFunctionInfo> info, |
| 1789 Handle<String> source) { | 1784 Handle<String> source) { |
| 1785 base::ElapsedTimer timer; |
| 1786 if (FLAG_profile_deserialization) timer.Start(); |
| 1787 |
| 1790 // Serialize code object. | 1788 // Serialize code object. |
| 1791 List<byte> payload; | 1789 List<byte> payload; |
| 1792 ListSnapshotSink list_sink(&payload); | 1790 ListSnapshotSink list_sink(&payload); |
| 1793 CodeSerializer cs(isolate, &list_sink, *source); | 1791 DebugSnapshotSink debug_sink(&list_sink); |
| 1792 SnapshotByteSink* sink = FLAG_trace_code_serializer |
| 1793 ? static_cast<SnapshotByteSink*>(&debug_sink) |
| 1794 : static_cast<SnapshotByteSink*>(&list_sink); |
| 1795 CodeSerializer cs(isolate, sink, *source); |
| 1794 DisallowHeapAllocation no_gc; | 1796 DisallowHeapAllocation no_gc; |
| 1795 Object** location = Handle<Object>::cast(info).location(); | 1797 Object** location = Handle<Object>::cast(info).location(); |
| 1796 cs.VisitPointer(location); | 1798 cs.VisitPointer(location); |
| 1797 cs.Pad(); | 1799 cs.Pad(); |
| 1798 | 1800 |
| 1799 SerializedCodeData data(&payload, &cs); | 1801 SerializedCodeData data(&payload, &cs); |
| 1800 return data.GetScriptData(); | 1802 ScriptData* script_data = data.GetScriptData(); |
| 1803 |
| 1804 if (FLAG_profile_deserialization) { |
| 1805 double ms = timer.Elapsed().InMillisecondsF(); |
| 1806 int length = script_data->length(); |
| 1807 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
| 1808 } |
| 1809 |
| 1810 return script_data; |
| 1801 } | 1811 } |
| 1802 | 1812 |
| 1803 | 1813 |
| 1804 void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, | 1814 void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
| 1805 WhereToPoint where_to_point, int skip) { | 1815 WhereToPoint where_to_point, int skip) { |
| 1806 CHECK(o->IsHeapObject()); | 1816 CHECK(o->IsHeapObject()); |
| 1807 HeapObject* heap_object = HeapObject::cast(o); | 1817 HeapObject* heap_object = HeapObject::cast(o); |
| 1808 | 1818 |
| 1809 // The code-caches link to context-specific code objects, which | 1819 // The code-caches link to context-specific code objects, which |
| 1810 // the startup and context serializes cannot currently handle. | 1820 // the startup and context serializes cannot currently handle. |
| 1811 DCHECK(!heap_object->IsMap() || | 1821 DCHECK(!heap_object->IsMap() || |
| 1812 Map::cast(heap_object)->code_cache() == | 1822 Map::cast(heap_object)->code_cache() == |
| 1813 heap_object->GetHeap()->empty_fixed_array()); | 1823 heap_object->GetHeap()->empty_fixed_array()); |
| 1814 | 1824 |
| 1815 int root_index; | 1825 int root_index; |
| 1816 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { | 1826 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { |
| 1817 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); | 1827 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); |
| 1818 return; | 1828 return; |
| 1819 } | 1829 } |
| 1820 | 1830 |
| 1821 // TODO(yangguo) wire up stubs from stub cache. | |
| 1822 // TODO(yangguo) wire up global object. | 1831 // TODO(yangguo) wire up global object. |
| 1823 // TODO(yangguo) We cannot deal with different hash seeds yet. | 1832 // TODO(yangguo) We cannot deal with different hash seeds yet. |
| 1824 DCHECK(!heap_object->IsHashTable()); | 1833 DCHECK(!heap_object->IsHashTable()); |
| 1825 | 1834 |
| 1826 if (address_mapper_.IsMapped(heap_object)) { | 1835 if (address_mapper_.IsMapped(heap_object)) { |
| 1827 int space = SpaceOfObject(heap_object); | 1836 SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, |
| 1828 int address = address_mapper_.MappedTo(heap_object); | 1837 skip); |
| 1829 SerializeReferenceToPreviousObject(space, address, how_to_code, | |
| 1830 where_to_point, skip); | |
| 1831 return; | 1838 return; |
| 1832 } | 1839 } |
| 1833 | 1840 |
| 1834 if (heap_object->IsCode()) { | 1841 if (heap_object->IsCode()) { |
| 1835 Code* code_object = Code::cast(heap_object); | 1842 Code* code_object = Code::cast(heap_object); |
| 1836 if (code_object->kind() == Code::BUILTIN) { | 1843 if (code_object->kind() == Code::BUILTIN) { |
| 1837 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); | 1844 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); |
| 1838 return; | 1845 return; |
| 1839 } | 1846 } |
| 1840 // TODO(yangguo) figure out whether other code kinds can be handled smarter. | 1847 if (code_object->IsCodeStubOrIC()) { |
| 1848 SerializeCodeStub(code_object, how_to_code, where_to_point, skip); |
| 1849 return; |
| 1850 } |
| 1851 code_object->ClearInlineCaches(); |
| 1841 } | 1852 } |
| 1842 | 1853 |
| 1843 if (heap_object == source_) { | 1854 if (heap_object == source_) { |
| 1844 SerializeSourceObject(how_to_code, where_to_point, skip); | 1855 SerializeSourceObject(how_to_code, where_to_point, skip); |
| 1845 return; | 1856 return; |
| 1846 } | 1857 } |
| 1847 | 1858 |
| 1859 SerializeHeapObject(heap_object, how_to_code, where_to_point, skip); |
| 1860 } |
| 1861 |
| 1862 |
| 1863 void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, |
| 1864 HowToCode how_to_code, |
| 1865 WhereToPoint where_to_point, |
| 1866 int skip) { |
| 1848 if (heap_object->IsScript()) { | 1867 if (heap_object->IsScript()) { |
| 1849 // The wrapper cache uses a Foreign object to point to a global handle. | 1868 // The wrapper cache uses a Foreign object to point to a global handle. |
| 1850 // However, the object visitor expects foreign objects to point to external | 1869 // However, the object visitor expects foreign objects to point to external |
| 1851 // references. Clear the cache to avoid this issue. | 1870 // references. Clear the cache to avoid this issue. |
| 1852 Script::cast(heap_object)->ClearWrapperCache(); | 1871 Script::cast(heap_object)->ClearWrapperCache(); |
| 1853 } | 1872 } |
| 1854 | 1873 |
| 1855 if (skip != 0) { | 1874 if (skip != 0) { |
| 1856 sink_->Put(kSkip, "SkipFromSerializeObject"); | 1875 sink_->Put(kSkip, "SkipFromSerializeObject"); |
| 1857 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | 1876 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); |
| 1858 } | 1877 } |
| 1878 |
| 1879 if (FLAG_trace_code_serializer) { |
| 1880 PrintF("Encoding heap object: "); |
| 1881 heap_object->ShortPrint(); |
| 1882 PrintF("\n"); |
| 1883 } |
| 1884 |
| 1859 // Object has not yet been serialized. Serialize it here. | 1885 // Object has not yet been serialized. Serialize it here. |
| 1860 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, | 1886 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, |
| 1861 where_to_point); | 1887 where_to_point); |
| 1862 serializer.Serialize(); | 1888 serializer.Serialize(); |
| 1863 } | 1889 } |
| 1864 | 1890 |
| 1865 | 1891 |
| 1866 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, | 1892 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, |
| 1867 WhereToPoint where_to_point, int skip) { | 1893 WhereToPoint where_to_point, int skip) { |
| 1868 if (skip != 0) { | 1894 if (skip != 0) { |
| 1869 sink_->Put(kSkip, "SkipFromSerializeBuiltin"); | 1895 sink_->Put(kSkip, "SkipFromSerializeBuiltin"); |
| 1870 sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); | 1896 sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); |
| 1871 } | 1897 } |
| 1872 | 1898 |
| 1873 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || | 1899 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 1874 (how_to_code == kPlain && where_to_point == kInnerPointer) || | 1900 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
| 1875 (how_to_code == kFromCode && where_to_point == kInnerPointer)); | 1901 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 1876 int builtin_index = builtin->builtin_index(); | 1902 int builtin_index = builtin->builtin_index(); |
| 1877 DCHECK_LT(builtin_index, Builtins::builtin_count); | 1903 DCHECK_LT(builtin_index, Builtins::builtin_count); |
| 1878 DCHECK_LE(0, builtin_index); | 1904 DCHECK_LE(0, builtin_index); |
| 1905 |
| 1906 if (FLAG_trace_code_serializer) { |
| 1907 PrintF("Encoding builtin: %s\n", |
| 1908 isolate()->builtins()->name(builtin_index)); |
| 1909 } |
| 1910 |
| 1879 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); | 1911 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
| 1880 sink_->PutInt(builtin_index, "builtin_index"); | 1912 sink_->PutInt(builtin_index, "builtin_index"); |
| 1881 } | 1913 } |
| 1882 | 1914 |
| 1883 | 1915 |
| 1916 void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code, |
| 1917 WhereToPoint where_to_point, int skip) { |
| 1918 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 1919 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
| 1920 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 1921 uint32_t stub_key = code->stub_key(); |
| 1922 |
| 1923 if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) { |
| 1924 if (FLAG_trace_code_serializer) { |
| 1925 PrintF("Encoding uncacheable code stub as heap object\n"); |
| 1926 } |
| 1927 SerializeHeapObject(code, how_to_code, where_to_point, skip); |
| 1928 return; |
| 1929 } |
| 1930 |
| 1931 if (skip != 0) { |
| 1932 sink_->Put(kSkip, "SkipFromSerializeCodeStub"); |
| 1933 sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub"); |
| 1934 } |
| 1935 |
| 1936 int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; |
| 1937 |
| 1938 if (FLAG_trace_code_serializer) { |
| 1939 PrintF("Encoding code stub %s as %d\n", |
| 1940 CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), |
| 1941 index); |
| 1942 } |
| 1943 |
| 1944 sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); |
| 1945 sink_->PutInt(index, "CodeStub key"); |
| 1946 } |
| 1947 |
| 1948 |
| 1949 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { |
| 1950 // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2). |
| 1951 int index = 0; |
| 1952 while (index < stub_keys_.length()) { |
| 1953 if (stub_keys_[index] == stub_key) return index; |
| 1954 index++; |
| 1955 } |
| 1956 stub_keys_.Add(stub_key); |
| 1957 return index; |
| 1958 } |
| 1959 |
| 1960 |
| 1884 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, | 1961 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, |
| 1885 WhereToPoint where_to_point, | 1962 WhereToPoint where_to_point, |
| 1886 int skip) { | 1963 int skip) { |
| 1887 if (skip != 0) { | 1964 if (skip != 0) { |
| 1888 sink_->Put(kSkip, "SkipFromSerializeSourceObject"); | 1965 sink_->Put(kSkip, "SkipFromSerializeSourceObject"); |
| 1889 sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject"); | 1966 sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject"); |
| 1890 } | 1967 } |
| 1891 | 1968 |
| 1969 if (FLAG_trace_code_serializer) { |
| 1970 PrintF("Encoding source object\n"); |
| 1971 } |
| 1972 |
| 1892 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | 1973 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); |
| 1893 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); | 1974 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); |
| 1894 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); | 1975 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); |
| 1895 } | 1976 } |
| 1896 | 1977 |
| 1897 | 1978 |
| 1898 Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, | 1979 Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, |
| 1899 ScriptData* data, | 1980 ScriptData* data, |
| 1900 Handle<String> source) { | 1981 Handle<String> source) { |
| 1901 base::ElapsedTimer timer; | 1982 base::ElapsedTimer timer; |
| 1902 if (FLAG_profile_deserialization) timer.Start(); | 1983 if (FLAG_profile_deserialization) timer.Start(); |
| 1903 SerializedCodeData scd(data, *source); | 1984 |
| 1904 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); | 1985 Object* root; |
| 1905 Deserializer deserializer(&payload); | 1986 |
| 1906 STATIC_ASSERT(NEW_SPACE == 0); | 1987 { |
| 1907 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { | 1988 HandleScope scope(isolate); |
| 1908 deserializer.set_reservation(i, scd.GetReservation(i)); | 1989 |
| 1990 SerializedCodeData scd(data, *source); |
| 1991 SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |
| 1992 Deserializer deserializer(&payload); |
| 1993 STATIC_ASSERT(NEW_SPACE == 0); |
| 1994 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
| 1995 deserializer.set_reservation(i, scd.GetReservation(i)); |
| 1996 } |
| 1997 |
| 1998 // Prepare and register list of attached objects. |
| 1999 Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys(); |
| 2000 Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New( |
| 2001 code_stub_keys.length() + kCodeStubsBaseIndex); |
| 2002 attached_objects[kSourceObjectIndex] = source; |
| 2003 for (int i = 0; i < code_stub_keys.length(); i++) { |
| 2004 attached_objects[i + kCodeStubsBaseIndex] = |
| 2005 CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked(); |
| 2006 } |
| 2007 deserializer.SetAttachedObjects(&attached_objects); |
| 2008 |
| 2009 // Deserialize. |
| 2010 deserializer.DeserializePartial(isolate, &root); |
| 2011 deserializer.FlushICacheForNewCodeObjects(); |
| 1909 } | 2012 } |
| 1910 | 2013 |
| 1911 // Prepare and register list of attached objects. | |
| 1912 Vector<Object*> attached_objects = Vector<Object*>::New(1); | |
| 1913 attached_objects[kSourceObjectIndex] = *source; | |
| 1914 deserializer.SetAttachedObjects(&attached_objects); | |
| 1915 | |
| 1916 Object* root; | |
| 1917 deserializer.DeserializePartial(isolate, &root); | |
| 1918 deserializer.FlushICacheForNewCodeObjects(); | |
| 1919 if (FLAG_profile_deserialization) { | 2014 if (FLAG_profile_deserialization) { |
| 1920 double ms = timer.Elapsed().InMillisecondsF(); | 2015 double ms = timer.Elapsed().InMillisecondsF(); |
| 1921 int length = data->length(); | 2016 int length = data->length(); |
| 1922 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); | 2017 PrintF("[Deserializing from %d bytes took %0.3f ms]\n", length, ms); |
| 1923 } | 2018 } |
| 1924 return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root), isolate); | 2019 return Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(root), isolate); |
| 1925 } | 2020 } |
| 1926 | 2021 |
| 1927 | 2022 |
| 1928 SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs) | 2023 SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs) |
| 1929 : owns_script_data_(true) { | 2024 : owns_script_data_(true) { |
| 1930 DisallowHeapAllocation no_gc; | 2025 DisallowHeapAllocation no_gc; |
| 1931 int data_length = payload->length() + kHeaderEntries * kIntSize; | 2026 List<uint32_t>* stub_keys = cs->stub_keys(); |
| 2027 |
| 2028 // Calculate sizes. |
| 2029 int num_stub_keys = stub_keys->length(); |
| 2030 int stub_keys_size = stub_keys->length() * kInt32Size; |
| 2031 int data_length = kHeaderSize + stub_keys_size + payload->length(); |
| 2032 |
| 2033 // Allocate backing store and create result data. |
| 1932 byte* data = NewArray<byte>(data_length); | 2034 byte* data = NewArray<byte>(data_length); |
| 1933 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); | 2035 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)); |
| 1934 CopyBytes(data + kHeaderEntries * kIntSize, payload->begin(), | |
| 1935 static_cast<size_t>(payload->length())); | |
| 1936 script_data_ = new ScriptData(data, data_length); | 2036 script_data_ = new ScriptData(data, data_length); |
| 1937 script_data_->AcquireDataOwnership(); | 2037 script_data_->AcquireDataOwnership(); |
| 2038 |
| 2039 // Set header values. |
| 1938 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); | 2040 SetHeaderValue(kCheckSumOffset, CheckSum(cs->source())); |
| 2041 SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); |
| 2042 SetHeaderValue(kPayloadLengthOffset, payload->length()); |
| 1939 STATIC_ASSERT(NEW_SPACE == 0); | 2043 STATIC_ASSERT(NEW_SPACE == 0); |
| 1940 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { | 2044 for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) { |
| 1941 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); | 2045 SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i)); |
| 1942 } | 2046 } |
| 2047 |
| 2048 // Copy code stub keys. |
| 2049 CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()), |
| 2050 stub_keys_size); |
| 2051 |
| 2052 // Copy serialized data. |
| 2053 CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(), |
| 2054 static_cast<size_t>(payload->length())); |
| 1943 } | 2055 } |
| 1944 | 2056 |
| 1945 | 2057 |
| 1946 bool SerializedCodeData::IsSane(String* source) { | 2058 bool SerializedCodeData::IsSane(String* source) { |
| 1947 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2059 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
| 1948 PayloadLength() >= SharedFunctionInfo::kSize; | 2060 PayloadLength() >= SharedFunctionInfo::kSize; |
| 1949 } | 2061 } |
| 1950 | 2062 |
| 1951 | 2063 |
| 1952 int SerializedCodeData::CheckSum(String* string) { | 2064 int SerializedCodeData::CheckSum(String* string) { |
| 1953 int checksum = Version::Hash(); | 2065 int checksum = Version::Hash(); |
| 1954 #ifdef DEBUG | 2066 #ifdef DEBUG |
| 1955 uint32_t seed = static_cast<uint32_t>(checksum); | 2067 uint32_t seed = static_cast<uint32_t>(checksum); |
| 1956 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); | 2068 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); |
| 1957 #endif // DEBUG | 2069 #endif // DEBUG |
| 1958 return checksum; | 2070 return checksum; |
| 1959 } | 2071 } |
| 1960 } } // namespace v8::internal | 2072 } } // namespace v8::internal |
| OLD | NEW |