blob: 8cde580fbbf1108f31ad2203465121018e19d835 [file] [log] [blame]
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "accessors.h"
31#include "api.h"
fschneider@chromium.orgfb144a02011-05-04 12:43:48 +000032#include "bootstrapper.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033#include "execution.h"
34#include "global-handles.h"
35#include "ic-inl.h"
36#include "natives.h"
37#include "platform.h"
38#include "runtime.h"
39#include "serialize.h"
40#include "stub-cache.h"
41#include "v8threads.h"
42
kasperl@chromium.org71affb52009-05-26 05:44:31 +000043namespace v8 {
44namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000046
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047// -----------------------------------------------------------------------------
48// Coding of external references.
49
50// The encoding of an external reference. The type is in the high word.
51// The id is in the low word.
52static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
53 return static_cast<uint32_t>(type) << 16 | id;
54}
55
56
57static int* GetInternalPointer(StatsCounter* counter) {
58 // All counters refer to dummy_counter, if deserializing happens without
59 // setting up counters.
60 static int dummy_counter = 0;
61 return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
62}
63
64
65// ExternalReferenceTable is a helper class that defines the relationship
66// between external references and their encodings. It is used to build
67// hashmaps in ExternalReferenceEncoder and ExternalReferenceDecoder.
68class ExternalReferenceTable {
69 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000070 static ExternalReferenceTable* instance(Isolate* isolate) {
71 ExternalReferenceTable* external_reference_table =
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;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000078 }
79
80 int size() const { return refs_.length(); }
81
82 Address address(int i) { return refs_[i].address; }
83
84 uint32_t code(int i) { return refs_[i].code; }
85
86 const char* name(int i) { return refs_[i].name; }
87
88 int max_id(int code) { return max_id_[code]; }
89
90 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000091 explicit ExternalReferenceTable(Isolate* isolate) : refs_(64) {
92 PopulateTable(isolate);
93 }
iposva@chromium.org245aa852009-02-10 00:49:54 +000094 ~ExternalReferenceTable() { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095
96 struct ExternalReferenceEntry {
97 Address address;
98 uint32_t code;
99 const char* name;
100 };
101
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000102 void PopulateTable(Isolate* isolate);
iposva@chromium.org245aa852009-02-10 00:49:54 +0000103
104 // For a few types of references, we can get their address from their id.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000105 void AddFromId(TypeCode type,
106 uint16_t id,
107 const char* name,
108 Isolate* isolate);
iposva@chromium.org245aa852009-02-10 00:49:54 +0000109
110 // For other types of references, the caller will figure out the address.
111 void Add(Address address, TypeCode type, uint16_t id, const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112
113 List<ExternalReferenceEntry> refs_;
114 int max_id_[kTypeCodeCount];
115};
116
117
iposva@chromium.org245aa852009-02-10 00:49:54 +0000118void ExternalReferenceTable::AddFromId(TypeCode type,
119 uint16_t id,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000120 const char* name,
121 Isolate* isolate) {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000122 Address address;
123 switch (type) {
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000124 case C_BUILTIN: {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000125 ExternalReference ref(static_cast<Builtins::CFunctionId>(id), isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000126 address = ref.address();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000127 break;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000128 }
129 case BUILTIN: {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000130 ExternalReference ref(static_cast<Builtins::Name>(id), isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000131 address = ref.address();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000132 break;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000133 }
134 case RUNTIME_FUNCTION: {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000135 ExternalReference ref(static_cast<Runtime::FunctionId>(id), isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000136 address = ref.address();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000137 break;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000138 }
139 case IC_UTILITY: {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000140 ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)),
141 isolate);
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000142 address = ref.address();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000143 break;
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000144 }
iposva@chromium.org245aa852009-02-10 00:49:54 +0000145 default:
146 UNREACHABLE();
147 return;
148 }
149 Add(address, type, id, name);
150}
151
152
153void ExternalReferenceTable::Add(Address address,
154 TypeCode type,
155 uint16_t id,
156 const char* name) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000157 ASSERT_NE(NULL, address);
iposva@chromium.org245aa852009-02-10 00:49:54 +0000158 ExternalReferenceEntry entry;
159 entry.address = address;
160 entry.code = EncodeExternal(type, id);
161 entry.name = name;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000162 ASSERT_NE(0, entry.code);
iposva@chromium.org245aa852009-02-10 00:49:54 +0000163 refs_.Add(entry);
164 if (id > max_id_[type]) max_id_[type] = id;
165}
166
167
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000168void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
170 max_id_[type_code] = 0;
171 }
172
iposva@chromium.org245aa852009-02-10 00:49:54 +0000173 // The following populates all of the different type of external references
174 // into the ExternalReferenceTable.
175 //
176 // NOTE: This function was originally 100k of code. It has since been
177 // rewritten to be mostly table driven, as the callback macro style tends to
178 // very easily cause code bloat. Please be careful in the future when adding
179 // new references.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180
iposva@chromium.org245aa852009-02-10 00:49:54 +0000181 struct RefTableEntry {
182 TypeCode type;
183 uint16_t id;
184 const char* name;
185 };
186
187 static const RefTableEntry ref_table[] = {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 // Builtins
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000189#define DEF_ENTRY_C(name, ignored) \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000190 { C_BUILTIN, \
191 Builtins::c_##name, \
192 "Builtins::" #name },
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000193
194 BUILTIN_LIST_C(DEF_ENTRY_C)
195#undef DEF_ENTRY_C
196
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000197#define DEF_ENTRY_C(name, ignored) \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000198 { BUILTIN, \
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000199 Builtins::k##name, \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000200 "Builtins::" #name },
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000201#define DEF_ENTRY_A(name, kind, state, extra) DEF_ENTRY_C(name, ignored)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202
203 BUILTIN_LIST_C(DEF_ENTRY_C)
204 BUILTIN_LIST_A(DEF_ENTRY_A)
ager@chromium.org8bb60582008-12-11 12:02:20 +0000205 BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000206#undef DEF_ENTRY_C
207#undef DEF_ENTRY_A
208
209 // Runtime functions
ager@chromium.orga1645e22009-09-09 19:27:10 +0000210#define RUNTIME_ENTRY(name, nargs, ressize) \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000211 { RUNTIME_FUNCTION, \
212 Runtime::k##name, \
213 "Runtime::" #name },
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214
215 RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
216#undef RUNTIME_ENTRY
217
218 // IC utilities
219#define IC_ENTRY(name) \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000220 { IC_UTILITY, \
221 IC::k##name, \
222 "IC::" #name },
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000223
224 IC_UTIL_LIST(IC_ENTRY)
225#undef IC_ENTRY
iposva@chromium.org245aa852009-02-10 00:49:54 +0000226 }; // end of ref_table[].
227
228 for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000229 AddFromId(ref_table[i].type,
230 ref_table[i].id,
231 ref_table[i].name,
232 isolate);
iposva@chromium.org245aa852009-02-10 00:49:54 +0000233 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000235#ifdef ENABLE_DEBUGGER_SUPPORT
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236 // Debug addresses
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000237 Add(Debug_Address(Debug::k_after_break_target_address).address(isolate),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238 DEBUG_ADDRESS,
239 Debug::k_after_break_target_address << kDebugIdShift,
240 "Debug::after_break_target_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000241 Add(Debug_Address(Debug::k_debug_break_slot_address).address(isolate),
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000242 DEBUG_ADDRESS,
243 Debug::k_debug_break_slot_address << kDebugIdShift,
244 "Debug::debug_break_slot_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000245 Add(Debug_Address(Debug::k_debug_break_return_address).address(isolate),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000246 DEBUG_ADDRESS,
247 Debug::k_debug_break_return_address << kDebugIdShift,
248 "Debug::debug_break_return_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000249 Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate),
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000250 DEBUG_ADDRESS,
251 Debug::k_restarter_frame_function_pointer << kDebugIdShift,
252 "Debug::restarter_frame_function_pointer_address()");
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000253#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000254
255 // Stat counters
iposva@chromium.org245aa852009-02-10 00:49:54 +0000256 struct StatsRefTableEntry {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000257 StatsCounter* (Counters::*counter)();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000258 uint16_t id;
259 const char* name;
260 };
261
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000262 const StatsRefTableEntry stats_ref_table[] = {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263#define COUNTER_ENTRY(name, caption) \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000264 { &Counters::name, \
iposva@chromium.org245aa852009-02-10 00:49:54 +0000265 Counters::k_##name, \
266 "Counters::" #name },
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000267
268 STATS_COUNTER_LIST_1(COUNTER_ENTRY)
269 STATS_COUNTER_LIST_2(COUNTER_ENTRY)
270#undef COUNTER_ENTRY
iposva@chromium.org245aa852009-02-10 00:49:54 +0000271 }; // end of stats_ref_table[].
272
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000273 Counters* counters = isolate->counters();
iposva@chromium.org245aa852009-02-10 00:49:54 +0000274 for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000275 Add(reinterpret_cast<Address>(GetInternalPointer(
276 (counters->*(stats_ref_table[i].counter))())),
iposva@chromium.org245aa852009-02-10 00:49:54 +0000277 STATS_COUNTER,
278 stats_ref_table[i].id,
279 stats_ref_table[i].name);
280 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281
282 // Top addresses
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000283
284 const char* AddressNames[] = {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000285#define C(name) "Isolate::" #name,
286 ISOLATE_ADDRESS_LIST(C)
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000287 NULL
288#undef C
289 };
290
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000291 for (uint16_t i = 0; i < Isolate::k_isolate_address_count; ++i) {
292 Add(isolate->get_address_from_id((Isolate::AddressId)i),
293 TOP_ADDRESS, i, AddressNames[i]);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000294 }
295
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296 // Accessors
297#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
298 Add((Address)&Accessors::name, \
299 ACCESSOR, \
300 Accessors::k##name, \
301 "Accessors::" #name);
302
303 ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
304#undef ACCESSOR_DESCRIPTOR_DECLARATION
305
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000306 StubCache* stub_cache = isolate->stub_cache();
307
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000308 // Stub cache tables
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000309 Add(stub_cache->key_reference(StubCache::kPrimary).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000310 STUB_CACHE_TABLE,
311 1,
312 "StubCache::primary_->key");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000313 Add(stub_cache->value_reference(StubCache::kPrimary).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000314 STUB_CACHE_TABLE,
315 2,
316 "StubCache::primary_->value");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000317 Add(stub_cache->key_reference(StubCache::kSecondary).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000318 STUB_CACHE_TABLE,
319 3,
320 "StubCache::secondary_->key");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000321 Add(stub_cache->value_reference(StubCache::kSecondary).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322 STUB_CACHE_TABLE,
323 4,
324 "StubCache::secondary_->value");
325
326 // Runtime entries
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000327 Add(ExternalReference::perform_gc_function(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000328 RUNTIME_ENTRY,
329 1,
330 "Runtime::PerformGC");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000331 Add(ExternalReference::fill_heap_number_with_random_function(
332 isolate).address(),
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000333 RUNTIME_ENTRY,
334 2,
ager@chromium.org357bf652010-04-12 11:30:10 +0000335 "V8::FillHeapNumberWithRandom");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000336 Add(ExternalReference::random_uint32_function(isolate).address(),
ager@chromium.org357bf652010-04-12 11:30:10 +0000337 RUNTIME_ENTRY,
338 3,
339 "V8::Random");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000340 Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
lrn@chromium.org303ada72010-10-27 09:33:13 +0000341 RUNTIME_ENTRY,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000342 4,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000343 "HandleScope::DeleteExtensions");
344
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000345 // Miscellaneous
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000346 Add(ExternalReference::the_hole_value_location(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347 UNCLASSIFIED,
348 2,
349 "Factory::the_hole_value().location()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000350 Add(ExternalReference::roots_address(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351 UNCLASSIFIED,
352 3,
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000353 "Heap::roots_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000354 Add(ExternalReference::address_of_stack_limit(isolate).address(),
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000355 UNCLASSIFIED,
356 4,
ager@chromium.org6f10e412009-02-13 10:11:16 +0000357 "StackGuard::address_of_jslimit()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000358 Add(ExternalReference::address_of_real_stack_limit(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000359 UNCLASSIFIED,
ager@chromium.orgab99eea2009-08-25 07:05:41 +0000360 5,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000361 "StackGuard::address_of_real_jslimit()");
ricow@chromium.org4980dff2010-07-19 08:33:45 +0000362#ifndef V8_INTERPRETED_REGEXP
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000363 Add(ExternalReference::address_of_regexp_stack_limit(isolate).address(),
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000364 UNCLASSIFIED,
365 6,
ager@chromium.org32912102009-01-16 10:38:43 +0000366 "RegExpStack::limit_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000367 Add(ExternalReference::address_of_regexp_stack_memory_address(
368 isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369 UNCLASSIFIED,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000370 7,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000371 "RegExpStack::memory_address()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000372 Add(ExternalReference::address_of_regexp_stack_memory_size(isolate).address(),
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000373 UNCLASSIFIED,
374 8,
375 "RegExpStack::memory_size()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000376 Add(ExternalReference::address_of_static_offsets_vector(isolate).address(),
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000377 UNCLASSIFIED,
378 9,
379 "OffsetsVector::static_offsets_vector");
ricow@chromium.org4980dff2010-07-19 08:33:45 +0000380#endif // V8_INTERPRETED_REGEXP
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000381 Add(ExternalReference::new_space_start(isolate).address(),
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000382 UNCLASSIFIED,
383 10,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000384 "Heap::NewSpaceStart()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000385 Add(ExternalReference::new_space_mask(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000386 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000387 11,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000388 "Heap::NewSpaceMask()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000389 Add(ExternalReference::heap_always_allocate_scope_depth(isolate).address(),
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000390 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000391 12,
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000392 "Heap::always_allocate_scope_depth()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000393 Add(ExternalReference::new_space_allocation_limit_address(isolate).address(),
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000394 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000395 13,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396 "Heap::NewSpaceAllocationLimitAddress()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000397 Add(ExternalReference::new_space_allocation_top_address(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000399 14,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000400 "Heap::NewSpaceAllocationTopAddress()");
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000401#ifdef ENABLE_DEBUGGER_SUPPORT
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000402 Add(ExternalReference::debug_break(isolate).address(),
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000403 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000404 15,
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000405 "Debug::Break()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000406 Add(ExternalReference::debug_step_in_fp_address(isolate).address(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000407 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000408 16,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409 "Debug::step_in_fp_addr()");
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000410#endif
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000411 Add(ExternalReference::double_fp_operation(Token::ADD, isolate).address(),
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000412 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000413 17,
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000414 "add_two_doubles");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000415 Add(ExternalReference::double_fp_operation(Token::SUB, isolate).address(),
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000416 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000417 18,
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000418 "sub_two_doubles");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000419 Add(ExternalReference::double_fp_operation(Token::MUL, isolate).address(),
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000420 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000421 19,
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000422 "mul_two_doubles");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000423 Add(ExternalReference::double_fp_operation(Token::DIV, isolate).address(),
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000424 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000425 20,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000426 "div_two_doubles");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000427 Add(ExternalReference::double_fp_operation(Token::MOD, isolate).address(),
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000428 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000429 21,
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000430 "mod_two_doubles");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000431 Add(ExternalReference::compare_doubles(isolate).address(),
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000432 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000433 22,
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000434 "compare_doubles");
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000435#ifndef V8_INTERPRETED_REGEXP
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000436 Add(ExternalReference::re_case_insensitive_compare_uc16(isolate).address(),
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000437 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000438 23,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000439 "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000440 Add(ExternalReference::re_check_stack_guard_state(isolate).address(),
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000441 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000442 24,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000443 "RegExpMacroAssembler*::CheckStackGuardState()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000444 Add(ExternalReference::re_grow_stack(isolate).address(),
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000445 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000446 25,
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000447 "NativeRegExpMacroAssembler::GrowStack()");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000448 Add(ExternalReference::re_word_character_map().address(),
449 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000450 26,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000451 "NativeRegExpMacroAssembler::word_character_map");
ricow@chromium.orgc9c80822010-04-21 08:22:37 +0000452#endif // V8_INTERPRETED_REGEXP
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000453 // Keyed lookup cache.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000454 Add(ExternalReference::keyed_lookup_cache_keys(isolate).address(),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000455 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000456 27,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000457 "KeyedLookupCache::keys()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000458 Add(ExternalReference::keyed_lookup_cache_field_offsets(isolate).address(),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000459 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000460 28,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000461 "KeyedLookupCache::field_offsets()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000462 Add(ExternalReference::transcendental_cache_array_address(isolate).address(),
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000463 UNCLASSIFIED,
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000464 29,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000465 "TranscendentalCache::caches()");
lrn@chromium.org303ada72010-10-27 09:33:13 +0000466 Add(ExternalReference::handle_scope_next_address().address(),
467 UNCLASSIFIED,
468 30,
469 "HandleScope::next");
470 Add(ExternalReference::handle_scope_limit_address().address(),
471 UNCLASSIFIED,
472 31,
473 "HandleScope::limit");
474 Add(ExternalReference::handle_scope_level_address().address(),
475 UNCLASSIFIED,
476 32,
477 "HandleScope::level");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000478 Add(ExternalReference::new_deoptimizer_function(isolate).address(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000479 UNCLASSIFIED,
480 33,
481 "Deoptimizer::New()");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000482 Add(ExternalReference::compute_output_frames_function(isolate).address(),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000483 UNCLASSIFIED,
484 34,
485 "Deoptimizer::ComputeOutputFrames()");
486 Add(ExternalReference::address_of_min_int().address(),
487 UNCLASSIFIED,
488 35,
489 "LDoubleConstant::min_int");
490 Add(ExternalReference::address_of_one_half().address(),
491 UNCLASSIFIED,
492 36,
493 "LDoubleConstant::one_half");
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000494 Add(ExternalReference::isolate_address().address(),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000495 UNCLASSIFIED,
496 37,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000497 "isolate");
498 Add(ExternalReference::address_of_minus_zero().address(),
499 UNCLASSIFIED,
500 38,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000501 "LDoubleConstant::minus_zero");
502 Add(ExternalReference::address_of_negative_infinity().address(),
503 UNCLASSIFIED,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000504 39,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000505 "LDoubleConstant::negative_infinity");
506 Add(ExternalReference::power_double_double_function(isolate).address(),
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000507 UNCLASSIFIED,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000508 40,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000509 "power_double_double_function");
510 Add(ExternalReference::power_double_int_function(isolate).address(),
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000511 UNCLASSIFIED,
ager@chromium.org378b34e2011-01-28 08:04:38 +0000512 41,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000513 "power_double_int_function");
514 Add(ExternalReference::arguments_marker_location(isolate).address(),
515 UNCLASSIFIED,
516 42,
kmillikin@chromium.orgd2c22f02011-01-10 08:15:37 +0000517 "Factory::arguments_marker().location()");
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000518}
519
520
521ExternalReferenceEncoder::ExternalReferenceEncoder()
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000522 : encodings_(Match),
523 isolate_(Isolate::Current()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000524 ExternalReferenceTable* external_references =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 ExternalReferenceTable::instance(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000526 for (int i = 0; i < external_references->size(); ++i) {
527 Put(external_references->address(i), i);
528 }
529}
530
531
532uint32_t ExternalReferenceEncoder::Encode(Address key) const {
533 int index = IndexOf(key);
whesse@chromium.orge90029b2010-08-02 11:52:17 +0000534 ASSERT(key == NULL || index >= 0);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000535 return index >=0 ?
536 ExternalReferenceTable::instance(isolate_)->code(index) : 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000537}
538
539
540const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
541 int index = IndexOf(key);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000542 return index >= 0 ?
543 ExternalReferenceTable::instance(isolate_)->name(index) : NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544}
545
546
547int ExternalReferenceEncoder::IndexOf(Address key) const {
548 if (key == NULL) return -1;
549 HashMap::Entry* entry =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000550 const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false);
ager@chromium.org9085a012009-05-11 19:22:57 +0000551 return entry == NULL
552 ? -1
553 : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554}
555
556
557void ExternalReferenceEncoder::Put(Address key, int index) {
558 HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000559 entry->value = reinterpret_cast<void*>(index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000560}
561
562
563ExternalReferenceDecoder::ExternalReferenceDecoder()
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000564 : encodings_(NewArray<Address*>(kTypeCodeCount)),
565 isolate_(Isolate::Current()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000566 ExternalReferenceTable* external_references =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000567 ExternalReferenceTable::instance(isolate_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
569 int max = external_references->max_id(type) + 1;
570 encodings_[type] = NewArray<Address>(max + 1);
571 }
572 for (int i = 0; i < external_references->size(); ++i) {
573 Put(external_references->code(i), external_references->address(i));
574 }
575}
576
577
578ExternalReferenceDecoder::~ExternalReferenceDecoder() {
579 for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
580 DeleteArray(encodings_[type]);
581 }
582 DeleteArray(encodings_);
583}
584
585
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000586bool Serializer::serialization_enabled_ = false;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000587bool Serializer::too_late_to_enable_now_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588
589
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000590Deserializer::Deserializer(SnapshotByteSource* source)
591 : isolate_(NULL),
592 source_(source),
593 external_reference_decoder_(NULL) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000594}
595
596
597// This routine both allocates a new object, and also keeps
598// track of where objects have been allocated so that we can
599// fix back references when deserializing.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000600Address Deserializer::Allocate(int space_index, Space* space, int size) {
601 Address address;
602 if (!SpaceIsLarge(space_index)) {
603 ASSERT(!SpaceIsPaged(space_index) ||
604 size <= Page::kPageSize - Page::kObjectStartOffset);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000605 MaybeObject* maybe_new_allocation;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000606 if (space_index == NEW_SPACE) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000607 maybe_new_allocation =
608 reinterpret_cast<NewSpace*>(space)->AllocateRaw(size);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000609 } else {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000610 maybe_new_allocation =
611 reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size);
ager@chromium.org3811b432009-10-28 14:53:37 +0000612 }
lrn@chromium.org303ada72010-10-27 09:33:13 +0000613 Object* new_allocation = maybe_new_allocation->ToObjectUnchecked();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000614 HeapObject* new_object = HeapObject::cast(new_allocation);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000615 address = new_object->address();
616 high_water_[space_index] = address + size;
617 } else {
618 ASSERT(SpaceIsLarge(space_index));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000619 LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space);
ager@chromium.org3811b432009-10-28 14:53:37 +0000620 Object* new_allocation;
621 if (space_index == kLargeData) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000622 new_allocation = lo_space->AllocateRaw(size)->ToObjectUnchecked();
ager@chromium.org3811b432009-10-28 14:53:37 +0000623 } else if (space_index == kLargeFixedArray) {
lrn@chromium.org303ada72010-10-27 09:33:13 +0000624 new_allocation =
625 lo_space->AllocateRawFixedArray(size)->ToObjectUnchecked();
ager@chromium.org3811b432009-10-28 14:53:37 +0000626 } else {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000627 ASSERT_EQ(kLargeCode, space_index);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000628 new_allocation = lo_space->AllocateRawCode(size)->ToObjectUnchecked();
ager@chromium.org3811b432009-10-28 14:53:37 +0000629 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000630 HeapObject* new_object = HeapObject::cast(new_allocation);
631 // Record all large objects in the same space.
632 address = new_object->address();
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000633 pages_[LO_SPACE].Add(address);
ager@chromium.org3811b432009-10-28 14:53:37 +0000634 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000635 last_object_address_ = address;
ager@chromium.org3811b432009-10-28 14:53:37 +0000636 return address;
637}
638
639
640// This returns the address of an object that has been described in the
641// snapshot as being offset bytes back in a particular space.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000642HeapObject* Deserializer::GetAddressFromEnd(int space) {
643 int offset = source_->GetInt();
644 ASSERT(!SpaceIsLarge(space));
645 offset <<= kObjectAlignmentBits;
646 return HeapObject::FromAddress(high_water_[space] - offset);
647}
648
649
650// This returns the address of an object that has been described in the
651// snapshot as being offset bytes into a particular space.
652HeapObject* Deserializer::GetAddressFromStart(int space) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000653 int offset = source_->GetInt();
654 if (SpaceIsLarge(space)) {
655 // Large spaces have one object per 'page'.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000656 return HeapObject::FromAddress(pages_[LO_SPACE][offset]);
ager@chromium.org3811b432009-10-28 14:53:37 +0000657 }
658 offset <<= kObjectAlignmentBits;
659 if (space == NEW_SPACE) {
660 // New space has only one space - numbered 0.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000661 return HeapObject::FromAddress(pages_[space][0] + offset);
ager@chromium.org3811b432009-10-28 14:53:37 +0000662 }
663 ASSERT(SpaceIsPaged(space));
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000664 int page_of_pointee = offset >> kPageSizeBits;
ager@chromium.org3811b432009-10-28 14:53:37 +0000665 Address object_address = pages_[space][page_of_pointee] +
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000666 (offset & Page::kPageAlignmentMask);
ager@chromium.org3811b432009-10-28 14:53:37 +0000667 return HeapObject::FromAddress(object_address);
668}
669
670
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000671void Deserializer::Deserialize() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000672 isolate_ = Isolate::Current();
ager@chromium.org3811b432009-10-28 14:53:37 +0000673 // Don't GC while deserializing - just expand the heap.
674 AlwaysAllocateScope always_allocate;
675 // Don't use the free lists while deserializing.
676 LinearAllocationScope allocate_linearly;
677 // No active threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000678 ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
ager@chromium.org3811b432009-10-28 14:53:37 +0000679 // No active handles.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000680 ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000681 // Make sure the entire partial snapshot cache is traversed, filling it with
682 // valid object pointers.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000683 isolate_->set_serialize_partial_snapshot_cache_length(
684 Isolate::kPartialSnapshotCacheCapacity);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000685 ASSERT_EQ(NULL, external_reference_decoder_);
ager@chromium.org3811b432009-10-28 14:53:37 +0000686 external_reference_decoder_ = new ExternalReferenceDecoder();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000687 isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
688 isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000689
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000690 isolate_->heap()->set_global_contexts_list(
691 isolate_->heap()->undefined_value());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000692}
693
694
695void Deserializer::DeserializePartial(Object** root) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000696 isolate_ = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000697 // Don't GC while deserializing - just expand the heap.
698 AlwaysAllocateScope always_allocate;
699 // Don't use the free lists while deserializing.
700 LinearAllocationScope allocate_linearly;
701 if (external_reference_decoder_ == NULL) {
702 external_reference_decoder_ = new ExternalReferenceDecoder();
703 }
704 VisitPointer(root);
705}
706
707
708Deserializer::~Deserializer() {
ager@chromium.org3811b432009-10-28 14:53:37 +0000709 ASSERT(source_->AtEOF());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000710 if (external_reference_decoder_) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000711 delete external_reference_decoder_;
712 external_reference_decoder_ = NULL;
713 }
ager@chromium.org3811b432009-10-28 14:53:37 +0000714}
715
716
717// This is called on the roots. It is the driver of the deserialization
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000718// process. It is also called on the body of each function.
719void Deserializer::VisitPointers(Object** start, Object** end) {
720 // The space must be new space. Any other space would cause ReadChunk to try
721 // to update the remembered using NULL as the address.
722 ReadChunk(start, end, NEW_SPACE, NULL);
ager@chromium.org3811b432009-10-28 14:53:37 +0000723}
724
725
726// This routine writes the new object into the pointer provided and then
727// returns true if the new object was in young space and false otherwise.
728// The reason for this strange interface is that otherwise the object is
729// written very late, which means the ByteArray map is not set up by the
730// time we need to use it to mark the space at the end of a page free (by
731// making it into a byte array).
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000732void Deserializer::ReadObject(int space_number,
733 Space* space,
734 Object** write_back) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000735 int size = source_->GetInt() << kObjectAlignmentBits;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000736 Address address = Allocate(space_number, space, size);
ager@chromium.org3811b432009-10-28 14:53:37 +0000737 *write_back = HeapObject::FromAddress(address);
738 Object** current = reinterpret_cast<Object**>(address);
739 Object** limit = current + (size >> kPointerSizeLog2);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000740 if (FLAG_log_snapshot_positions) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000741 LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000742 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000743 ReadChunk(current, limit, space_number, address);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000744#ifdef DEBUG
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000745 bool is_codespace = (space == HEAP->code_space()) ||
746 ((space == HEAP->lo_space()) && (space_number == kLargeCode));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000747 ASSERT(HeapObject::FromAddress(address)->IsCode() == is_codespace);
748#endif
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000749}
750
751
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000752// This macro is always used with a constant argument so it should all fold
753// away to almost nothing in the generated code. It might be nicer to do this
754// with the ternary operator but there are type issues with that.
755#define ASSIGN_DEST_SPACE(space_number) \
756 Space* dest_space; \
757 if (space_number == NEW_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000758 dest_space = isolate->heap()->new_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000759 } else if (space_number == OLD_POINTER_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000760 dest_space = isolate->heap()->old_pointer_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000761 } else if (space_number == OLD_DATA_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000762 dest_space = isolate->heap()->old_data_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000763 } else if (space_number == CODE_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000764 dest_space = isolate->heap()->code_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000765 } else if (space_number == MAP_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000766 dest_space = isolate->heap()->map_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000767 } else if (space_number == CELL_SPACE) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000768 dest_space = isolate->heap()->cell_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000769 } else { \
770 ASSERT(space_number >= LO_SPACE); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000771 dest_space = isolate->heap()->lo_space(); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000772 }
773
774
775static const int kUnknownOffsetFromStart = -1;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000776
777
778void Deserializer::ReadChunk(Object** current,
779 Object** limit,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000780 int source_space,
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000781 Address address) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000782 Isolate* const isolate = isolate_;
ager@chromium.org3811b432009-10-28 14:53:37 +0000783 while (current < limit) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000784 int data = source_->Get();
ager@chromium.org3811b432009-10-28 14:53:37 +0000785 switch (data) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000786#define CASE_STATEMENT(where, how, within, space_number) \
787 case where + how + within + space_number: \
788 ASSERT((where & ~kPointedToMask) == 0); \
789 ASSERT((how & ~kHowToCodeMask) == 0); \
790 ASSERT((within & ~kWhereToPointMask) == 0); \
791 ASSERT((space_number & ~kSpaceMask) == 0);
792
793#define CASE_BODY(where, how, within, space_number_if_any, offset_from_start) \
794 { \
795 bool emit_write_barrier = false; \
796 bool current_was_incremented = false; \
797 int space_number = space_number_if_any == kAnyOldSpace ? \
798 (data & kSpaceMask) : space_number_if_any; \
799 if (where == kNewObject && how == kPlain && within == kStartOfObject) {\
800 ASSIGN_DEST_SPACE(space_number) \
801 ReadObject(space_number, dest_space, current); \
802 emit_write_barrier = \
803 (space_number == NEW_SPACE && source_space != NEW_SPACE); \
804 } else { \
805 Object* new_object = NULL; /* May not be a real Object pointer. */ \
806 if (where == kNewObject) { \
807 ASSIGN_DEST_SPACE(space_number) \
808 ReadObject(space_number, dest_space, &new_object); \
809 } else if (where == kRootArray) { \
810 int root_id = source_->GetInt(); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000811 new_object = isolate->heap()->roots_address()[root_id]; \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000812 } else if (where == kPartialSnapshotCache) { \
813 int cache_index = source_->GetInt(); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000814 new_object = isolate->serialize_partial_snapshot_cache() \
815 [cache_index]; \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000816 } else if (where == kExternalReference) { \
817 int reference_id = source_->GetInt(); \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000818 Address address = external_reference_decoder_-> \
819 Decode(reference_id); \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000820 new_object = reinterpret_cast<Object*>(address); \
821 } else if (where == kBackref) { \
822 emit_write_barrier = \
823 (space_number == NEW_SPACE && source_space != NEW_SPACE); \
824 new_object = GetAddressFromEnd(data & kSpaceMask); \
825 } else { \
826 ASSERT(where == kFromStart); \
827 if (offset_from_start == kUnknownOffsetFromStart) { \
828 emit_write_barrier = \
829 (space_number == NEW_SPACE && source_space != NEW_SPACE); \
830 new_object = GetAddressFromStart(data & kSpaceMask); \
831 } else { \
832 Address object_address = pages_[space_number][0] + \
833 (offset_from_start << kObjectAlignmentBits); \
834 new_object = HeapObject::FromAddress(object_address); \
835 } \
836 } \
837 if (within == kFirstInstruction) { \
838 Code* new_code_object = reinterpret_cast<Code*>(new_object); \
839 new_object = reinterpret_cast<Object*>( \
840 new_code_object->instruction_start()); \
841 } \
842 if (how == kFromCode) { \
843 Address location_of_branch_data = \
844 reinterpret_cast<Address>(current); \
845 Assembler::set_target_at(location_of_branch_data, \
846 reinterpret_cast<Address>(new_object)); \
847 if (within == kFirstInstruction) { \
848 location_of_branch_data += Assembler::kCallTargetSize; \
849 current = reinterpret_cast<Object**>(location_of_branch_data); \
850 current_was_incremented = true; \
851 } \
852 } else { \
853 *current = new_object; \
854 } \
855 } \
856 if (emit_write_barrier) { \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000857 isolate->heap()->RecordWrite(address, static_cast<int>( \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000858 reinterpret_cast<Address>(current) - address)); \
859 } \
860 if (!current_was_incremented) { \
861 current++; /* Increment current if it wasn't done above. */ \
862 } \
863 break; \
864 } \
865
866// This generates a case and a body for each space. The large object spaces are
867// very rare in snapshots so they are grouped in one body.
868#define ONE_PER_SPACE(where, how, within) \
869 CASE_STATEMENT(where, how, within, NEW_SPACE) \
870 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \
871 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
872 CASE_BODY(where, how, within, OLD_DATA_SPACE, kUnknownOffsetFromStart) \
873 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
874 CASE_BODY(where, how, within, OLD_POINTER_SPACE, kUnknownOffsetFromStart) \
875 CASE_STATEMENT(where, how, within, CODE_SPACE) \
876 CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \
877 CASE_STATEMENT(where, how, within, CELL_SPACE) \
878 CASE_BODY(where, how, within, CELL_SPACE, kUnknownOffsetFromStart) \
879 CASE_STATEMENT(where, how, within, MAP_SPACE) \
880 CASE_BODY(where, how, within, MAP_SPACE, kUnknownOffsetFromStart) \
881 CASE_STATEMENT(where, how, within, kLargeData) \
882 CASE_STATEMENT(where, how, within, kLargeCode) \
883 CASE_STATEMENT(where, how, within, kLargeFixedArray) \
884 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
885
886// This generates a case and a body for the new space (which has to do extra
887// write barrier handling) and handles the other spaces with 8 fall-through
888// cases and one body.
889#define ALL_SPACES(where, how, within) \
890 CASE_STATEMENT(where, how, within, NEW_SPACE) \
891 CASE_BODY(where, how, within, NEW_SPACE, kUnknownOffsetFromStart) \
892 CASE_STATEMENT(where, how, within, OLD_DATA_SPACE) \
893 CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE) \
894 CASE_STATEMENT(where, how, within, CODE_SPACE) \
895 CASE_STATEMENT(where, how, within, CELL_SPACE) \
896 CASE_STATEMENT(where, how, within, MAP_SPACE) \
897 CASE_STATEMENT(where, how, within, kLargeData) \
898 CASE_STATEMENT(where, how, within, kLargeCode) \
899 CASE_STATEMENT(where, how, within, kLargeFixedArray) \
900 CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
901
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000902#define ONE_PER_CODE_SPACE(where, how, within) \
903 CASE_STATEMENT(where, how, within, CODE_SPACE) \
904 CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \
905 CASE_STATEMENT(where, how, within, kLargeCode) \
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000906 CASE_BODY(where, how, within, kLargeCode, kUnknownOffsetFromStart)
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000907
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000908#define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number, \
909 space_number, \
910 offset_from_start) \
911 CASE_STATEMENT(kFromStart, kPlain, kStartOfObject, pseudo_space_number) \
912 CASE_BODY(kFromStart, kPlain, kStartOfObject, space_number, offset_from_start)
913
914 // We generate 15 cases and bodies that process special tags that combine
915 // the raw data tag and the length into one byte.
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000916#define RAW_CASE(index, size) \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000917 case kRawData + index: { \
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000918 byte* raw_data_out = reinterpret_cast<byte*>(current); \
919 source_->CopyRaw(raw_data_out, size); \
920 current = reinterpret_cast<Object**>(raw_data_out + size); \
921 break; \
922 }
923 COMMON_RAW_LENGTHS(RAW_CASE)
924#undef RAW_CASE
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000925
926 // Deserialize a chunk of raw data that doesn't have one of the popular
927 // lengths.
928 case kRawData: {
ager@chromium.org3811b432009-10-28 14:53:37 +0000929 int size = source_->GetInt();
930 byte* raw_data_out = reinterpret_cast<byte*>(current);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000931 source_->CopyRaw(raw_data_out, size);
932 current = reinterpret_cast<Object**>(raw_data_out + size);
ager@chromium.org3811b432009-10-28 14:53:37 +0000933 break;
934 }
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000935
936 // Deserialize a new object and write a pointer to it to the current
937 // object.
938 ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject)
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000939 // Support for direct instruction pointers in functions
940 ONE_PER_CODE_SPACE(kNewObject, kPlain, kFirstInstruction)
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000941 // Deserialize a new code object and write a pointer to its first
942 // instruction to the current code object.
943 ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction)
944 // Find a recently deserialized object using its offset from the current
945 // allocation point and write a pointer to it to the current object.
946 ALL_SPACES(kBackref, kPlain, kStartOfObject)
947 // Find a recently deserialized code object using its offset from the
948 // current allocation point and write a pointer to its first instruction
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000949 // to the current code object or the instruction pointer in a function
950 // object.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000951 ALL_SPACES(kBackref, kFromCode, kFirstInstruction)
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000952 ALL_SPACES(kBackref, kPlain, kFirstInstruction)
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000953 // Find an already deserialized object using its offset from the start
954 // and write a pointer to it to the current object.
955 ALL_SPACES(kFromStart, kPlain, kStartOfObject)
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000956 ALL_SPACES(kFromStart, kPlain, kFirstInstruction)
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000957 // Find an already deserialized code object using its offset from the
958 // start and write a pointer to its first instruction to the current code
959 // object.
960 ALL_SPACES(kFromStart, kFromCode, kFirstInstruction)
961 // Find an already deserialized object at one of the predetermined popular
962 // offsets from the start and write a pointer to it in the current object.
963 COMMON_REFERENCE_PATTERNS(EMIT_COMMON_REFERENCE_PATTERNS)
964 // Find an object in the roots array and write a pointer to it to the
965 // current object.
966 CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
967 CASE_BODY(kRootArray, kPlain, kStartOfObject, 0, kUnknownOffsetFromStart)
968 // Find an object in the partial snapshots cache and write a pointer to it
969 // to the current object.
970 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
971 CASE_BODY(kPartialSnapshotCache,
972 kPlain,
973 kStartOfObject,
974 0,
975 kUnknownOffsetFromStart)
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000976 // Find an code entry in the partial snapshots cache and
977 // write a pointer to it to the current object.
978 CASE_STATEMENT(kPartialSnapshotCache, kPlain, kFirstInstruction, 0)
979 CASE_BODY(kPartialSnapshotCache,
980 kPlain,
981 kFirstInstruction,
982 0,
983 kUnknownOffsetFromStart)
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000984 // Find an external reference and write a pointer to it to the current
985 // object.
986 CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
987 CASE_BODY(kExternalReference,
988 kPlain,
989 kStartOfObject,
990 0,
991 kUnknownOffsetFromStart)
992 // Find an external reference and write a pointer to it in the current
993 // code object.
994 CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
995 CASE_BODY(kExternalReference,
996 kFromCode,
997 kStartOfObject,
998 0,
999 kUnknownOffsetFromStart)
1000
1001#undef CASE_STATEMENT
1002#undef CASE_BODY
1003#undef ONE_PER_SPACE
1004#undef ALL_SPACES
1005#undef EMIT_COMMON_REFERENCE_PATTERNS
1006#undef ASSIGN_DEST_SPACE
1007
1008 case kNewPage: {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001009 int space = source_->Get();
1010 pages_[space].Add(last_object_address_);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001011 if (space == CODE_SPACE) {
1012 CPU::FlushICache(last_object_address_, Page::kPageSize);
1013 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001014 break;
1015 }
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001016
1017 case kNativesStringResource: {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001018 int index = source_->Get();
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001019 Vector<const char> source_vector = Natives::GetRawScriptSource(index);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001020 NativesExternalStringResource* resource =
jkummerow@chromium.orge297f592011-06-08 10:05:15 +00001021 new NativesExternalStringResource(isolate->bootstrapper(),
1022 source_vector.start(),
1023 source_vector.length());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001024 *current++ = reinterpret_cast<Object*>(resource);
1025 break;
1026 }
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001027
1028 case kSynchronize: {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001029 // If we get here then that indicates that you have a mismatch between
1030 // the number of GC roots when serializing and deserializing.
1031 UNREACHABLE();
1032 }
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001033
ager@chromium.org3811b432009-10-28 14:53:37 +00001034 default:
1035 UNREACHABLE();
1036 }
1037 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001038 ASSERT_EQ(current, limit);
ager@chromium.org3811b432009-10-28 14:53:37 +00001039}
1040
1041
1042void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
1043 const int max_shift = ((kPointerSize * kBitsPerByte) / 7) * 7;
1044 for (int shift = max_shift; shift > 0; shift -= 7) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001045 if (integer >= static_cast<uintptr_t>(1u) << shift) {
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001046 Put((static_cast<int>((integer >> shift)) & 0x7f) | 0x80, "IntPart");
ager@chromium.org3811b432009-10-28 14:53:37 +00001047 }
1048 }
fschneider@chromium.orgb95b98b2010-02-23 10:34:29 +00001049 PutSection(static_cast<int>(integer & 0x7f), "IntLastPart");
ager@chromium.org3811b432009-10-28 14:53:37 +00001050}
1051
1052#ifdef DEBUG
1053
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001054void Deserializer::Synchronize(const char* tag) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001055 int data = source_->Get();
1056 // If this assert fails then that indicates that you have a mismatch between
1057 // the number of GC roots when serializing and deserializing.
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001058 ASSERT_EQ(kSynchronize, data);
ager@chromium.org3811b432009-10-28 14:53:37 +00001059 do {
1060 int character = source_->Get();
1061 if (character == 0) break;
1062 if (FLAG_debug_serialization) {
1063 PrintF("%c", character);
1064 }
1065 } while (true);
1066 if (FLAG_debug_serialization) {
1067 PrintF("\n");
1068 }
1069}
1070
1071
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001072void Serializer::Synchronize(const char* tag) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001073 sink_->Put(kSynchronize, tag);
ager@chromium.org3811b432009-10-28 14:53:37 +00001074 int character;
1075 do {
1076 character = *tag++;
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001077 sink_->PutSection(character, "TagCharacter");
ager@chromium.org3811b432009-10-28 14:53:37 +00001078 } while (character != 0);
1079}
1080
1081#endif
1082
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001083Serializer::Serializer(SnapshotByteSink* sink)
ager@chromium.org3811b432009-10-28 14:53:37 +00001084 : sink_(sink),
1085 current_root_index_(0),
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001086 external_reference_encoder_(new ExternalReferenceEncoder),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001087 large_object_total_(0) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001088 // The serializer is meant to be used only to generate initial heap images
1089 // from a context in which there is only one isolate.
1090 ASSERT(Isolate::Current()->IsDefaultIsolate());
ager@chromium.org3811b432009-10-28 14:53:37 +00001091 for (int i = 0; i <= LAST_SPACE; i++) {
1092 fullness_[i] = 0;
1093 }
1094}
1095
1096
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001097Serializer::~Serializer() {
1098 delete external_reference_encoder_;
1099}
1100
1101
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001102void StartupSerializer::SerializeStrongReferences() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001103 Isolate* isolate = Isolate::Current();
ager@chromium.org3811b432009-10-28 14:53:37 +00001104 // No active threads.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001105 CHECK_EQ(NULL, Isolate::Current()->thread_manager()->FirstThreadStateInUse());
ager@chromium.org3811b432009-10-28 14:53:37 +00001106 // No active or weak handles.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001107 CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
1108 CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001109 // We don't support serializing installed extensions.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001110 for (RegisteredExtension* ext = v8::RegisteredExtension::first_extension();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001111 ext != NULL;
1112 ext = ext->next()) {
1113 CHECK_NE(v8::INSTALLED, ext->state());
1114 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001115 HEAP->IterateStrongRoots(this, VISIT_ONLY_STRONG);
ager@chromium.org3811b432009-10-28 14:53:37 +00001116}
1117
1118
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001119void PartialSerializer::Serialize(Object** object) {
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001120 this->VisitPointer(object);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001121 Isolate* isolate = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001122
1123 // After we have done the partial serialization the partial snapshot cache
1124 // will contain some references needed to decode the partial snapshot. We
1125 // fill it up with undefineds so it has a predictable length so the
1126 // deserialization code doesn't need to know the length.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001127 for (int index = isolate->serialize_partial_snapshot_cache_length();
1128 index < Isolate::kPartialSnapshotCacheCapacity;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001129 index++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001130 isolate->serialize_partial_snapshot_cache()[index] =
1131 isolate->heap()->undefined_value();
1132 startup_serializer_->VisitPointer(
1133 &isolate->serialize_partial_snapshot_cache()[index]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001134 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001135 isolate->set_serialize_partial_snapshot_cache_length(
1136 Isolate::kPartialSnapshotCacheCapacity);
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001137}
1138
1139
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001140void Serializer::VisitPointers(Object** start, Object** end) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001141 for (Object** current = start; current < end; current++) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001142 if ((*current)->IsSmi()) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001143 sink_->Put(kRawData, "RawData");
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001144 sink_->PutInt(kPointerSize, "length");
1145 for (int i = 0; i < kPointerSize; i++) {
1146 sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
1147 }
1148 } else {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001149 SerializeObject(*current, kPlain, kStartOfObject);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001150 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001151 }
1152}
1153
1154
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001155// This ensures that the partial snapshot cache keeps things alive during GC and
1156// tracks their movement. When it is called during serialization of the startup
1157// snapshot the partial snapshot is empty, so nothing happens. When the partial
1158// (context) snapshot is created, this array is populated with the pointers that
1159// the partial snapshot will need. As that happens we emit serialized objects to
1160// the startup snapshot that correspond to the elements of this cache array. On
1161// deserialization we therefore need to visit the cache array. This fills it up
1162// with pointers to deserialized objects.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +00001163void SerializerDeserializer::Iterate(ObjectVisitor* visitor) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001164 Isolate* isolate = Isolate::Current();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001165 visitor->VisitPointers(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001166 isolate->serialize_partial_snapshot_cache(),
1167 &isolate->serialize_partial_snapshot_cache()[
1168 isolate->serialize_partial_snapshot_cache_length()]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001169}
1170
1171
1172// When deserializing we need to set the size of the snapshot cache. This means
1173// the root iteration code (above) will iterate over array elements, writing the
1174// references to deserialized objects in them.
1175void SerializerDeserializer::SetSnapshotCacheSize(int size) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001176 Isolate::Current()->set_serialize_partial_snapshot_cache_length(size);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001177}
1178
1179
1180int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001181 Isolate* isolate = Isolate::Current();
1182
1183 for (int i = 0;
1184 i < isolate->serialize_partial_snapshot_cache_length();
1185 i++) {
1186 Object* entry = isolate->serialize_partial_snapshot_cache()[i];
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001187 if (entry == heap_object) return i;
1188 }
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001189
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001190 // We didn't find the object in the cache. So we add it to the cache and
1191 // then visit the pointer so that it becomes part of the startup snapshot
1192 // and we can refer to it from the partial snapshot.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001193 int length = isolate->serialize_partial_snapshot_cache_length();
1194 CHECK(length < Isolate::kPartialSnapshotCacheCapacity);
1195 isolate->serialize_partial_snapshot_cache()[length] = heap_object;
1196 startup_serializer_->VisitPointer(
1197 &isolate->serialize_partial_snapshot_cache()[length]);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001198 // We don't recurse from the startup snapshot generator into the partial
1199 // snapshot generator.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001200 ASSERT(length == isolate->serialize_partial_snapshot_cache_length());
1201 isolate->set_serialize_partial_snapshot_cache_length(length + 1);
1202 return length;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001203}
1204
1205
1206int PartialSerializer::RootIndex(HeapObject* heap_object) {
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001207 for (int i = 0; i < Heap::kRootListLength; i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001208 Object* root = HEAP->roots_address()[i];
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001209 if (root == heap_object) return i;
1210 }
1211 return kInvalidRootIndex;
1212}
1213
1214
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001215// Encode the location of an already deserialized object in order to write its
1216// location into a later object. We can encode the location as an offset from
1217// the start of the deserialized objects or as an offset backwards from the
1218// current allocation pointer.
1219void Serializer::SerializeReferenceToPreviousObject(
1220 int space,
1221 int address,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001222 HowToCode how_to_code,
1223 WhereToPoint where_to_point) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001224 int offset = CurrentAllocationAddress(space) - address;
1225 bool from_start = true;
1226 if (SpaceIsPaged(space)) {
1227 // For paged space it is simple to encode back from current allocation if
1228 // the object is on the same page as the current allocation pointer.
1229 if ((CurrentAllocationAddress(space) >> kPageSizeBits) ==
1230 (address >> kPageSizeBits)) {
1231 from_start = false;
1232 address = offset;
1233 }
1234 } else if (space == NEW_SPACE) {
1235 // For new space it is always simple to encode back from current allocation.
1236 if (offset < address) {
1237 from_start = false;
1238 address = offset;
1239 }
1240 }
1241 // If we are actually dealing with real offsets (and not a numbering of
1242 // all objects) then we should shift out the bits that are always 0.
1243 if (!SpaceIsLarge(space)) address >>= kObjectAlignmentBits;
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001244 if (from_start) {
1245#define COMMON_REFS_CASE(pseudo_space, actual_space, offset) \
1246 if (space == actual_space && address == offset && \
1247 how_to_code == kPlain && where_to_point == kStartOfObject) { \
1248 sink_->Put(kFromStart + how_to_code + where_to_point + \
1249 pseudo_space, "RefSer"); \
1250 } else /* NOLINT */
1251 COMMON_REFERENCE_PATTERNS(COMMON_REFS_CASE)
1252#undef COMMON_REFS_CASE
1253 { /* NOLINT */
1254 sink_->Put(kFromStart + how_to_code + where_to_point + space, "RefSer");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001255 sink_->PutInt(address, "address");
1256 }
1257 } else {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001258 sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
1259 sink_->PutInt(address, "address");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001260 }
1261}
1262
1263
1264void StartupSerializer::SerializeObject(
ager@chromium.org3811b432009-10-28 14:53:37 +00001265 Object* o,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001266 HowToCode how_to_code,
1267 WhereToPoint where_to_point) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001268 CHECK(o->IsHeapObject());
1269 HeapObject* heap_object = HeapObject::cast(o);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001270
1271 if (address_mapper_.IsMapped(heap_object)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001272 int space = SpaceOfAlreadySerializedObject(heap_object);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001273 int address = address_mapper_.MappedTo(heap_object);
1274 SerializeReferenceToPreviousObject(space,
1275 address,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001276 how_to_code,
1277 where_to_point);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001278 } else {
1279 // Object has not yet been serialized. Serialize it here.
1280 ObjectSerializer object_serializer(this,
1281 heap_object,
1282 sink_,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001283 how_to_code,
1284 where_to_point);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001285 object_serializer.Serialize();
1286 }
1287}
1288
1289
1290void StartupSerializer::SerializeWeakReferences() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001291 for (int i = Isolate::Current()->serialize_partial_snapshot_cache_length();
1292 i < Isolate::kPartialSnapshotCacheCapacity;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001293 i++) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001294 sink_->Put(kRootArray + kPlain + kStartOfObject, "RootSerialization");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001295 sink_->PutInt(Heap::kUndefinedValueRootIndex, "root_index");
1296 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001297 HEAP->IterateWeakRoots(this, VISIT_ALL);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001298}
1299
1300
1301void PartialSerializer::SerializeObject(
1302 Object* o,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001303 HowToCode how_to_code,
1304 WhereToPoint where_to_point) {
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001305 CHECK(o->IsHeapObject());
1306 HeapObject* heap_object = HeapObject::cast(o);
1307
1308 int root_index;
1309 if ((root_index = RootIndex(heap_object)) != kInvalidRootIndex) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001310 sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001311 sink_->PutInt(root_index, "root_index");
1312 return;
1313 }
1314
1315 if (ShouldBeInThePartialSnapshotCache(heap_object)) {
1316 int cache_index = PartialSnapshotCacheIndex(heap_object);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001317 sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
1318 "PartialSnapshotCache");
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001319 sink_->PutInt(cache_index, "partial_snapshot_cache_index");
1320 return;
1321 }
1322
1323 // Pointers from the partial snapshot to the objects in the startup snapshot
1324 // should go through the root array or through the partial snapshot cache.
1325 // If this is not the case you may have to add something to the root array.
1326 ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object));
1327 // All the symbols that the partial snapshot needs should be either in the
1328 // root table or in the partial snapshot cache.
1329 ASSERT(!heap_object->IsSymbol());
1330
1331 if (address_mapper_.IsMapped(heap_object)) {
1332 int space = SpaceOfAlreadySerializedObject(heap_object);
1333 int address = address_mapper_.MappedTo(heap_object);
1334 SerializeReferenceToPreviousObject(space,
1335 address,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001336 how_to_code,
1337 where_to_point);
ager@chromium.org3811b432009-10-28 14:53:37 +00001338 } else {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001339 // Object has not yet been serialized. Serialize it here.
1340 ObjectSerializer serializer(this,
1341 heap_object,
1342 sink_,
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001343 how_to_code,
1344 where_to_point);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001345 serializer.Serialize();
ager@chromium.org3811b432009-10-28 14:53:37 +00001346 }
1347}
1348
1349
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001350void Serializer::ObjectSerializer::Serialize() {
1351 int space = Serializer::SpaceOfObject(object_);
ager@chromium.org3811b432009-10-28 14:53:37 +00001352 int size = object_->Size();
1353
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001354 sink_->Put(kNewObject + reference_representation_ + space,
1355 "ObjectSerialization");
ager@chromium.org3811b432009-10-28 14:53:37 +00001356 sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
1357
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001358 LOG(i::Isolate::Current(),
1359 SnapshotPositionEvent(object_->address(), sink_->Position()));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001360
ager@chromium.org3811b432009-10-28 14:53:37 +00001361 // Mark this object as already serialized.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001362 bool start_new_page;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001363 int offset = serializer_->Allocate(space, size, &start_new_page);
1364 serializer_->address_mapper()->AddMapping(object_, offset);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001365 if (start_new_page) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001366 sink_->Put(kNewPage, "NewPage");
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001367 sink_->PutSection(space, "NewPageSpace");
1368 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001369
1370 // Serialize the map (first word of the object).
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001371 serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject);
ager@chromium.org3811b432009-10-28 14:53:37 +00001372
1373 // Serialize the rest of the object.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001374 CHECK_EQ(0, bytes_processed_so_far_);
ager@chromium.org3811b432009-10-28 14:53:37 +00001375 bytes_processed_so_far_ = kPointerSize;
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001376 object_->IterateBody(object_->map()->instance_type(), size, this);
ager@chromium.org3811b432009-10-28 14:53:37 +00001377 OutputRawData(object_->address() + size);
1378}
1379
1380
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001381void Serializer::ObjectSerializer::VisitPointers(Object** start,
1382 Object** end) {
1383 Object** current = start;
1384 while (current < end) {
1385 while (current < end && (*current)->IsSmi()) current++;
1386 if (current < end) OutputRawData(reinterpret_cast<Address>(current));
ager@chromium.org3811b432009-10-28 14:53:37 +00001387
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001388 while (current < end && !(*current)->IsSmi()) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001389 serializer_->SerializeObject(*current, kPlain, kStartOfObject);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001390 bytes_processed_so_far_ += kPointerSize;
1391 current++;
1392 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001393 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001394}
1395
1396
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001397void Serializer::ObjectSerializer::VisitExternalReferences(Address* start,
1398 Address* end) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001399 Address references_start = reinterpret_cast<Address>(start);
1400 OutputRawData(references_start);
1401
1402 for (Address* current = start; current < end; current++) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001403 sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef");
ager@chromium.org3811b432009-10-28 14:53:37 +00001404 int reference_id = serializer_->EncodeExternalReference(*current);
1405 sink_->PutInt(reference_id, "reference id");
1406 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001407 bytes_processed_so_far_ += static_cast<int>((end - start) * kPointerSize);
ager@chromium.org3811b432009-10-28 14:53:37 +00001408}
1409
1410
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001411void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
1412 Address target_start = rinfo->target_address_address();
1413 OutputRawData(target_start);
1414 Address target = rinfo->target_address();
1415 uint32_t encoding = serializer_->EncodeExternalReference(target);
1416 CHECK(target == NULL ? encoding == 0 : encoding != 0);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001417 int representation;
1418 // Can't use a ternary operator because of gcc.
1419 if (rinfo->IsCodedSpecially()) {
1420 representation = kStartOfObject + kFromCode;
1421 } else {
1422 representation = kStartOfObject + kPlain;
1423 }
1424 sink_->Put(kExternalReference + representation, "ExternalReference");
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001425 sink_->PutInt(encoding, "reference id");
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001426 bytes_processed_so_far_ += rinfo->target_address_size();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001427}
1428
1429
1430void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
1431 CHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
ager@chromium.org3811b432009-10-28 14:53:37 +00001432 Address target_start = rinfo->target_address_address();
1433 OutputRawData(target_start);
1434 Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001435 serializer_->SerializeObject(target, kFromCode, kFirstInstruction);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00001436 bytes_processed_so_far_ += rinfo->target_address_size();
ager@chromium.org3811b432009-10-28 14:53:37 +00001437}
1438
1439
erik.corry@gmail.com145eff52010-08-23 11:36:18 +00001440void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
1441 Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
1442 OutputRawData(entry_address);
1443 serializer_->SerializeObject(target, kPlain, kFirstInstruction);
1444 bytes_processed_so_far_ += kPointerSize;
1445}
1446
1447
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001448void Serializer::ObjectSerializer::VisitGlobalPropertyCell(RelocInfo* rinfo) {
1449 // We shouldn't have any global property cell references in code
1450 // objects in the snapshot.
1451 UNREACHABLE();
1452}
1453
1454
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001455void Serializer::ObjectSerializer::VisitExternalAsciiString(
1456 v8::String::ExternalAsciiStringResource** resource_pointer) {
1457 Address references_start = reinterpret_cast<Address>(resource_pointer);
1458 OutputRawData(references_start);
1459 for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001460 Object* source = HEAP->natives_source_cache()->get(i);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001461 if (!source->IsUndefined()) {
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +00001462 ExternalAsciiString* string = ExternalAsciiString::cast(source);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001463 typedef v8::String::ExternalAsciiStringResource Resource;
1464 Resource* resource = string->resource();
1465 if (resource == *resource_pointer) {
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001466 sink_->Put(kNativesStringResource, "NativesStringResource");
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001467 sink_->PutSection(i, "NativesStringResourceEnd");
1468 bytes_processed_so_far_ += sizeof(resource);
1469 return;
1470 }
1471 }
1472 }
1473 // One of the strings in the natives cache should match the resource. We
1474 // can't serialize any other kinds of external strings.
1475 UNREACHABLE();
1476}
1477
1478
1479void Serializer::ObjectSerializer::OutputRawData(Address up_to) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001480 Address object_start = object_->address();
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001481 int up_to_offset = static_cast<int>(up_to - object_start);
ager@chromium.org3811b432009-10-28 14:53:37 +00001482 int skipped = up_to_offset - bytes_processed_so_far_;
1483 // This assert will fail if the reloc info gives us the target_address_address
1484 // locations in a non-ascending order. Luckily that doesn't happen.
1485 ASSERT(skipped >= 0);
1486 if (skipped != 0) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001487 Address base = object_start + bytes_processed_so_far_;
1488#define RAW_CASE(index, length) \
1489 if (skipped == length) { \
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001490 sink_->PutSection(kRawData + index, "RawDataFixed"); \
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001491 } else /* NOLINT */
1492 COMMON_RAW_LENGTHS(RAW_CASE)
1493#undef RAW_CASE
1494 { /* NOLINT */
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001495 sink_->Put(kRawData, "RawData");
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001496 sink_->PutInt(skipped, "length");
ager@chromium.org3811b432009-10-28 14:53:37 +00001497 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001498 for (int i = 0; i < skipped; i++) {
1499 unsigned int data = base[i];
1500 sink_->PutSection(data, "Byte");
1501 }
1502 bytes_processed_so_far_ += skipped;
ager@chromium.org3811b432009-10-28 14:53:37 +00001503 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001504}
1505
1506
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001507int Serializer::SpaceOfObject(HeapObject* object) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001508 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1509 AllocationSpace s = static_cast<AllocationSpace>(i);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001510 if (HEAP->InSpace(object, s)) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001511 if (i == LO_SPACE) {
1512 if (object->IsCode()) {
1513 return kLargeCode;
1514 } else if (object->IsFixedArray()) {
1515 return kLargeFixedArray;
1516 } else {
1517 return kLargeData;
1518 }
1519 }
1520 return i;
1521 }
1522 }
1523 UNREACHABLE();
1524 return 0;
1525}
1526
1527
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001528int Serializer::SpaceOfAlreadySerializedObject(HeapObject* object) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001529 for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1530 AllocationSpace s = static_cast<AllocationSpace>(i);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001531 if (HEAP->InSpace(object, s)) {
ager@chromium.org3811b432009-10-28 14:53:37 +00001532 return i;
1533 }
1534 }
1535 UNREACHABLE();
1536 return 0;
1537}
1538
1539
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001540int Serializer::Allocate(int space, int size, bool* new_page) {
1541 CHECK(space >= 0 && space < kNumberOfSpaces);
ager@chromium.org3811b432009-10-28 14:53:37 +00001542 if (SpaceIsLarge(space)) {
1543 // In large object space we merely number the objects instead of trying to
1544 // determine some sort of address.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001545 *new_page = true;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001546 large_object_total_ += size;
ager@chromium.org3811b432009-10-28 14:53:37 +00001547 return fullness_[LO_SPACE]++;
1548 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001549 *new_page = false;
1550 if (fullness_[space] == 0) {
1551 *new_page = true;
1552 }
ager@chromium.org3811b432009-10-28 14:53:37 +00001553 if (SpaceIsPaged(space)) {
1554 // Paged spaces are a little special. We encode their addresses as if the
1555 // pages were all contiguous and each page were filled up in the range
1556 // 0 - Page::kObjectAreaSize. In practice the pages may not be contiguous
1557 // and allocation does not start at offset 0 in the page, but this scheme
1558 // means the deserializer can get the page number quickly by shifting the
1559 // serialized address.
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001560 CHECK(IsPowerOf2(Page::kPageSize));
ager@chromium.org3811b432009-10-28 14:53:37 +00001561 int used_in_this_page = (fullness_[space] & (Page::kPageSize - 1));
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001562 CHECK(size <= Page::kObjectAreaSize);
ager@chromium.org3811b432009-10-28 14:53:37 +00001563 if (used_in_this_page + size > Page::kObjectAreaSize) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001564 *new_page = true;
ager@chromium.org3811b432009-10-28 14:53:37 +00001565 fullness_[space] = RoundUp(fullness_[space], Page::kPageSize);
1566 }
1567 }
1568 int allocation_address = fullness_[space];
1569 fullness_[space] = allocation_address + size;
1570 return allocation_address;
1571}
1572
1573
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001574} } // namespace v8::internal