| Index: src/serialize.cc
|
| diff --git a/src/serialize.cc b/src/serialize.cc
|
| index 1a19ab0c502b2882f1a6b053586cdc36a2c234b8..9447fc82d9555f8da4ec20badb739a8fa4c9cf7d 100644
|
| --- a/src/serialize.cc
|
| +++ b/src/serialize.cc
|
| @@ -8,6 +8,7 @@
|
| #include "src/api.h"
|
| #include "src/base/platform/platform.h"
|
| #include "src/bootstrapper.h"
|
| +#include "src/code-stubs.h"
|
| #include "src/deoptimizer.h"
|
| #include "src/execution.h"
|
| #include "src/global-handles.h"
|
| @@ -872,7 +873,7 @@ void Deserializer::ReadChunk(Object** current,
|
| } else if (where == kAttachedReference) { \
|
| DCHECK(deserializing_user_code()); \
|
| int index = source_->GetInt(); \
|
| - new_object = attached_objects_->at(index); \
|
| + new_object = *attached_objects_->at(index); \
|
| emit_write_barrier = isolate->heap()->InNewSpace(new_object); \
|
| } else { \
|
| DCHECK(where == kBackrefWithSkip); \
|
| @@ -1137,6 +1138,10 @@ void Deserializer::ReadChunk(Object** current,
|
| // the current object.
|
| CASE_STATEMENT(kAttachedReference, kPlain, kStartOfObject, 0)
|
| CASE_BODY(kAttachedReference, kPlain, kStartOfObject, 0)
|
| + CASE_STATEMENT(kAttachedReference, kPlain, kInnerPointer, 0)
|
| + CASE_BODY(kAttachedReference, kPlain, kInnerPointer, 0)
|
| + CASE_STATEMENT(kAttachedReference, kFromCode, kInnerPointer, 0)
|
| + CASE_BODY(kAttachedReference, kFromCode, kInnerPointer, 0)
|
|
|
| #undef CASE_STATEMENT
|
| #undef CASE_BODY
|
| @@ -1314,12 +1319,12 @@ int Serializer::RootIndex(HeapObject* heap_object, HowToCode from) {
|
| // location into a later object. We can encode the location as an offset from
|
| // the start of the deserialized objects or as an offset backwards from the
|
| // current allocation pointer.
|
| -void Serializer::SerializeReferenceToPreviousObject(
|
| - int space,
|
| - int address,
|
| - HowToCode how_to_code,
|
| - WhereToPoint where_to_point,
|
| - int skip) {
|
| +void Serializer::SerializeReferenceToPreviousObject(HeapObject* heap_object,
|
| + HowToCode how_to_code,
|
| + WhereToPoint where_to_point,
|
| + int skip) {
|
| + int space = SpaceOfObject(heap_object);
|
| + int address = address_mapper_.MappedTo(heap_object);
|
| int offset = CurrentAllocationAddress(space) - address;
|
| // Shift out the bits that are always 0.
|
| offset >>= kObjectAlignmentBits;
|
| @@ -1350,12 +1355,7 @@ void StartupSerializer::SerializeObject(
|
| }
|
|
|
| if (address_mapper_.IsMapped(heap_object)) {
|
| - int space = SpaceOfObject(heap_object);
|
| - int address = address_mapper_.MappedTo(heap_object);
|
| - SerializeReferenceToPreviousObject(space,
|
| - address,
|
| - how_to_code,
|
| - where_to_point,
|
| + SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
| skip);
|
| } else {
|
| if (skip != 0) {
|
| @@ -1458,12 +1458,7 @@ void PartialSerializer::SerializeObject(
|
| DCHECK(!heap_object->IsInternalizedString());
|
|
|
| if (address_mapper_.IsMapped(heap_object)) {
|
| - int space = SpaceOfObject(heap_object);
|
| - int address = address_mapper_.MappedTo(heap_object);
|
| - SerializeReferenceToPreviousObject(space,
|
| - address,
|
| - how_to_code,
|
| - where_to_point,
|
| + SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
| skip);
|
| } else {
|
| if (skip != 0) {
|
| @@ -1787,17 +1782,32 @@ void Serializer::InitializeCodeAddressMap() {
|
| ScriptData* CodeSerializer::Serialize(Isolate* isolate,
|
| Handle<SharedFunctionInfo> info,
|
| Handle<String> source) {
|
| + base::ElapsedTimer timer;
|
| + if (FLAG_profile_deserialization) timer.Start();
|
| +
|
| // Serialize code object.
|
| List<byte> payload;
|
| ListSnapshotSink list_sink(&payload);
|
| - CodeSerializer cs(isolate, &list_sink, *source);
|
| + DebugSnapshotSink debug_sink(&list_sink);
|
| + SnapshotByteSink* sink = FLAG_trace_code_serializer
|
| + ? static_cast<SnapshotByteSink*>(&debug_sink)
|
| + : static_cast<SnapshotByteSink*>(&list_sink);
|
| + CodeSerializer cs(isolate, sink, *source);
|
| DisallowHeapAllocation no_gc;
|
| Object** location = Handle<Object>::cast(info).location();
|
| cs.VisitPointer(location);
|
| cs.Pad();
|
|
|
| SerializedCodeData data(&payload, &cs);
|
| - return data.GetScriptData();
|
| + ScriptData* script_data = data.GetScriptData();
|
| +
|
| + if (FLAG_profile_deserialization) {
|
| + double ms = timer.Elapsed().InMillisecondsF();
|
| + int length = script_data->length();
|
| + PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms);
|
| + }
|
| +
|
| + return script_data;
|
| }
|
|
|
|
|
| @@ -1818,16 +1828,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
| return;
|
| }
|
|
|
| - // TODO(yangguo) wire up stubs from stub cache.
|
| // TODO(yangguo) wire up global object.
|
| // TODO(yangguo) We cannot deal with different hash seeds yet.
|
| DCHECK(!heap_object->IsHashTable());
|
|
|
| if (address_mapper_.IsMapped(heap_object)) {
|
| - int space = SpaceOfObject(heap_object);
|
| - int address = address_mapper_.MappedTo(heap_object);
|
| - SerializeReferenceToPreviousObject(space, address, how_to_code,
|
| - where_to_point, skip);
|
| + SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point,
|
| + skip);
|
| return;
|
| }
|
|
|
| @@ -1837,7 +1844,11 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
| SerializeBuiltin(code_object, how_to_code, where_to_point, skip);
|
| return;
|
| }
|
| - // TODO(yangguo) figure out whether other code kinds can be handled smarter.
|
| + if (code_object->IsCodeStubOrIC()) {
|
| + SerializeCodeStub(code_object, how_to_code, where_to_point, skip);
|
| + return;
|
| + }
|
| + code_object->ClearInlineCaches();
|
| }
|
|
|
| if (heap_object == source_) {
|
| @@ -1845,6 +1856,14 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
| return;
|
| }
|
|
|
| + SerializeHeapObject(heap_object, how_to_code, where_to_point, skip);
|
| +}
|
| +
|
| +
|
| +void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
|
| + HowToCode how_to_code,
|
| + WhereToPoint where_to_point,
|
| + int skip) {
|
| if (heap_object->IsScript()) {
|
| // The wrapper cache uses a Foreign object to point to a global handle.
|
| // However, the object visitor expects foreign objects to point to external
|
| @@ -1856,6 +1875,13 @@ void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code,
|
| sink_->Put(kSkip, "SkipFromSerializeObject");
|
| sink_->PutInt(skip, "SkipDistanceFromSerializeObject");
|
| }
|
| +
|
| + if (FLAG_trace_code_serializer) {
|
| + PrintF("Encoding heap object: ");
|
| + heap_object->ShortPrint();
|
| + PrintF("\n");
|
| + }
|
| +
|
| // Object has not yet been serialized. Serialize it here.
|
| ObjectSerializer serializer(this, heap_object, sink_, how_to_code,
|
| where_to_point);
|
| @@ -1876,11 +1902,62 @@ void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code,
|
| int builtin_index = builtin->builtin_index();
|
| DCHECK_LT(builtin_index, Builtins::builtin_count);
|
| DCHECK_LE(0, builtin_index);
|
| +
|
| + if (FLAG_trace_code_serializer) {
|
| + PrintF("Encoding builtin: %s\n",
|
| + isolate()->builtins()->name(builtin_index));
|
| + }
|
| +
|
| sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin");
|
| sink_->PutInt(builtin_index, "builtin_index");
|
| }
|
|
|
|
|
| +void CodeSerializer::SerializeCodeStub(Code* code, HowToCode how_to_code,
|
| + WhereToPoint where_to_point, int skip) {
|
| + DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) ||
|
| + (how_to_code == kPlain && where_to_point == kInnerPointer) ||
|
| + (how_to_code == kFromCode && where_to_point == kInnerPointer));
|
| + uint32_t stub_key = code->stub_key();
|
| +
|
| + if (CodeStub::MajorKeyFromKey(stub_key) == CodeStub::NoCacheKey()) {
|
| + if (FLAG_trace_code_serializer) {
|
| + PrintF("Encoding uncacheable code stub as heap object\n");
|
| + }
|
| + SerializeHeapObject(code, how_to_code, where_to_point, skip);
|
| + return;
|
| + }
|
| +
|
| + if (skip != 0) {
|
| + sink_->Put(kSkip, "SkipFromSerializeCodeStub");
|
| + sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub");
|
| + }
|
| +
|
| + int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex;
|
| +
|
| + if (FLAG_trace_code_serializer) {
|
| + PrintF("Encoding code stub %s as %d\n",
|
| + CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false),
|
| + index);
|
| + }
|
| +
|
| + sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub");
|
| + sink_->PutInt(index, "CodeStub key");
|
| +}
|
| +
|
| +
|
| +int CodeSerializer::AddCodeStubKey(uint32_t stub_key) {
|
| + // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2).
|
| + int index = 0;
|
| + while (index < stub_keys_.length()) {
|
| + if (stub_keys_[index] == stub_key) return index;
|
| + index++;
|
| + }
|
| + stub_keys_.Add(stub_key);
|
| + return index;
|
| +}
|
| +
|
| +
|
| void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
|
| WhereToPoint where_to_point,
|
| int skip) {
|
| @@ -1889,6 +1966,10 @@ void CodeSerializer::SerializeSourceObject(HowToCode how_to_code,
|
| sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject");
|
| }
|
|
|
| + if (FLAG_trace_code_serializer) {
|
| + PrintF("Encoding source object\n");
|
| + }
|
| +
|
| DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject);
|
| sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source");
|
| sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex");
|
| @@ -1900,22 +1981,36 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
|
| Handle<String> source) {
|
| base::ElapsedTimer timer;
|
| if (FLAG_profile_deserialization) timer.Start();
|
| - SerializedCodeData scd(data, *source);
|
| - SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
| - Deserializer deserializer(&payload);
|
| - STATIC_ASSERT(NEW_SPACE == 0);
|
| - for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
| - deserializer.set_reservation(i, scd.GetReservation(i));
|
| - }
|
| -
|
| - // Prepare and register list of attached objects.
|
| - Vector<Object*> attached_objects = Vector<Object*>::New(1);
|
| - attached_objects[kSourceObjectIndex] = *source;
|
| - deserializer.SetAttachedObjects(&attached_objects);
|
|
|
| Object* root;
|
| - deserializer.DeserializePartial(isolate, &root);
|
| - deserializer.FlushICacheForNewCodeObjects();
|
| +
|
| + {
|
| + HandleScope scope(isolate);
|
| +
|
| + SerializedCodeData scd(data, *source);
|
| + SnapshotByteSource payload(scd.Payload(), scd.PayloadLength());
|
| + Deserializer deserializer(&payload);
|
| + STATIC_ASSERT(NEW_SPACE == 0);
|
| + for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
| + deserializer.set_reservation(i, scd.GetReservation(i));
|
| + }
|
| +
|
| + // Prepare and register list of attached objects.
|
| + Vector<const uint32_t> code_stub_keys = scd.CodeStubKeys();
|
| + Vector<Handle<Object> > attached_objects = Vector<Handle<Object> >::New(
|
| + code_stub_keys.length() + kCodeStubsBaseIndex);
|
| + attached_objects[kSourceObjectIndex] = source;
|
| + for (int i = 0; i < code_stub_keys.length(); i++) {
|
| + attached_objects[i + kCodeStubsBaseIndex] =
|
| + CodeStub::GetCode(isolate, code_stub_keys[i]).ToHandleChecked();
|
| + }
|
| + deserializer.SetAttachedObjects(&attached_objects);
|
| +
|
| + // Deserialize.
|
| + deserializer.DeserializePartial(isolate, &root);
|
| + deserializer.FlushICacheForNewCodeObjects();
|
| + }
|
| +
|
| if (FLAG_profile_deserialization) {
|
| double ms = timer.Elapsed().InMillisecondsF();
|
| int length = data->length();
|
| @@ -1928,18 +2023,35 @@ Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate,
|
| SerializedCodeData::SerializedCodeData(List<byte>* payload, CodeSerializer* cs)
|
| : owns_script_data_(true) {
|
| DisallowHeapAllocation no_gc;
|
| - int data_length = payload->length() + kHeaderEntries * kIntSize;
|
| + List<uint32_t>* stub_keys = cs->stub_keys();
|
| +
|
| + // Calculate sizes.
|
| + int num_stub_keys = stub_keys->length();
|
| + int stub_keys_size = stub_keys->length() * kInt32Size;
|
| + int data_length = kHeaderSize + stub_keys_size + payload->length();
|
| +
|
| + // Allocate backing store and create result data.
|
| byte* data = NewArray<byte>(data_length);
|
| DCHECK(IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment));
|
| - CopyBytes(data + kHeaderEntries * kIntSize, payload->begin(),
|
| - static_cast<size_t>(payload->length()));
|
| script_data_ = new ScriptData(data, data_length);
|
| script_data_->AcquireDataOwnership();
|
| +
|
| + // Set header values.
|
| SetHeaderValue(kCheckSumOffset, CheckSum(cs->source()));
|
| + SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys);
|
| + SetHeaderValue(kPayloadLengthOffset, payload->length());
|
| STATIC_ASSERT(NEW_SPACE == 0);
|
| for (int i = NEW_SPACE; i <= PROPERTY_CELL_SPACE; i++) {
|
| SetHeaderValue(kReservationsOffset + i, cs->CurrentAllocationAddress(i));
|
| }
|
| +
|
| + // Copy code stub keys.
|
| + CopyBytes(data + kHeaderSize, reinterpret_cast<byte*>(stub_keys->begin()),
|
| + stub_keys_size);
|
| +
|
| + // Copy serialized data.
|
| + CopyBytes(data + kHeaderSize + stub_keys_size, payload->begin(),
|
| + static_cast<size_t>(payload->length()));
|
| }
|
|
|
|
|
|
|