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 |