1// Copyright 2012 the V8 project authors. All rights reserved.
2// 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"
32#include "bootstrapper.h"
33#include "deoptimizer.h"
34#include "execution.h"
35#include "global-handles.h"
36#include "ic-inl.h"
37#include "natives.h"
38#include "platform.h"
39#include "runtime.h"
40#include "serialize.h"
41#include "snapshot.h"
42#include "stub-cache.h"
43#include "v8threads.h"
44
45namespace v8 {
46namespace internal {
47
48
49// -----------------------------------------------------------------------------
50// Coding of external references.
51
52// The encoding of an external reference. The type is in the high word.
53// The id is in the low word.
54static uint32_t EncodeExternal(TypeCode type, uint16_t id) {
55  return static_cast<uint32_t>(type) << 16 | id;
56}
57
58
59static int* GetInternalPointer(StatsCounter* counter) {
60  // All counters refer to dummy_counter, if deserializing happens without
61  // setting up counters.
62  static int dummy_counter = 0;
63  return counter->Enabled() ? counter->GetInternalPointer() : &dummy_counter;
64}
65
66
67ExternalReferenceTable* ExternalReferenceTable::instance(Isolate* isolate) {
68  ExternalReferenceTable* external_reference_table =
69      isolate->external_reference_table();
70  if (external_reference_table == NULL) {
71    external_reference_table = new ExternalReferenceTable(isolate);
72    isolate->set_external_reference_table(external_reference_table);
73  }
74  return external_reference_table;
75}
76
77
78void ExternalReferenceTable::AddFromId(TypeCode type,
79                                       uint16_t id,
80                                       const char* name,
81                                       Isolate* isolate) {
82  Address address;
83  switch (type) {
84    case C_BUILTIN: {
85      ExternalReference ref(static_cast<Builtins::CFunctionId>(id), isolate);
86      address = ref.address();
87      break;
88    }
89    case BUILTIN: {
90      ExternalReference ref(static_cast<Builtins::Name>(id), isolate);
91      address = ref.address();
92      break;
93    }
94    case RUNTIME_FUNCTION: {
95      ExternalReference ref(static_cast<Runtime::FunctionId>(id), isolate);
96      address = ref.address();
97      break;
98    }
99    case IC_UTILITY: {
100      ExternalReference ref(IC_Utility(static_cast<IC::UtilityId>(id)),
101                            isolate);
102      address = ref.address();
103      break;
104    }
105    default:
106      UNREACHABLE();
107      return;
108  }
109  Add(address, type, id, name);
110}
111
112
113void ExternalReferenceTable::Add(Address address,
114                                 TypeCode type,
115                                 uint16_t id,
116                                 const char* name) {
117  ASSERT_NE(NULL, address);
118  ExternalReferenceEntry entry;
119  entry.address = address;
120  entry.code = EncodeExternal(type, id);
121  entry.name = name;
122  ASSERT_NE(0, entry.code);
123  refs_.Add(entry);
124  if (id > max_id_[type]) max_id_[type] = id;
125}
126
127
128void ExternalReferenceTable::PopulateTable(Isolate* isolate) {
129  for (int type_code = 0; type_code < kTypeCodeCount; type_code++) {
130    max_id_[type_code] = 0;
131  }
132
133  // The following populates all of the different type of external references
134  // into the ExternalReferenceTable.
135  //
136  // NOTE: This function was originally 100k of code.  It has since been
137  // rewritten to be mostly table driven, as the callback macro style tends to
138  // very easily cause code bloat.  Please be careful in the future when adding
139  // new references.
140
141  struct RefTableEntry {
142    TypeCode type;
143    uint16_t id;
144    const char* name;
145  };
146
147  static const RefTableEntry ref_table[] = {
148  // Builtins
149#define DEF_ENTRY_C(name, ignored) \
150  { C_BUILTIN, \
151    Builtins::c_##name, \
152    "Builtins::" #name },
153
154  BUILTIN_LIST_C(DEF_ENTRY_C)
155#undef DEF_ENTRY_C
156
157#define DEF_ENTRY_C(name, ignored) \
158  { BUILTIN, \
159    Builtins::k##name, \
160    "Builtins::" #name },
161#define DEF_ENTRY_A(name, kind, state, extra) DEF_ENTRY_C(name, ignored)
162
163  BUILTIN_LIST_C(DEF_ENTRY_C)
164  BUILTIN_LIST_A(DEF_ENTRY_A)
165  BUILTIN_LIST_DEBUG_A(DEF_ENTRY_A)
166#undef DEF_ENTRY_C
167#undef DEF_ENTRY_A
168
169  // Runtime functions
170#define RUNTIME_ENTRY(name, nargs, ressize) \
171  { RUNTIME_FUNCTION, \
172    Runtime::k##name, \
173    "Runtime::" #name },
174
175  RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY)
176#undef RUNTIME_ENTRY
177
178  // IC utilities
179#define IC_ENTRY(name) \
180  { IC_UTILITY, \
181    IC::k##name, \
182    "IC::" #name },
183
184  IC_UTIL_LIST(IC_ENTRY)
185#undef IC_ENTRY
186  };  // end of ref_table[].
187
188  for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) {
189    AddFromId(ref_table[i].type,
190              ref_table[i].id,
191              ref_table[i].name,
192              isolate);
193  }
194
195#ifdef ENABLE_DEBUGGER_SUPPORT
196  // Debug addresses
197  Add(Debug_Address(Debug::k_after_break_target_address).address(isolate),
198      DEBUG_ADDRESS,
199      Debug::k_after_break_target_address << kDebugIdShift,
200      "Debug::after_break_target_address()");
201  Add(Debug_Address(Debug::k_debug_break_slot_address).address(isolate),
202      DEBUG_ADDRESS,
203      Debug::k_debug_break_slot_address << kDebugIdShift,
204      "Debug::debug_break_slot_address()");
205  Add(Debug_Address(Debug::k_debug_break_return_address).address(isolate),
206      DEBUG_ADDRESS,
207      Debug::k_debug_break_return_address << kDebugIdShift,
208      "Debug::debug_break_return_address()");
209  Add(Debug_Address(Debug::k_restarter_frame_function_pointer).address(isolate),
210      DEBUG_ADDRESS,
211      Debug::k_restarter_frame_function_pointer << kDebugIdShift,
212      "Debug::restarter_frame_function_pointer_address()");
213#endif
214
215  // Stat counters
216  struct StatsRefTableEntry {
217    StatsCounter* (Counters::*counter)();
218    uint16_t id;
219    const char* name;
220  };
221
222  const StatsRefTableEntry stats_ref_table[] = {
223#define COUNTER_ENTRY(name, caption) \
224  { &Counters::name,    \
225    Counters::k_##name, \
226    "Counters::" #name },
227
228  STATS_COUNTER_LIST_1(COUNTER_ENTRY)
229  STATS_COUNTER_LIST_2(COUNTER_ENTRY)
230#undef COUNTER_ENTRY
231  };  // end of stats_ref_table[].
232
233  Counters* counters = isolate->counters();
234  for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) {
235    Add(reinterpret_cast<Address>(GetInternalPointer(
236            (counters->*(stats_ref_table[i].counter))())),
237        STATS_COUNTER,
238        stats_ref_table[i].id,
239        stats_ref_table[i].name);
240  }
241
242  // Top addresses
243
244  const char* AddressNames[] = {
245#define BUILD_NAME_LITERAL(CamelName, hacker_name)      \
246    "Isolate::" #hacker_name "_address",
247    FOR_EACH_ISOLATE_ADDRESS_NAME(BUILD_NAME_LITERAL)
248    NULL
249#undef BUILD_NAME_LITERAL
250  };
251
252  for (uint16_t i = 0; i < Isolate::kIsolateAddressCount; ++i) {
253    Add(isolate->get_address_from_id((Isolate::AddressId)i),
254        TOP_ADDRESS, i, AddressNames[i]);
255  }
256
257  // Accessors
258#define ACCESSOR_DESCRIPTOR_DECLARATION(name) \
259  Add((Address)&Accessors::name, \
260      ACCESSOR, \
261      Accessors::k##name, \
262      "Accessors::" #name);
263
264  ACCESSOR_DESCRIPTOR_LIST(ACCESSOR_DESCRIPTOR_DECLARATION)
265#undef ACCESSOR_DESCRIPTOR_DECLARATION
266
267  StubCache* stub_cache = isolate->stub_cache();
268
269  // Stub cache tables
270  Add(stub_cache->key_reference(StubCache::kPrimary).address(),
271      STUB_CACHE_TABLE,
272      1,
273      "StubCache::primary_->key");
274  Add(stub_cache->value_reference(StubCache::kPrimary).address(),
275      STUB_CACHE_TABLE,
276      2,
277      "StubCache::primary_->value");
278  Add(stub_cache->map_reference(StubCache::kPrimary).address(),
279      STUB_CACHE_TABLE,
280      3,
281      "StubCache::primary_->map");
282  Add(stub_cache->key_reference(StubCache::kSecondary).address(),
283      STUB_CACHE_TABLE,
284      4,
285      "StubCache::secondary_->key");
286  Add(stub_cache->value_reference(StubCache::kSecondary).address(),
287      STUB_CACHE_TABLE,
288      5,
289      "StubCache::secondary_->value");
290  Add(stub_cache->map_reference(StubCache::kSecondary).address(),
291      STUB_CACHE_TABLE,
292      6,
293      "StubCache::secondary_->map");
294
295  // Runtime entries
296  Add(ExternalReference::perform_gc_function(isolate).address(),
297      RUNTIME_ENTRY,
298      1,
299      "Runtime::PerformGC");
300  Add(ExternalReference::delete_handle_scope_extensions(isolate).address(),
301      RUNTIME_ENTRY,
302      4,
303      "HandleScope::DeleteExtensions");
304  Add(ExternalReference::
305          incremental_marking_record_write_function(isolate).address(),
306      RUNTIME_ENTRY,
307      5,
308      "IncrementalMarking::RecordWrite");
309  Add(ExternalReference::store_buffer_overflow_function(isolate).address(),
310      RUNTIME_ENTRY,
311      6,
312      "StoreBuffer::StoreBufferOverflow");
313  Add(ExternalReference::
314          incremental_evacuation_record_write_function(isolate).address(),
315      RUNTIME_ENTRY,
316      7,
317      "IncrementalMarking::RecordWrite");
318
319  // Miscellaneous
320  Add(ExternalReference::roots_array_start(isolate).address(),
321      UNCLASSIFIED,
322      3,
323      "Heap::roots_array_start()");
324  Add(ExternalReference::address_of_stack_limit(isolate).address(),
325      UNCLASSIFIED,
326      4,
327      "StackGuard::address_of_jslimit()");
328  Add(ExternalReference::address_of_real_stack_limit(isolate).address(),
329      UNCLASSIFIED,
330      5,
331      "StackGuard::address_of_real_jslimit()");
332#ifndef V8_INTERPRETED_REGEXP
333  Add(ExternalReference::address_of_regexp_stack_limit(isolate).address(),
334      UNCLASSIFIED,
335      6,
336      "RegExpStack::limit_address()");
337  Add(ExternalReference::address_of_regexp_stack_memory_address(
338          isolate).address(),
339      UNCLASSIFIED,
340      7,
341      "RegExpStack::memory_address()");
342  Add(ExternalReference::address_of_regexp_stack_memory_size(isolate).address(),
343      UNCLASSIFIED,
344      8,
345      "RegExpStack::memory_size()");
346  Add(ExternalReference::address_of_static_offsets_vector(isolate).address(),
347      UNCLASSIFIED,
348      9,
349      "OffsetsVector::static_offsets_vector");
350#endif  // V8_INTERPRETED_REGEXP
351  Add(ExternalReference::new_space_start(isolate).address(),
352      UNCLASSIFIED,
353      10,
354      "Heap::NewSpaceStart()");
355  Add(ExternalReference::new_space_mask(isolate).address(),
356      UNCLASSIFIED,
357      11,
358      "Heap::NewSpaceMask()");
359  Add(ExternalReference::heap_always_allocate_scope_depth(isolate).address(),
360      UNCLASSIFIED,
361      12,
362      "Heap::always_allocate_scope_depth()");
363  Add(ExternalReference::new_space_allocation_limit_address(isolate).address(),
364      UNCLASSIFIED,
365      14,
366      "Heap::NewSpaceAllocationLimitAddress()");
367  Add(ExternalReference::new_space_allocation_top_address(isolate).address(),
368      UNCLASSIFIED,
369      15,
370      "Heap::NewSpaceAllocationTopAddress()");
371#ifdef ENABLE_DEBUGGER_SUPPORT
372  Add(ExternalReference::debug_break(isolate).address(),
373      UNCLASSIFIED,
374      16,
375      "Debug::Break()");
376  Add(ExternalReference::debug_step_in_fp_address(isolate).address(),
377      UNCLASSIFIED,
378      17,
379      "Debug::step_in_fp_addr()");
380#endif
381  Add(ExternalReference::double_fp_operation(Token::ADD, isolate).address(),
382      UNCLASSIFIED,
383      18,
384      "add_two_doubles");
385  Add(ExternalReference::double_fp_operation(Token::SUB, isolate).address(),
386      UNCLASSIFIED,
387      19,
388      "sub_two_doubles");
389  Add(ExternalReference::double_fp_operation(Token::MUL, isolate).address(),
390      UNCLASSIFIED,
391      20,
392      "mul_two_doubles");
393  Add(ExternalReference::double_fp_operation(Token::DIV, isolate).address(),
394      UNCLASSIFIED,
395      21,
396      "div_two_doubles");
397  Add(ExternalReference::double_fp_operation(Token::MOD, isolate).address(),
398      UNCLASSIFIED,
399      22,
400      "mod_two_doubles");
401  Add(ExternalReference::compare_doubles(isolate).address(),
402      UNCLASSIFIED,
403      23,
404      "compare_doubles");
405#ifndef V8_INTERPRETED_REGEXP
406  Add(ExternalReference::re_case_insensitive_compare_uc16(isolate).address(),
407      UNCLASSIFIED,
408      24,
409      "NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()");
410  Add(ExternalReference::re_check_stack_guard_state(isolate).address(),
411      UNCLASSIFIED,
412      25,
413      "RegExpMacroAssembler*::CheckStackGuardState()");
414  Add(ExternalReference::re_grow_stack(isolate).address(),
415      UNCLASSIFIED,
416      26,
417      "NativeRegExpMacroAssembler::GrowStack()");
418  Add(ExternalReference::re_word_character_map().address(),
419      UNCLASSIFIED,
420      27,
421      "NativeRegExpMacroAssembler::word_character_map");
422#endif  // V8_INTERPRETED_REGEXP
423  // Keyed lookup cache.
424  Add(ExternalReference::keyed_lookup_cache_keys(isolate).address(),
425      UNCLASSIFIED,
426      28,
427      "KeyedLookupCache::keys()");
428  Add(ExternalReference::keyed_lookup_cache_field_offsets(isolate).address(),
429      UNCLASSIFIED,
430      29,
431      "KeyedLookupCache::field_offsets()");
432  Add(ExternalReference::transcendental_cache_array_address(isolate).address(),
433      UNCLASSIFIED,
434      30,
435      "TranscendentalCache::caches()");
436  Add(ExternalReference::handle_scope_next_address(isolate).address(),
437      UNCLASSIFIED,
438      31,
439      "HandleScope::next");
440  Add(ExternalReference::handle_scope_limit_address(isolate).address(),
441      UNCLASSIFIED,
442      32,
443      "HandleScope::limit");
444  Add(ExternalReference::handle_scope_level_address(isolate).address(),
445      UNCLASSIFIED,
446      33,
447      "HandleScope::level");
448  Add(ExternalReference::new_deoptimizer_function(isolate).address(),
449      UNCLASSIFIED,
450      34,
451      "Deoptimizer::New()");
452  Add(ExternalReference::compute_output_frames_function(isolate).address(),
453      UNCLASSIFIED,
454      35,
455      "Deoptimizer::ComputeOutputFrames()");
456  Add(ExternalReference::address_of_min_int().address(),
457      UNCLASSIFIED,
458      36,
459      "LDoubleConstant::min_int");
460  Add(ExternalReference::address_of_one_half().address(),
461      UNCLASSIFIED,
462      37,
463      "LDoubleConstant::one_half");
464  Add(ExternalReference::isolate_address(isolate).address(),
465      UNCLASSIFIED,
466      38,
467      "isolate");
468  Add(ExternalReference::address_of_minus_zero().address(),
469      UNCLASSIFIED,
470      39,
471      "LDoubleConstant::minus_zero");
472  Add(ExternalReference::address_of_negative_infinity().address(),
473      UNCLASSIFIED,
474      40,
475      "LDoubleConstant::negative_infinity");
476  Add(ExternalReference::power_double_double_function(isolate).address(),
477      UNCLASSIFIED,
478      41,
479      "power_double_double_function");
480  Add(ExternalReference::power_double_int_function(isolate).address(),
481      UNCLASSIFIED,
482      42,
483      "power_double_int_function");
484  Add(ExternalReference::store_buffer_top(isolate).address(),
485      UNCLASSIFIED,
486      43,
487      "store_buffer_top");
488  Add(ExternalReference::address_of_canonical_non_hole_nan().address(),
489      UNCLASSIFIED,
490      44,
491      "canonical_nan");
492  Add(ExternalReference::address_of_the_hole_nan().address(),
493      UNCLASSIFIED,
494      45,
495      "the_hole_nan");
496  Add(ExternalReference::get_date_field_function(isolate).address(),
497      UNCLASSIFIED,
498      46,
499      "JSDate::GetField");
500  Add(ExternalReference::date_cache_stamp(isolate).address(),
501      UNCLASSIFIED,
502      47,
503      "date_cache_stamp");
504  Add(ExternalReference::address_of_pending_message_obj(isolate).address(),
505      UNCLASSIFIED,
506      48,
507      "address_of_pending_message_obj");
508  Add(ExternalReference::address_of_has_pending_message(isolate).address(),
509      UNCLASSIFIED,
510      49,
511      "address_of_has_pending_message");
512  Add(ExternalReference::address_of_pending_message_script(isolate).address(),
513      UNCLASSIFIED,
514      50,
515      "pending_message_script");
516  Add(ExternalReference::get_make_code_young_function(isolate).address(),
517      UNCLASSIFIED,
518      51,
519      "Code::MakeCodeYoung");
520  Add(ExternalReference::cpu_features().address(),
521      UNCLASSIFIED,
522      52,
523      "cpu_features");
524  Add(ExternalReference(Runtime::kAllocateInNewSpace, isolate).address(),
525      UNCLASSIFIED,
526      53,
527      "Runtime::AllocateInNewSpace");
528  Add(ExternalReference(Runtime::kAllocateInTargetSpace, isolate).address(),
529      UNCLASSIFIED,
530      54,
531      "Runtime::AllocateInTargetSpace");
532  Add(ExternalReference::old_pointer_space_allocation_top_address(
533      isolate).address(),
534      UNCLASSIFIED,
535      55,
536      "Heap::OldPointerSpaceAllocationTopAddress");
537  Add(ExternalReference::old_pointer_space_allocation_limit_address(
538      isolate).address(),
539      UNCLASSIFIED,
540      56,
541      "Heap::OldPointerSpaceAllocationLimitAddress");
542  Add(ExternalReference::old_data_space_allocation_top_address(
543      isolate).address(),
544      UNCLASSIFIED,
545      57,
546      "Heap::OldDataSpaceAllocationTopAddress");
547  Add(ExternalReference::old_data_space_allocation_limit_address(
548      isolate).address(),
549      UNCLASSIFIED,
550      58,
551      "Heap::OldDataSpaceAllocationLimitAddress");
552  Add(ExternalReference::new_space_high_promotion_mode_active_address(isolate).
553      address(),
554      UNCLASSIFIED,
555      59,
556      "Heap::NewSpaceAllocationLimitAddress");
557  Add(ExternalReference::allocation_sites_list_address(isolate).address(),
558      UNCLASSIFIED,
559      60,
560      "Heap::allocation_sites_list_address()");
561  Add(ExternalReference::address_of_uint32_bias().address(),
562      UNCLASSIFIED,
563      61,
564      "uint32_bias");
565  Add(ExternalReference::get_mark_code_as_executed_function(isolate).address(),
566      UNCLASSIFIED,
567      62,
568      "Code::MarkCodeAsExecuted");
569
570  // Add a small set of deopt entry addresses to encoder without generating the
571  // deopt table code, which isn't possible at deserialization time.
572  HandleScope scope(isolate);
573  for (int entry = 0; entry < kDeoptTableSerializeEntryCount; ++entry) {
574    Address address = Deoptimizer::GetDeoptimizationEntry(
575        isolate,
576        entry,
577        Deoptimizer::LAZY,
578        Deoptimizer::CALCULATE_ENTRY_ADDRESS);
579    Add(address, LAZY_DEOPTIMIZATION, entry, "lazy_deopt");
580  }
581}
582
583
584ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate)
585    : encodings_(Match),
586      isolate_(isolate) {
587  ExternalReferenceTable* external_references =
588      ExternalReferenceTable::instance(isolate_);
589  for (int i = 0; i < external_references->size(); ++i) {
590    Put(external_references->address(i), i);
591  }
592}
593
594
595uint32_t ExternalReferenceEncoder::Encode(Address key) const {
596  int index = IndexOf(key);
597  ASSERT(key == NULL || index >= 0);
598  return index >=0 ?
599         ExternalReferenceTable::instance(isolate_)->code(index) : 0;
600}
601
602
603const char* ExternalReferenceEncoder::NameOfAddress(Address key) const {
604  int index = IndexOf(key);
605  return index >= 0 ?
606      ExternalReferenceTable::instance(isolate_)->name(index) : NULL;
607}
608
609
610int ExternalReferenceEncoder::IndexOf(Address key) const {
611  if (key == NULL) return -1;
612  HashMap::Entry* entry =
613      const_cast<HashMap&>(encodings_).Lookup(key, Hash(key), false);
614  return entry == NULL
615      ? -1
616      : static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
617}
618
619
620void ExternalReferenceEncoder::Put(Address key, int index) {
621  HashMap::Entry* entry = encodings_.Lookup(key, Hash(key), true);
622  entry->value = reinterpret_cast<void*>(index);
623}
624
625
626ExternalReferenceDecoder::ExternalReferenceDecoder(Isolate* isolate)
627    : encodings_(NewArray<Address*>(kTypeCodeCount)),
628      isolate_(isolate) {
629  ExternalReferenceTable* external_references =
630      ExternalReferenceTable::instance(isolate_);
631  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
632    int max = external_references->max_id(type) + 1;
633    encodings_[type] = NewArray<Address>(max + 1);
634  }
635  for (int i = 0; i < external_references->size(); ++i) {
636    Put(external_references->code(i), external_references->address(i));
637  }
638}
639
640
641ExternalReferenceDecoder::~ExternalReferenceDecoder() {
642  for (int type = kFirstTypeCode; type < kTypeCodeCount; ++type) {
643    DeleteArray(encodings_[type]);
644  }
645  DeleteArray(encodings_);
646}
647
648
649bool Serializer::serialization_enabled_ = false;
650bool Serializer::too_late_to_enable_now_ = false;
651
652
653class CodeAddressMap: public CodeEventLogger {
654 public:
655  explicit CodeAddressMap(Isolate* isolate)
656      : isolate_(isolate) {
657    isolate->logger()->addCodeEventListener(this);
658  }
659
660  virtual ~CodeAddressMap() {
661    isolate_->logger()->removeCodeEventListener(this);
662  }
663
664  virtual void CodeMoveEvent(Address from, Address to) {
665    address_to_name_map_.Move(from, to);
666  }
667
668  virtual void CodeDeleteEvent(Address from) {
669    address_to_name_map_.Remove(from);
670  }
671
672  const char* Lookup(Address address) {
673    return address_to_name_map_.Lookup(address);
674  }
675
676 private:
677  class NameMap {
678   public:
679    NameMap() : impl_(&PointerEquals) {}
680
681    ~NameMap() {
682      for (HashMap::Entry* p = impl_.Start(); p != NULL; p = impl_.Next(p)) {
683        DeleteArray(static_cast<const char*>(p->value));
684      }
685    }
686
687    void Insert(Address code_address, const char* name, int name_size) {
688      HashMap::Entry* entry = FindOrCreateEntry(code_address);
689      if (entry->value == NULL) {
690        entry->value = CopyName(name, name_size);
691      }
692    }
693
694    const char* Lookup(Address code_address) {
695      HashMap::Entry* entry = FindEntry(code_address);
696      return (entry != NULL) ? static_cast<const char*>(entry->value) : NULL;
697    }
698
699    void Remove(Address code_address) {
700      HashMap::Entry* entry = FindEntry(code_address);
701      if (entry != NULL) {
702        DeleteArray(static_cast<char*>(entry->value));
703        RemoveEntry(entry);
704      }
705    }
706
707    void Move(Address from, Address to) {
708      if (from == to) return;
709      HashMap::Entry* from_entry = FindEntry(from);
710      ASSERT(from_entry != NULL);
711      void* value = from_entry->value;
712      RemoveEntry(from_entry);
713      HashMap::Entry* to_entry = FindOrCreateEntry(to);
714      ASSERT(to_entry->value == NULL);
715      to_entry->value = value;
716    }
717
718   private:
719    static bool PointerEquals(void* lhs, void* rhs) {
720      return lhs == rhs;
721    }
722
723    static char* CopyName(const char* name, int name_size) {
724      char* result = NewArray<char>(name_size + 1);
725      for (int i = 0; i < name_size; ++i) {
726        char c = name[i];
727        if (c == '\0') c = ' ';
728        result[i] = c;
729      }
730      result[name_size] = '\0';
731      return result;
732    }
733
734    HashMap::Entry* FindOrCreateEntry(Address code_address) {
735      return impl_.Lookup(code_address, ComputePointerHash(code_address), true);
736    }
737
738    HashMap::Entry* FindEntry(Address code_address) {
739      return impl_.Lookup(code_address,
740                          ComputePointerHash(code_address),
741                          false);
742    }
743
744    void RemoveEntry(HashMap::Entry* entry) {
745      impl_.Remove(entry->key, entry->hash);
746    }
747
748    HashMap impl_;
749
750    DISALLOW_COPY_AND_ASSIGN(NameMap);
751  };
752
753  virtual void LogRecordedBuffer(Code* code,
754                                 SharedFunctionInfo*,
755                                 const char* name,
756                                 int length) {
757    address_to_name_map_.Insert(code->address(), name, length);
758  }
759
760  NameMap address_to_name_map_;
761  Isolate* isolate_;
762};
763
764
765CodeAddressMap* Serializer::code_address_map_ = NULL;
766
767
768void Serializer::Enable(Isolate* isolate) {
769  if (!serialization_enabled_) {
770    ASSERT(!too_late_to_enable_now_);
771  }
772  if (serialization_enabled_) return;
773  serialization_enabled_ = true;
774  isolate->InitializeLoggingAndCounters();
775  code_address_map_ = new CodeAddressMap(isolate);
776}
777
778
779void Serializer::Disable() {
780  if (!serialization_enabled_) return;
781  serialization_enabled_ = false;
782  delete code_address_map_;
783  code_address_map_ = NULL;
784}
785
786
787Deserializer::Deserializer(SnapshotByteSource* source)
788    : isolate_(NULL),
789      source_(source),
790      external_reference_decoder_(NULL) {
791  for (int i = 0; i < LAST_SPACE + 1; i++) {
792    reservations_[i] = kUninitializedReservation;
793  }
794}
795
796
797void Deserializer::FlushICacheForNewCodeObjects() {
798  PageIterator it(isolate_->heap()->code_space());
799  while (it.has_next()) {
800    Page* p = it.next();
801    CPU::FlushICache(p->area_start(), p->area_end() - p->area_start());
802  }
803}
804
805
806void Deserializer::Deserialize(Isolate* isolate) {
807  isolate_ = isolate;
808  ASSERT(isolate_ != NULL);
809  isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
810  // No active threads.
811  ASSERT_EQ(NULL, isolate_->thread_manager()->FirstThreadStateInUse());
812  // No active handles.
813  ASSERT(isolate_->handle_scope_implementer()->blocks()->is_empty());
814  ASSERT_EQ(NULL, external_reference_decoder_);
815  external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
816  isolate_->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
817  isolate_->heap()->RepairFreeListsAfterBoot();
818  isolate_->heap()->IterateWeakRoots(this, VISIT_ALL);
819
820  isolate_->heap()->set_native_contexts_list(
821      isolate_->heap()->undefined_value());
822  isolate_->heap()->set_array_buffers_list(
823      isolate_->heap()->undefined_value());
824
825  // The allocation site list is build during root iteration, but if no sites
826  // were encountered then it needs to be initialized to undefined.
827  if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) {
828    isolate_->heap()->set_allocation_sites_list(
829        isolate_->heap()->undefined_value());
830  }
831
832  isolate_->heap()->InitializeWeakObjectToCodeTable();
833
834  // Update data pointers to the external strings containing natives sources.
835  for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
836    Object* source = isolate_->heap()->natives_source_cache()->get(i);
837    if (!source->IsUndefined()) {
838      ExternalAsciiString::cast(source)->update_data_cache();
839    }
840  }
841
842  FlushICacheForNewCodeObjects();
843
844  // Issue code events for newly deserialized code objects.
845  LOG_CODE_EVENT(isolate_, LogCodeObjects());
846  LOG_CODE_EVENT(isolate_, LogCompiledFunctions());
847}
848
849
850void Deserializer::DeserializePartial(Isolate* isolate, Object** root) {
851  isolate_ = isolate;
852  for (int i = NEW_SPACE; i < kNumberOfSpaces; i++) {
853    ASSERT(reservations_[i] != kUninitializedReservation);
854  }
855  isolate_->heap()->ReserveSpace(reservations_, &high_water_[0]);
856  if (external_reference_decoder_ == NULL) {
857    external_reference_decoder_ = new ExternalReferenceDecoder(isolate);
858  }
859
860  // Keep track of the code space start and end pointers in case new
861  // code objects were unserialized
862  OldSpace* code_space = isolate_->heap()->code_space();
863  Address start_address = code_space->top();
864  VisitPointer(root);
865
866  // There's no code deserialized here. If this assert fires
867  // then that's changed and logging should be added to notify
868  // the profiler et al of the new code.
869  CHECK_EQ(start_address, code_space->top());
870}
871
872
873Deserializer::~Deserializer() {
874  ASSERT(source_->AtEOF());
875  if (external_reference_decoder_) {
876    delete external_reference_decoder_;
877    external_reference_decoder_ = NULL;
878  }
879}
880
881
882// This is called on the roots.  It is the driver of the deserialization
883// process.  It is also called on the body of each function.
884void Deserializer::VisitPointers(Object** start, Object** end) {
885  // The space must be new space.  Any other space would cause ReadChunk to try
886  // to update the remembered using NULL as the address.
887  ReadChunk(start, end, NEW_SPACE, NULL);
888}
889
890
891void Deserializer::RelinkAllocationSite(AllocationSite* site) {
892  if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) {
893    site->set_weak_next(isolate_->heap()->undefined_value());
894  } else {
895    site->set_weak_next(isolate_->heap()->allocation_sites_list());
896  }
897  isolate_->heap()->set_allocation_sites_list(site);
898}
899
900
901// This routine writes the new object into the pointer provided and then
902// returns true if the new object was in young space and false otherwise.
903// The reason for this strange interface is that otherwise the object is
904// written very late, which means the FreeSpace map is not set up by the
905// time we need to use it to mark the space at the end of a page free.
906void Deserializer::ReadObject(int space_number,
907                              Object** write_back) {
908  int size = source_->GetInt() << kObjectAlignmentBits;
909  Address address = Allocate(space_number, size);
910  HeapObject* obj = HeapObject::FromAddress(address);
911  *write_back = obj;
912  Object** current = reinterpret_cast<Object**>(address);
913  Object** limit = current + (size >> kPointerSizeLog2);
914  if (FLAG_log_snapshot_positions) {
915    LOG(isolate_, SnapshotPositionEvent(address, source_->position()));
916  }
917  ReadChunk(current, limit, space_number, address);
918
919  // TODO(mvstanton): consider treating the heap()->allocation_sites_list()
920  // as a (weak) root. If this root is relocated correctly,
921  // RelinkAllocationSite() isn't necessary.
922  if (obj->IsAllocationSite()) {
923    RelinkAllocationSite(AllocationSite::cast(obj));
924  }
925
926#ifdef DEBUG
927  bool is_codespace = (space_number == CODE_SPACE);
928  ASSERT(obj->IsCode() == is_codespace);
929#endif
930}
931
932void Deserializer::ReadChunk(Object** current,
933                             Object** limit,
934                             int source_space,
935                             Address current_object_address) {
936  Isolate* const isolate = isolate_;
937  // Write barrier support costs around 1% in startup time.  In fact there
938  // are no new space objects in current boot snapshots, so it's not needed,
939  // but that may change.
940  bool write_barrier_needed = (current_object_address != NULL &&
941                               source_space != NEW_SPACE &&
942                               source_space != CELL_SPACE &&
943                               source_space != PROPERTY_CELL_SPACE &&
944                               source_space != CODE_SPACE &&
945                               source_space != OLD_DATA_SPACE);
946  while (current < limit) {
947    int data = source_->Get();
948    switch (data) {
949#define CASE_STATEMENT(where, how, within, space_number)                       \
950      case where + how + within + space_number:                                \
951      ASSERT((where & ~kPointedToMask) == 0);                                  \
952      ASSERT((how & ~kHowToCodeMask) == 0);                                    \
953      ASSERT((within & ~kWhereToPointMask) == 0);                              \
954      ASSERT((space_number & ~kSpaceMask) == 0);
955
956#define CASE_BODY(where, how, within, space_number_if_any)                     \
957      {                                                                        \
958        bool emit_write_barrier = false;                                       \
959        bool current_was_incremented = false;                                  \
960        int space_number =  space_number_if_any == kAnyOldSpace ?              \
961                            (data & kSpaceMask) : space_number_if_any;         \
962        if (where == kNewObject && how == kPlain && within == kStartOfObject) {\
963          ReadObject(space_number, current);                                   \
964          emit_write_barrier = (space_number == NEW_SPACE);                    \
965        } else {                                                               \
966          Object* new_object = NULL;  /* May not be a real Object pointer. */  \
967          if (where == kNewObject) {                                           \
968            ReadObject(space_number, &new_object);                             \
969          } else if (where == kRootArray) {                                    \
970            int root_id = source_->GetInt();                                   \
971            new_object = isolate->heap()->roots_array_start()[root_id];        \
972            emit_write_barrier = isolate->heap()->InNewSpace(new_object);      \
973          } else if (where == kPartialSnapshotCache) {                         \
974            int cache_index = source_->GetInt();                               \
975            new_object = isolate->serialize_partial_snapshot_cache()           \
976                [cache_index];                                                 \
977            emit_write_barrier = isolate->heap()->InNewSpace(new_object);      \
978          } else if (where == kExternalReference) {                            \
979            int skip = source_->GetInt();                                      \
980            current = reinterpret_cast<Object**>(reinterpret_cast<Address>(    \
981                current) + skip);                                              \
982            int reference_id = source_->GetInt();                              \
983            Address address = external_reference_decoder_->                    \
984                Decode(reference_id);                                          \
985            new_object = reinterpret_cast<Object*>(address);                   \
986          } else if (where == kBackref) {                                      \
987            emit_write_barrier = (space_number == NEW_SPACE);                  \
988            new_object = GetAddressFromEnd(data & kSpaceMask);                 \
989          } else {                                                             \
990            ASSERT(where == kBackrefWithSkip);                                 \
991            int skip = source_->GetInt();                                      \
992            current = reinterpret_cast<Object**>(                              \
993                reinterpret_cast<Address>(current) + skip);                    \
994            emit_write_barrier = (space_number == NEW_SPACE);                  \
995            new_object = GetAddressFromEnd(data & kSpaceMask);                 \
996          }                                                                    \
997          if (within == kInnerPointer) {                                       \
998            if (space_number != CODE_SPACE || new_object->IsCode()) {          \
999              Code* new_code_object = reinterpret_cast<Code*>(new_object);     \
1000              new_object = reinterpret_cast<Object*>(                          \
1001                  new_code_object->instruction_start());                       \
1002            } else {                                                           \
1003              ASSERT(space_number == CODE_SPACE);                              \
1004              Cell* cell = Cell::cast(new_object);                             \
1005              new_object = reinterpret_cast<Object*>(                          \
1006                  cell->ValueAddress());                                       \
1007            }                                                                  \
1008          }                                                                    \
1009          if (how == kFromCode) {                                              \
1010            Address location_of_branch_data =                                  \
1011                reinterpret_cast<Address>(current);                            \
1012            Assembler::deserialization_set_special_target_at(                  \
1013                location_of_branch_data,                                       \
1014                reinterpret_cast<Address>(new_object));                        \
1015            location_of_branch_data += Assembler::kSpecialTargetSize;          \
1016            current = reinterpret_cast<Object**>(location_of_branch_data);     \
1017            current_was_incremented = true;                                    \
1018          } else {                                                             \
1019            *current = new_object;                                             \
1020          }                                                                    \
1021        }                                                                      \
1022        if (emit_write_barrier && write_barrier_needed) {                      \
1023          Address current_address = reinterpret_cast<Address>(current);        \
1024          isolate->heap()->RecordWrite(                                        \
1025              current_object_address,                                          \
1026              static_cast<int>(current_address - current_object_address));     \
1027        }                                                                      \
1028        if (!current_was_incremented) {                                        \
1029          current++;                                                           \
1030        }                                                                      \
1031        break;                                                                 \
1032      }                                                                        \
1033
1034// This generates a case and a body for the new space (which has to do extra
1035// write barrier handling) and handles the other spaces with 8 fall-through
1036// cases and one body.
1037#define ALL_SPACES(where, how, within)                                         \
1038  CASE_STATEMENT(where, how, within, NEW_SPACE)                                \
1039  CASE_BODY(where, how, within, NEW_SPACE)                                     \
1040  CASE_STATEMENT(where, how, within, OLD_DATA_SPACE)                           \
1041  CASE_STATEMENT(where, how, within, OLD_POINTER_SPACE)                        \
1042  CASE_STATEMENT(where, how, within, CODE_SPACE)                               \
1043  CASE_STATEMENT(where, how, within, CELL_SPACE)                               \
1044  CASE_STATEMENT(where, how, within, PROPERTY_CELL_SPACE)                      \
1045  CASE_STATEMENT(where, how, within, MAP_SPACE)                                \
1046  CASE_BODY(where, how, within, kAnyOldSpace)
1047
1048#define FOUR_CASES(byte_code)             \
1049  case byte_code:                         \
1050  case byte_code + 1:                     \
1051  case byte_code + 2:                     \
1052  case byte_code + 3:
1053
1054#define SIXTEEN_CASES(byte_code)          \
1055  FOUR_CASES(byte_code)                   \
1056  FOUR_CASES(byte_code + 4)               \
1057  FOUR_CASES(byte_code + 8)               \
1058  FOUR_CASES(byte_code + 12)
1059
1060#define COMMON_RAW_LENGTHS(f)        \
1061  f(1)  \
1062  f(2)  \
1063  f(3)  \
1064  f(4)  \
1065  f(5)  \
1066  f(6)  \
1067  f(7)  \
1068  f(8)  \
1069  f(9)  \
1070  f(10) \
1071  f(11) \
1072  f(12) \
1073  f(13) \
1074  f(14) \
1075  f(15) \
1076  f(16) \
1077  f(17) \
1078  f(18) \
1079  f(19) \
1080  f(20) \
1081  f(21) \
1082  f(22) \
1083  f(23) \
1084  f(24) \
1085  f(25) \
1086  f(26) \
1087  f(27) \
1088  f(28) \
1089  f(29) \
1090  f(30) \
1091  f(31)
1092
1093      // We generate 15 cases and bodies that process special tags that combine
1094      // the raw data tag and the length into one byte.
1095#define RAW_CASE(index)                                                      \
1096      case kRawData + index: {                                               \
1097        byte* raw_data_out = reinterpret_cast<byte*>(current);               \
1098        source_->CopyRaw(raw_data_out, index * kPointerSize);                \
1099        current =                                                            \
1100            reinterpret_cast<Object**>(raw_data_out + index * kPointerSize); \
1101        break;                                                               \
1102      }
1103      COMMON_RAW_LENGTHS(RAW_CASE)
1104#undef RAW_CASE
1105
1106      // Deserialize a chunk of raw data that doesn't have one of the popular
1107      // lengths.
1108      case kRawData: {
1109        int size = source_->GetInt();
1110        byte* raw_data_out = reinterpret_cast<byte*>(current);
1111        source_->CopyRaw(raw_data_out, size);
1112        break;
1113      }
1114
1115      SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance)
1116      SIXTEEN_CASES(kRootArrayConstants + kNoSkipDistance + 16) {
1117        int root_id = RootArrayConstantFromByteCode(data);
1118        Object* object = isolate->heap()->roots_array_start()[root_id];
1119        ASSERT(!isolate->heap()->InNewSpace(object));
1120        *current++ = object;
1121        break;
1122      }
1123
1124      SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance)
1125      SIXTEEN_CASES(kRootArrayConstants + kHasSkipDistance + 16) {
1126        int root_id = RootArrayConstantFromByteCode(data);
1127        int skip = source_->GetInt();
1128        current = reinterpret_cast<Object**>(
1129            reinterpret_cast<intptr_t>(current) + skip);
1130        Object* object = isolate->heap()->roots_array_start()[root_id];
1131        ASSERT(!isolate->heap()->InNewSpace(object));
1132        *current++ = object;
1133        break;
1134      }
1135
1136      case kRepeat: {
1137        int repeats = source_->GetInt();
1138        Object* object = current[-1];
1139        ASSERT(!isolate->heap()->InNewSpace(object));
1140        for (int i = 0; i < repeats; i++) current[i] = object;
1141        current += repeats;
1142        break;
1143      }
1144
1145      STATIC_ASSERT(kRootArrayNumberOfConstantEncodings ==
1146                    Heap::kOldSpaceRoots);
1147      STATIC_ASSERT(kMaxRepeats == 13);
1148      case kConstantRepeat:
1149      FOUR_CASES(kConstantRepeat + 1)
1150      FOUR_CASES(kConstantRepeat + 5)
1151      FOUR_CASES(kConstantRepeat + 9) {
1152        int repeats = RepeatsForCode(data);
1153        Object* object = current[-1];
1154        ASSERT(!isolate->heap()->InNewSpace(object));
1155        for (int i = 0; i < repeats; i++) current[i] = object;
1156        current += repeats;
1157        break;
1158      }
1159
1160      // Deserialize a new object and write a pointer to it to the current
1161      // object.
1162      ALL_SPACES(kNewObject, kPlain, kStartOfObject)
1163      // Support for direct instruction pointers in functions.  It's an inner
1164      // pointer because it points at the entry point, not at the start of the
1165      // code object.
1166      CASE_STATEMENT(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
1167      CASE_BODY(kNewObject, kPlain, kInnerPointer, CODE_SPACE)
1168      // Deserialize a new code object and write a pointer to its first
1169      // instruction to the current code object.
1170      ALL_SPACES(kNewObject, kFromCode, kInnerPointer)
1171      // Find a recently deserialized object using its offset from the current
1172      // allocation point and write a pointer to it to the current object.
1173      ALL_SPACES(kBackref, kPlain, kStartOfObject)
1174      ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
1175#if V8_TARGET_ARCH_MIPS
1176      // Deserialize a new object from pointer found in code and write
1177      // a pointer to it to the current object. Required only for MIPS, and
1178      // omitted on the other architectures because it is fully unrolled and
1179      // would cause bloat.
1180      ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
1181      // Find a recently deserialized code object using its offset from the
1182      // current allocation point and write a pointer to it to the current
1183      // object. Required only for MIPS.
1184      ALL_SPACES(kBackref, kFromCode, kStartOfObject)
1185      ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
1186#endif
1187      // Find a recently deserialized code object using its offset from the
1188      // current allocation point and write a pointer to its first instruction
1189      // to the current code object or the instruction pointer in a function
1190      // object.
1191      ALL_SPACES(kBackref, kFromCode, kInnerPointer)
1192      ALL_SPACES(kBackrefWithSkip, kFromCode, kInnerPointer)
1193      ALL_SPACES(kBackref, kPlain, kInnerPointer)
1194      ALL_SPACES(kBackrefWithSkip, kPlain, kInnerPointer)
1195      // Find an object in the roots array and write a pointer to it to the
1196      // current object.
1197      CASE_STATEMENT(kRootArray, kPlain, kStartOfObject, 0)
1198      CASE_BODY(kRootArray, kPlain, kStartOfObject, 0)
1199      // Find an object in the partial snapshots cache and write a pointer to it
1200      // to the current object.
1201      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kStartOfObject, 0)
1202      CASE_BODY(kPartialSnapshotCache,
1203                kPlain,
1204                kStartOfObject,
1205                0)
1206      // Find an code entry in the partial snapshots cache and
1207      // write a pointer to it to the current object.
1208      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kInnerPointer, 0)
1209      CASE_BODY(kPartialSnapshotCache,
1210                kPlain,
1211                kInnerPointer,
1212                0)
1213      // Find an external reference and write a pointer to it to the current
1214      // object.
1215      CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
1216      CASE_BODY(kExternalReference,
1217                kPlain,
1218                kStartOfObject,
1219                0)
1220      // Find an external reference and write a pointer to it in the current
1221      // code object.
1222      CASE_STATEMENT(kExternalReference, kFromCode, kStartOfObject, 0)
1223      CASE_BODY(kExternalReference,
1224                kFromCode,
1225                kStartOfObject,
1226                0)
1227
1228#undef CASE_STATEMENT
1229#undef CASE_BODY
1230#undef ALL_SPACES
1231
1232      case kSkip: {
1233        int size = source_->GetInt();
1234        current = reinterpret_cast<Object**>(
1235            reinterpret_cast<intptr_t>(current) + size);
1236        break;
1237      }
1238
1239      case kNativesStringResource: {
1240        int index = source_->Get();
1241        Vector<const char> source_vector = Natives::GetRawScriptSource(index);
1242        NativesExternalStringResource* resource =
1243            new NativesExternalStringResource(isolate->bootstrapper(),
1244                                              source_vector.start(),
1245                                              source_vector.length());
1246        *current++ = reinterpret_cast<Object*>(resource);
1247        break;
1248      }
1249
1250      case kSynchronize: {
1251        // If we get here then that indicates that you have a mismatch between
1252        // the number of GC roots when serializing and deserializing.
1253        UNREACHABLE();
1254      }
1255
1256      default:
1257        UNREACHABLE();
1258    }
1259  }
1260  ASSERT_EQ(limit, current);
1261}
1262
1263
1264void SnapshotByteSink::PutInt(uintptr_t integer, const char* description) {
1265  ASSERT(integer < 1 << 22);
1266  integer <<= 2;
1267  int bytes = 1;
1268  if (integer > 0xff) bytes = 2;
1269  if (integer > 0xffff) bytes = 3;
1270  integer |= bytes;
1271  Put(static_cast<int>(integer & 0xff), "IntPart1");
1272  if (bytes > 1) Put(static_cast<int>((integer >> 8) & 0xff), "IntPart2");
1273  if (bytes > 2) Put(static_cast<int>((integer >> 16) & 0xff), "IntPart3");
1274}
1275
1276
1277Serializer::Serializer(Isolate* isolate, SnapshotByteSink* sink)
1278    : isolate_(isolate),
1279      sink_(sink),
1280      current_root_index_(0),
1281      external_reference_encoder_(new ExternalReferenceEncoder(isolate)),
1282      root_index_wave_front_(0) {
1283  // The serializer is meant to be used only to generate initial heap images
1284  // from a context in which there is only one isolate.
1285  for (int i = 0; i <= LAST_SPACE; i++) {
1286    fullness_[i] = 0;
1287  }
1288}
1289
1290
1291Serializer::~Serializer() {
1292  delete external_reference_encoder_;
1293}
1294
1295
1296void StartupSerializer::SerializeStrongReferences() {
1297  Isolate* isolate = this->isolate();
1298  // No active threads.
1299  CHECK_EQ(NULL, isolate->thread_manager()->FirstThreadStateInUse());
1300  // No active or weak handles.
1301  CHECK(isolate->handle_scope_implementer()->blocks()->is_empty());
1302  CHECK_EQ(0, isolate->global_handles()->NumberOfWeakHandles());
1303  CHECK_EQ(0, isolate->eternal_handles()->NumberOfHandles());
1304  // We don't support serializing installed extensions.
1305  CHECK(!isolate->has_installed_extensions());
1306
1307  isolate->heap()->IterateStrongRoots(this, VISIT_ONLY_STRONG);
1308}
1309
1310
1311void PartialSerializer::Serialize(Object** object) {
1312  this->VisitPointer(object);
1313  Pad();
1314}
1315
1316
1317bool Serializer::ShouldBeSkipped(Object** current) {
1318  Object** roots = isolate()->heap()->roots_array_start();
1319  return current == &roots[Heap::kStoreBufferTopRootIndex]
1320      || current == &roots[Heap::kStackLimitRootIndex]
1321      || current == &roots[Heap::kRealStackLimitRootIndex];
1322}
1323
1324
1325void Serializer::VisitPointers(Object** start, Object** end) {
1326  Isolate* isolate = this->isolate();;
1327
1328  for (Object** current = start; current < end; current++) {
1329    if (start == isolate->heap()->roots_array_start()) {
1330      root_index_wave_front_ =
1331          Max(root_index_wave_front_, static_cast<intptr_t>(current - start));
1332    }
1333    if (ShouldBeSkipped(current)) {
1334      sink_->Put(kSkip, "Skip");
1335      sink_->PutInt(kPointerSize, "SkipOneWord");
1336    } else if ((*current)->IsSmi()) {
1337      sink_->Put(kRawData + 1, "Smi");
1338      for (int i = 0; i < kPointerSize; i++) {
1339        sink_->Put(reinterpret_cast<byte*>(current)[i], "Byte");
1340      }
1341    } else {
1342      SerializeObject(*current, kPlain, kStartOfObject, 0);
1343    }
1344  }
1345}
1346
1347
1348// This ensures that the partial snapshot cache keeps things alive during GC and
1349// tracks their movement.  When it is called during serialization of the startup
1350// snapshot nothing happens.  When the partial (context) snapshot is created,
1351// this array is populated with the pointers that the partial snapshot will
1352// need. As that happens we emit serialized objects to the startup snapshot
1353// that correspond to the elements of this cache array.  On deserialization we
1354// therefore need to visit the cache array.  This fills it up with pointers to
1355// deserialized objects.
1356void SerializerDeserializer::Iterate(Isolate* isolate,
1357                                     ObjectVisitor* visitor) {
1358  if (Serializer::enabled()) return;
1359  for (int i = 0; ; i++) {
1360    if (isolate->serialize_partial_snapshot_cache_length() <= i) {
1361      // Extend the array ready to get a value from the visitor when
1362      // deserializing.
1363      isolate->PushToPartialSnapshotCache(Smi::FromInt(0));
1364    }
1365    Object** cache = isolate->serialize_partial_snapshot_cache();
1366    visitor->VisitPointers(&cache[i], &cache[i + 1]);
1367    // Sentinel is the undefined object, which is a root so it will not normally
1368    // be found in the cache.
1369    if (cache[i] == isolate->heap()->undefined_value()) {
1370      break;
1371    }
1372  }
1373}
1374
1375
1376int PartialSerializer::PartialSnapshotCacheIndex(HeapObject* heap_object) {
1377  Isolate* isolate = this->isolate();
1378
1379  for (int i = 0;
1380       i < isolate->serialize_partial_snapshot_cache_length();
1381       i++) {
1382    Object* entry = isolate->serialize_partial_snapshot_cache()[i];
1383    if (entry == heap_object) return i;
1384  }
1385
1386  // We didn't find the object in the cache.  So we add it to the cache and
1387  // then visit the pointer so that it becomes part of the startup snapshot
1388  // and we can refer to it from the partial snapshot.
1389  int length = isolate->serialize_partial_snapshot_cache_length();
1390  isolate->PushToPartialSnapshotCache(heap_object);
1391  startup_serializer_->VisitPointer(reinterpret_cast<Object**>(&heap_object));
1392  // We don't recurse from the startup snapshot generator into the partial
1393  // snapshot generator.
1394  ASSERT(length == isolate->serialize_partial_snapshot_cache_length() - 1);
1395  return length;
1396}
1397
1398
1399int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
1400  Heap* heap = isolate()->heap();
1401  if (heap->InNewSpace(heap_object)) return kInvalidRootIndex;
1402  for (int i = 0; i < root_index_wave_front_; i++) {
1403    Object* root = heap->roots_array_start()[i];
1404    if (!root->IsSmi() && root == heap_object) {
1405#if V8_TARGET_ARCH_MIPS
1406      if (from == kFromCode) {
1407        // In order to avoid code bloat in the deserializer we don't have
1408        // support for the encoding that specifies a particular root should
1409        // be written into the lui/ori instructions on MIPS.  Therefore we
1410        // should not generate such serialization data for MIPS.
1411        return kInvalidRootIndex;
1412      }
1413#endif
1414      return i;
1415    }
1416  }
1417  return kInvalidRootIndex;
1418}
1419
1420
1421// Encode the location of an already deserialized object in order to write its
1422// location into a later object.  We can encode the location as an offset from
1423// the start of the deserialized objects or as an offset backwards from the
1424// current allocation pointer.
1425void Serializer::SerializeReferenceToPreviousObject(
1426    int space,
1427    int address,
1428    HowToCode how_to_code,
1429    WhereToPoint where_to_point,
1430    int skip) {
1431  int offset = CurrentAllocationAddress(space) - address;
1432  // Shift out the bits that are always 0.
1433  offset >>= kObjectAlignmentBits;
1434  if (skip == 0) {
1435    sink_->Put(kBackref + how_to_code + where_to_point + space, "BackRefSer");
1436  } else {
1437    sink_->Put(kBackrefWithSkip + how_to_code + where_to_point + space,
1438               "BackRefSerWithSkip");
1439    sink_->PutInt(skip, "BackRefSkipDistance");
1440  }
1441  sink_->PutInt(offset, "offset");
1442}
1443
1444
1445void StartupSerializer::SerializeObject(
1446    Object* o,
1447    HowToCode how_to_code,
1448    WhereToPoint where_to_point,
1449    int skip) {
1450  CHECK(o->IsHeapObject());
1451  HeapObject* heap_object = HeapObject::cast(o);
1452
1453  int root_index;
1454  if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
1455    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
1456    return;
1457  }
1458
1459  if (address_mapper_.IsMapped(heap_object)) {
1460    int space = SpaceOfObject(heap_object);
1461    int address = address_mapper_.MappedTo(heap_object);
1462    SerializeReferenceToPreviousObject(space,
1463                                       address,
1464                                       how_to_code,
1465                                       where_to_point,
1466                                       skip);
1467  } else {
1468    if (skip != 0) {
1469      sink_->Put(kSkip, "FlushPendingSkip");
1470      sink_->PutInt(skip, "SkipDistance");
1471    }
1472
1473    // Object has not yet been serialized.  Serialize it here.
1474    ObjectSerializer object_serializer(this,
1475                                       heap_object,
1476                                       sink_,
1477                                       how_to_code,
1478                                       where_to_point);
1479    object_serializer.Serialize();
1480  }
1481}
1482
1483
1484void StartupSerializer::SerializeWeakReferences() {
1485  // This phase comes right after the partial serialization (of the snapshot).
1486  // After we have done the partial serialization the partial snapshot cache
1487  // will contain some references needed to decode the partial snapshot.  We
1488  // add one entry with 'undefined' which is the sentinel that the deserializer
1489  // uses to know it is done deserializing the array.
1490  Object* undefined = isolate()->heap()->undefined_value();
1491  VisitPointer(&undefined);
1492  isolate()->heap()->IterateWeakRoots(this, VISIT_ALL);
1493  Pad();
1494}
1495
1496
1497void Serializer::PutRoot(int root_index,
1498                         HeapObject* object,
1499                         SerializerDeserializer::HowToCode how_to_code,
1500                         SerializerDeserializer::WhereToPoint where_to_point,
1501                         int skip) {
1502  if (how_to_code == kPlain &&
1503      where_to_point == kStartOfObject &&
1504      root_index < kRootArrayNumberOfConstantEncodings &&
1505      !isolate()->heap()->InNewSpace(object)) {
1506    if (skip == 0) {
1507      sink_->Put(kRootArrayConstants + kNoSkipDistance + root_index,
1508                 "RootConstant");
1509    } else {
1510      sink_->Put(kRootArrayConstants + kHasSkipDistance + root_index,
1511                 "RootConstant");
1512      sink_->PutInt(skip, "SkipInPutRoot");
1513    }
1514  } else {
1515    if (skip != 0) {
1516      sink_->Put(kSkip, "SkipFromPutRoot");
1517      sink_->PutInt(skip, "SkipFromPutRootDistance");
1518    }
1519    sink_->Put(kRootArray + how_to_code + where_to_point, "RootSerialization");
1520    sink_->PutInt(root_index, "root_index");
1521  }
1522}
1523
1524
1525void PartialSerializer::SerializeObject(
1526    Object* o,
1527    HowToCode how_to_code,
1528    WhereToPoint where_to_point,
1529    int skip) {
1530  CHECK(o->IsHeapObject());
1531  HeapObject* heap_object = HeapObject::cast(o);
1532
1533  if (heap_object->IsMap()) {
1534    // The code-caches link to context-specific code objects, which
1535    // the startup and context serializes cannot currently handle.
1536    ASSERT(Map::cast(heap_object)->code_cache() ==
1537           heap_object->GetHeap()->empty_fixed_array());
1538  }
1539
1540  int root_index;
1541  if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) {
1542    PutRoot(root_index, heap_object, how_to_code, where_to_point, skip);
1543    return;
1544  }
1545
1546  if (ShouldBeInThePartialSnapshotCache(heap_object)) {
1547    if (skip != 0) {
1548      sink_->Put(kSkip, "SkipFromSerializeObject");
1549      sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
1550    }
1551
1552    int cache_index = PartialSnapshotCacheIndex(heap_object);
1553    sink_->Put(kPartialSnapshotCache + how_to_code + where_to_point,
1554               "PartialSnapshotCache");
1555    sink_->PutInt(cache_index, "partial_snapshot_cache_index");
1556    return;
1557  }
1558
1559  // Pointers from the partial snapshot to the objects in the startup snapshot
1560  // should go through the root array or through the partial snapshot cache.
1561  // If this is not the case you may have to add something to the root array.
1562  ASSERT(!startup_serializer_->address_mapper()->IsMapped(heap_object));
1563  // All the internalized strings that the partial snapshot needs should be
1564  // either in the root table or in the partial snapshot cache.
1565  ASSERT(!heap_object->IsInternalizedString());
1566
1567  if (address_mapper_.IsMapped(heap_object)) {
1568    int space = SpaceOfObject(heap_object);
1569    int address = address_mapper_.MappedTo(heap_object);
1570    SerializeReferenceToPreviousObject(space,
1571                                       address,
1572                                       how_to_code,
1573                                       where_to_point,
1574                                       skip);
1575  } else {
1576    if (skip != 0) {
1577      sink_->Put(kSkip, "SkipFromSerializeObject");
1578      sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
1579    }
1580    // Object has not yet been serialized.  Serialize it here.
1581    ObjectSerializer serializer(this,
1582                                heap_object,
1583                                sink_,
1584                                how_to_code,
1585                                where_to_point);
1586    serializer.Serialize();
1587  }
1588}
1589
1590
1591void Serializer::ObjectSerializer::Serialize() {
1592  int space = Serializer::SpaceOfObject(object_);
1593  int size = object_->Size();
1594
1595  sink_->Put(kNewObject + reference_representation_ + space,
1596             "ObjectSerialization");
1597  sink_->PutInt(size >> kObjectAlignmentBits, "Size in words");
1598
1599  ASSERT(code_address_map_);
1600  const char* code_name = code_address_map_->Lookup(object_->address());
1601  LOG(serializer_->isolate_,
1602      CodeNameEvent(object_->address(), sink_->Position(), code_name));
1603  LOG(serializer_->isolate_,
1604      SnapshotPositionEvent(object_->address(), sink_->Position()));
1605
1606  // Mark this object as already serialized.
1607  int offset = serializer_->Allocate(space, size);
1608  serializer_->address_mapper()->AddMapping(object_, offset);
1609
1610  // Serialize the map (first word of the object).
1611  serializer_->SerializeObject(object_->map(), kPlain, kStartOfObject, 0);
1612
1613  // Serialize the rest of the object.
1614  CHECK_EQ(0, bytes_processed_so_far_);
1615  bytes_processed_so_far_ = kPointerSize;
1616  object_->IterateBody(object_->map()->instance_type(), size, this);
1617  OutputRawData(object_->address() + size);
1618}
1619
1620
1621void Serializer::ObjectSerializer::VisitPointers(Object** start,
1622                                                 Object** end) {
1623  Object** current = start;
1624  while (current < end) {
1625    while (current < end && (*current)->IsSmi()) current++;
1626    if (current < end) OutputRawData(reinterpret_cast<Address>(current));
1627
1628    while (current < end && !(*current)->IsSmi()) {
1629      HeapObject* current_contents = HeapObject::cast(*current);
1630      int root_index = serializer_->RootIndex(current_contents, kPlain);
1631      // Repeats are not subject to the write barrier so there are only some
1632      // objects that can be used in a repeat encoding.  These are the early
1633      // ones in the root array that are never in new space.
1634      if (current != start &&
1635          root_index != kInvalidRootIndex &&
1636          root_index < kRootArrayNumberOfConstantEncodings &&
1637          current_contents == current[-1]) {
1638        ASSERT(!serializer_->isolate()->heap()->InNewSpace(current_contents));
1639        int repeat_count = 1;
1640        while (current < end - 1 && current[repeat_count] == current_contents) {
1641          repeat_count++;
1642        }
1643        current += repeat_count;
1644        bytes_processed_so_far_ += repeat_count * kPointerSize;
1645        if (repeat_count > kMaxRepeats) {
1646          sink_->Put(kRepeat, "SerializeRepeats");
1647          sink_->PutInt(repeat_count, "SerializeRepeats");
1648        } else {
1649          sink_->Put(CodeForRepeats(repeat_count), "SerializeRepeats");
1650        }
1651      } else {
1652        serializer_->SerializeObject(
1653                current_contents, kPlain, kStartOfObject, 0);
1654        bytes_processed_so_far_ += kPointerSize;
1655        current++;
1656      }
1657    }
1658  }
1659}
1660
1661
1662void Serializer::ObjectSerializer::VisitEmbeddedPointer(RelocInfo* rinfo) {
1663  int skip = OutputRawData(rinfo->target_address_address(),
1664                           kCanReturnSkipInsteadOfSkipping);
1665  HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
1666  Object* object = rinfo->target_object();
1667  serializer_->SerializeObject(object, how_to_code, kStartOfObject, skip);
1668  bytes_processed_so_far_ += rinfo->target_address_size();
1669}
1670
1671
1672void Serializer::ObjectSerializer::VisitExternalReference(Address* p) {
1673  int skip = OutputRawData(reinterpret_cast<Address>(p),
1674                           kCanReturnSkipInsteadOfSkipping);
1675  sink_->Put(kExternalReference + kPlain + kStartOfObject, "ExternalRef");
1676  sink_->PutInt(skip, "SkipB4ExternalRef");
1677  Address target = *p;
1678  sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id");
1679  bytes_processed_so_far_ += kPointerSize;
1680}
1681
1682
1683void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) {
1684  int skip = OutputRawData(rinfo->target_address_address(),
1685                           kCanReturnSkipInsteadOfSkipping);
1686  HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
1687  sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef");
1688  sink_->PutInt(skip, "SkipB4ExternalRef");
1689  Address target = rinfo->target_reference();
1690  sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id");
1691  bytes_processed_so_far_ += rinfo->target_address_size();
1692}
1693
1694
1695void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) {
1696  int skip = OutputRawData(rinfo->target_address_address(),
1697                           kCanReturnSkipInsteadOfSkipping);
1698  HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
1699  sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef");
1700  sink_->PutInt(skip, "SkipB4ExternalRef");
1701  Address target = rinfo->target_address();
1702  sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id");
1703  bytes_processed_so_far_ += rinfo->target_address_size();
1704}
1705
1706
1707void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
1708  int skip = OutputRawData(rinfo->target_address_address(),
1709                           kCanReturnSkipInsteadOfSkipping);
1710  Code* object = Code::GetCodeFromTargetAddress(rinfo->target_address());
1711  serializer_->SerializeObject(object, kFromCode, kInnerPointer, skip);
1712  bytes_processed_so_far_ += rinfo->target_address_size();
1713}
1714
1715
1716void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
1717  int skip = OutputRawData(entry_address, kCanReturnSkipInsteadOfSkipping);
1718  Code* object = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
1719  serializer_->SerializeObject(object, kPlain, kInnerPointer, skip);
1720  bytes_processed_so_far_ += kPointerSize;
1721}
1722
1723
1724void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) {
1725  int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping);
1726  Cell* object = Cell::cast(rinfo->target_cell());
1727  serializer_->SerializeObject(object, kPlain, kInnerPointer, skip);
1728}
1729
1730
1731void Serializer::ObjectSerializer::VisitExternalAsciiString(
1732    v8::String::ExternalAsciiStringResource** resource_pointer) {
1733  Address references_start = reinterpret_cast<Address>(resource_pointer);
1734  OutputRawData(references_start);
1735  for (int i = 0; i < Natives::GetBuiltinsCount(); i++) {
1736    Object* source =
1737        serializer_->isolate()->heap()->natives_source_cache()->get(i);
1738    if (!source->IsUndefined()) {
1739      ExternalAsciiString* string = ExternalAsciiString::cast(source);
1740      typedef v8::String::ExternalAsciiStringResource Resource;
1741      const Resource* resource = string->resource();
1742      if (resource == *resource_pointer) {
1743        sink_->Put(kNativesStringResource, "NativesStringResource");
1744        sink_->PutSection(i, "NativesStringResourceEnd");
1745        bytes_processed_so_far_ += sizeof(resource);
1746        return;
1747      }
1748    }
1749  }
1750  // One of the strings in the natives cache should match the resource.  We
1751  // can't serialize any other kinds of external strings.
1752  UNREACHABLE();
1753}
1754
1755
1756static Code* CloneCodeObject(HeapObject* code) {
1757  Address copy = new byte[code->Size()];
1758  OS::MemCopy(copy, code->address(), code->Size());
1759  return Code::cast(HeapObject::FromAddress(copy));
1760}
1761
1762
1763static void WipeOutRelocations(Code* code) {
1764  int mode_mask =
1765      RelocInfo::kCodeTargetMask |
1766      RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
1767      RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
1768      RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
1769  for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
1770    it.rinfo()->WipeOut();
1771  }
1772}
1773
1774
1775int Serializer::ObjectSerializer::OutputRawData(
1776    Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) {
1777  Address object_start = object_->address();
1778  int base = bytes_processed_so_far_;
1779  int up_to_offset = static_cast<int>(up_to - object_start);
1780  int to_skip = up_to_offset - bytes_processed_so_far_;
1781  int bytes_to_output = to_skip;
1782  bytes_processed_so_far_ +=  to_skip;
1783  // This assert will fail if the reloc info gives us the target_address_address
1784  // locations in a non-ascending order.  Luckily that doesn't happen.
1785  ASSERT(to_skip >= 0);
1786  bool outputting_code = false;
1787  if (to_skip != 0 && code_object_ && !code_has_been_output_) {
1788    // Output the code all at once and fix later.
1789    bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_;
1790    outputting_code = true;
1791    code_has_been_output_ = true;
1792  }
1793  if (bytes_to_output != 0 &&
1794      (!code_object_ || outputting_code)) {
1795#define RAW_CASE(index)                                                        \
1796    if (!outputting_code && bytes_to_output == index * kPointerSize &&         \
1797        index * kPointerSize == to_skip) {                                     \
1798      sink_->PutSection(kRawData + index, "RawDataFixed");                     \
1799      to_skip = 0;  /* This insn already skips. */                             \
1800    } else  /* NOLINT */
1801    COMMON_RAW_LENGTHS(RAW_CASE)
1802#undef RAW_CASE
1803    {  /* NOLINT */
1804      // We always end up here if we are outputting the code of a code object.
1805      sink_->Put(kRawData, "RawData");
1806      sink_->PutInt(bytes_to_output, "length");
1807    }
1808
1809    // To make snapshots reproducible, we need to wipe out all pointers in code.
1810    if (code_object_) {
1811      Code* code = CloneCodeObject(object_);
1812      WipeOutRelocations(code);
1813      // We need to wipe out the header fields *after* wiping out the
1814      // relocations, because some of these fields are needed for the latter.
1815      code->WipeOutHeader();
1816      object_start = code->address();
1817    }
1818
1819    const char* description = code_object_ ? "Code" : "Byte";
1820    for (int i = 0; i < bytes_to_output; i++) {
1821      sink_->PutSection(object_start[base + i], description);
1822    }
1823    if (code_object_) delete[] object_start;
1824  }
1825  if (to_skip != 0 && return_skip == kIgnoringReturn) {
1826    sink_->Put(kSkip, "Skip");
1827    sink_->PutInt(to_skip, "SkipDistance");
1828    to_skip = 0;
1829  }
1830  return to_skip;
1831}
1832
1833
1834int Serializer::SpaceOfObject(HeapObject* object) {
1835  for (int i = FIRST_SPACE; i <= LAST_SPACE; i++) {
1836    AllocationSpace s = static_cast<AllocationSpace>(i);
1837    if (object->GetHeap()->InSpace(object, s)) {
1838      ASSERT(i < kNumberOfSpaces);
1839      return i;
1840    }
1841  }
1842  UNREACHABLE();
1843  return 0;
1844}
1845
1846
1847int Serializer::Allocate(int space, int size) {
1848  CHECK(space >= 0 && space < kNumberOfSpaces);
1849  int allocation_address = fullness_[space];
1850  fullness_[space] = allocation_address + size;
1851  return allocation_address;
1852}
1853
1854
1855int Serializer::SpaceAreaSize(int space) {
1856  if (space == CODE_SPACE) {
1857    return isolate_->memory_allocator()->CodePageAreaSize();
1858  } else {
1859    return Page::kPageSize - Page::kObjectStartOffset;
1860  }
1861}
1862
1863
1864void Serializer::Pad() {
1865  // The non-branching GetInt will read up to 3 bytes too far, so we need
1866  // to pad the snapshot to make sure we don't read over the end.
1867  for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) {
1868    sink_->Put(kNop, "Padding");
1869  }
1870}
1871
1872
1873bool SnapshotByteSource::AtEOF() {
1874  if (0u + length_ - position_ > 2 * sizeof(uint32_t)) return false;
1875  for (int x = position_; x < length_; x++) {
1876    if (data_[x] != SerializerDeserializer::nop()) return false;
1877  }
1878  return true;
1879}
1880
1881} }  // namespace v8::internal
1882