Save Initializer for field and pass into debugger to enable breakpoint setting.
Change-Id: I9f7afcdd057f161873d3c6e47cb0ce171806f301 Reviewed-on: https://dart-review.googlesource.com/c/91120 Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Zichang Guo <zichangguo@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
631c550ff9
commit
7e81f56ad7
@@ -91,9 +91,9 @@ var tests = <IsolateTest>[
|
||||
final numRanges = coverage['ranges'].length;
|
||||
expect(coverage['type'], equals('SourceReport'));
|
||||
|
||||
// Running in app_jitk mode will result in the number of ranges being 9
|
||||
// during the training run and 10 when running from the snapshot.
|
||||
expect(((numRanges == 9) || (numRanges == 10)), isTrue);
|
||||
// Running in app_jitk mode will result in the number of ranges being 10
|
||||
// during the training run and 11 when running from the snapshot.
|
||||
expect(((numRanges == 10) || (numRanges == 11)), isTrue);
|
||||
expect(coverage['ranges'][0], equals(expectedRange));
|
||||
expect(coverage['scripts'].length, 1);
|
||||
expect(
|
||||
@@ -108,7 +108,7 @@ var tests = <IsolateTest>[
|
||||
};
|
||||
coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
|
||||
expect(coverage['type'], equals('SourceReport'));
|
||||
expect(coverage['ranges'].length, numRanges + 2);
|
||||
expect(coverage['ranges'].length, numRanges + 3);
|
||||
expect(allRangesCompiled(coverage), isTrue);
|
||||
|
||||
// One function
|
||||
|
||||
@@ -31,6 +31,7 @@ List<String> expected = [
|
||||
"$file:${LINE+0}:5", // after 'code'
|
||||
|
||||
"$file:${LINE+1}:11", // on switchOnMe
|
||||
"$file:${LINE+17}:27", // on switchOnMe initializer starting '['
|
||||
"$file:${LINE+1}:22", // on length
|
||||
|
||||
"$file:${LINE+2}:10", // on 0
|
||||
|
||||
@@ -876,16 +876,16 @@ class FieldSerializationCluster : public SerializationCluster {
|
||||
s->Push(field->ptr()->value_.static_value_);
|
||||
} else {
|
||||
// Otherwise, for static fields we write out the initial static value.
|
||||
s->Push(field->ptr()->initializer_.saved_value_);
|
||||
s->Push(field->ptr()->saved_initial_value_);
|
||||
}
|
||||
} else {
|
||||
s->Push(field->ptr()->value_.offset_);
|
||||
}
|
||||
// Write out the initializer function or saved initial value.
|
||||
if (kind == Snapshot::kFullAOT) {
|
||||
s->Push(field->ptr()->initializer_.precompiled_);
|
||||
} else {
|
||||
s->Push(field->ptr()->initializer_.saved_value_);
|
||||
// Write out the initializer function
|
||||
s->Push(field->ptr()->initializer_);
|
||||
if (kind != Snapshot::kFullAOT) {
|
||||
// Write out the saved initial value
|
||||
s->Push(field->ptr()->saved_initial_value_);
|
||||
}
|
||||
if (kind != Snapshot::kFullAOT) {
|
||||
// Write out the guarded list length.
|
||||
@@ -927,16 +927,15 @@ class FieldSerializationCluster : public SerializationCluster {
|
||||
WriteField(field, value_.static_value_);
|
||||
} else {
|
||||
// Otherwise, for static fields we write out the initial static value.
|
||||
WriteField(field, initializer_.saved_value_);
|
||||
WriteField(field, saved_initial_value_);
|
||||
}
|
||||
} else {
|
||||
WriteField(field, value_.offset_);
|
||||
}
|
||||
// Write out the initializer function or saved initial value.
|
||||
if (kind == Snapshot::kFullAOT) {
|
||||
WriteField(field, initializer_.precompiled_);
|
||||
} else {
|
||||
WriteField(field, initializer_.saved_value_);
|
||||
WriteField(field, initializer_);
|
||||
if (kind != Snapshot::kFullAOT) {
|
||||
WriteField(field, saved_initial_value_);
|
||||
}
|
||||
if (kind != Snapshot::kFullAOT) {
|
||||
// Write out the guarded list length.
|
||||
|
||||
@@ -878,8 +878,8 @@ void Precompiler::AddField(const Field& field) {
|
||||
// Should not be in the middle of initialization while precompiling.
|
||||
ASSERT(value.raw() != Object::transition_sentinel().raw());
|
||||
|
||||
if (!field.HasPrecompiledInitializer() ||
|
||||
!Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) {
|
||||
if (!field.HasInitializer() ||
|
||||
!Function::Handle(Z, field.Initializer()).HasCode()) {
|
||||
if (FLAG_trace_precompiler) {
|
||||
THR_Print("Precompiling initializer for %s\n", field.ToCString());
|
||||
}
|
||||
@@ -891,7 +891,7 @@ void Precompiler::AddField(const Field& field) {
|
||||
const Function& initializer =
|
||||
Function::Handle(Z, CompileStaticInitializer(field));
|
||||
ASSERT(!initializer.IsNull());
|
||||
field.SetPrecompiledInitializer(initializer);
|
||||
field.SetInitializer(initializer);
|
||||
AddCalleesOf(initializer, gop_offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,6 +700,19 @@ RawCode* CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result->IsNull()) {
|
||||
#if !defined(PRODUCT)
|
||||
if (!function.HasOptimizedCode()) {
|
||||
isolate()->debugger()->NotifyCompilation(function);
|
||||
}
|
||||
#endif
|
||||
if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
|
||||
Disassembler::DisassembleCode(function, *result, optimized());
|
||||
} else if (FLAG_disassemble_optimized && optimized() &&
|
||||
FlowGraphPrinter::ShouldPrint(function)) {
|
||||
Disassembler::DisassembleCode(function, *result, true);
|
||||
}
|
||||
}
|
||||
// Exit the loop and the function with the correct result value.
|
||||
done = true;
|
||||
} else {
|
||||
@@ -874,17 +887,6 @@ static RawObject* CompileFunctionHelper(CompilationPipeline* pipeline,
|
||||
per_compile_timer.TotalElapsedTime());
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT)
|
||||
isolate->debugger()->NotifyCompilation(function);
|
||||
#endif
|
||||
|
||||
if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
|
||||
Disassembler::DisassembleCode(function, result, optimized);
|
||||
} else if (FLAG_disassemble_optimized && optimized &&
|
||||
FlowGraphPrinter::ShouldPrint(function)) {
|
||||
Disassembler::DisassembleCode(function, result, true);
|
||||
}
|
||||
|
||||
return result.raw();
|
||||
} else {
|
||||
Thread* const thread = Thread::Current();
|
||||
@@ -1193,9 +1195,10 @@ RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
|
||||
ASSERT(thread->IsMutatorThread());
|
||||
NoOOBMessageScope no_msg_scope(thread);
|
||||
NoReloadScope no_reload_scope(thread->isolate(), thread);
|
||||
// Under lazy compilation initializer has not yet been created, so create
|
||||
// it now, but don't bother remembering it because it won't be used again.
|
||||
ASSERT(!field.HasPrecompiledInitializer());
|
||||
if (field.HasInitializer()) {
|
||||
const Function& initializer = Function::Handle(field.Initializer());
|
||||
return DartEntry::InvokeFunction(initializer, Object::empty_array());
|
||||
}
|
||||
{
|
||||
#if defined(SUPPORT_TIMELINE)
|
||||
VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
|
||||
@@ -1698,9 +1701,8 @@ RawError* Compiler::CompileAllFunctions(const Class& cls) {
|
||||
}
|
||||
|
||||
RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
|
||||
ASSERT(field.HasPrecompiledInitializer());
|
||||
const Function& initializer =
|
||||
Function::Handle(field.PrecompiledInitializer());
|
||||
ASSERT(field.HasInitializer());
|
||||
const Function& initializer = Function::Handle(field.Initializer());
|
||||
return DartEntry::InvokeFunction(initializer, Object::empty_array());
|
||||
}
|
||||
|
||||
|
||||
@@ -2123,6 +2123,9 @@ RawFunction::Kind KernelLoader::GetFunctionType(
|
||||
RawFunction* CreateFieldInitializerFunction(Thread* thread,
|
||||
Zone* zone,
|
||||
const Field& field) {
|
||||
if (field.Initializer() != Function::null()) {
|
||||
return field.Initializer();
|
||||
}
|
||||
String& init_name = String::Handle(zone, field.name());
|
||||
init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
|
||||
|
||||
@@ -2155,9 +2158,11 @@ RawFunction* CreateFieldInitializerFunction(Thread* thread,
|
||||
initializer_owner, TokenPosition::kNoSource));
|
||||
initializer_fun.set_kernel_offset(field.kernel_offset());
|
||||
initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
|
||||
initializer_fun.set_is_debuggable(false);
|
||||
initializer_fun.set_is_reflectable(false);
|
||||
initializer_fun.set_is_inlinable(false);
|
||||
initializer_fun.set_token_pos(field.token_pos());
|
||||
initializer_fun.set_end_token_pos(field.end_token_pos());
|
||||
field.SetInitializer(initializer_fun);
|
||||
return initializer_fun.raw();
|
||||
}
|
||||
|
||||
|
||||
@@ -8481,14 +8481,13 @@ bool Field::IsUninitialized() const {
|
||||
return value.raw() == Object::sentinel().raw();
|
||||
}
|
||||
|
||||
void Field::SetPrecompiledInitializer(const Function& initializer) const {
|
||||
void Field::SetInitializer(const Function& initializer) const {
|
||||
ASSERT(IsOriginal());
|
||||
StorePointer(&raw_ptr()->initializer_.precompiled_, initializer.raw());
|
||||
StorePointer(&raw_ptr()->initializer_, initializer.raw());
|
||||
}
|
||||
|
||||
bool Field::HasPrecompiledInitializer() const {
|
||||
return raw_ptr()->initializer_.precompiled_->IsHeapObject() &&
|
||||
raw_ptr()->initializer_.precompiled_->IsFunction();
|
||||
bool Field::HasInitializer() const {
|
||||
return raw_ptr()->initializer_ != Function::null();
|
||||
}
|
||||
|
||||
RawError* Field::EvaluateInitializer() const {
|
||||
|
||||
+6
-7
@@ -3354,11 +3354,9 @@ class Field : public Object {
|
||||
|
||||
DART_WARN_UNUSED_RESULT RawError* EvaluateInitializer() const;
|
||||
|
||||
RawFunction* PrecompiledInitializer() const {
|
||||
return raw_ptr()->initializer_.precompiled_;
|
||||
}
|
||||
void SetPrecompiledInitializer(const Function& initializer) const;
|
||||
bool HasPrecompiledInitializer() const;
|
||||
RawFunction* Initializer() const { return raw_ptr()->initializer_; }
|
||||
void SetInitializer(const Function& initializer) const;
|
||||
bool HasInitializer() const;
|
||||
|
||||
// For static fields only. Constructs a closure that gets/sets the
|
||||
// field value.
|
||||
@@ -9149,8 +9147,9 @@ void Field::SetStaticValue(const Instance& value,
|
||||
ASSERT(is_static()); // Valid only for static dart fields.
|
||||
StorePointer(&raw_ptr()->value_.static_value_, value.raw());
|
||||
if (save_initial_value) {
|
||||
ASSERT(!HasPrecompiledInitializer());
|
||||
StorePointer(&raw_ptr()->initializer_.saved_value_, value.raw());
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
StorePointer(&raw_ptr()->saved_initial_value_, value.raw());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ class ClassFunctionVisitor : public ClassVisitor {
|
||||
fields_ = cls.fields();
|
||||
for (intptr_t j = 0; j < fields_.Length(); j++) {
|
||||
field_ ^= fields_.At(j);
|
||||
if (field_.is_static() && field_.HasPrecompiledInitializer()) {
|
||||
function_ ^= field_.PrecompiledInitializer();
|
||||
if (field_.is_static() && field_.HasInitializer()) {
|
||||
function_ ^= field_.Initializer();
|
||||
visitor_->Visit(function_);
|
||||
}
|
||||
}
|
||||
@@ -885,7 +885,7 @@ void ProgramVisitor::DedupInstructionsWithSameMetadata() {
|
||||
ProgramVisitor::VisitFunctions(&visitor);
|
||||
#endif // defined(DART_PRECOMPILER)
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
void ProgramVisitor::Dedup() {
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
@@ -912,7 +912,7 @@ void ProgramVisitor::Dedup() {
|
||||
DedupInstructions();
|
||||
}
|
||||
#endif
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
@@ -1013,15 +1013,13 @@ class RawField : public RawObject {
|
||||
RawInstance* static_value_; // Value for static fields.
|
||||
RawSmi* offset_; // Offset in words for instance fields.
|
||||
} value_;
|
||||
union {
|
||||
// When precompiling we need to save the static initializer function here
|
||||
// so that code for it can be generated.
|
||||
RawFunction* precompiled_; // Static initializer function - precompiling.
|
||||
// When generating script snapshots after running the application it is
|
||||
// necessary to save the initial value of static fields so that we can
|
||||
// restore the value back to the original initial value.
|
||||
RawInstance* saved_value_; // Saved initial value - static fields.
|
||||
} initializer_;
|
||||
RawFunction* initializer_; // Static initializer function.
|
||||
// When generating APPJIT snapshots after running the application it is
|
||||
// necessary to save the initial value of static fields so that we can
|
||||
// restore the value back to the original initial value.
|
||||
NOT_IN_PRECOMPILED(
|
||||
RawInstance*
|
||||
saved_initial_value_); // Saved initial value - static fields.
|
||||
RawSmi* guarded_list_length_;
|
||||
RawArray* dependent_code_;
|
||||
RawObject** to_snapshot(Snapshot::Kind kind) {
|
||||
|
||||
Reference in New Issue
Block a user