| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "api.h" | 31 #include "api.h" |
| 32 #include "execution.h" | 32 #include "execution.h" |
| 33 #include "global-handles.h" | 33 #include "global-handles.h" |
| 34 #include "ic-inl.h" | 34 #include "ic-inl.h" |
| 35 #include "natives.h" | 35 #include "natives.h" |
| 36 #include "platform.h" | 36 #include "platform.h" |
| 37 #include "runtime.h" | 37 #include "runtime.h" |
| 38 #include "serialize.h" | 38 #include "serialize.h" |
| 39 #include "stub-cache.h" | 39 #include "stub-cache.h" |
| 40 #include "v8threads.h" | 40 #include "v8threads.h" |
| 41 #include "top.h" | |
| 42 #include "bootstrapper.h" | 41 #include "bootstrapper.h" |
| 43 | 42 |
| 44 namespace v8 { | 43 namespace v8 { |
| 45 namespace internal { | 44 namespace internal { |
| 46 | 45 |
| 47 | 46 |
| 48 // ----------------------------------------------------------------------------- | 47 // ----------------------------------------------------------------------------- |
| 49 // Coding of external references. | 48 // Coding of external references. |
| 50 | 49 |
| 51 // The encoding of an external reference. The type is in the high word. | 50 // The encoding of an external reference. The type is in the high word. |
| 52 // The id is in the low word. | 51 // The id is in the low word. |
| 53 static uint32_t EncodeExternal(TypeCode type, uint16_t id) { | 52 static uint32_t EncodeExternal(TypeCode type, uint16_t id) { |
| 54 return static_cast<uint32_t>(type) << 16 | id; | 53 return static_cast<uint32_t>(type) << 16 | id; |
| 55 } | 54 } |
| 56 | 55 |
| 57 | 56 |
| 58 static int* GetInternalPointer(StatsCounter* counter) { | 57 static int* GetInternalPointer(StatsCounter* counter) { |
| 59 // All counters refer to dummy_counter, if deserializing happens without | 58 // All counters refer to dummy_counter, if deserializing happens without |
| 60 // setting up counters. | 59 // setting up counters. |
| 61 static int dummy_counter = 0; | 60 static int dummy_counter = 0; |
| 62 return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter; | 61 return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter; |
| 63 } | 62 } |
| 64 | 63 |
| 65 | 64 |
| 66 // ExternalReferenceTable is a helper class that defines the relationship | 65 // ExternalReferenceTable is a helper class that defines the relationship |
| 67 // between external references and their encodings. It is used to build | 66 // between external references and their encodings. It is used to build |
| 68 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder. | 67 // hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder. |
| 69 class ExternalReferenceTable { | 68 class ExternalReferenceTable { |
| 70 public: | 69 public: |
| 71 static ExternalReferenceTable* instance() { | 70 static ExternalReferenceTable* instance(Isolate* isolate) { |
| 72 if (!instance_) instance_ = new ExternalReferenceTable(); | 71 ExternalReferenceTable* external_reference_table = |
| 73 return instance_; | 72 isolate->external_reference_table(); |
| 73 if (external_reference_table == NULL) { |
| 74 external_reference_table = new ExternalReferenceTable(isolate); |
| 75 isolate->set_external_reference_table(external_reference_table); |
| 76 } |
| 77 return external_reference_table; |
| 74 } | 78 } |
| 75 | 79 |
| 76 int size() const { return refs_.length(); } | 80 int size() const { return refs_.length(); } |
| 77 | 81 |
| 78 Address address(int i) { return refs_[i].address; } | 82 Address address(int i) { return refs_[i].address; } |
| 79 | 83 |
| 80 uint32_t code(int i) { return refs_[i].code; } | 84 uint32_t code(int i) { return refs_[i].code; } |
| 81 | 85 |
| 82 const char* name(int i) { return refs_[i].name; } | 86 const char* name(int i) { return refs_[i].name; } |
| 83 | 87 |
| 84 int max_id(int code) { return max_id_[code]; } | 88 int max_id(int code) { return max_id_[code]; } |
| 85 | 89 |
| 86 private: | 90 private: |
| 87 static ExternalReferenceTable* instance_; | 91 explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) { |
| 88 | 92 PopulateTable(isolate); |
| 89 ExternalReferenceTable() : refs_(64) { PopulateTable(); } | 93 } |
| 90 ~ExternalReferenceTable() { } | 94 ~ExternalReferenceTable() { } |
| 91 | 95 |
| 92 struct ExternalReferenceEntry { | 96 struct ExternalReferenceEntry { |
| 93 Address address; | 97 Address address; |
| 94 uint32_t code; | 98 uint32_t code; |
| 95 const char* name; | 99 const char* name; |
| 96 }; | 100 }; |
| 97 | 101 |
| 98 void PopulateTable(); | 102 void PopulateTable(Isolate* isolate); |
| 99 | 103 |
| 100 // For a few types of references, we can get their address from their id. | 104 // For a few types of references, we can get their address from their id. |
| 101 void AddFromId(TypeCode type, uint16_t id, const char* name); | 105 void AddFromId(TypeCode type, uint16_t id, const char* name); |
| 102 | 106 |
| 103 // For other types of references, the caller will figure out the address. | 107 // For other types of references, the caller will figure out the address. |
| 104 void Add(Address address, TypeCode type, uint16_t id, const char* name); | 108 void Add(Address address, TypeCode type, uint16_t id, const char* name); |
| 105 | 109 |
| 106 List<ExternalReferenceEntry> refs_; | 110 List<ExternalReferenceEntry> refs_; |
| 107 int max_id_[kTypeCodeCount]; | 111 int max_id_[kTypeCodeCount]; |
| 108 }; | 112 }; |
| 109 | 113 |
| 110 | 114 |
| 111 ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL; | |
| 112 | |
| 113 | |
| 114 void ExternalReferenceTable::AddFromId(TypeCode type, | 115 void ExternalReferenceTable::AddFromId(TypeCode type, |
| 115 uint16_t id, | 116 uint16_t id, |
| 116 const char* name) { | 117 const char* name) { |
| 117 Address address; | 118 Address address; |
| 118 switch (type) { | 119 switch (type) { |
| 119 case C_BUILTIN: { | 120 case C_BUILTIN: { |
| 120 ExternalReference ref(static_cast<Builtins::CFunctionId>(id)); | 121 ExternalReference ref(static_cast<Builtins::CFunctionId>(id)); |
| 121 address = ref.address(); | 122 address = ref.address(); |
| 122 break; | 123 break; |
| 123 } | 124 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 152 ExternalReferenceEntry entry; | 153 ExternalReferenceEntry entry; |
| 153 entry.address = address; | 154 entry.address = address; |
| 154 entry.code = EncodeExternal(type, id); | 155 entry.code = EncodeExternal(type, id); |
| 155 entry.name = name; | 156 entry.name = name; |
| 156 ASSERT_NE(0, entry.code); | 157 ASSERT_NE(0, entry.code); |
| 157 refs_.Add(entry); | 158 refs_.Add(entry); |
| 158 if (id > max_id_[type]) max_id_[type] = id; | 159 if (id > max_id_[type]) max_id_[type] = id; |
| 159 } | 160 } |
| 160 | 161 |
| 161 | 162 |
| 162 void ExternalReferenceTable::PopulateTable() { | 163 void ExternalReferenceTable::PopulateTable(Isolate* isolate) { |
| 163 for (int type_code = 0; type_code < kTypeCodeCount; type_code++) { | 164 for (int type_code = 0; type_code < kTypeCodeCount; type_code++) { |
| 164 max_id_[type_code] = 0; | 165 max_id_[type_code] = 0; |
| 165 } | 166 } |
| 166 | 167 |
| 167 // The following populates all of the different type of external references | 168 // The following populates all of the different type of external references |
| 168 // into the ExternalReferenceTable. | 169 // into the ExternalReferenceTable. |
| 169 // | 170 // |
| 170 // NOTE: This function was originally 100k of code. It has since been | 171 // NOTE: This function was originally 100k of code. It has since been |
| 171 // rewritten to be mostly table driven, as the callback macro style tends to | 172 // rewritten to be mostly table driven, as the callback macro style tends to |
| 172 // very easily cause code bloat. Please be careful in the future when adding | 173 // very easily cause code bloat. Please be careful in the future when adding |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 IC_UTIL_LIST(IC_ENTRY) | 219 IC_UTIL_LIST(IC_ENTRY) |
| 219 #undef IC_ENTRY | 220 #undef IC_ENTRY |
| 220 }; // end of ref_table[]. | 221 }; // end of ref_table[]. |
| 221 | 222 |
| 222 for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) { | 223 for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) { |
| 223 AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name); | 224 AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name); |
| 224 } | 225 } |
| 225 | 226 |
| 226 #ifdef ENABLE_DEBUGGER_SUPPORT | 227 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 227 // Debug addresses | 228 // Debug addresses |
| 228 Add(Debug_Address(Debug::k_after_break_target_address).address(), | 229 Add(Debug_Address(Debug::k_after_break_target_address).address(isolate), |
| 229 DEBUG_ADDRESS, | 230 DEBUG_ADDRESS, |
| 230 Debug::k_after_break_target_address << kDebugIdShift, | 231 Debug::k_after_break_target_address << kDebugIdShift, |
| 231 "Debug::after_break_target_address()"); | 232 "Debug::after_break_target_address()"); |
| 232 Add(Debug_Address(Debug::k_debug_break_slot_address).address(), | 233 Add(Debug_Address(Debug::k_debug_break_slot_address).address(isolate), |
| 233 DEBUG_ADDRESS, | 234 DEBUG_ADDRESS, |
| 234 Debug::k_debug_break_slot_address << kDebugIdShift, | 235 Debug::k_debug_break_slot_address << kDebugIdShift, |
| 235 "Debug::debug_break_slot_address()"); | 236 "Debug::debug_break_slot_address()"); |
| 236 Add(Debug_Address(Debug::k_debug_break_return_address).address(), | 237 Add(Debug_Address(Debug::k_debug_break_return_address).address(isolate), |
| 237 DEBUG_ADDRESS, | 238 DEBUG_ADDRESS, |
| 238 Debug::k_debug_break_return_address << kDebugIdShift, | 239 Debug::k_debug_break_return_address << kDebugIdShift, |
| 239 "Debug::debug_break_return_address()"); | 240 "Debug::debug_break_return_address()"); |
| 240 Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(), | 241 Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate), |
| 241 DEBUG_ADDRESS, | 242 DEBUG_ADDRESS, |
| 242 Debug::k_restarter_frame_function_pointer << kDebugIdShift, | 243 Debug::k_restarter_frame_function_pointer << kDebugIdShift, |
| 243 "Debug::restarter_frame_function_pointer_address()"); | 244 "Debug::restarter_frame_function_pointer_address()"); |
| 244 #endif | 245 #endif |
| 245 | 246 |
| 246 // Stat counters | 247 // Stat counters |
| 247 struct StatsRefTableEntry { | 248 struct StatsRefTableEntry { |
| 248 StatsCounter* counter; | 249 StatsCounter* (Counters::*counter)(); |
| 249 uint16_t id; | 250 uint16_t id; |
| 250 const char* name; | 251 const char* name; |
| 251 }; | 252 }; |
| 252 | 253 |
| 253 static const StatsRefTableEntry stats_ref_table[] = { | 254 const StatsRefTableEntry stats_ref_table[] = { |
| 254 #define COUNTER_ENTRY(name, caption) \ | 255 #define COUNTER_ENTRY(name, caption) \ |
| 255 { &Counters::name, \ | 256 { &Counters::name, \ |
| 256 Counters::k_##name, \ | 257 Counters::k_##name, \ |
| 257 "Counters::" #name }, | 258 "Counters::" #name }, |
| 258 | 259 |
| 259 STATS_COUNTER_LIST_1(COUNTER_ENTRY) | 260 STATS_COUNTER_LIST_1(COUNTER_ENTRY) |
| 260 STATS_COUNTER_LIST_2(COUNTER_ENTRY) | 261 STATS_COUNTER_LIST_2(COUNTER_ENTRY) |
| 261 #undef COUNTER_ENTRY | 262 #undef COUNTER_ENTRY |
| 262 }; // end of stats_ref_table[]. | 263 }; // end of stats_ref_table[]. |
| 263 | 264 |
| 265 Counters* counters = isolate->counters(); |
| 264 for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) { | 266 for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) { |
| 265 Add(reinterpret_cast<Address>( | 267 Add(reinterpret_cast<Address>(GetInternalPointer( |
| 266 GetInternalPointer(stats_ref_table[i].counter)), | 268 (counters->*(stats_ref_table[i].counter))())), |
| 267 STATS_COUNTER, | 269 STATS_COUNTER, |
| 268 stats_ref_table[i].id, | 270 stats_ref_table[i].id, |
| 269 stats_ref_table[i].name); | 271 stats_ref_table[i].name); |
| 270 } | 272 } |
| 271 | 273 |
| 272 // Top addresses | 274 // Top addresses |
| 273 const char* top_address_format = "Top::%s"; | |
| 274 | 275 |
| 275 const char* AddressNames[] = { | 276 const char* AddressNames[] = { |
| 276 #define C(name) #name, | 277 #define C(name) "Isolate::" #name, |
| 277 TOP_ADDRESS_LIST(C) | 278 ISOLATE_ADDRESS_LIST(C) |
| 278 TOP_ADDRESS_LIST_PROF(C) | 279 ISOLATE_ADDRESS_LIST_PROF(C) |
| 279 NULL | 280 NULL |
| 280 #undef C | 281 #undef C |
| 281 }; | 282 }; |
| 282 | 283 |
| 283 int top_format_length = StrLength(top_address_format) - 2; | 284 for (uint16_t i = 0; i < Isolate::k_isolate_address_count; ++i) { |
| 284 for (uint16_t i = 0; i < Top::k_top_address_count; ++i) { | 285 Add(isolate->get_address_from_id((Isolate::AddressId)i), |
| 285 const char* address_name = AddressNames[i]; | 286 TOP_ADDRESS, i, AddressNames[i]); |
| 286 Vector<char> name = | |
| 287 Vector<char>::New(top_format_length + StrLength(address_name) + 1); | |
| 288 const char* chars = name.start(); | |
| 289 OS::SNPrintF(name, top_address_format, address_name); | |
| 290 Add(Top::get_address_from_id((Top::AddressId)i), TOP_ADDRESS, i, chars); | |
| 291 } | 287 } |
| 292 | 288 |
| 293 // Accessors | 289 // Accessors |
| 294 #define ACCESSOR_DESCRIPTOR_DECLARATION(name) \ | 290 #define ACCESSOR_DESCRIPTOR_DECLARATION(name) \ |
| 295 Add((Address)&Accessors::name, \ | 291 Add((Address)&Accessors::name, \ |
| 296 ACCESSOR, \ | 292 ACCESSOR, \ |
| 297 Accessors::k##name, \ | 293 Accessors::k##name, \ |
| 298 "Accessors::" #name); | 294 "Accessors::" #name); |
| 299 | 295 |
| 300 ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION) | 296 ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION) |
| 301 #undef ACCESSOR_DESCRIPTOR_DECLARATION | 297 #undef ACCESSOR_DESCRIPTOR_DECLARATION |
| 302 | 298 |
| 299 StubCache* stub_cache = isolate->stub_cache(); |
| 300 |
| 303 // Stub cache tables | 301 // Stub cache tables |
| 304 Add(SCTableReference::keyReference(StubCache::kPrimary).address(), | 302 Add(stub_cache->key_reference(StubCache::kPrimary).address(), |
| 305 STUB_CACHE_TABLE, | 303 STUB_CACHE_TABLE, |
| 306 1, | 304 1, |
| 307 "StubCache::primary_->key"); | 305 "StubCache::primary_->key"); |
| 308 Add(SCTableReference::valueReference(StubCache::kPrimary).address(), | 306 Add(stub_cache->value_reference(StubCache::kPrimary).address(), |
| 309 STUB_CACHE_TABLE, | 307 STUB_CACHE_TABLE, |
| 310 2, | 308 2, |
| 311 "StubCache::primary_->value"); | 309 "StubCache::primary_->value"); |
| 312 Add(SCTableReference::keyReference(StubCache::kSecondary).address(), | 310 Add(stub_cache->key_reference(StubCache::kSecondary).address(), |
| 313 STUB_CACHE_TABLE, | 311 STUB_CACHE_TABLE, |
| 314 3, | 312 3, |
| 315 "StubCache::secondary_->key"); | 313 "StubCache::secondary_->key"); |
| 316 Add(SCTableReference::valueReference(StubCache::kSecondary).address(), | 314 Add(stub_cache->value_reference(StubCache::kSecondary).address(), |
| 317 STUB_CACHE_TABLE, | 315 STUB_CACHE_TABLE, |
| 318 4, | 316 4, |
| 319 "StubCache::secondary_->value"); | 317 "StubCache::secondary_->value"); |
| 320 | 318 |
| 321 // Runtime entries | 319 // Runtime entries |
| 322 Add(ExternalReference::perform_gc_function().address(), | 320 Add(ExternalReference::perform_gc_function().address(), |
| 323 RUNTIME_ENTRY, | 321 RUNTIME_ENTRY, |
| 324 1, | 322 1, |
| 325 "Runtime::PerformGC"); | 323 "Runtime::PerformGC"); |
| 326 Add(ExternalReference::fill_heap_number_with_random_function().address(), | 324 Add(ExternalReference::fill_heap_number_with_random_function().address(), |
| 327 RUNTIME_ENTRY, | 325 RUNTIME_ENTRY, |
| 328 2, | 326 2, |
| 329 "V8::FillHeapNumberWithRandom"); | 327 "V8::FillHeapNumberWithRandom"); |
| 330 | |
| 331 Add(ExternalReference::random_uint32_function().address(), | 328 Add(ExternalReference::random_uint32_function().address(), |
| 332 RUNTIME_ENTRY, | 329 RUNTIME_ENTRY, |
| 333 3, | 330 3, |
| 334 "V8::Random"); | 331 "V8::Random"); |
| 335 | |
| 336 Add(ExternalReference::delete_handle_scope_extensions().address(), | 332 Add(ExternalReference::delete_handle_scope_extensions().address(), |
| 337 RUNTIME_ENTRY, | 333 RUNTIME_ENTRY, |
| 338 4, | 334 4, |
| 339 "HandleScope::DeleteExtensions"); | 335 "HandleScope::DeleteExtensions"); |
| 340 | 336 |
| 341 // Miscellaneous | 337 // Miscellaneous |
| 342 Add(ExternalReference::the_hole_value_location().address(), | 338 Add(ExternalReference::the_hole_value_location().address(), |
| 343 UNCLASSIFIED, | 339 UNCLASSIFIED, |
| 344 2, | 340 2, |
| 345 "Factory::the_hole_value().location()"); | 341 "Factory::the_hole_value().location()"); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 34, | 475 34, |
| 480 "Deoptimizer::ComputeOutputFrames()"); | 476 "Deoptimizer::ComputeOutputFrames()"); |
| 481 Add(ExternalReference::address_of_min_int().address(), | 477 Add(ExternalReference::address_of_min_int().address(), |
| 482 UNCLASSIFIED, | 478 UNCLASSIFIED, |
| 483 35, | 479 35, |
| 484 "LDoubleConstant::min_int"); | 480 "LDoubleConstant::min_int"); |
| 485 Add(ExternalReference::address_of_one_half().address(), | 481 Add(ExternalReference::address_of_one_half().address(), |
| 486 UNCLASSIFIED, | 482 UNCLASSIFIED, |
| 487 36, | 483 36, |
| 488 "LDoubleConstant::one_half"); | 484 "LDoubleConstant::one_half"); |
| 485 Add(ExternalReference::isolate_address().address(), |
| 486 UNCLASSIFIED, |
| 487 37, |
| 488 "isolate"); |
| 489 Add(ExternalReference::address_of_minus_zero().address(), | 489 Add(ExternalReference::address_of_minus_zero().address(), |
| 490 UNCLASSIFIED, | 490 UNCLASSIFIED, |
| 491 37, | 491 38, |
| 492 "LDoubleConstant::minus_zero"); | 492 "LDoubleConstant::minus_zero"); |
| 493 Add(ExternalReference::address_of_negative_infinity().address(), | 493 Add(ExternalReference::address_of_negative_infinity().address(), |
| 494 UNCLASSIFIED, | 494 UNCLASSIFIED, |
| 495 38, | 495 39, |
| 496 "LDoubleConstant::negative_infinity"); | 496 "LDoubleConstant::negative_infinity"); |
| 497 Add(ExternalReference::power_double_double_function().address(), | 497 Add(ExternalReference::power_double_double_function().address(), |
| 498 UNCLASSIFIED, | 498 UNCLASSIFIED, |
| 499 39, | 499 40, |
| 500 "power_double_double_function"); | 500 "power_double_double_function"); |
| 501 Add(ExternalReference::power_double_int_function().address(), | 501 Add(ExternalReference::power_double_int_function().address(), |
| 502 UNCLASSIFIED, | 502 UNCLASSIFIED, |
| 503 40, | 503 41, |
| 504 "power_double_int_function"); | 504 "power_double_int_function"); |
| 505 Add(ExternalReference::arguments_marker_location().address(), | 505 Add(ExternalReference::arguments_marker_location().address(), |
| 506 UNCLASSIFIED, | 506 UNCLASSIFIED, |
| 507 41, | 507 42, |
| 508 "Factory::arguments_marker().location()"); | 508 "Factory::arguments_marker().location()"); |
| 509 } | 509 } |
| 510 | 510 |
| 511 | 511 |
| 512 ExternalReferenceEncoder::ExternalReferenceEncoder() | 512 ExternalReferenceEncoder::ExternalReferenceEncoder() |
| 513 : encodings_(Match) { | 513 : encodings_(Match), |
| 514 isolate_(Isolate::Current()) { |
| 514 ExternalReferenceTable* external_references = | 515 ExternalReferenceTable* external_references = |
| 515 ExternalReferenceTable::instance(); | 516 ExternalReferenceTable::instance(isolate_); |
| 516 for (int i = 0; i < external_references->size(); ++i) { | 517 for (int i = 0; i < external_references->size(); ++i) { |
| 517 Put(external_references->address(i), i); | 518 Put(external_references->address(i), i); |
| 518 } | 519 } |
| 519 } | 520 } |
| 520 | 521 |
| 521 | 522 |
| 522 uint32_t ExternalReferenceEncoder::Encode(Address key) const { | 523 uint32_t ExternalReferenceEncoder::Encode(Address key) const { |
| 523 int index = IndexOf(key); | 524 int index = IndexOf(key); |
| 524 ASSERT(key == NULL || index >= 0); | 525 ASSERT(key == NULL || index >= 0); |
| 525 return index >=0 ? ExternalReferenceTable::instance()->code(index) : 0; | 526 return index >=0 ? |
| 527 ExternalReferenceTable::instance(isolate_)->code(index) : 0; |
| 526 } | 528 } |
| 527 | 529 |
| 528 | 530 |
| 529 const char* ExternalReferenceEncoder::NameOfAddress(Address key) const { | 531 const char* ExternalReferenceEncoder::NameOfAddress(Address key) const { |
| 530 int index = IndexOf(key); | 532 int index = IndexOf(key); |
| 531 return index >=0 ? ExternalReferenceTable::instance()->name(index) : NULL; | 533 return index >= 0 ? |
| 534 ExternalReferenceTable::instance(isolate_)->name(index) : NULL; |
| 532 } | 535 } |
| 533 | 536 |
| 534 | 537 |
| 535 int ExternalReferenceEncoder::IndexOf(Address key) const { | 538 int ExternalReferenceEncoder::IndexOf(Address key) const { |
| 536 if (key == NULL) return -1; | 539 if (key == NULL) return -1; |
| 537 HashMap::Entry* entry = | 540 HashMap::Entry* entry = |
| 538 const_cast<HashMap &>(encodings_).Lookup(key, Hash(key), false); | 541 const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false); |
| 539 return entry == NULL | 542 return entry == NULL |
| 540 ? -1 | 543 ? -1 |
| 541 : static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); | 544 : static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); |
| 542 } | 545 } |
| 543 | 546 |
| 544 | 547 |
| 545 void ExternalReferenceEncoder::Put(Address key, int index) { | 548 void ExternalReferenceEncoder::Put(Address key, int index) { |
| 546 HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true); | 549 HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true); |
| 547 entry->value = reinterpret_cast<void*>(index); | 550 entry->value = reinterpret_cast<void*>(index); |
| 548 } | 551 } |
| 549 | 552 |
| 550 | 553 |
| 551 ExternalReferenceDecoder::ExternalReferenceDecoder() | 554 ExternalReferenceDecoder::ExternalReferenceDecoder() |
| 552 : encodings_(NewArray<Address*>(kTypeCodeCount)) { | 555 : encodings_(NewArray<Address*>(kTypeCodeCount)), |
| 556 isolate_(Isolate::Current()) { |
| 553 ExternalReferenceTable* external_references = | 557 ExternalReferenceTable* external_references = |
| 554 ExternalReferenceTable::instance(); | 558 ExternalReferenceTable::instance(isolate_); |
| 555 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { | 559 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { |
| 556 int max = external_references->max_id(type) + 1; | 560 int max = external_references->max_id(type) + 1; |
| 557 encodings_[type] = NewArray<Address>(max + 1); | 561 encodings_[type] = NewArray<Address>(max + 1); |
| 558 } | 562 } |
| 559 for (int i = 0; i < external_references->size(); ++i) { | 563 for (int i = 0; i < external_references->size(); ++i) { |
| 560 Put(external_references->code(i), external_references->address(i)); | 564 Put(external_references->code(i), external_references->address(i)); |
| 561 } | 565 } |
| 562 } | 566 } |
| 563 | 567 |
| 564 | 568 |
| 565 ExternalReferenceDecoder::~ExternalReferenceDecoder() { | 569 ExternalReferenceDecoder::~ExternalReferenceDecoder() { |
| 566 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { | 570 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) { |
| 567 DeleteArray(encodings_[type]); | 571 DeleteArray(encodings_[type]); |
| 568 } | 572 } |
| 569 DeleteArray(encodings_); | 573 DeleteArray(encodings_); |
| 570 } | 574 } |
| 571 | 575 |
| 572 | 576 |
| 573 bool Serializer::serialization_enabled_ = false; | 577 bool Serializer::serialization_enabled_ = false; |
| 574 bool Serializer::too_late_to_enable_now_ = false; | 578 bool Serializer::too_late_to_enable_now_ = false; |
| 575 ExternalReferenceDecoder* Deserializer::external_reference_decoder_ = NULL; | |
| 576 | 579 |
| 577 | 580 |
| 578 Deserializer::Deserializer(SnapshotByteSource* source) : source_(source) { | 581 Deserializer::Deserializer(SnapshotByteSource* source) |
| 582 : isolate_(NULL), |
| 583 source_(source), |
| 584 external_reference_decoder_(NULL) { |
| 579 } | 585 } |
| 580 | 586 |
| 581 | 587 |
| 582 // This routine both allocates a new object, and also keeps | 588 // This routine both allocates a new object, and also keeps |
| 583 // track of where objects have been allocated so that we can | 589 // track of where objects have been allocated so that we can |
| 584 // fix back references when deserializing. | 590 // fix back references when deserializing. |
| 585 Address Deserializer::Allocate(int space_index, Space* space, int size) { | 591 Address Deserializer::Allocate(int space_index, Space* space, int size) { |
| 586 Address address; | 592 Address address; |
| 587 if (!SpaceIsLarge(space_index)) { | 593 if (!SpaceIsLarge(space_index)) { |
| 588 ASSERT(!SpaceIsPaged(space_index) || | 594 ASSERT(!SpaceIsPaged(space_index) || |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 } | 653 } |
| 648 ASSERT(SpaceIsPaged(space)); | 654 ASSERT(SpaceIsPaged(space)); |
| 649 int page_of_pointee = offset >> kPageSizeBits; | 655 int page_of_pointee = offset >> kPageSizeBits; |
| 650 Address object_address = pages_[space][page_of_pointee] + | 656 Address object_address = pages_[space][page_of_pointee] + |
| 651 (offset & Page::kPageAlignmentMask); | 657 (offset & Page::kPageAlignmentMask); |
| 652 return HeapObject::FromAddress(object_address); | 658 return HeapObject::FromAddress(object_address); |
| 653 } | 659 } |
| 654 | 660 |
| 655 | 661 |
| 656 void Deserializer::Deserialize() { | 662 void Deserializer::Deserialize() { |
| 663 isolate_ = Isolate::Current(); |
| 657 // Don't GC while deserializing - just expand the heap. | 664 // Don't GC while deserializing - just expand the heap. |
| 658 AlwaysAllocateScope always_allocate; | 665 AlwaysAllocateScope always_allocate; |
| 659 // Don't use the free lists while deserializing. | 666 // Don't use the free lists while deserializing. |
| 660 LinearAllocationScope allocate_linearly; | 667 LinearAllocationScope allocate_linearly; |
| 661 // No active threads. | 668 // No active threads. |
| 662 ASSERT_EQ(NULL, ThreadState::FirstInUse()); | 669 ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse()); |
| 663 // No active handles. | 670 // No active handles. |
| 664 ASSERT(HandleScopeImplementer::instance()->blocks()->is_empty()); | 671 ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty()); |
| 665 // Make sure the entire partial snapshot cache is traversed, filling it with | 672 // Make sure the entire partial snapshot cache is traversed, filling it with |
| 666 // valid object pointers. | 673 // valid object pointers. |
| 667 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; | 674 isolate_->set_serialize_partial_snapshot_cache_length( |
| 675 Isolate::kPartialSnapshotCacheCapacity); |
| 668 ASSERT_EQ(NULL, external_reference_decoder_); | 676 ASSERT_EQ(NULL, external_reference_decoder_); |
| 669 external_reference_decoder_ = new ExternalReferenceDecoder(); | 677 external_reference_decoder_ = new ExternalReferenceDecoder(); |
| 670 Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG); | 678 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG); |
| 671 Heap::IterateWeakRoots(this, VISIT_ALL); | 679 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL); |
| 672 | 680 |
| 673 Heap::set_global_contexts_list(Heap::undefined_value()); | 681 isolate_->heap()->set_global_contexts_list( |
| 682 isolate_->heap()->undefined_value()); |
| 674 } | 683 } |
| 675 | 684 |
| 676 | 685 |
| 677 void Deserializer::DeserializePartial(Object** root) { | 686 void Deserializer::DeserializePartial(Object** root) { |
| 687 isolate_ = Isolate::Current(); |
| 678 // Don't GC while deserializing - just expand the heap. | 688 // Don't GC while deserializing - just expand the heap. |
| 679 AlwaysAllocateScope always_allocate; | 689 AlwaysAllocateScope always_allocate; |
| 680 // Don't use the free lists while deserializing. | 690 // Don't use the free lists while deserializing. |
| 681 LinearAllocationScope allocate_linearly; | 691 LinearAllocationScope allocate_linearly; |
| 682 if (external_reference_decoder_ == NULL) { | 692 if (external_reference_decoder_ == NULL) { |
| 683 external_reference_decoder_ = new ExternalReferenceDecoder(); | 693 external_reference_decoder_ = new ExternalReferenceDecoder(); |
| 684 } | 694 } |
| 685 VisitPointer(root); | 695 VisitPointer(root); |
| 686 } | 696 } |
| 687 | 697 |
| 688 | 698 |
| 689 Deserializer::~Deserializer() { | 699 Deserializer::~Deserializer() { |
| 690 ASSERT(source_->AtEOF()); | 700 ASSERT(source_->AtEOF()); |
| 691 if (external_reference_decoder_ != NULL) { | 701 if (external_reference_decoder_) { |
| 692 delete external_reference_decoder_; | 702 delete external_reference_decoder_; |
| 693 external_reference_decoder_ = NULL; | 703 external_reference_decoder_ = NULL; |
| 694 } | 704 } |
| 695 } | 705 } |
| 696 | 706 |
| 697 | 707 |
| 698 // This is called on the roots. It is the driver of the deserialization | 708 // This is called on the roots. It is the driver of the deserialization |
| 699 // process. It is also called on the body of each function. | 709 // process. It is also called on the body of each function. |
| 700 void Deserializer::VisitPointers(Object** start, Object** end) { | 710 void Deserializer::VisitPointers(Object** start, Object** end) { |
| 701 // The space must be new space. Any other space would cause ReadChunk to try | 711 // The space must be new space. Any other space would cause ReadChunk to try |
| (...skipping 10 matching lines...) Expand all Loading... |
| 712 // making it into a byte array). | 722 // making it into a byte array). |
| 713 void Deserializer::ReadObject(int space_number, | 723 void Deserializer::ReadObject(int space_number, |
| 714 Space* space, | 724 Space* space, |
| 715 Object** write_back) { | 725 Object** write_back) { |
| 716 int size = source_->GetInt() << kObjectAlignmentBits; | 726 int size = source_->GetInt() << kObjectAlignmentBits; |
| 717 Address address = Allocate(space_number, space, size); | 727 Address address = Allocate(space_number, space, size); |
| 718 *write_back = HeapObject::FromAddress(address); | 728 *write_back = HeapObject::FromAddress(address); |
| 719 Object** current = reinterpret_cast<Object**>(address); | 729 Object** current = reinterpret_cast<Object**>(address); |
| 720 Object** limit = current + (size >> kPointerSizeLog2); | 730 Object** limit = current + (size >> kPointerSizeLog2); |
| 721 if (FLAG_log_snapshot_positions) { | 731 if (FLAG_log_snapshot_positions) { |
| 722 LOG(SnapshotPositionEvent(address, source_->position())); | 732 LOG(isolate_, SnapshotPositionEvent(address, source_->position())); |
| 723 } | 733 } |
| 724 ReadChunk(current, limit, space_number, address); | 734 ReadChunk(current, limit, space_number, address); |
| 725 #ifdef DEBUG | 735 #ifdef DEBUG |
| 726 bool is_codespace = (space == Heap::code_space()) || | 736 bool is_codespace = (space == HEAP->code_space()) || |
| 727 ((space == Heap::lo_space()) && (space_number == kLargeCode)); | 737 ((space == HEAP->lo_space()) && (space_number == kLargeCode)); |
| 728 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace); | 738 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace); |
| 729 #endif | 739 #endif |
| 730 } | 740 } |
| 731 | 741 |
| 732 | 742 |
| 733 // This macro is always used with a constant argument so it should all fold | 743 // This macro is always used with a constant argument so it should all fold |
| 734 // away to almost nothing in the generated code. It might be nicer to do this | 744 // away to almost nothing in the generated code. It might be nicer to do this |
| 735 // with the ternary operator but there are type issues with that. | 745 // with the ternary operator but there are type issues with that. |
| 736 #define ASSIGN_DEST_SPACE(space_number) \ | 746 #define ASSIGN_DEST_SPACE(space_number) \ |
| 737 Space* dest_space; \ | 747 Space* dest_space; \ |
| 738 if (space_number == NEW_SPACE) { \ | 748 if (space_number == NEW_SPACE) { \ |
| 739 dest_space = Heap::new_space(); \ | 749 dest_space = isolate->heap()->new_space(); \ |
| 740 } else if (space_number == OLD_POINTER_SPACE) { \ | 750 } else if (space_number == OLD_POINTER_SPACE) { \ |
| 741 dest_space = Heap::old_pointer_space(); \ | 751 dest_space = isolate->heap()->old_pointer_space(); \ |
| 742 } else if (space_number == OLD_DATA_SPACE) { \ | 752 } else if (space_number == OLD_DATA_SPACE) { \ |
| 743 dest_space = Heap::old_data_space(); \ | 753 dest_space = isolate->heap()->old_data_space(); \ |
| 744 } else if (space_number == CODE_SPACE) { \ | 754 } else if (space_number == CODE_SPACE) { \ |
| 745 dest_space = Heap::code_space(); \ | 755 dest_space = isolate->heap()->code_space(); \ |
| 746 } else if (space_number == MAP_SPACE) { \ | 756 } else if (space_number == MAP_SPACE) { \ |
| 747 dest_space = Heap::map_space(); \ | 757 dest_space = isolate->heap()->map_space(); \ |
| 748 } else if (space_number == CELL_SPACE) { \ | 758 } else if (space_number == CELL_SPACE) { \ |
| 749 dest_space = Heap::cell_space(); \ | 759 dest_space = isolate->heap()->cell_space(); \ |
| 750 } else { \ | 760 } else { \ |
| 751 ASSERT(space_number >= LO_SPACE); \ | 761 ASSERT(space_number >= LO_SPACE); \ |
| 752 dest_space = Heap::lo_space(); \ | 762 dest_space = isolate->heap()->lo_space(); \ |
| 753 } | 763 } |
| 754 | 764 |
| 755 | 765 |
| 756 static const int kUnknownOffsetFromStart = -1; | 766 static const int kUnknownOffsetFromStart = -1; |
| 757 | 767 |
| 758 | 768 |
| 759 void Deserializer::ReadChunk(Object** current, | 769 void Deserializer::ReadChunk(Object** current, |
| 760 Object** limit, | 770 Object** limit, |
| 761 int source_space, | 771 int source_space, |
| 762 Address address) { | 772 Address address) { |
| 773 Isolate* const isolate = isolate_; |
| 763 while (current < limit) { | 774 while (current < limit) { |
| 764 int data = source_->Get(); | 775 int data = source_->Get(); |
| 765 switch (data) { | 776 switch (data) { |
| 766 #define CASE_STATEMENT(where, how, within, space_number) \ | 777 #define CASE_STATEMENT(where, how, within, space_number) \ |
| 767 case where + how + within + space_number: \ | 778 case where + how + within + space_number: \ |
| 768 ASSERT((where & ~kPointedToMask) == 0); \ | 779 ASSERT((where & ~kPointedToMask) == 0); \ |
| 769 ASSERT((how & ~kHowToCodeMask) == 0); \ | 780 ASSERT((how & ~kHowToCodeMask) == 0); \ |
| 770 ASSERT((within & ~kWhereToPointMask) == 0); \ | 781 ASSERT((within & ~kWhereToPointMask) == 0); \ |
| 771 ASSERT((space_number & ~kSpaceMask) == 0); | 782 ASSERT((space_number & ~kSpaceMask) == 0); |
| 772 | 783 |
| 773 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \ | 784 #define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \ |
| 774 { \ | 785 { \ |
| 775 bool emit_write_barrier = false; \ | 786 bool emit_write_barrier = false; \ |
| 776 bool current_was_incremented = false; \ | 787 bool current_was_incremented = false; \ |
| 777 int space_number = space_number_if_any == kAnyOldSpace ? \ | 788 int space_number = space_number_if_any == kAnyOldSpace ? \ |
| 778 (data & kSpaceMask) : space_number_if_any; \ | 789 (data & kSpaceMask) : space_number_if_any; \ |
| 779 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ | 790 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ |
| 780 ASSIGN_DEST_SPACE(space_number) \ | 791 ASSIGN_DEST_SPACE(space_number) \ |
| 781 ReadObject(space_number, dest_space, current); \ | 792 ReadObject(space_number, dest_space, current); \ |
| 782 emit_write_barrier = \ | 793 emit_write_barrier = \ |
| 783 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ | 794 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| 784 } else { \ | 795 } else { \ |
| 785 Object* new_object = NULL; /* May not be a real Object pointer. */ \ | 796 Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
| 786 if (where == kNewObject) { \ | 797 if (where == kNewObject) { \ |
| 787 ASSIGN_DEST_SPACE(space_number) \ | 798 ASSIGN_DEST_SPACE(space_number) \ |
| 788 ReadObject(space_number, dest_space, &new_object); \ | 799 ReadObject(space_number, dest_space, &new_object); \ |
| 789 } else if (where == kRootArray) { \ | 800 } else if (where == kRootArray) { \ |
| 790 int root_id = source_->GetInt(); \ | 801 int root_id = source_->GetInt(); \ |
| 791 new_object = Heap::roots_address()[root_id]; \ | 802 new_object = isolate->heap()->roots_address()[root_id]; \ |
| 792 } else if (where == kPartialSnapshotCache) { \ | 803 } else if (where == kPartialSnapshotCache) { \ |
| 793 int cache_index = source_->GetInt(); \ | 804 int cache_index = source_->GetInt(); \ |
| 794 new_object = partial_snapshot_cache_[cache_index]; \ | 805 new_object = isolate->serialize_partial_snapshot_cache() \ |
| 806 [cache_index]; \ |
| 795 } else if (where == kExternalReference) { \ | 807 } else if (where == kExternalReference) { \ |
| 796 int reference_id = source_->GetInt(); \ | 808 int reference_id = source_->GetInt(); \ |
| 797 Address address = \ | 809 Address address = external_reference_decoder_-> \ |
| 798 external_reference_decoder_->Decode(reference_id); \ | 810 Decode(reference_id); \ |
| 799 new_object = reinterpret_cast<Object*>(address); \ | 811 new_object = reinterpret_cast<Object*>(address); \ |
| 800 } else if (where == kBackref) { \ | 812 } else if (where == kBackref) { \ |
| 801 emit_write_barrier = \ | 813 emit_write_barrier = \ |
| 802 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ | 814 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| 803 new_object = GetAddressFromEnd(data & kSpaceMask); \ | 815 new_object = GetAddressFromEnd(data & kSpaceMask); \ |
| 804 } else { \ | 816 } else { \ |
| 805 ASSERT(where == kFromStart); \ | 817 ASSERT(where == kFromStart); \ |
| 806 if (offset_from_start == kUnknownOffsetFromStart) { \ | 818 if (offset_from_start == kUnknownOffsetFromStart) { \ |
| 807 emit_write_barrier = \ | 819 emit_write_barrier = \ |
| 808 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ | 820 (space_number == NEW_SPACE && source_space != NEW_SPACE); \ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 826 if (within == kFirstInstruction) { \ | 838 if (within == kFirstInstruction) { \ |
| 827 location_of_branch_data += Assembler::kCallTargetSize; \ | 839 location_of_branch_data += Assembler::kCallTargetSize; \ |
| 828 current = reinterpret_cast<Object**>(location_of_branch_data); \ | 840 current = reinterpret_cast<Object**>(location_of_branch_data); \ |
| 829 current_was_incremented = true; \ | 841 current_was_incremented = true; \ |
| 830 } \ | 842 } \ |
| 831 } else { \ | 843 } else { \ |
| 832 *current = new_object; \ | 844 *current = new_object; \ |
| 833 } \ | 845 } \ |
| 834 } \ | 846 } \ |
| 835 if (emit_write_barrier) { \ | 847 if (emit_write_barrier) { \ |
| 836 Heap::RecordWrite(address, static_cast<int>( \ | 848 isolate->heap()->RecordWrite(address, static_cast<int>( \ |
| 837 reinterpret_cast<Address>(current) - address)); \ | 849 reinterpret_cast<Address>(current) - address)); \ |
| 838 } \ | 850 } \ |
| 839 if (!current_was_incremented) { \ | 851 if (!current_was_incremented) { \ |
| 840 current++; /* Increment current if it wasn't done above. */ \ | 852 current++; /* Increment current if it wasn't done above. */ \ |
| 841 } \ | 853 } \ |
| 842 break; \ | 854 break; \ |
| 843 } \ | 855 } \ |
| 844 | 856 |
| 845 // This generates a case and a body for each space. The large object spaces are | 857 // This generates a case and a body for each space. The large object spaces are |
| 846 // very rare in snapshots so they are grouped in one body. | 858 // very rare in snapshots so they are grouped in one body. |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 if (space == CODE_SPACE) { | 1002 if (space == CODE_SPACE) { |
| 991 CPU::FlushICache(last_object_address_, Page::kPageSize); | 1003 CPU::FlushICache(last_object_address_, Page::kPageSize); |
| 992 } | 1004 } |
| 993 break; | 1005 break; |
| 994 } | 1006 } |
| 995 | 1007 |
| 996 case kNativesStringResource: { | 1008 case kNativesStringResource: { |
| 997 int index = source_->Get(); | 1009 int index = source_->Get(); |
| 998 Vector<const char> source_vector = Natives::GetScriptSource(index); | 1010 Vector<const char> source_vector = Natives::GetScriptSource(index); |
| 999 NativesExternalStringResource* resource = | 1011 NativesExternalStringResource* resource = |
| 1000 new NativesExternalStringResource(source_vector.start()); | 1012 new NativesExternalStringResource( |
| 1013 isolate->bootstrapper(), source_vector.start()); |
| 1001 *current++ = reinterpret_cast<Object*>(resource); | 1014 *current++ = reinterpret_cast<Object*>(resource); |
| 1002 break; | 1015 break; |
| 1003 } | 1016 } |
| 1004 | 1017 |
| 1005 case kSynchronize: { | 1018 case kSynchronize: { |
| 1006 // If we get here then that indicates that you have a mismatch between | 1019 // If we get here then that indicates that you have a mismatch between |
| 1007 // the number of GC roots when serializing and deserializing. | 1020 // the number of GC roots when serializing and deserializing. |
| 1008 UNREACHABLE(); | 1021 UNREACHABLE(); |
| 1009 } | 1022 } |
| 1010 | 1023 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 } while (character != 0); | 1068 } while (character != 0); |
| 1056 } | 1069 } |
| 1057 | 1070 |
| 1058 #endif | 1071 #endif |
| 1059 | 1072 |
| 1060 Serializer::Serializer(SnapshotByteSink* sink) | 1073 Serializer::Serializer(SnapshotByteSink* sink) |
| 1061 : sink_(sink), | 1074 : sink_(sink), |
| 1062 current_root_index_(0), | 1075 current_root_index_(0), |
| 1063 external_reference_encoder_(new ExternalReferenceEncoder), | 1076 external_reference_encoder_(new ExternalReferenceEncoder), |
| 1064 large_object_total_(0) { | 1077 large_object_total_(0) { |
| 1078 // The serializer is meant to be used only to generate initial heap images |
| 1079 // from a context in which there is only one isolate. |
| 1080 ASSERT(Isolate::Current()->IsDefaultIsolate()); |
| 1065 for (int i = 0; i <= LAST_SPACE; i++) { | 1081 for (int i = 0; i <= LAST_SPACE; i++) { |
| 1066 fullness_[i] = 0; | 1082 fullness_[i] = 0; |
| 1067 } | 1083 } |
| 1068 } | 1084 } |
| 1069 | 1085 |
| 1070 | 1086 |
| 1071 Serializer::~Serializer() { | 1087 Serializer::~Serializer() { |
| 1072 delete external_reference_encoder_; | 1088 delete external_reference_encoder_; |
| 1073 } | 1089 } |
| 1074 | 1090 |
| 1075 | 1091 |
| 1076 void StartupSerializer::SerializeStrongReferences() { | 1092 void StartupSerializer::SerializeStrongReferences() { |
| 1093 Isolate* isolate = Isolate::Current(); |
| 1077 // No active threads. | 1094 // No active threads. |
| 1078 CHECK_EQ(NULL, ThreadState::FirstInUse()); | 1095 CHECK_EQ(NULL, Isolate::Current()->thread_manager()->FirstThreadStateInUse()); |
| 1079 // No active or weak handles. | 1096 // No active or weak handles. |
| 1080 CHECK(HandleScopeImplementer::instance()->blocks()->is_empty()); | 1097 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty()); |
| 1081 CHECK_EQ(0, GlobalHandles::NumberOfWeakHandles()); | 1098 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles()); |
| 1082 // We don't support serializing installed extensions. | 1099 // We don't support serializing installed extensions. |
| 1083 for (RegisteredExtension* ext = RegisteredExtension::first_extension(); | 1100 for (RegisteredExtension* ext = v8::RegisteredExtension::first_extension(); |
| 1084 ext != NULL; | 1101 ext != NULL; |
| 1085 ext = ext->next()) { | 1102 ext = ext->next()) { |
| 1086 CHECK_NE(v8::INSTALLED, ext->state()); | 1103 CHECK_NE(v8::INSTALLED, ext->state()); |
| 1087 } | 1104 } |
| 1088 Heap::IterateStrongRoots(this, VISIT_ONLY_STRONG); | 1105 HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG); |
| 1089 } | 1106 } |
| 1090 | 1107 |
| 1091 | 1108 |
| 1092 void PartialSerializer::Serialize(Object** object) { | 1109 void PartialSerializer::Serialize(Object** object) { |
| 1093 this->VisitPointer(object); | 1110 this->VisitPointer(object); |
| 1111 Isolate* isolate = Isolate::Current(); |
| 1094 | 1112 |
| 1095 // After we have done the partial serialization the partial snapshot cache | 1113 // After we have done the partial serialization the partial snapshot cache |
| 1096 // will contain some references needed to decode the partial snapshot. We | 1114 // will contain some references needed to decode the partial snapshot. We |
| 1097 // fill it up with undefineds so it has a predictable length so the | 1115 // fill it up with undefineds so it has a predictable length so the |
| 1098 // deserialization code doesn't need to know the length. | 1116 // deserialization code doesn't need to know the length. |
| 1099 for (int index = partial_snapshot_cache_length_; | 1117 for (int index = isolate->serialize_partial_snapshot_cache_length(); |
| 1100 index < kPartialSnapshotCacheCapacity; | 1118 index < Isolate::kPartialSnapshotCacheCapacity; |
| 1101 index++) { | 1119 index++) { |
| 1102 partial_snapshot_cache_[index] = Heap::undefined_value(); | 1120 isolate->serialize_partial_snapshot_cache()[index] = |
| 1103 startup_serializer_->VisitPointer(&partial_snapshot_cache_[index]); | 1121 isolate->heap()->undefined_value(); |
| 1122 startup_serializer_->VisitPointer( |
| 1123 &isolate->serialize_partial_snapshot_cache()[index]); |
| 1104 } | 1124 } |
| 1105 partial_snapshot_cache_length_ = kPartialSnapshotCacheCapacity; | 1125 isolate->set_serialize_partial_snapshot_cache_length( |
| 1126 Isolate::kPartialSnapshotCacheCapacity); |
| 1106 } | 1127 } |
| 1107 | 1128 |
| 1108 | 1129 |
| 1109 void Serializer::VisitPointers(Object** start, Object** end) { | 1130 void Serializer::VisitPointers(Object** start, Object** end) { |
| 1110 for (Object** current = start; current < end; current++) { | 1131 for (Object** current = start; current < end; current++) { |
| 1111 if ((*current)->IsSmi()) { | 1132 if ((*current)->IsSmi()) { |
| 1112 sink_->Put(kRawData, "RawData"); | 1133 sink_->Put(kRawData, "RawData"); |
| 1113 sink_->PutInt(kPointerSize, "length"); | 1134 sink_->PutInt(kPointerSize, "length"); |
| 1114 for (int i = 0; i < kPointerSize; i++) { | 1135 for (int i = 0; i < kPointerSize; i++) { |
| 1115 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); | 1136 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte"); |
| 1116 } | 1137 } |
| 1117 } else { | 1138 } else { |
| 1118 SerializeObject(*current, kPlain, kStartOfObject); | 1139 SerializeObject(*current, kPlain, kStartOfObject); |
| 1119 } | 1140 } |
| 1120 } | 1141 } |
| 1121 } | 1142 } |
| 1122 | 1143 |
| 1123 | 1144 |
| 1124 Object* SerializerDeserializer::partial_snapshot_cache_[ | |
| 1125 kPartialSnapshotCacheCapacity]; | |
| 1126 int SerializerDeserializer::partial_snapshot_cache_length_ = 0; | |
| 1127 | |
| 1128 | |
| 1129 // This ensures that the partial snapshot cache keeps things alive during GC and | 1145 // This ensures that the partial snapshot cache keeps things alive during GC and |
| 1130 // tracks their movement. When it is called during serialization of the startup | 1146 // tracks their movement. When it is called during serialization of the startup |
| 1131 // snapshot the partial snapshot is empty, so nothing happens. When the partial | 1147 // snapshot the partial snapshot is empty, so nothing happens. When the partial |
| 1132 // (context) snapshot is created, this array is populated with the pointers that | 1148 // (context) snapshot is created, this array is populated with the pointers that |
| 1133 // the partial snapshot will need. As that happens we emit serialized objects to | 1149 // the partial snapshot will need. As that happens we emit serialized objects to |
| 1134 // the startup snapshot that correspond to the elements of this cache array. On | 1150 // the startup snapshot that correspond to the elements of this cache array. On |
| 1135 // deserialization we therefore need to visit the cache array. This fills it up | 1151 // deserialization we therefore need to visit the cache array. This fills it up |
| 1136 // with pointers to deserialized objects. | 1152 // with pointers to deserialized objects. |
| 1137 void SerializerDeserializer::Iterate(ObjectVisitor* visitor) { | 1153 void SerializerDeserializer::Iterate(ObjectVisitor* visitor) { |
| 1154 Isolate* isolate = Isolate::Current(); |
| 1138 visitor->VisitPointers( | 1155 visitor->VisitPointers( |
| 1139 &partial_snapshot_cache_[0], | 1156 isolate->serialize_partial_snapshot_cache(), |
| 1140 &partial_snapshot_cache_[partial_snapshot_cache_length_]); | 1157 &isolate->serialize_partial_snapshot_cache()[ |
| 1158 isolate->serialize_partial_snapshot_cache_length()]); |
| 1141 } | 1159 } |
| 1142 | 1160 |
| 1143 | 1161 |
| 1144 // When deserializing we need to set the size of the snapshot cache. This means | 1162 // When deserializing we need to set the size of the snapshot cache. This means |
| 1145 // the root iteration code (above) will iterate over array elements, writing the | 1163 // the root iteration code (above) will iterate over array elements, writing the |
| 1146 // references to deserialized objects in them. | 1164 // references to deserialized objects in them. |
| 1147 void SerializerDeserializer::SetSnapshotCacheSize(int size) { | 1165 void SerializerDeserializer::SetSnapshotCacheSize(int size) { |
| 1148 partial_snapshot_cache_length_ = size; | 1166 Isolate::Current()->set_serialize_partial_snapshot_cache_length(size); |
| 1149 } | 1167 } |
| 1150 | 1168 |
| 1151 | 1169 |
| 1152 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { | 1170 int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) { |
| 1153 for (int i = 0; i < partial_snapshot_cache_length_; i++) { | 1171 Isolate* isolate = Isolate::Current(); |
| 1154 Object* entry = partial_snapshot_cache_[i]; | 1172 |
| 1173 for (int i = 0; |
| 1174 i < isolate->serialize_partial_snapshot_cache_length(); |
| 1175 i++) { |
| 1176 Object* entry = isolate->serialize_partial_snapshot_cache()[i]; |
| 1155 if (entry == heap_object) return i; | 1177 if (entry == heap_object) return i; |
| 1156 } | 1178 } |
| 1157 | 1179 |
| 1158 // We didn't find the object in the cache. So we add it to the cache and | 1180 // We didn't find the object in the cache. So we add it to the cache and |
| 1159 // then visit the pointer so that it becomes part of the startup snapshot | 1181 // then visit the pointer so that it becomes part of the startup snapshot |
| 1160 // and we can refer to it from the partial snapshot. | 1182 // and we can refer to it from the partial snapshot. |
| 1161 int length = partial_snapshot_cache_length_; | 1183 int length = isolate->serialize_partial_snapshot_cache_length(); |
| 1162 CHECK(length < kPartialSnapshotCacheCapacity); | 1184 CHECK(length < Isolate::kPartialSnapshotCacheCapacity); |
| 1163 partial_snapshot_cache_[length] = heap_object; | 1185 isolate->serialize_partial_snapshot_cache()[length] = heap_object; |
| 1164 startup_serializer_->VisitPointer(&partial_snapshot_cache_[length]); | 1186 startup_serializer_->VisitPointer( |
| 1187 &isolate->serialize_partial_snapshot_cache()[length]); |
| 1165 // We don't recurse from the startup snapshot generator into the partial | 1188 // We don't recurse from the startup snapshot generator into the partial |
| 1166 // snapshot generator. | 1189 // snapshot generator. |
| 1167 ASSERT(length == partial_snapshot_cache_length_); | 1190 ASSERT(length == isolate->serialize_partial_snapshot_cache_length()); |
| 1168 return partial_snapshot_cache_length_++; | 1191 isolate->set_serialize_partial_snapshot_cache_length(length + 1); |
| 1192 return length; |
| 1169 } | 1193 } |
| 1170 | 1194 |
| 1171 | 1195 |
| 1172 int PartialSerializer::RootIndex(HeapObject* heap_object) { | 1196 int PartialSerializer::RootIndex(HeapObject* heap_object) { |
| 1173 for (int i = 0; i < Heap::kRootListLength; i++) { | 1197 for (int i = 0; i < Heap::kRootListLength; i++) { |
| 1174 Object* root = Heap::roots_address()[i]; | 1198 Object* root = HEAP->roots_address()[i]; |
| 1175 if (root == heap_object) return i; | 1199 if (root == heap_object) return i; |
| 1176 } | 1200 } |
| 1177 return kInvalidRootIndex; | 1201 return kInvalidRootIndex; |
| 1178 } | 1202 } |
| 1179 | 1203 |
| 1180 | 1204 |
| 1181 // Encode the location of an already deserialized object in order to write its | 1205 // Encode the location of an already deserialized object in order to write its |
| 1182 // location into a later object. We can encode the location as an offset from | 1206 // location into a later object. We can encode the location as an offset from |
| 1183 // the start of the deserialized objects or as an offset backwards from the | 1207 // the start of the deserialized objects or as an offset backwards from the |
| 1184 // current allocation pointer. | 1208 // current allocation pointer. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1247 heap_object, | 1271 heap_object, |
| 1248 sink_, | 1272 sink_, |
| 1249 how_to_code, | 1273 how_to_code, |
| 1250 where_to_point); | 1274 where_to_point); |
| 1251 object_serializer.Serialize(); | 1275 object_serializer.Serialize(); |
| 1252 } | 1276 } |
| 1253 } | 1277 } |
| 1254 | 1278 |
| 1255 | 1279 |
| 1256 void StartupSerializer::SerializeWeakReferences() { | 1280 void StartupSerializer::SerializeWeakReferences() { |
| 1257 for (int i = partial_snapshot_cache_length_; | 1281 for (int i = Isolate::Current()->serialize_partial_snapshot_cache_length(); |
| 1258 i < kPartialSnapshotCacheCapacity; | 1282 i < Isolate::kPartialSnapshotCacheCapacity; |
| 1259 i++) { | 1283 i++) { |
| 1260 sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization"); | 1284 sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization"); |
| 1261 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); | 1285 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index"); |
| 1262 } | 1286 } |
| 1263 Heap::IterateWeakRoots(this, VISIT_ALL); | 1287 HEAP->IterateWeakRoots(this, VISIT_ALL); |
| 1264 } | 1288 } |
| 1265 | 1289 |
| 1266 | 1290 |
| 1267 void PartialSerializer::SerializeObject( | 1291 void PartialSerializer::SerializeObject( |
| 1268 Object* o, | 1292 Object* o, |
| 1269 HowToCode how_to_code, | 1293 HowToCode how_to_code, |
| 1270 WhereToPoint where_to_point) { | 1294 WhereToPoint where_to_point) { |
| 1271 CHECK(o->IsHeapObject()); | 1295 CHECK(o->IsHeapObject()); |
| 1272 HeapObject* heap_object = HeapObject::cast(o); | 1296 HeapObject* heap_object = HeapObject::cast(o); |
| 1273 | 1297 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1314 | 1338 |
| 1315 | 1339 |
| 1316 void Serializer::ObjectSerializer::Serialize() { | 1340 void Serializer::ObjectSerializer::Serialize() { |
| 1317 int space = Serializer::SpaceOfObject(object_); | 1341 int space = Serializer::SpaceOfObject(object_); |
| 1318 int size = object_->Size(); | 1342 int size = object_->Size(); |
| 1319 | 1343 |
| 1320 sink_->Put(kNewObject + reference_representation_ + space, | 1344 sink_->Put(kNewObject + reference_representation_ + space, |
| 1321 "ObjectSerialization"); | 1345 "ObjectSerialization"); |
| 1322 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); | 1346 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words"); |
| 1323 | 1347 |
| 1324 LOG(SnapshotPositionEvent(object_->address(), sink_->Position())); | 1348 LOG(i::Isolate::Current(), |
| 1349 SnapshotPositionEvent(object_->address(), sink_->Position())); |
| 1325 | 1350 |
| 1326 // Mark this object as already serialized. | 1351 // Mark this object as already serialized. |
| 1327 bool start_new_page; | 1352 bool start_new_page; |
| 1328 int offset = serializer_->Allocate(space, size, &start_new_page); | 1353 int offset = serializer_->Allocate(space, size, &start_new_page); |
| 1329 serializer_->address_mapper()->AddMapping(object_, offset); | 1354 serializer_->address_mapper()->AddMapping(object_, offset); |
| 1330 if (start_new_page) { | 1355 if (start_new_page) { |
| 1331 sink_->Put(kNewPage, "NewPage"); | 1356 sink_->Put(kNewPage, "NewPage"); |
| 1332 sink_->PutSection(space, "NewPageSpace"); | 1357 sink_->PutSection(space, "NewPageSpace"); |
| 1333 } | 1358 } |
| 1334 | 1359 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 // objects in the snapshot. | 1440 // objects in the snapshot. |
| 1416 UNREACHABLE(); | 1441 UNREACHABLE(); |
| 1417 } | 1442 } |
| 1418 | 1443 |
| 1419 | 1444 |
| 1420 void Serializer::ObjectSerializer::VisitExternalAsciiString( | 1445 void Serializer::ObjectSerializer::VisitExternalAsciiString( |
| 1421 v8::String::ExternalAsciiStringResource** resource_pointer) { | 1446 v8::String::ExternalAsciiStringResource** resource_pointer) { |
| 1422 Address references_start = reinterpret_cast<Address>(resource_pointer); | 1447 Address references_start = reinterpret_cast<Address>(resource_pointer); |
| 1423 OutputRawData(references_start); | 1448 OutputRawData(references_start); |
| 1424 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { | 1449 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) { |
| 1425 Object* source = Heap::natives_source_cache()->get(i); | 1450 Object* source = HEAP->natives_source_cache()->get(i); |
| 1426 if (!source->IsUndefined()) { | 1451 if (!source->IsUndefined()) { |
| 1427 ExternalAsciiString* string = ExternalAsciiString::cast(source); | 1452 ExternalAsciiString* string = ExternalAsciiString::cast(source); |
| 1428 typedef v8::String::ExternalAsciiStringResource Resource; | 1453 typedef v8::String::ExternalAsciiStringResource Resource; |
| 1429 Resource* resource = string->resource(); | 1454 Resource* resource = string->resource(); |
| 1430 if (resource == *resource_pointer) { | 1455 if (resource == *resource_pointer) { |
| 1431 sink_->Put(kNativesStringResource, "NativesStringResource"); | 1456 sink_->Put(kNativesStringResource, "NativesStringResource"); |
| 1432 sink_->PutSection(i, "NativesStringResourceEnd"); | 1457 sink_->PutSection(i, "NativesStringResourceEnd"); |
| 1433 bytes_processed_so_far_ += sizeof(resource); | 1458 bytes_processed_so_far_ += sizeof(resource); |
| 1434 return; | 1459 return; |
| 1435 } | 1460 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1465 sink_->PutSection(data, "Byte"); | 1490 sink_->PutSection(data, "Byte"); |
| 1466 } | 1491 } |
| 1467 bytes_processed_so_far_ += skipped; | 1492 bytes_processed_so_far_ += skipped; |
| 1468 } | 1493 } |
| 1469 } | 1494 } |
| 1470 | 1495 |
| 1471 | 1496 |
| 1472 int Serializer::SpaceOfObject(HeapObject* object) { | 1497 int Serializer::SpaceOfObject(HeapObject* object) { |
| 1473 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { | 1498 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { |
| 1474 AllocationSpace s = static_cast<AllocationSpace>(i); | 1499 AllocationSpace s = static_cast<AllocationSpace>(i); |
| 1475 if (Heap::InSpace(object, s)) { | 1500 if (HEAP->InSpace(object, s)) { |
| 1476 if (i == LO_SPACE) { | 1501 if (i == LO_SPACE) { |
| 1477 if (object->IsCode()) { | 1502 if (object->IsCode()) { |
| 1478 return kLargeCode; | 1503 return kLargeCode; |
| 1479 } else if (object->IsFixedArray()) { | 1504 } else if (object->IsFixedArray()) { |
| 1480 return kLargeFixedArray; | 1505 return kLargeFixedArray; |
| 1481 } else { | 1506 } else { |
| 1482 return kLargeData; | 1507 return kLargeData; |
| 1483 } | 1508 } |
| 1484 } | 1509 } |
| 1485 return i; | 1510 return i; |
| 1486 } | 1511 } |
| 1487 } | 1512 } |
| 1488 UNREACHABLE(); | 1513 UNREACHABLE(); |
| 1489 return 0; | 1514 return 0; |
| 1490 } | 1515 } |
| 1491 | 1516 |
| 1492 | 1517 |
| 1493 int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) { | 1518 int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) { |
| 1494 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { | 1519 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) { |
| 1495 AllocationSpace s = static_cast<AllocationSpace>(i); | 1520 AllocationSpace s = static_cast<AllocationSpace>(i); |
| 1496 if (Heap::InSpace(object, s)) { | 1521 if (HEAP->InSpace(object, s)) { |
| 1497 return i; | 1522 return i; |
| 1498 } | 1523 } |
| 1499 } | 1524 } |
| 1500 UNREACHABLE(); | 1525 UNREACHABLE(); |
| 1501 return 0; | 1526 return 0; |
| 1502 } | 1527 } |
| 1503 | 1528 |
| 1504 | 1529 |
| 1505 int Serializer::Allocate(int space, int size, bool* new_page) { | 1530 int Serializer::Allocate(int space, int size, bool* new_page) { |
| 1506 CHECK(space >= 0 && space < kNumberOfSpaces); | 1531 CHECK(space >= 0 && space < kNumberOfSpaces); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1530 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); | 1555 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize); |
| 1531 } | 1556 } |
| 1532 } | 1557 } |
| 1533 int allocation_address = fullness_[space]; | 1558 int allocation_address = fullness_[space]; |
| 1534 fullness_[space] = allocation_address + size; | 1559 fullness_[space] = allocation_address + size; |
| 1535 return allocation_address; | 1560 return allocation_address; |
| 1536 } | 1561 } |
| 1537 | 1562 |
| 1538 | 1563 |
| 1539 } } // namespace v8::internal | 1564 } } // namespace v8::internal |
| OLD | NEW |