Index: src/serialize.cc |
diff --git a/src/serialize.cc b/src/serialize.cc |
index dc086a6ff3fe76b940022bae714de4557438ce18..89ba1be099afc6d9a295907b54d002c7711fa5f6 100644 |
--- a/src/serialize.cc |
+++ b/src/serialize.cc |
@@ -889,83 +889,88 @@ void Deserializer::ReadChunk(Object** current, |
STATIC_ASSERT((space_number & ~kSpaceMask) == 0); |
#define CASE_BODY(where, how, within, space_number_if_any) \ |
- { \ |
- bool emit_write_barrier = false; \ |
- bool current_was_incremented = false; \ |
- int space_number = space_number_if_any == kAnyOldSpace ? \ |
- (data & kSpaceMask) : space_number_if_any; \ |
- if (where == kNewObject && how == kPlain && within == kStartOfObject) {\ |
- ReadObject(space_number, current); \ |
- emit_write_barrier = (space_number == NEW_SPACE); \ |
+ { \ |
+ bool emit_write_barrier = false; \ |
+ bool current_was_incremented = false; \ |
+ int space_number = space_number_if_any == kAnyOldSpace \ |
+ ? (data & kSpaceMask) \ |
+ : space_number_if_any; \ |
+ if (where == kNewObject && how == kPlain && within == kStartOfObject) { \ |
+ ReadObject(space_number, current); \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
+ } else { \ |
+ Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
+ if (where == kNewObject) { \ |
+ ReadObject(space_number, &new_object); \ |
+ } else if (where == kRootArray) { \ |
+ int root_id = source_->GetInt(); \ |
+ new_object = isolate->heap()->roots_array_start()[root_id]; \ |
+ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
+ } else if (where == kPartialSnapshotCache) { \ |
+ int cache_index = source_->GetInt(); \ |
+ new_object = isolate->serialize_partial_snapshot_cache()[cache_index]; \ |
+ emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
+ } else if (where == kExternalReference) { \ |
+ int skip = source_->GetInt(); \ |
+ current = reinterpret_cast<Object**>( \ |
+ reinterpret_cast<Address>(current) + skip); \ |
+ int reference_id = source_->GetInt(); \ |
+ Address address = external_reference_decoder_->Decode(reference_id); \ |
+ new_object = reinterpret_cast<Object*>(address); \ |
+ } else if (where == kBackref) { \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
+ new_object = GetAddressFromEnd(data & kSpaceMask); \ |
+ } else if (where == kBuiltin) { \ |
+ int builtin_id = source_->GetInt(); \ |
+ ASSERT_LE(0, builtin_id); \ |
+ ASSERT_LT(builtin_id, Builtins::builtin_count); \ |
+ Builtins::Name name = static_cast<Builtins::Name>(builtin_id); \ |
+ new_object = isolate->builtins()->builtin(name); \ |
+ emit_write_barrier = false; \ |
+ PrintF("BUILTIN how within %d, %d\n", how, within); \ |
+ } else { \ |
+ ASSERT(where == kBackrefWithSkip); \ |
+ int skip = source_->GetInt(); \ |
+ current = reinterpret_cast<Object**>( \ |
+ reinterpret_cast<Address>(current) + skip); \ |
+ emit_write_barrier = (space_number == NEW_SPACE); \ |
+ new_object = GetAddressFromEnd(data & kSpaceMask); \ |
+ } \ |
+ if (within == kInnerPointer) { \ |
+ if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
+ Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
+ new_object = \ |
+ reinterpret_cast<Object*>(new_code_object->instruction_start()); \ |
} else { \ |
- Object* new_object = NULL; /* May not be a real Object pointer. */ \ |
- if (where == kNewObject) { \ |
- ReadObject(space_number, &new_object); \ |
- } else if (where == kRootArray) { \ |
- int root_id = source_->GetInt(); \ |
- new_object = isolate->heap()->roots_array_start()[root_id]; \ |
- emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
- } else if (where == kPartialSnapshotCache) { \ |
- int cache_index = source_->GetInt(); \ |
- new_object = isolate->serialize_partial_snapshot_cache() \ |
- [cache_index]; \ |
- emit_write_barrier = isolate->heap()->InNewSpace(new_object); \ |
- } else if (where == kExternalReference) { \ |
- int skip = source_->GetInt(); \ |
- current = reinterpret_cast<Object**>(reinterpret_cast<Address>( \ |
- current) + skip); \ |
- int reference_id = source_->GetInt(); \ |
- Address address = external_reference_decoder_-> \ |
- Decode(reference_id); \ |
- new_object = reinterpret_cast<Object*>(address); \ |
- } else if (where == kBackref) { \ |
- emit_write_barrier = (space_number == NEW_SPACE); \ |
- new_object = GetAddressFromEnd(data & kSpaceMask); \ |
- } else { \ |
- ASSERT(where == kBackrefWithSkip); \ |
- int skip = source_->GetInt(); \ |
- current = reinterpret_cast<Object**>( \ |
- reinterpret_cast<Address>(current) + skip); \ |
- emit_write_barrier = (space_number == NEW_SPACE); \ |
- new_object = GetAddressFromEnd(data & kSpaceMask); \ |
- } \ |
- if (within == kInnerPointer) { \ |
- if (space_number != CODE_SPACE || new_object->IsCode()) { \ |
- Code* new_code_object = reinterpret_cast<Code*>(new_object); \ |
- new_object = reinterpret_cast<Object*>( \ |
- new_code_object->instruction_start()); \ |
- } else { \ |
- ASSERT(space_number == CODE_SPACE); \ |
- Cell* cell = Cell::cast(new_object); \ |
- new_object = reinterpret_cast<Object*>( \ |
- cell->ValueAddress()); \ |
- } \ |
- } \ |
- if (how == kFromCode) { \ |
- Address location_of_branch_data = \ |
- reinterpret_cast<Address>(current); \ |
- Assembler::deserialization_set_special_target_at( \ |
- location_of_branch_data, \ |
- Code::cast(HeapObject::FromAddress(current_object_address)), \ |
- reinterpret_cast<Address>(new_object)); \ |
- location_of_branch_data += Assembler::kSpecialTargetSize; \ |
- current = reinterpret_cast<Object**>(location_of_branch_data); \ |
- current_was_incremented = true; \ |
- } else { \ |
- *current = new_object; \ |
- } \ |
- } \ |
- if (emit_write_barrier && write_barrier_needed) { \ |
- Address current_address = reinterpret_cast<Address>(current); \ |
- isolate->heap()->RecordWrite( \ |
- current_object_address, \ |
- static_cast<int>(current_address - current_object_address)); \ |
+ ASSERT(space_number == CODE_SPACE); \ |
+ Cell* cell = Cell::cast(new_object); \ |
+ new_object = reinterpret_cast<Object*>(cell->ValueAddress()); \ |
} \ |
- if (!current_was_incremented) { \ |
- current++; \ |
- } \ |
- break; \ |
} \ |
+ if (how == kFromCode) { \ |
+ Address location_of_branch_data = reinterpret_cast<Address>(current); \ |
+ Assembler::deserialization_set_special_target_at( \ |
+ location_of_branch_data, \ |
+ Code::cast(HeapObject::FromAddress(current_object_address)), \ |
+ reinterpret_cast<Address>(new_object)); \ |
+ location_of_branch_data += Assembler::kSpecialTargetSize; \ |
+ current = reinterpret_cast<Object**>(location_of_branch_data); \ |
+ current_was_incremented = true; \ |
+ } else { \ |
+ *current = new_object; \ |
+ } \ |
+ } \ |
+ if (emit_write_barrier && write_barrier_needed) { \ |
+ Address current_address = reinterpret_cast<Address>(current); \ |
+ isolate->heap()->RecordWrite( \ |
+ current_object_address, \ |
+ static_cast<int>(current_address - current_object_address)); \ |
+ } \ |
+ if (!current_was_incremented) { \ |
+ current++; \ |
+ } \ |
+ break; \ |
+ } |
// This generates a case and a body for the new space (which has to do extra |
// write barrier handling) and handles the other spaces with 8 fall-through |
@@ -1161,6 +1166,12 @@ void Deserializer::ReadChunk(Object** current, |
kFromCode, |
kStartOfObject, |
0) |
+ // Find a builtin and write a pointer to it to the current object. |
+ CASE_STATEMENT(kBuiltin, kPlain, kStartOfObject, 0) |
+ CASE_BODY(kBuiltin, kPlain, kStartOfObject, 0) |
+ // Find a builtin and write a pointer to it in the current code object. |
+ CASE_STATEMENT(kBuiltin, kFromCode, kInnerPointer, 0) |
+ CASE_BODY(kBuiltin, kFromCode, kInnerPointer, 0) |
#undef CASE_STATEMENT |
#undef CASE_BODY |
@@ -1717,7 +1728,7 @@ int Serializer::ObjectSerializer::OutputRawData( |
int up_to_offset = static_cast<int>(up_to - object_start); |
int to_skip = up_to_offset - bytes_processed_so_far_; |
int bytes_to_output = to_skip; |
- bytes_processed_so_far_ += to_skip; |
+ bytes_processed_so_far_ += to_skip; |
// This assert will fail if the reloc info gives us the target_address_address |
// locations in a non-ascending order. Luckily that doesn't happen. |
ASSERT(to_skip >= 0); |
@@ -1846,7 +1857,6 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
return; |
} |
- // TODO(yangguo) wire up builtins. |
// TODO(yangguo) wire up stubs from stub cache. |
// TODO(yangguo) wire up script source. |
// TODO(yangguo) wire up internalized strings |
@@ -1854,6 +1864,14 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
// TODO(yangguo) We cannot deal with different hash seeds yet. |
ASSERT(!heap_object->IsHashTable()); |
+ if (heap_object->IsCode()) { |
+ Code* code_object = Code::cast(heap_object); |
+ if (code_object->kind() == Code::BUILTIN) { |
+ SerializeBuiltin(code_object, how_to_code, where_to_point, skip); |
+ return; |
+ } |
+ } |
+ |
if (address_mapper_.IsMapped(heap_object)) { |
int space = SpaceOfObject(heap_object); |
int address = address_mapper_.MappedTo(heap_object); |
@@ -1873,6 +1891,27 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
} |
+void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, |
+ WhereToPoint where_to_point, int skip) { |
+ if (skip != 0) { |
+ sink_->Put(kSkip, "SkipFromSerializeBuiltin"); |
+ sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); |
+ } |
+ |
+ ASSERT((how_to_code == kPlain && where_to_point == kStartOfObject) || |
+ (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
+ int id = 0; |
+ do { // Look for existing builtins in the list. |
+ Code* b = isolate()->builtins()->builtin(static_cast<Builtins::Name>(id)); |
+ if (builtin == b) break; |
+ } while (++id < Builtins::builtin_count); |
+ ASSERT(id < Builtins::builtin_count); // We must have found a one. |
+ |
+ sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
+ sink_->PutInt(id, "builtin_index"); |
+} |
+ |
+ |
Object* CodeSerializer::Deserialize(Isolate* isolate, ScriptData* data) { |
SerializedCodeData scd(data); |
SnapshotByteSource payload(scd.Payload(), scd.PayloadLength()); |