Index: runtime/vm/raw_object_snapshot.cc |
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc |
index 1a90c2cdcfb20709aa2b79195f6132c1f4c9ae69..dd22de0949462e7b51c5a16800e69029da83e237 100644 |
--- a/runtime/vm/raw_object_snapshot.cc |
+++ b/runtime/vm/raw_object_snapshot.cc |
@@ -644,13 +644,12 @@ void RawClosureData::WriteTo(SnapshotWriter* writer, |
// Context scope. |
if (ptr()->context_scope_ == Object::empty_context_scope().raw()) { |
writer->WriteVMIsolateObject(kEmptyContextScopeObject); |
+ } else if (ptr()->context_scope_->ptr()->is_implicit_ || |
+ (kind == Snapshot::kAppWithJIT)) { |
+ writer->WriteObjectImpl(ptr()->context_scope_, kAsInlinedObject); |
} else { |
- if (ptr()->context_scope_->ptr()->is_implicit_) { |
- writer->WriteObjectImpl(ptr()->context_scope_, kAsInlinedObject); |
- } else { |
- // We don't write non implicit context scopes in the snapshot. |
- writer->WriteVMIsolateObject(kNullObject); |
- } |
+ // We don't write non implicit context scopes in the snapshot. |
+ writer->WriteVMIsolateObject(kNullObject); |
} |
// Parent function. |
@@ -730,7 +729,7 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader, |
func.set_kind_tag(reader->Read<uint32_t>()); |
func.set_token_pos(TokenPosition::SnapshotDecode(token_pos)); |
func.set_end_token_pos(TokenPosition::SnapshotDecode(end_token_pos)); |
- if (Snapshot::IncludesCode(kind)) { |
+ if (kind == Snapshot::kAppNoJIT) { |
func.set_usage_counter(0); |
func.set_deoptimization_counter(0); |
func.set_optimized_instruction_count(0); |
@@ -748,12 +747,23 @@ RawFunction* Function::ReadFrom(SnapshotReader* reader, |
func.raw()->from(), func.raw()->to_snapshot(), |
kAsReference); |
// Initialize all fields that are not part of the snapshot. |
- if (Snapshot::IncludesCode(kind)) { |
+ if (kind == Snapshot::kAppNoJIT) { |
func.ClearICDataArray(); |
func.ClearCode(); |
// Read the code object and fixup entry point. |
(*reader->CodeHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject); |
func.SetInstructions(*reader->CodeHandle()); |
+ } else if (kind == Snapshot::kAppWithJIT) { |
+ func.ClearICDataArray(); |
+ func.ClearCode(); |
+ (*reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference); |
+ func.set_ic_data_array(*reader->ArrayHandle()); |
+ (*reader->CodeHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject); |
+ func.set_unoptimized_code(*reader->CodeHandle()); |
+ if (!reader->CodeHandle()->IsNull()) { |
+ func.SetInstructions(*reader->CodeHandle()); |
+ func.set_was_compiled(true); |
+ } |
} else { |
bool is_optimized = func.usage_counter() != 0; |
if (is_optimized) { |
@@ -784,7 +794,7 @@ void RawFunction::WriteTo(SnapshotWriter* writer, |
intptr_t tags = writer->GetObjectTags(ptr()->owner_); |
intptr_t cid = ClassIdTag::decode(tags); |
owner_is_class = (cid == kClassCid); |
- is_in_fullsnapshot = owner_is_class ? |
+ is_in_fullsnapshot = owner_is_class ? |
Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->owner_)) : |
PatchClass::IsInFullSnapshot( |
reinterpret_cast<RawPatchClass*>(ptr()->owner_)); |
@@ -811,7 +821,7 @@ void RawFunction::WriteTo(SnapshotWriter* writer, |
writer->Write<int16_t>(ptr()->num_fixed_parameters_); |
writer->Write<int16_t>(ptr()->num_optional_parameters_); |
writer->Write<uint32_t>(ptr()->kind_tag_); |
- if (Snapshot::IncludesCode(kind)) { |
+ if (kind == Snapshot::kAppNoJIT) { |
// Omit fields used to support de/reoptimization. |
} else { |
if (is_optimized) { |
@@ -827,15 +837,16 @@ void RawFunction::WriteTo(SnapshotWriter* writer, |
// Write out all the object pointer fields. |
SnapshotWriterVisitor visitor(writer, kAsReference); |
visitor.VisitPointers(from(), to_snapshot()); |
- if (Snapshot::IncludesCode(kind)) { |
+ if (kind == Snapshot::kAppNoJIT) { |
ASSERT(ptr()->ic_data_array_ == Array::null()); |
ASSERT((ptr()->code_ == ptr()->unoptimized_code_) || |
(ptr()->unoptimized_code_ == Code::null())); |
- // Write out the code object as we are generating a precompiled snapshot. |
writer->WriteObjectImpl(ptr()->code_, kAsInlinedObject); |
+ } else if (kind == Snapshot::kAppWithJIT) { |
+ writer->WriteObjectImpl(ptr()->ic_data_array_, kAsReference); |
+ writer->WriteObjectImpl(ptr()->unoptimized_code_, kAsInlinedObject); |
} else if (is_optimized) { |
- // Write out the ic data array as the function is optimized or |
- // we are generating a precompiled snapshot. |
+ // Write out the ic data array as the function is optimized. |
writer->WriteObjectImpl(ptr()->ic_data_array_, kAsReference); |
} |
} else { |
@@ -922,6 +933,9 @@ void RawField::WriteTo(SnapshotWriter* writer, |
// For precompiled static fields, the value was already reset and |
// initializer_ now contains a Function. |
writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference); |
+ } else if (Field::ConstBit::decode(ptr()->kind_bits_)) { |
+ // Do not reset const fields. |
+ writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference); |
} else { |
// Otherwise, for static fields we write out the initial static value. |
writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference); |
@@ -1361,20 +1375,24 @@ RawCode* Code::ReadFrom(SnapshotReader* reader, |
result.set_lazy_deopt_pc_offset(-1); |
int32_t text_offset = reader->Read<int32_t>(); |
- int32_t instructions_size = reader->Read<int32_t>(); |
- uword entry_point = reader->GetInstructionsAt(text_offset); |
+ RawInstructions* instr = reinterpret_cast<RawInstructions*>( |
+ reader->GetInstructionsAt(text_offset) + kHeapObjectTag); |
+ uword entry_point = Instructions::EntryPoint(instr); |
#if defined(DEBUG) |
+ ASSERT(instr->IsMarked()); |
+ ASSERT(instr->IsVMHeapObject()); |
uword expected_check = reader->Read<uword>(); |
+ intptr_t instructions_size = Utils::RoundUp(instr->size_, |
+ OS::PreferredCodeAlignment()); |
uword actual_check = Checksum(entry_point, instructions_size); |
ASSERT(expected_check == actual_check); |
#endif |
result.StoreNonPointer(&result.raw_ptr()->entry_point_, entry_point); |
- result.StorePointer(reinterpret_cast<RawSmi*const*>( |
- &result.raw_ptr()->instructions_), |
- Smi::New(instructions_size)); |
+ result.StorePointer(&result.raw_ptr()->active_instructions_, instr); |
+ result.StorePointer(&result.raw_ptr()->instructions_, instr); |
(*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference); |
result.StorePointer(reinterpret_cast<RawObject*const*>( |
@@ -1418,9 +1436,6 @@ RawCode* Code::ReadFrom(SnapshotReader* reader, |
result.StorePointer(&result.raw_ptr()->return_address_metadata_, |
Object::null()); |
- ASSERT(result.Size() == instructions_size); |
- ASSERT(result.EntryPoint() == entry_point); |
- |
return result.raw(); |
} |
@@ -1434,9 +1449,18 @@ void RawCode::WriteTo(SnapshotWriter* writer, |
intptr_t pointer_offsets_length = |
Code::PtrOffBits::decode(ptr()->state_bits_); |
- if (pointer_offsets_length != 0) { |
- // Should only be IA32. |
- FATAL("Cannot serialize code with embedded pointers"); |
+ // Cannot serialize code with embedded pointers (IA32). |
+ ASSERT(pointer_offsets_length == 0); |
+ if (kind == Snapshot::kAppNoJIT) { |
+ // No disabled code in precompilation. |
+ ASSERT(ptr()->instructions_ == ptr()->active_instructions_); |
+ } else { |
+ ASSERT(kind == Snapshot::kAppWithJIT); |
+ // We never include optimized code in JIT precompilation. Deoptimization |
+ // requires code patching and we cannot patch code that is shared between |
+ // isolates and should not mutate memory allocated by the embedder. |
+ bool is_optimized = Code::PtrOffBits::decode(ptr()->state_bits_); |
+ ASSERT(!is_optimized); |
} |
// Write out the serialization header value for this object. |
@@ -1450,13 +1474,14 @@ void RawCode::WriteTo(SnapshotWriter* writer, |
writer->Write<int32_t>(ptr()->state_bits_); |
RawInstructions* instr = ptr()->instructions_; |
- intptr_t size = instr->ptr()->size_; |
int32_t text_offset = writer->GetInstructionsId(instr, this); |
writer->Write<int32_t>(text_offset); |
- writer->Write<int32_t>(size); |
+ |
#if defined(DEBUG) |
uword entry = ptr()->entry_point_; |
- uword check = Checksum(entry, size); |
+ intptr_t instructions_size = Utils::RoundUp(instr->size_, |
+ OS::PreferredCodeAlignment()); |
+ uword check = Checksum(entry, instructions_size); |
writer->Write<uword>(check); |
#endif |
@@ -1927,6 +1952,19 @@ RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader, |
context_scope.SetContextIndexAt(0, 0); |
context_scope.SetContextLevelAt(0, 0); |
return context_scope.raw(); |
+ } else if (kind == Snapshot::kAppWithJIT) { |
+ int32_t num_vars = reader->Read<int32_t>(); |
+ |
+ ContextScope& context_scope = ContextScope::ZoneHandle(); |
+ context_scope = reader->NewContextScope(num_vars); |
+ context_scope.set_is_implicit(false); |
+ reader->AddBackRef(object_id, &context_scope, kIsDeserialized); |
+ |
+ READ_OBJECT_FIELDS(context_scope, |
+ context_scope.raw()->from(), |
+ context_scope.raw()->to(num_vars), |
+ kAsInlinedObject); |
+ return context_scope.raw(); |
} |
UNREACHABLE(); |
return NULL; |
@@ -1957,6 +1995,23 @@ void RawContextScope::WriteTo(SnapshotWriter* writer, |
writer->WriteObjectImpl(var->type, kAsInlinedObject); |
return; |
+ } else if (kind == Snapshot::kAppWithJIT) { |
+ // Write out the serialization header value for this object. |
+ writer->WriteInlinedObjectHeader(object_id); |
+ |
+ // Write out the class and tags information. |
+ writer->WriteVMIsolateObject(kContextScopeCid); |
+ writer->WriteTags(writer->GetObjectTags(this)); |
+ |
+ // Write out is_implicit flag for the context scope. |
+ writer->Write<bool>(false); |
+ int32_t num_vars = ptr()->num_variables_; |
+ writer->Write<int32_t>(num_vars); |
+ |
+ SnapshotWriterVisitor visitor(writer, kAsInlinedObject); |
+ visitor.VisitPointers(from(), to(num_vars)); |
+ |
+ return; |
} |
UNREACHABLE(); |
} |