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" |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 StringTableInsertionKey key(string); | 787 StringTableInsertionKey key(string); |
788 String* canonical = *StringTable::LookupKey(isolate_, &key); | 788 String* canonical = *StringTable::LookupKey(isolate_, &key); |
789 string->SetForwardedInternalizedString(canonical); | 789 string->SetForwardedInternalizedString(canonical); |
790 return canonical; | 790 return canonical; |
791 } | 791 } |
792 } | 792 } |
793 return obj; | 793 return obj; |
794 } | 794 } |
795 | 795 |
796 | 796 |
797 Object* Deserializer::ProcessBackRefInSerializedCode(Object* obj) { | 797 HeapObject* Deserializer::GetBackReferencedObject(int space) { |
798 if (obj->IsInternalizedString()) { | 798 HeapObject* obj; |
799 return String::cast(obj)->GetForwardedInternalizedString(); | 799 if (space == LO_SPACE) { |
| 800 uint32_t index = source_->GetInt(); |
| 801 obj = deserialized_large_objects_[index]; |
| 802 } else { |
| 803 BackReference back_reference(source_->GetInt()); |
| 804 DCHECK(space < kNumberOfPreallocatedSpaces); |
| 805 uint32_t chunk_index = back_reference.chunk_index(); |
| 806 DCHECK_LE(chunk_index, current_chunk_[space]); |
| 807 uint32_t chunk_offset = back_reference.chunk_offset(); |
| 808 obj = HeapObject::FromAddress(reservations_[space][chunk_index].start + |
| 809 chunk_offset); |
800 } | 810 } |
| 811 if (deserializing_user_code() && obj->IsInternalizedString()) { |
| 812 obj = String::cast(obj)->GetForwardedInternalizedString(); |
| 813 } |
| 814 hot_objects_.Add(obj); |
801 return obj; | 815 return obj; |
802 } | 816 } |
803 | 817 |
804 | 818 |
805 // This routine writes the new object into the pointer provided and then | 819 // This routine writes the new object into the pointer provided and then |
806 // returns true if the new object was in young space and false otherwise. | 820 // returns true if the new object was in young space and false otherwise. |
807 // The reason for this strange interface is that otherwise the object is | 821 // The reason for this strange interface is that otherwise the object is |
808 // written very late, which means the FreeSpace map is not set up by the | 822 // written very late, which means the FreeSpace map is not set up by the |
809 // time we need to use it to mark the space at the end of a page free. | 823 // time we need to use it to mark the space at the end of a page free. |
810 void Deserializer::ReadObject(int space_number, Object** write_back) { | 824 void Deserializer::ReadObject(int space_number, Object** write_back) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 // Write barrier support costs around 1% in startup time. In fact there | 911 // Write barrier support costs around 1% in startup time. In fact there |
898 // are no new space objects in current boot snapshots, so it's not needed, | 912 // are no new space objects in current boot snapshots, so it's not needed, |
899 // but that may change. | 913 // but that may change. |
900 bool write_barrier_needed = (current_object_address != NULL && | 914 bool write_barrier_needed = (current_object_address != NULL && |
901 source_space != NEW_SPACE && | 915 source_space != NEW_SPACE && |
902 source_space != CELL_SPACE && | 916 source_space != CELL_SPACE && |
903 source_space != PROPERTY_CELL_SPACE && | 917 source_space != PROPERTY_CELL_SPACE && |
904 source_space != CODE_SPACE && | 918 source_space != CODE_SPACE && |
905 source_space != OLD_DATA_SPACE); | 919 source_space != OLD_DATA_SPACE); |
906 while (current < limit) { | 920 while (current < limit) { |
907 int data = source_->Get(); | 921 byte data = source_->Get(); |
908 switch (data) { | 922 switch (data) { |
909 #define CASE_STATEMENT(where, how, within, space_number) \ | 923 #define CASE_STATEMENT(where, how, within, space_number) \ |
910 case where + how + within + space_number: \ | 924 case where + how + within + space_number: \ |
911 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ | 925 STATIC_ASSERT((where & ~kPointedToMask) == 0); \ |
912 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ | 926 STATIC_ASSERT((how & ~kHowToCodeMask) == 0); \ |
913 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ | 927 STATIC_ASSERT((within & ~kWhereToPointMask) == 0); \ |
914 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); | 928 STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
915 | 929 |
916 #define CASE_BODY(where, how, within, space_number_if_any) \ | 930 #define CASE_BODY(where, how, within, space_number_if_any) \ |
917 { \ | 931 { \ |
(...skipping 20 matching lines...) Expand all Loading... |
938 } else if (where == kExternalReference) { \ | 952 } else if (where == kExternalReference) { \ |
939 int skip = source_->GetInt(); \ | 953 int skip = source_->GetInt(); \ |
940 current = reinterpret_cast<Object**>( \ | 954 current = reinterpret_cast<Object**>( \ |
941 reinterpret_cast<Address>(current) + skip); \ | 955 reinterpret_cast<Address>(current) + skip); \ |
942 int reference_id = source_->GetInt(); \ | 956 int reference_id = source_->GetInt(); \ |
943 Address address = external_reference_decoder_->Decode(reference_id); \ | 957 Address address = external_reference_decoder_->Decode(reference_id); \ |
944 new_object = reinterpret_cast<Object*>(address); \ | 958 new_object = reinterpret_cast<Object*>(address); \ |
945 } else if (where == kBackref) { \ | 959 } else if (where == kBackref) { \ |
946 emit_write_barrier = (space_number == NEW_SPACE); \ | 960 emit_write_barrier = (space_number == NEW_SPACE); \ |
947 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 961 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
948 if (deserializing_user_code()) { \ | |
949 new_object = ProcessBackRefInSerializedCode(new_object); \ | |
950 } \ | |
951 } else if (where == kBuiltin) { \ | 962 } else if (where == kBuiltin) { \ |
952 DCHECK(deserializing_user_code()); \ | 963 DCHECK(deserializing_user_code()); \ |
953 int builtin_id = source_->GetInt(); \ | 964 int builtin_id = source_->GetInt(); \ |
954 DCHECK_LE(0, builtin_id); \ | 965 DCHECK_LE(0, builtin_id); \ |
955 DCHECK_LT(builtin_id, Builtins::builtin_count); \ | 966 DCHECK_LT(builtin_id, Builtins::builtin_count); \ |
956 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ | 967 Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
957 new_object = isolate->builtins()->builtin(name); \ | 968 new_object = isolate->builtins()->builtin(name); \ |
958 emit_write_barrier = false; \ | 969 emit_write_barrier = false; \ |
959 } else if (where == kAttachedReference) { \ | 970 } else if (where == kAttachedReference) { \ |
960 DCHECK(deserializing_user_code()); \ | 971 DCHECK(deserializing_user_code()); \ |
961 int index = source_->GetInt(); \ | 972 int index = source_->GetInt(); \ |
962 new_object = *attached_objects_->at(index); \ | 973 new_object = *attached_objects_->at(index); \ |
963 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ | 974 emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
964 } else { \ | 975 } else { \ |
965 DCHECK(where == kBackrefWithSkip); \ | 976 DCHECK(where == kBackrefWithSkip); \ |
966 int skip = source_->GetInt(); \ | 977 int skip = source_->GetInt(); \ |
967 current = reinterpret_cast<Object**>( \ | 978 current = reinterpret_cast<Object**>( \ |
968 reinterpret_cast<Address>(current) + skip); \ | 979 reinterpret_cast<Address>(current) + skip); \ |
969 emit_write_barrier = (space_number == NEW_SPACE); \ | 980 emit_write_barrier = (space_number == NEW_SPACE); \ |
970 new_object = GetBackReferencedObject(data & kSpaceMask); \ | 981 new_object = GetBackReferencedObject(data & kSpaceMask); \ |
971 if (deserializing_user_code()) { \ | |
972 new_object = ProcessBackRefInSerializedCode(new_object); \ | |
973 } \ | |
974 } \ | 982 } \ |
975 if (within == kInnerPointer) { \ | 983 if (within == kInnerPointer) { \ |
976 if (space_number != CODE_SPACE || new_object->IsCode()) { \ | 984 if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
977 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ | 985 Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
978 new_object = \ | 986 new_object = \ |
979 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ | 987 reinterpret_cast<Object*>(new_code_object->instruction_start()); \ |
980 } else { \ | 988 } else { \ |
981 DCHECK(space_number == CODE_SPACE); \ | 989 DCHECK(space_number == CODE_SPACE); \ |
982 Cell* cell = Cell::cast(new_object); \ | 990 Cell* cell = Cell::cast(new_object); \ |
983 new_object = reinterpret_cast<Object*>(cell->ValueAddress()); \ | 991 new_object = reinterpret_cast<Object*>(cell->ValueAddress()); \ |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1104 int root_id = RootArrayConstantFromByteCode(data); | 1112 int root_id = RootArrayConstantFromByteCode(data); |
1105 int skip = source_->GetInt(); | 1113 int skip = source_->GetInt(); |
1106 current = reinterpret_cast<Object**>( | 1114 current = reinterpret_cast<Object**>( |
1107 reinterpret_cast<intptr_t>(current) + skip); | 1115 reinterpret_cast<intptr_t>(current) + skip); |
1108 Object* object = isolate->heap()->roots_array_start()[root_id]; | 1116 Object* object = isolate->heap()->roots_array_start()[root_id]; |
1109 DCHECK(!isolate->heap()->InNewSpace(object)); | 1117 DCHECK(!isolate->heap()->InNewSpace(object)); |
1110 *current++ = object; | 1118 *current++ = object; |
1111 break; | 1119 break; |
1112 } | 1120 } |
1113 | 1121 |
1114 case kRepeat: { | 1122 case kVariableRepeat: { |
1115 int repeats = source_->GetInt(); | 1123 int repeats = source_->GetInt(); |
1116 Object* object = current[-1]; | 1124 Object* object = current[-1]; |
1117 DCHECK(!isolate->heap()->InNewSpace(object)); | 1125 DCHECK(!isolate->heap()->InNewSpace(object)); |
1118 for (int i = 0; i < repeats; i++) current[i] = object; | 1126 for (int i = 0; i < repeats; i++) current[i] = object; |
1119 current += repeats; | 1127 current += repeats; |
1120 break; | 1128 break; |
1121 } | 1129 } |
1122 | 1130 |
1123 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == | 1131 STATIC_ASSERT(kRootArrayNumberOfConstantEncodings == |
1124 Heap::kOldSpaceRoots); | 1132 Heap::kOldSpaceRoots); |
1125 STATIC_ASSERT(kMaxRepeats == 13); | 1133 STATIC_ASSERT(kMaxFixedRepeats == 15); |
1126 case kConstantRepeat: | 1134 FOUR_CASES(kFixedRepeat) |
1127 FOUR_CASES(kConstantRepeat + 1) | 1135 FOUR_CASES(kFixedRepeat + 4) |
1128 FOUR_CASES(kConstantRepeat + 5) | 1136 FOUR_CASES(kFixedRepeat + 8) |
1129 FOUR_CASES(kConstantRepeat + 9) { | 1137 case kFixedRepeat + 12: |
| 1138 case kFixedRepeat + 13: |
| 1139 case kFixedRepeat + 14: { |
1130 int repeats = RepeatsForCode(data); | 1140 int repeats = RepeatsForCode(data); |
1131 Object* object = current[-1]; | 1141 Object* object = current[-1]; |
1132 DCHECK(!isolate->heap()->InNewSpace(object)); | 1142 DCHECK(!isolate->heap()->InNewSpace(object)); |
1133 for (int i = 0; i < repeats; i++) current[i] = object; | 1143 for (int i = 0; i < repeats; i++) current[i] = object; |
1134 current += repeats; | 1144 current += repeats; |
1135 break; | 1145 break; |
1136 } | 1146 } |
1137 | 1147 |
1138 // Deserialize a new object and write a pointer to it to the current | 1148 // Deserialize a new object and write a pointer to it to the current |
1139 // object. | 1149 // object. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1254 const Heap::Reservation& reservation = reservations_[space]; | 1264 const Heap::Reservation& reservation = reservations_[space]; |
1255 // Make sure the current chunk is indeed exhausted. | 1265 // Make sure the current chunk is indeed exhausted. |
1256 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); | 1266 CHECK_EQ(reservation[chunk_index].end, high_water_[space]); |
1257 // Move to next reserved chunk. | 1267 // Move to next reserved chunk. |
1258 chunk_index = ++current_chunk_[space]; | 1268 chunk_index = ++current_chunk_[space]; |
1259 DCHECK_LT(chunk_index, reservation.length()); | 1269 DCHECK_LT(chunk_index, reservation.length()); |
1260 high_water_[space] = reservation[chunk_index].start; | 1270 high_water_[space] = reservation[chunk_index].start; |
1261 break; | 1271 break; |
1262 } | 1272 } |
1263 | 1273 |
| 1274 FOUR_CASES(kHotObjectWithSkip) |
| 1275 FOUR_CASES(kHotObjectWithSkip + 4) { |
| 1276 int skip = source_->GetInt(); |
| 1277 current = reinterpret_cast<Object**>( |
| 1278 reinterpret_cast<Address>(current) + skip); |
| 1279 // Fall through. |
| 1280 } |
| 1281 FOUR_CASES(kHotObject) |
| 1282 FOUR_CASES(kHotObject + 4) { |
| 1283 int index = data & kHotObjectIndexMask; |
| 1284 *current = hot_objects_.Get(index); |
| 1285 if (write_barrier_needed && isolate->heap()->InNewSpace(*current)) { |
| 1286 Address current_address = reinterpret_cast<Address>(current); |
| 1287 isolate->heap()->RecordWrite( |
| 1288 current_object_address, |
| 1289 static_cast<int>(current_address - current_object_address)); |
| 1290 } |
| 1291 current++; |
| 1292 break; |
| 1293 } |
| 1294 |
1264 case kSynchronize: { | 1295 case kSynchronize: { |
1265 // If we get here then that indicates that you have a mismatch between | 1296 // If we get here then that indicates that you have a mismatch between |
1266 // the number of GC roots when serializing and deserializing. | 1297 // the number of GC roots when serializing and deserializing. |
1267 UNREACHABLE(); | 1298 UNREACHABLE(); |
1268 } | 1299 } |
1269 | 1300 |
1270 default: | 1301 default: |
1271 UNREACHABLE(); | 1302 UNREACHABLE(); |
1272 } | 1303 } |
1273 } | 1304 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1317 void StartupSerializer::VisitPointers(Object** start, Object** end) { | 1348 void StartupSerializer::VisitPointers(Object** start, Object** end) { |
1318 for (Object** current = start; current < end; current++) { | 1349 for (Object** current = start; current < end; current++) { |
1319 if (start == isolate()->heap()->roots_array_start()) { | 1350 if (start == isolate()->heap()->roots_array_start()) { |
1320 root_index_wave_front_ = | 1351 root_index_wave_front_ = |
1321 Max(root_index_wave_front_, static_cast<intptr_t>(current - start)); | 1352 Max(root_index_wave_front_, static_cast<intptr_t>(current - start)); |
1322 } | 1353 } |
1323 if (ShouldBeSkipped(current)) { | 1354 if (ShouldBeSkipped(current)) { |
1324 sink_->Put(kSkip, "Skip"); | 1355 sink_->Put(kSkip, "Skip"); |
1325 sink_->PutInt(kPointerSize, "SkipOneWord"); | 1356 sink_->PutInt(kPointerSize, "SkipOneWord"); |
1326 } else if ((*current)->IsSmi()) { | 1357 } else if ((*current)->IsSmi()) { |
1327 sink_->Put(kRawData + 1, "Smi"); | 1358 sink_->Put(kOnePointerRawData, "Smi"); |
1328 for (int i = 0; i < kPointerSize; i++) { | 1359 for (int i = 0; i < kPointerSize; i++) { |
1329 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1360 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
1330 } | 1361 } |
1331 } else { | 1362 } else { |
1332 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); | 1363 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); |
1333 } | 1364 } |
1334 } | 1365 } |
1335 } | 1366 } |
1336 | 1367 |
1337 | 1368 |
1338 void PartialSerializer::Serialize(Object** object) { | 1369 void PartialSerializer::Serialize(Object** object) { |
1339 this->VisitPointer(object); | 1370 this->VisitPointer(object); |
1340 Pad(); | 1371 Pad(); |
1341 } | 1372 } |
1342 | 1373 |
1343 | 1374 |
1344 bool Serializer::ShouldBeSkipped(Object** current) { | 1375 bool Serializer::ShouldBeSkipped(Object** current) { |
1345 Object** roots = isolate()->heap()->roots_array_start(); | 1376 Object** roots = isolate()->heap()->roots_array_start(); |
1346 return current == &roots[Heap::kStoreBufferTopRootIndex] | 1377 return current == &roots[Heap::kStoreBufferTopRootIndex] |
1347 || current == &roots[Heap::kStackLimitRootIndex] | 1378 || current == &roots[Heap::kStackLimitRootIndex] |
1348 || current == &roots[Heap::kRealStackLimitRootIndex]; | 1379 || current == &roots[Heap::kRealStackLimitRootIndex]; |
1349 } | 1380 } |
1350 | 1381 |
1351 | 1382 |
1352 void Serializer::VisitPointers(Object** start, Object** end) { | 1383 void Serializer::VisitPointers(Object** start, Object** end) { |
1353 for (Object** current = start; current < end; current++) { | 1384 for (Object** current = start; current < end; current++) { |
1354 if ((*current)->IsSmi()) { | 1385 if ((*current)->IsSmi()) { |
1355 sink_->Put(kRawData + 1, "Smi"); | 1386 sink_->Put(kOnePointerRawData, "Smi"); |
1356 for (int i = 0; i < kPointerSize; i++) { | 1387 for (int i = 0; i < kPointerSize; i++) { |
1357 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1388 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
1358 } | 1389 } |
1359 } else { | 1390 } else { |
1360 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); | 1391 SerializeObject(HeapObject::cast(*current), kPlain, kStartOfObject, 0); |
1361 } | 1392 } |
1362 } | 1393 } |
1363 } | 1394 } |
1364 | 1395 |
1365 | 1396 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 int length = isolate->serialize_partial_snapshot_cache_length(); | 1450 int length = isolate->serialize_partial_snapshot_cache_length(); |
1420 isolate->PushToPartialSnapshotCache(heap_object); | 1451 isolate->PushToPartialSnapshotCache(heap_object); |
1421 startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object)); | 1452 startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object)); |
1422 // We don't recurse from the startup snapshot generator into the partial | 1453 // We don't recurse from the startup snapshot generator into the partial |
1423 // snapshot generator. | 1454 // snapshot generator. |
1424 DCHECK(length == isolate->serialize_partial_snapshot_cache_length() - 1); | 1455 DCHECK(length == isolate->serialize_partial_snapshot_cache_length() - 1); |
1425 return length; | 1456 return length; |
1426 } | 1457 } |
1427 | 1458 |
1428 | 1459 |
1429 // Encode the location of an already deserialized object in order to write its | 1460 bool Serializer::SerializeKnownObject(HeapObject* obj, HowToCode how_to_code, |
1430 // location into a later object. We can encode the location as an offset from | 1461 WhereToPoint where_to_point, int skip) { |
1431 // the start of the deserialized objects or as an offset backwards from the | 1462 if (how_to_code == kPlain && where_to_point == kStartOfObject) { |
1432 // current allocation pointer. | 1463 // Encode a reference to a hot object by its index in the working set. |
1433 void Serializer::SerializeBackReference(BackReference back_reference, | 1464 int index = hot_objects_.Find(obj); |
1434 HowToCode how_to_code, | 1465 if (index != HotObjectsList::kNotFound) { |
1435 WhereToPoint where_to_point, int skip) { | 1466 DCHECK(index >= 0 && index <= kMaxHotObjectIndex); |
1436 AllocationSpace space = back_reference.space(); | 1467 if (FLAG_trace_serializer) { |
1437 if (skip == 0) { | 1468 PrintF(" Encoding hot object %d:", index); |
1438 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer"); | 1469 obj->ShortPrint(); |
1439 } else { | 1470 PrintF("\n"); |
1440 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, | 1471 } |
1441 "BackRefSerWithSkip"); | 1472 if (skip != 0) { |
1442 sink_->PutInt(skip, "BackRefSkipDistance"); | 1473 sink_->Put(kHotObjectWithSkip + index, "HotObjectWithSkip"); |
| 1474 sink_->PutInt(skip, "HotObjectSkipDistance"); |
| 1475 } else { |
| 1476 sink_->Put(kHotObject + index, "HotObject"); |
| 1477 } |
| 1478 return true; |
| 1479 } |
1443 } | 1480 } |
| 1481 BackReference back_reference = back_reference_map_.Lookup(obj); |
| 1482 if (back_reference.is_valid()) { |
| 1483 // Encode the location of an already deserialized object in order to write |
| 1484 // its location into a later object. We can encode the location as an |
| 1485 // offset fromthe start of the deserialized objects or as an offset |
| 1486 // backwards from thecurrent allocation pointer. |
| 1487 if (back_reference.is_source()) { |
| 1488 FlushSkip(skip); |
| 1489 if (FLAG_trace_serializer) PrintF(" Encoding source object\n"); |
| 1490 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); |
| 1491 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); |
| 1492 sink_->PutInt(kSourceObjectReference, "kSourceObjectIndex"); |
| 1493 } else { |
| 1494 if (FLAG_trace_serializer) { |
| 1495 PrintF(" Encoding back reference to: "); |
| 1496 obj->ShortPrint(); |
| 1497 PrintF("\n"); |
| 1498 } |
1444 | 1499 |
1445 sink_->PutInt(back_reference.reference(), | 1500 AllocationSpace space = back_reference.space(); |
1446 (space == LO_SPACE) ? "large object index" : "allocation"); | 1501 if (skip == 0) { |
| 1502 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRef"); |
| 1503 } else { |
| 1504 sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space, |
| 1505 "BackRefWithSkip"); |
| 1506 sink_->PutInt(skip, "BackRefSkipDistance"); |
| 1507 } |
| 1508 sink_->PutInt(back_reference.reference(), "BackRefValue"); |
| 1509 |
| 1510 hot_objects_.Add(obj); |
| 1511 } |
| 1512 return true; |
| 1513 } |
| 1514 return false; |
1447 } | 1515 } |
1448 | 1516 |
1449 | 1517 |
1450 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1518 void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1451 WhereToPoint where_to_point, int skip) { | 1519 WhereToPoint where_to_point, int skip) { |
1452 DCHECK(!obj->IsJSFunction()); | 1520 DCHECK(!obj->IsJSFunction()); |
1453 | 1521 |
1454 int root_index = root_index_map_.Lookup(obj); | 1522 int root_index = root_index_map_.Lookup(obj); |
1455 // We can only encode roots as such if it has already been serialized. | 1523 // We can only encode roots as such if it has already been serialized. |
1456 // That applies to root indices below the wave front. | 1524 // That applies to root indices below the wave front. |
1457 if (root_index != RootIndexMap::kInvalidRootIndex && | 1525 if (root_index != RootIndexMap::kInvalidRootIndex && |
1458 root_index < root_index_wave_front_) { | 1526 root_index < root_index_wave_front_) { |
1459 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 1527 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
1460 return; | 1528 return; |
1461 } | 1529 } |
1462 | 1530 |
1463 BackReference back_reference = back_reference_map_.Lookup(obj); | 1531 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; |
1464 if (back_reference.is_valid()) { | |
1465 SerializeBackReference(back_reference, how_to_code, where_to_point, skip); | |
1466 return; | |
1467 } | |
1468 | 1532 |
1469 if (skip != 0) { | 1533 FlushSkip(skip); |
1470 sink_->Put(kSkip, "FlushPendingSkip"); | |
1471 sink_->PutInt(skip, "SkipDistance"); | |
1472 } | |
1473 | 1534 |
1474 // Object has not yet been serialized. Serialize it here. | 1535 // Object has not yet been serialized. Serialize it here. |
1475 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, | 1536 ObjectSerializer object_serializer(this, obj, sink_, how_to_code, |
1476 where_to_point); | 1537 where_to_point); |
1477 object_serializer.Serialize(); | 1538 object_serializer.Serialize(); |
1478 } | 1539 } |
1479 | 1540 |
1480 | 1541 |
1481 void StartupSerializer::SerializeWeakReferences() { | 1542 void StartupSerializer::SerializeWeakReferences() { |
1482 // This phase comes right after the partial serialization (of the snapshot). | 1543 // This phase comes right after the serialization (of the snapshot). |
1483 // After we have done the partial serialization the partial snapshot cache | 1544 // After we have done the partial serialization the partial snapshot cache |
1484 // will contain some references needed to decode the partial snapshot. We | 1545 // will contain some references needed to decode the partial snapshot. We |
1485 // add one entry with 'undefined' which is the sentinel that the deserializer | 1546 // add one entry with 'undefined' which is the sentinel that the deserializer |
1486 // uses to know it is done deserializing the array. | 1547 // uses to know it is done deserializing the array. |
1487 Object* undefined = isolate()->heap()->undefined_value(); | 1548 Object* undefined = isolate()->heap()->undefined_value(); |
1488 VisitPointer(&undefined); | 1549 VisitPointer(&undefined); |
1489 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL); | 1550 isolate()->heap()->IterateWeakRoots(this, VISIT_ALL); |
1490 Pad(); | 1551 Pad(); |
1491 } | 1552 } |
1492 | 1553 |
1493 | 1554 |
1494 void Serializer::PutRoot(int root_index, | 1555 void Serializer::PutRoot(int root_index, |
1495 HeapObject* object, | 1556 HeapObject* object, |
1496 SerializerDeserializer::HowToCode how_to_code, | 1557 SerializerDeserializer::HowToCode how_to_code, |
1497 SerializerDeserializer::WhereToPoint where_to_point, | 1558 SerializerDeserializer::WhereToPoint where_to_point, |
1498 int skip) { | 1559 int skip) { |
| 1560 if (FLAG_trace_serializer) { |
| 1561 PrintF(" Encoding root %d:", root_index); |
| 1562 object->ShortPrint(); |
| 1563 PrintF("\n"); |
| 1564 } |
| 1565 |
1499 if (how_to_code == kPlain && | 1566 if (how_to_code == kPlain && |
1500 where_to_point == kStartOfObject && | 1567 where_to_point == kStartOfObject && |
1501 root_index < kRootArrayNumberOfConstantEncodings && | 1568 root_index < kRootArrayNumberOfConstantEncodings && |
1502 !isolate()->heap()->InNewSpace(object)) { | 1569 !isolate()->heap()->InNewSpace(object)) { |
1503 if (skip == 0) { | 1570 if (skip == 0) { |
1504 sink_->Put(kRootArrayConstants + kNoSkipDistance + root_index, | 1571 sink_->Put(kRootArrayConstants + kNoSkipDistance + root_index, |
1505 "RootConstant"); | 1572 "RootConstant"); |
1506 } else { | 1573 } else { |
1507 sink_->Put(kRootArrayConstants + kHasSkipDistance + root_index, | 1574 sink_->Put(kRootArrayConstants + kHasSkipDistance + root_index, |
1508 "RootConstant"); | 1575 "RootConstant"); |
1509 sink_->PutInt(skip, "SkipInPutRoot"); | 1576 sink_->PutInt(skip, "SkipInPutRoot"); |
1510 } | 1577 } |
1511 } else { | 1578 } else { |
1512 if (skip != 0) { | 1579 FlushSkip(skip); |
1513 sink_->Put(kSkip, "SkipFromPutRoot"); | |
1514 sink_->PutInt(skip, "SkipFromPutRootDistance"); | |
1515 } | |
1516 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); | 1580 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization"); |
1517 sink_->PutInt(root_index, "root_index"); | 1581 sink_->PutInt(root_index, "root_index"); |
1518 } | 1582 } |
1519 } | 1583 } |
1520 | 1584 |
1521 | 1585 |
1522 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 1586 void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
1523 WhereToPoint where_to_point, int skip) { | 1587 WhereToPoint where_to_point, int skip) { |
1524 if (obj->IsMap()) { | 1588 if (obj->IsMap()) { |
1525 // The code-caches link to context-specific code objects, which | 1589 // The code-caches link to context-specific code objects, which |
1526 // the startup and context serializes cannot currently handle. | 1590 // the startup and context serializes cannot currently handle. |
1527 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); | 1591 DCHECK(Map::cast(obj)->code_cache() == obj->GetHeap()->empty_fixed_array()); |
1528 } | 1592 } |
1529 | 1593 |
1530 int root_index = root_index_map_.Lookup(obj); | 1594 int root_index = root_index_map_.Lookup(obj); |
1531 if (root_index != RootIndexMap::kInvalidRootIndex) { | 1595 if (root_index != RootIndexMap::kInvalidRootIndex) { |
1532 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 1596 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
1533 return; | 1597 return; |
1534 } | 1598 } |
1535 | 1599 |
1536 if (ShouldBeInThePartialSnapshotCache(obj)) { | 1600 if (ShouldBeInThePartialSnapshotCache(obj)) { |
1537 if (skip != 0) { | 1601 FlushSkip(skip); |
1538 sink_->Put(kSkip, "SkipFromSerializeObject"); | |
1539 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | |
1540 } | |
1541 | 1602 |
1542 int cache_index = PartialSnapshotCacheIndex(obj); | 1603 int cache_index = PartialSnapshotCacheIndex(obj); |
1543 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point, | 1604 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point, |
1544 "PartialSnapshotCache"); | 1605 "PartialSnapshotCache"); |
1545 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); | 1606 sink_->PutInt(cache_index, "partial_snapshot_cache_index"); |
1546 return; | 1607 return; |
1547 } | 1608 } |
1548 | 1609 |
1549 // Pointers from the partial snapshot to the objects in the startup snapshot | 1610 // Pointers from the partial snapshot to the objects in the startup snapshot |
1550 // should go through the root array or through the partial snapshot cache. | 1611 // should go through the root array or through the partial snapshot cache. |
1551 // If this is not the case you may have to add something to the root array. | 1612 // If this is not the case you may have to add something to the root array. |
1552 DCHECK(!startup_serializer_->back_reference_map()->Lookup(obj).is_valid()); | 1613 DCHECK(!startup_serializer_->back_reference_map()->Lookup(obj).is_valid()); |
1553 // All the internalized strings that the partial snapshot needs should be | 1614 // All the internalized strings that the partial snapshot needs should be |
1554 // either in the root table or in the partial snapshot cache. | 1615 // either in the root table or in the partial snapshot cache. |
1555 DCHECK(!obj->IsInternalizedString()); | 1616 DCHECK(!obj->IsInternalizedString()); |
1556 | 1617 |
1557 BackReference back_reference = back_reference_map_.Lookup(obj); | 1618 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; |
1558 if (back_reference.is_valid()) { | |
1559 SerializeBackReference(back_reference, how_to_code, where_to_point, skip); | |
1560 return; | |
1561 } | |
1562 | 1619 |
1563 if (skip != 0) { | 1620 FlushSkip(skip); |
1564 sink_->Put(kSkip, "SkipFromSerializeObject"); | 1621 |
1565 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | |
1566 } | |
1567 // Object has not yet been serialized. Serialize it here. | 1622 // Object has not yet been serialized. Serialize it here. |
1568 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); | 1623 ObjectSerializer serializer(this, obj, sink_, how_to_code, where_to_point); |
1569 serializer.Serialize(); | 1624 serializer.Serialize(); |
1570 } | 1625 } |
1571 | 1626 |
1572 | 1627 |
1573 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, | 1628 void Serializer::ObjectSerializer::SerializePrologue(AllocationSpace space, |
1574 int size, Map* map) { | 1629 int size, Map* map) { |
1575 if (serializer_->code_address_map_) { | 1630 if (serializer_->code_address_map_) { |
1576 const char* code_name = | 1631 const char* code_name = |
1577 serializer_->code_address_map_->Lookup(object_->address()); | 1632 serializer_->code_address_map_->Lookup(object_->address()); |
1578 LOG(serializer_->isolate_, | 1633 LOG(serializer_->isolate_, |
1579 CodeNameEvent(object_->address(), sink_->Position(), code_name)); | 1634 CodeNameEvent(object_->address(), sink_->Position(), code_name)); |
1580 LOG(serializer_->isolate_, | 1635 LOG(serializer_->isolate_, |
1581 SnapshotPositionEvent(object_->address(), sink_->Position())); | 1636 SnapshotPositionEvent(object_->address(), sink_->Position())); |
1582 } | 1637 } |
1583 | 1638 |
1584 BackReference back_reference; | 1639 BackReference back_reference; |
1585 if (space == LO_SPACE) { | 1640 if (space == LO_SPACE) { |
1586 sink_->Put(kNewObject + reference_representation_ + space, | 1641 sink_->Put(kNewObject + reference_representation_ + space, |
1587 "new large object"); | 1642 "NewLargeObject"); |
1588 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 1643 sink_->PutInt(size >> kObjectAlignmentBits, "ObjectSizeInWords"); |
1589 if (object_->IsCode()) { | 1644 if (object_->IsCode()) { |
1590 sink_->Put(EXECUTABLE, "executable large object"); | 1645 sink_->Put(EXECUTABLE, "executable large object"); |
1591 } else { | 1646 } else { |
1592 sink_->Put(NOT_EXECUTABLE, "not executable large object"); | 1647 sink_->Put(NOT_EXECUTABLE, "not executable large object"); |
1593 } | 1648 } |
1594 back_reference = serializer_->AllocateLargeObject(size); | 1649 back_reference = serializer_->AllocateLargeObject(size); |
1595 } else { | 1650 } else { |
1596 if (object_->NeedsToEnsureDoubleAlignment()) { | 1651 if (object_->NeedsToEnsureDoubleAlignment()) { |
1597 // Add wriggle room for double alignment padding. | 1652 // Add wriggle room for double alignment padding. |
1598 back_reference = serializer_->Allocate(space, size + kPointerSize); | 1653 back_reference = serializer_->Allocate(space, size + kPointerSize); |
1599 sink_->PutInt(kDoubleAlignmentSentinel, "double align"); | 1654 sink_->PutInt(kDoubleAlignmentSentinel, "DoubleAlignSentinel"); |
1600 } else { | 1655 } else { |
1601 back_reference = serializer_->Allocate(space, size); | 1656 back_reference = serializer_->Allocate(space, size); |
1602 } | 1657 } |
1603 sink_->Put(kNewObject + reference_representation_ + space, "new object"); | 1658 sink_->Put(kNewObject + reference_representation_ + space, "NewObject"); |
1604 int encoded_size = size >> kObjectAlignmentBits; | 1659 int encoded_size = size >> kObjectAlignmentBits; |
1605 DCHECK_NE(kDoubleAlignmentSentinel, encoded_size); | 1660 DCHECK_NE(kDoubleAlignmentSentinel, encoded_size); |
1606 sink_->PutInt(encoded_size, "Size in words"); | 1661 sink_->PutInt(encoded_size, "ObjectSizeInWords"); |
1607 } | 1662 } |
1608 | 1663 |
1609 // Mark this object as already serialized. | 1664 // Mark this object as already serialized. |
1610 serializer_->back_reference_map()->Add(object_, back_reference); | 1665 serializer_->back_reference_map()->Add(object_, back_reference); |
1611 | 1666 |
1612 // Serialize the map (first word of the object). | 1667 // Serialize the map (first word of the object). |
1613 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); | 1668 serializer_->SerializeObject(map, kPlain, kStartOfObject, 0); |
1614 } | 1669 } |
1615 | 1670 |
1616 | 1671 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1670 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; | 1725 int padding_size = allocation_size - SeqString::kHeaderSize - content_size; |
1671 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); | 1726 DCHECK(0 <= padding_size && padding_size < kObjectAlignment); |
1672 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); | 1727 for (int i = 0; i < padding_size; i++) sink_->PutSection(0, "StringPadding"); |
1673 | 1728 |
1674 sink_->Put(kSkip, "SkipAfterString"); | 1729 sink_->Put(kSkip, "SkipAfterString"); |
1675 sink_->PutInt(bytes_to_output, "SkipDistance"); | 1730 sink_->PutInt(bytes_to_output, "SkipDistance"); |
1676 } | 1731 } |
1677 | 1732 |
1678 | 1733 |
1679 void Serializer::ObjectSerializer::Serialize() { | 1734 void Serializer::ObjectSerializer::Serialize() { |
| 1735 if (FLAG_trace_serializer) { |
| 1736 PrintF(" Encoding heap object: "); |
| 1737 object_->ShortPrint(); |
| 1738 PrintF("\n"); |
| 1739 } |
| 1740 |
1680 if (object_->IsExternalString()) { | 1741 if (object_->IsExternalString()) { |
1681 Heap* heap = serializer_->isolate()->heap(); | 1742 Heap* heap = serializer_->isolate()->heap(); |
1682 if (object_->map() != heap->native_source_string_map()) { | 1743 if (object_->map() != heap->native_source_string_map()) { |
1683 // Usually we cannot recreate resources for external strings. To work | 1744 // Usually we cannot recreate resources for external strings. To work |
1684 // around this, external strings are serialized to look like ordinary | 1745 // around this, external strings are serialized to look like ordinary |
1685 // sequential strings. | 1746 // sequential strings. |
1686 // The exception are native source code strings, since we can recreate | 1747 // The exception are native source code strings, since we can recreate |
1687 // their resources. In that case we fall through and leave it to | 1748 // their resources. In that case we fall through and leave it to |
1688 // VisitExternalOneByteString further down. | 1749 // VisitExternalOneByteString further down. |
1689 SerializeExternalString(); | 1750 SerializeExternalString(); |
(...skipping 30 matching lines...) Expand all Loading... |
1720 Heap::RootIsImmortalImmovable(root_index) && | 1781 Heap::RootIsImmortalImmovable(root_index) && |
1721 current_contents == current[-1]) { | 1782 current_contents == current[-1]) { |
1722 DCHECK(!serializer_->isolate()->heap()->InNewSpace(current_contents)); | 1783 DCHECK(!serializer_->isolate()->heap()->InNewSpace(current_contents)); |
1723 int repeat_count = 1; | 1784 int repeat_count = 1; |
1724 while (¤t[repeat_count] < end - 1 && | 1785 while (¤t[repeat_count] < end - 1 && |
1725 current[repeat_count] == current_contents) { | 1786 current[repeat_count] == current_contents) { |
1726 repeat_count++; | 1787 repeat_count++; |
1727 } | 1788 } |
1728 current += repeat_count; | 1789 current += repeat_count; |
1729 bytes_processed_so_far_ += repeat_count * kPointerSize; | 1790 bytes_processed_so_far_ += repeat_count * kPointerSize; |
1730 if (repeat_count > kMaxRepeats) { | 1791 if (repeat_count > kMaxFixedRepeats) { |
1731 sink_->Put(kRepeat, "SerializeRepeats"); | 1792 sink_->Put(kVariableRepeat, "SerializeRepeats"); |
1732 sink_->PutInt(repeat_count, "SerializeRepeats"); | 1793 sink_->PutInt(repeat_count, "SerializeRepeats"); |
1733 } else { | 1794 } else { |
1734 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats"); | 1795 sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats"); |
1735 } | 1796 } |
1736 } else { | 1797 } else { |
1737 serializer_->SerializeObject( | 1798 serializer_->SerializeObject( |
1738 current_contents, kPlain, kStartOfObject, 0); | 1799 current_contents, kPlain, kStartOfObject, 0); |
1739 bytes_processed_so_far_ += kPointerSize; | 1800 bytes_processed_so_far_ += kPointerSize; |
1740 current++; | 1801 current++; |
1741 } | 1802 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1950 } | 2011 } |
1951 | 2012 |
1952 | 2013 |
1953 BackReference Serializer::Allocate(AllocationSpace space, int size) { | 2014 BackReference Serializer::Allocate(AllocationSpace space, int size) { |
1954 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); | 2015 DCHECK(space >= 0 && space < kNumberOfPreallocatedSpaces); |
1955 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); | 2016 DCHECK(size > 0 && size <= static_cast<int>(max_chunk_size(space))); |
1956 uint32_t new_chunk_size = pending_chunk_[space] + size; | 2017 uint32_t new_chunk_size = pending_chunk_[space] + size; |
1957 if (new_chunk_size > max_chunk_size(space)) { | 2018 if (new_chunk_size > max_chunk_size(space)) { |
1958 // The new chunk size would not fit onto a single page. Complete the | 2019 // The new chunk size would not fit onto a single page. Complete the |
1959 // current chunk and start a new one. | 2020 // current chunk and start a new one. |
1960 sink_->Put(kNextChunk, "move to next chunk"); | 2021 sink_->Put(kNextChunk, "NextChunk"); |
1961 sink_->Put(space, "space of next chunk"); | 2022 sink_->Put(space, "NextChunkSpace"); |
1962 completed_chunks_[space].Add(pending_chunk_[space]); | 2023 completed_chunks_[space].Add(pending_chunk_[space]); |
1963 pending_chunk_[space] = 0; | 2024 pending_chunk_[space] = 0; |
1964 new_chunk_size = size; | 2025 new_chunk_size = size; |
1965 } | 2026 } |
1966 uint32_t offset = pending_chunk_[space]; | 2027 uint32_t offset = pending_chunk_[space]; |
1967 pending_chunk_[space] = new_chunk_size; | 2028 pending_chunk_[space] = new_chunk_size; |
1968 return BackReference::Reference(space, completed_chunks_[space].length(), | 2029 return BackReference::Reference(space, completed_chunks_[space].length(), |
1969 offset); | 2030 offset); |
1970 } | 2031 } |
1971 | 2032 |
(...skipping 11 matching lines...) Expand all Loading... |
1983 isolate_->InitializeLoggingAndCounters(); | 2044 isolate_->InitializeLoggingAndCounters(); |
1984 code_address_map_ = new CodeAddressMap(isolate_); | 2045 code_address_map_ = new CodeAddressMap(isolate_); |
1985 } | 2046 } |
1986 | 2047 |
1987 | 2048 |
1988 ScriptData* CodeSerializer::Serialize(Isolate* isolate, | 2049 ScriptData* CodeSerializer::Serialize(Isolate* isolate, |
1989 Handle<SharedFunctionInfo> info, | 2050 Handle<SharedFunctionInfo> info, |
1990 Handle<String> source) { | 2051 Handle<String> source) { |
1991 base::ElapsedTimer timer; | 2052 base::ElapsedTimer timer; |
1992 if (FLAG_profile_deserialization) timer.Start(); | 2053 if (FLAG_profile_deserialization) timer.Start(); |
1993 if (FLAG_trace_code_serializer) { | 2054 if (FLAG_trace_serializer) { |
1994 PrintF("[Serializing from"); | 2055 PrintF("[Serializing from"); |
1995 Object* script = info->script(); | 2056 Object* script = info->script(); |
1996 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); | 2057 if (script->IsScript()) Script::cast(script)->name()->ShortPrint(); |
1997 PrintF("]\n"); | 2058 PrintF("]\n"); |
1998 } | 2059 } |
1999 | 2060 |
2000 // Serialize code object. | 2061 // Serialize code object. |
2001 SnapshotByteSink sink(info->code()->CodeSize() * 2); | 2062 SnapshotByteSink sink(info->code()->CodeSize() * 2); |
2002 CodeSerializer cs(isolate, &sink, *source, info->code()); | 2063 CodeSerializer cs(isolate, &sink, *source, info->code()); |
2003 DisallowHeapAllocation no_gc; | 2064 DisallowHeapAllocation no_gc; |
(...skipping 19 matching lines...) Expand all Loading... |
2023 } | 2084 } |
2024 | 2085 |
2025 return script_data; | 2086 return script_data; |
2026 } | 2087 } |
2027 | 2088 |
2028 | 2089 |
2029 void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, | 2090 void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, |
2030 WhereToPoint where_to_point, int skip) { | 2091 WhereToPoint where_to_point, int skip) { |
2031 int root_index = root_index_map_.Lookup(obj); | 2092 int root_index = root_index_map_.Lookup(obj); |
2032 if (root_index != RootIndexMap::kInvalidRootIndex) { | 2093 if (root_index != RootIndexMap::kInvalidRootIndex) { |
2033 if (FLAG_trace_code_serializer) { | |
2034 PrintF(" Encoding root: %d\n", root_index); | |
2035 } | |
2036 PutRoot(root_index, obj, how_to_code, where_to_point, skip); | 2094 PutRoot(root_index, obj, how_to_code, where_to_point, skip); |
2037 return; | 2095 return; |
2038 } | 2096 } |
2039 | 2097 |
2040 BackReference back_reference = back_reference_map_.Lookup(obj); | 2098 if (SerializeKnownObject(obj, how_to_code, where_to_point, skip)) return; |
2041 if (back_reference.is_valid()) { | |
2042 if (back_reference.is_source()) { | |
2043 DCHECK_EQ(source_, obj); | |
2044 SerializeSourceObject(how_to_code, where_to_point); | |
2045 } else { | |
2046 if (FLAG_trace_code_serializer) { | |
2047 PrintF(" Encoding back reference to: "); | |
2048 obj->ShortPrint(); | |
2049 PrintF("\n"); | |
2050 } | |
2051 SerializeBackReference(back_reference, how_to_code, where_to_point, skip); | |
2052 } | |
2053 return; | |
2054 } | |
2055 | 2099 |
2056 if (skip != 0) { | 2100 FlushSkip(skip); |
2057 sink_->Put(kSkip, "SkipFromSerializeObject"); | |
2058 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | |
2059 } | |
2060 | 2101 |
2061 if (obj->IsCode()) { | 2102 if (obj->IsCode()) { |
2062 Code* code_object = Code::cast(obj); | 2103 Code* code_object = Code::cast(obj); |
2063 switch (code_object->kind()) { | 2104 switch (code_object->kind()) { |
2064 case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet. | 2105 case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet. |
2065 case Code::HANDLER: // No handlers patched in yet. | 2106 case Code::HANDLER: // No handlers patched in yet. |
2066 case Code::REGEXP: // No regexp literals initialized yet. | 2107 case Code::REGEXP: // No regexp literals initialized yet. |
2067 case Code::NUMBER_OF_KINDS: // Pseudo enum value. | 2108 case Code::NUMBER_OF_KINDS: // Pseudo enum value. |
2068 CHECK(false); | 2109 CHECK(false); |
2069 case Code::BUILTIN: | 2110 case Code::BUILTIN: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2102 // We expect no instantiated function objects or contexts. | 2143 // We expect no instantiated function objects or contexts. |
2103 CHECK(!obj->IsJSFunction() && !obj->IsContext()); | 2144 CHECK(!obj->IsJSFunction() && !obj->IsContext()); |
2104 | 2145 |
2105 SerializeGeneric(obj, how_to_code, where_to_point); | 2146 SerializeGeneric(obj, how_to_code, where_to_point); |
2106 } | 2147 } |
2107 | 2148 |
2108 | 2149 |
2109 void CodeSerializer::SerializeGeneric(HeapObject* heap_object, | 2150 void CodeSerializer::SerializeGeneric(HeapObject* heap_object, |
2110 HowToCode how_to_code, | 2151 HowToCode how_to_code, |
2111 WhereToPoint where_to_point) { | 2152 WhereToPoint where_to_point) { |
2112 if (FLAG_trace_code_serializer) { | |
2113 PrintF(" Encoding heap object: "); | |
2114 heap_object->ShortPrint(); | |
2115 PrintF("\n"); | |
2116 } | |
2117 | |
2118 if (heap_object->IsInternalizedString()) num_internalized_strings_++; | 2153 if (heap_object->IsInternalizedString()) num_internalized_strings_++; |
2119 | 2154 |
2120 // Object has not yet been serialized. Serialize it here. | 2155 // Object has not yet been serialized. Serialize it here. |
2121 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, | 2156 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, |
2122 where_to_point); | 2157 where_to_point); |
2123 serializer.Serialize(); | 2158 serializer.Serialize(); |
2124 } | 2159 } |
2125 | 2160 |
2126 | 2161 |
2127 void CodeSerializer::SerializeBuiltin(int builtin_index, HowToCode how_to_code, | 2162 void CodeSerializer::SerializeBuiltin(int builtin_index, HowToCode how_to_code, |
2128 WhereToPoint where_to_point) { | 2163 WhereToPoint where_to_point) { |
2129 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || | 2164 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
2130 (how_to_code == kPlain && where_to_point == kInnerPointer) || | 2165 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
2131 (how_to_code == kFromCode && where_to_point == kInnerPointer)); | 2166 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
2132 DCHECK_LT(builtin_index, Builtins::builtin_count); | 2167 DCHECK_LT(builtin_index, Builtins::builtin_count); |
2133 DCHECK_LE(0, builtin_index); | 2168 DCHECK_LE(0, builtin_index); |
2134 | 2169 |
2135 if (FLAG_trace_code_serializer) { | 2170 if (FLAG_trace_serializer) { |
2136 PrintF(" Encoding builtin: %s\n", | 2171 PrintF(" Encoding builtin: %s\n", |
2137 isolate()->builtins()->name(builtin_index)); | 2172 isolate()->builtins()->name(builtin_index)); |
2138 } | 2173 } |
2139 | 2174 |
2140 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); | 2175 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
2141 sink_->PutInt(builtin_index, "builtin_index"); | 2176 sink_->PutInt(builtin_index, "builtin_index"); |
2142 } | 2177 } |
2143 | 2178 |
2144 | 2179 |
2145 void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code, | 2180 void CodeSerializer::SerializeCodeStub(uint32_t stub_key, HowToCode how_to_code, |
2146 WhereToPoint where_to_point) { | 2181 WhereToPoint where_to_point) { |
2147 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || | 2182 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
2148 (how_to_code == kPlain && where_to_point == kInnerPointer) || | 2183 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
2149 (how_to_code == kFromCode && where_to_point == kInnerPointer)); | 2184 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
2150 DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); | 2185 DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); |
2151 DCHECK(!CodeStub::GetCode(isolate(), stub_key).is_null()); | 2186 DCHECK(!CodeStub::GetCode(isolate(), stub_key).is_null()); |
2152 | 2187 |
2153 int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; | 2188 int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; |
2154 | 2189 |
2155 if (FLAG_trace_code_serializer) { | 2190 if (FLAG_trace_serializer) { |
2156 PrintF(" Encoding code stub %s as %d\n", | 2191 PrintF(" Encoding code stub %s as %d\n", |
2157 CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), | 2192 CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), |
2158 index); | 2193 index); |
2159 } | 2194 } |
2160 | 2195 |
2161 sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); | 2196 sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); |
2162 sink_->PutInt(index, "CodeStub key"); | 2197 sink_->PutInt(index, "CodeStub key"); |
2163 } | 2198 } |
2164 | 2199 |
2165 | 2200 |
2166 void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code, | 2201 void CodeSerializer::SerializeIC(Code* ic, HowToCode how_to_code, |
2167 WhereToPoint where_to_point) { | 2202 WhereToPoint where_to_point) { |
2168 // The IC may be implemented as a stub. | 2203 // The IC may be implemented as a stub. |
2169 uint32_t stub_key = ic->stub_key(); | 2204 uint32_t stub_key = ic->stub_key(); |
2170 if (stub_key != CodeStub::NoCacheKey()) { | 2205 if (stub_key != CodeStub::NoCacheKey()) { |
2171 if (FLAG_trace_code_serializer) { | 2206 if (FLAG_trace_serializer) { |
2172 PrintF(" %s is a code stub\n", Code::Kind2String(ic->kind())); | 2207 PrintF(" %s is a code stub\n", Code::Kind2String(ic->kind())); |
2173 } | 2208 } |
2174 SerializeCodeStub(stub_key, how_to_code, where_to_point); | 2209 SerializeCodeStub(stub_key, how_to_code, where_to_point); |
2175 return; | 2210 return; |
2176 } | 2211 } |
2177 // The IC may be implemented as builtin. Only real builtins have an | 2212 // The IC may be implemented as builtin. Only real builtins have an |
2178 // actual builtin_index value attached (otherwise it's just garbage). | 2213 // actual builtin_index value attached (otherwise it's just garbage). |
2179 // Compare to make sure we are really dealing with a builtin. | 2214 // Compare to make sure we are really dealing with a builtin. |
2180 int builtin_index = ic->builtin_index(); | 2215 int builtin_index = ic->builtin_index(); |
2181 if (builtin_index < Builtins::builtin_count) { | 2216 if (builtin_index < Builtins::builtin_count) { |
2182 Builtins::Name name = static_cast<Builtins::Name>(builtin_index); | 2217 Builtins::Name name = static_cast<Builtins::Name>(builtin_index); |
2183 Code* builtin = isolate()->builtins()->builtin(name); | 2218 Code* builtin = isolate()->builtins()->builtin(name); |
2184 if (builtin == ic) { | 2219 if (builtin == ic) { |
2185 if (FLAG_trace_code_serializer) { | 2220 if (FLAG_trace_serializer) { |
2186 PrintF(" %s is a builtin\n", Code::Kind2String(ic->kind())); | 2221 PrintF(" %s is a builtin\n", Code::Kind2String(ic->kind())); |
2187 } | 2222 } |
2188 DCHECK(ic->kind() == Code::KEYED_LOAD_IC || | 2223 DCHECK(ic->kind() == Code::KEYED_LOAD_IC || |
2189 ic->kind() == Code::KEYED_STORE_IC); | 2224 ic->kind() == Code::KEYED_STORE_IC); |
2190 SerializeBuiltin(builtin_index, how_to_code, where_to_point); | 2225 SerializeBuiltin(builtin_index, how_to_code, where_to_point); |
2191 return; | 2226 return; |
2192 } | 2227 } |
2193 } | 2228 } |
2194 // The IC may also just be a piece of code kept in the non_monomorphic_cache. | 2229 // The IC may also just be a piece of code kept in the non_monomorphic_cache. |
2195 // In that case, just serialize as a normal code object. | 2230 // In that case, just serialize as a normal code object. |
2196 if (FLAG_trace_code_serializer) { | 2231 if (FLAG_trace_serializer) { |
2197 PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind())); | 2232 PrintF(" %s has no special handling\n", Code::Kind2String(ic->kind())); |
2198 } | 2233 } |
2199 DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC); | 2234 DCHECK(ic->kind() == Code::LOAD_IC || ic->kind() == Code::STORE_IC); |
2200 SerializeGeneric(ic, how_to_code, where_to_point); | 2235 SerializeGeneric(ic, how_to_code, where_to_point); |
2201 } | 2236 } |
2202 | 2237 |
2203 | 2238 |
2204 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { | 2239 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { |
2205 // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2). | 2240 // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2). |
2206 int index = 0; | 2241 int index = 0; |
2207 while (index < stub_keys_.length()) { | 2242 while (index < stub_keys_.length()) { |
2208 if (stub_keys_[index] == stub_key) return index; | 2243 if (stub_keys_[index] == stub_key) return index; |
2209 index++; | 2244 index++; |
2210 } | 2245 } |
2211 stub_keys_.Add(stub_key); | 2246 stub_keys_.Add(stub_key); |
2212 return index; | 2247 return index; |
2213 } | 2248 } |
2214 | 2249 |
2215 | 2250 |
2216 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, | 2251 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, |
2217 WhereToPoint where_to_point) { | 2252 WhereToPoint where_to_point) { |
2218 if (FLAG_trace_code_serializer) PrintF(" Encoding source object\n"); | 2253 if (FLAG_trace_serializer) PrintF(" Encoding source object\n"); |
2219 | 2254 |
2220 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | 2255 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); |
2221 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); | 2256 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); |
2222 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); | 2257 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); |
2223 } | 2258 } |
2224 | 2259 |
2225 | 2260 |
2226 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( | 2261 MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize( |
2227 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { | 2262 Isolate* isolate, ScriptData* cached_data, Handle<String> source) { |
2228 base::ElapsedTimer timer; | 2263 base::ElapsedTimer timer; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2356 bool SerializedCodeData::IsSane(String* source) { | 2391 bool SerializedCodeData::IsSane(String* source) { |
2357 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && | 2392 return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && |
2358 PayloadLength() >= SharedFunctionInfo::kSize; | 2393 PayloadLength() >= SharedFunctionInfo::kSize; |
2359 } | 2394 } |
2360 | 2395 |
2361 | 2396 |
2362 int SerializedCodeData::CheckSum(String* string) { | 2397 int SerializedCodeData::CheckSum(String* string) { |
2363 return Version::Hash() ^ string->length(); | 2398 return Version::Hash() ^ string->length(); |
2364 } | 2399 } |
2365 } } // namespace v8::internal | 2400 } } // namespace v8::internal |
OLD | NEW |