Version 2.11.0-245.0.dev
Merge commit '37abbb2e3d146f83f4baf47dc5d83f1b6179e767' into 'dev'
diff --git a/.gitignore b/.gitignore
index 0ad331e..d7864e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -103,3 +103,11 @@
/generated/
/crash_logs/
/build/config/gclient_args.gni
+/pkg/front_end/testcases/old_dills/
+/logs.json
+/results.json
+/async_lazy_debug.so
+/dwarf.so
+/dwarf_obfuscate.so
+/il_tmp.txt
+
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
index a53ba28..01d0673 100755
--- a/build/mac/find_sdk.py
+++ b/build/mac/find_sdk.py
@@ -107,7 +107,7 @@
else:
sdk_dir = os.path.join(out.rstrip(), 'SDKs')
sdks = [
- re.findall('^MacOSX(10\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)
+ re.findall('^MacOSX(1[01]\.\d+)\.sdk$', s) for s in os.listdir(sdk_dir)
]
sdks = [s[0] for s in sdks if s] # [['10.5'], ['10.6']] => ['10.5', '10.6']
sdks = [
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
index 52e5a2f..cc183b9 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
@@ -77,15 +77,15 @@
MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot);
+ /// The path of the Dart logo displayed in the toolbar.
+ String get dartLogoPath => PreviewSite.dartLogoPath;
+
/// The path to the highlight.pack.js script, relative to [unitInfo].
String get highlightJsPath => PreviewSite.highlightJsPath;
/// The path to the highlight.pack.js stylesheet, relative to [unitInfo].
String get highlightStylePath => PreviewSite.highlightCssPath;
- /// The path of the Dart logo displayed in the toolbar.
- String get dartLogoPath => PreviewSite.dartLogoPath;
-
/// The path of the Material icons font.
String get materialIconsPath => PreviewSite.materialIconsPath;
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 774a398..f0c2d76 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -51,7 +51,7 @@
ObjectStore* object_store = thread->isolate()->object_store();
Zone* zone = thread->zone();
Class& cls = Class::Handle(zone, object_store->closure_class());
- ClassFinalizer::LoadClassMembers(cls);
+ cls.EnsureIsFinalized(thread);
// Make sure _Closure fields are not marked as unboxing candidates
// as they are accessed with plain loads.
@@ -88,7 +88,7 @@
// Eagerly compile Bool class, bool constants are used from within compiler.
cls = object_store->bool_class();
- ClassFinalizer::LoadClassMembers(cls);
+ cls.EnsureIsFinalized(thread);
}
static ErrorPtr BootstrapFromKernel(Thread* thread,
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 29a708a..7f91581 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -10,13 +10,14 @@
namespace dart {
static ClassPtr CreateTestClass(const char* name) {
- const String& class_name =
- String::Handle(Symbols::New(Thread::Current(), name));
+ Thread* thread = Thread::Current();
+ const String& class_name = String::Handle(Symbols::New(thread, name));
const Script& script = Script::Handle();
const Class& cls = Class::Handle(Class::New(
Library::Handle(), class_name, script, TokenPosition::kNoSource));
cls.set_interfaces(Object::empty_array());
cls.set_is_declaration_loaded();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
cls.SetFunctions(Object::empty_array());
cls.SetFields(Object::empty_array());
return cls.raw();
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 62c6dd0..41933d8 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1724,6 +1724,7 @@
}
};
+ SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
auto& dispatchers_array = Array::Handle(Z);
auto& name = String::Handle(Z);
auto& desc = Array::Handle(Z);
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 2ddd261..ef3a137 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -2472,7 +2472,11 @@
functions_->SetAt(function_index_++, function);
}
- cls.SetFunctions(*functions_);
+ {
+ Thread* thread = Thread::Current();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(*functions_);
+ }
if (cls.IsTopLevel()) {
const Library& library = Library::Handle(Z, cls.library());
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index cd1a70c..8ad542d 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -1919,7 +1919,8 @@
// Iterate over all classes, deoptimize functions.
// TODO(hausner): Could possibly be combined with RemoveOptimizedCode()
const ClassTable& class_table = *isolate_->class_table();
- Zone* zone = Thread::Current()->zone();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
CallSiteResetter resetter(zone);
Class& cls = Class::Handle(zone);
Array& functions = Array::Handle(zone);
@@ -1929,6 +1930,9 @@
const intptr_t num_classes = class_table.NumCids();
const intptr_t num_tlc_classes = class_table.NumTopLevelCids();
+ // TODO(dartbug.com/36097): Need to stop other mutators running in same IG
+ // before deoptimizing the world.
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
for (intptr_t i = 1; i < num_classes + num_tlc_classes; i++) {
const classid_t cid =
i < num_classes ? i : ClassTable::CidFromTopLevelIndex(i - num_classes);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 5aa297b..3f7e002 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -374,6 +374,7 @@
NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
type_arguments_canonicalization_mutex_(NOT_IN_PRODUCT(
"IsolateGroup::type_arguments_canonicalization_mutex_")),
+ program_lock_(new SafepointRwLock()),
active_mutators_monitor_(new Monitor()),
max_active_mutators_(Scavenger::MaxMutatorThreadCount()) {
const bool is_vm_isolate = Dart::VmIsolateNameEquals(source_->name);
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 51d50d91..68c72ed 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -435,6 +435,8 @@
Mutex* initializer_functions_mutex() { return &initializer_functions_mutex_; }
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ SafepointRwLock* program_lock() { return program_lock_.get(); }
+
static inline IsolateGroup* Current() {
Thread* thread = Thread::Current();
return thread == nullptr ? nullptr : thread->isolate_group();
@@ -725,6 +727,11 @@
Mutex initializer_functions_mutex_;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ // Ensures synchronized access to classes functions, fields and other
+ // program structure elements to accommodate concurrent modification done
+ // by multiple isolates and background compiler.
+ std::unique_ptr<SafepointRwLock> program_lock_;
+
// Allow us to ensure the number of active mutators is limited by a maximum.
std::unique_ptr<Monitor> active_mutators_monitor_;
intptr_t active_mutators_ = 0;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 567f4e1..7a7f4f6 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -734,6 +734,7 @@
}
ObjectPtr KernelLoader::LoadProgram(bool process_pending_classes) {
+ SafepointWriteRwLocker ml(thread_, thread_->isolate_group()->program_lock());
ASSERT(kernel_program_info_.constants() == Array::null());
if (!program_->is_single_program()) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b45e2f1..ba6f92c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1116,7 +1116,11 @@
cls = type_arguments_class_;
cls.set_interfaces(Object::empty_array());
cls.SetFields(Object::empty_array());
- cls.SetFunctions(Object::empty_array());
+ {
+ Thread* thread = Thread::Current();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(Object::empty_array());
+ }
cls = Class::New<Bool, RTN::Bool>(isolate);
isolate->object_store()->set_bool_class(cls);
@@ -1654,6 +1658,7 @@
// This will initialize isolate group object_store, shared by all isolates
// running in the isolate group.
ObjectStore* object_store = isolate->object_store();
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
Class& cls = Class::Handle(zone);
Type& type = Type::Handle(zone);
@@ -3000,7 +3005,11 @@
typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;
void Class::SetFunctions(const Array& value) const {
- ASSERT(Thread::Current()->IsMutatorThread());
+#if defined(DEBUG)
+ Thread* thread = Thread::Current();
+ ASSERT(thread->IsMutatorThread());
+ ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+#endif
ASSERT(!value.IsNull());
set_functions(value);
const intptr_t len = value.Length();
@@ -3020,7 +3029,11 @@
}
void Class::AddFunction(const Function& function) const {
- ASSERT(Thread::Current()->IsMutatorThread());
+#if defined(DEBUG)
+ Thread* thread = Thread::Current();
+ ASSERT(thread->IsMutatorThread());
+ ASSERT(thread->isolate_group()->program_lock()->IsCurrentThreadWriter());
+#endif
const Array& arr = Array::Handle(functions());
const Array& new_array =
Array::Handle(Array::Grow(arr, arr.Length() + 1, Heap::kOld));
@@ -3616,13 +3629,19 @@
const Function& closure_function =
Function::Handle(ImplicitClosureFunction());
const Class& owner = Class::Handle(closure_function.Owner());
- if (owner.EnsureIsFinalized(Thread::Current()) != Error::null()) {
+ Thread* thread = Thread::Current();
+ if (owner.EnsureIsFinalized(thread) != Error::null()) {
return Function::null();
}
+ IsolateGroup* group = thread->isolate_group();
Function& result =
Function::Handle(owner.LookupDynamicFunctionUnsafe(getter_name));
if (result.IsNull()) {
- result = CreateMethodExtractor(getter_name);
+ SafepointWriteRwLocker ml(thread, group->program_lock());
+ result = owner.LookupDynamicFunctionUnsafe(getter_name);
+ if (result.IsNull()) {
+ result = CreateMethodExtractor(getter_name);
+ }
}
ASSERT(result.kind() == FunctionLayout::kMethodExtractor);
return result.raw();
@@ -4288,6 +4307,10 @@
Compiler::AbortBackgroundCompilation(DeoptId::kNone,
"Class finalization while compiling");
}
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ if (is_finalized()) {
+ return Error::null();
+ }
ASSERT(thread->IsMutatorThread());
ASSERT(thread != NULL);
const Error& error =
@@ -13126,7 +13149,8 @@
const String& klass,
const Array& arguments,
const TypeArguments& type_arguments) {
- Zone* zone = Thread::Current()->zone();
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
#if defined(DART_PRECOMPILED_RUNTIME)
const String& error_str = String::Handle(
zone,
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index d46aae1..a9c2fcb 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -121,7 +121,10 @@
functions.SetAt(5, function);
// Setup the functions in the class.
- cls.SetFunctions(functions);
+ {
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(functions);
+ }
// The class can now be finalized.
cls.Finalize();
@@ -200,7 +203,11 @@
}
cls.set_interfaces(Array::empty_array());
- cls.SetFunctions(Array::empty_array());
+ {
+ SafepointWriteRwLocker ml(thread,
+ thread->isolate_group()->program_lock());
+ cls.SetFunctions(Array::empty_array());
+ }
cls.SetFields(fields);
cls.Finalize();
@@ -2516,7 +2523,10 @@
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
- cls.SetFunctions(functions);
+ {
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(functions);
+ }
Function& function = Function::Handle();
const String& function_name = String::Handle(Symbols::New(thread, "foo"));
@@ -3766,7 +3776,10 @@
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
- cls.SetFunctions(functions);
+ {
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(functions);
+ }
Function& function = Function::Handle();
const String& function_name = String::Handle(Symbols::New(thread, "foo"));
@@ -3802,7 +3815,10 @@
Function::New(parent_name, FunctionLayout::kRegularFunction, false, false,
false, false, false, cls, TokenPosition::kMinSource);
functions.SetAt(0, parent);
- cls.SetFunctions(functions);
+ {
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ cls.SetFunctions(functions);
+ }
cls.Finalize();
// Add invocation dispatcher.
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 57b2051..cdf4fac 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -57,6 +57,7 @@
const bool is_dyn_call = demangled.raw() != function_name.raw();
+ bool need_to_create_method_extractor = false;
while (!cls.IsNull()) {
if (is_dyn_call) {
// Try to find a dyn:* forwarder & return it.
@@ -82,12 +83,8 @@
function = lookup(cls, demangled_getter_name);
if (!function.IsNull()) {
if (allow_add && FLAG_lazy_dispatchers) {
- // We were looking for the getter but found a method with the same
- // name. Create a method extractor and return it.
- // The extractor does not exist yet, so using GetMethodExtractor is
- // not necessary here.
- function = function.CreateMethodExtractor(demangled);
- return function.raw();
+ need_to_create_method_extractor = true;
+ break;
} else {
return Function::null();
}
@@ -95,6 +92,13 @@
}
cls = cls.SuperClass();
}
+ if (need_to_create_method_extractor) {
+ // We were looking for the getter but found a method with the same
+ // name. Create a method extractor and return it.
+ // Use GetMethodExtractor instead of CreateMethodExtractor to ensure
+ // nobody created method extractor since we last checked under ReadRwLocker.
+ function = function.GetMethodExtractor(demangled);
+ }
return function.raw();
}
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 3435afe..601befe 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -109,27 +109,6 @@
}
#endif
-// Add function to a class and that class to the class dictionary so that
-// frame walking can be used.
-const Function& RegisterFakeFunction(const char* name, const Code& code) {
- Thread* thread = Thread::Current();
- const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
- const Script& script = Script::Handle();
- const Library& lib = Library::Handle(Library::CoreLibrary());
- const Class& owner_class = Class::Handle(
- Class::New(lib, class_name, script, TokenPosition::kNoSource));
- const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
- const Function& function = Function::ZoneHandle(Function::New(
- function_name, FunctionLayout::kRegularFunction, true, false, false,
- false, false, owner_class, TokenPosition::kMinSource));
- const Array& functions = Array::Handle(Array::New(1));
- functions.SetAt(0, function);
- owner_class.SetFunctions(functions);
- lib.AddClass(owner_class);
- function.AttachCode(code);
- return function;
-}
-
DEFINE_RUNTIME_ENTRY(RangeError, 2) {
const Instance& length = Instance::CheckedHandle(zone, arguments.ArgAt(0));
const Instance& index = Instance::CheckedHandle(zone, arguments.ArgAt(1));
@@ -1776,10 +1755,10 @@
const String& name,
const Array& descriptor) {
ASSERT(name.IsSymbol());
-
- ArgumentsDescriptor args_desc(descriptor);
Function& target_function = Function::Handle(zone);
+
if (receiver_class.EnsureIsFinalized(thread) == Error::null()) {
+ ArgumentsDescriptor args_desc(descriptor);
target_function = Resolver::ResolveDynamicForReceiverClass(receiver_class,
name, args_desc);
}
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index a09361b..9427a30 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -16,6 +16,7 @@
#include "vm/compiler/assembler/disassembler.h"
#include "vm/constants.h"
#include "vm/cpu.h"
+#include "vm/image_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/os_thread.h"
#include "vm/stack_frame.h"
@@ -95,7 +96,9 @@
static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc);
- static void PrintDartFrame(uword pc,
+ static void PrintDartFrame(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
uword fp,
uword sp,
const Function& function,
@@ -241,7 +244,29 @@
return token_pos;
}
-void SimulatorDebugger::PrintDartFrame(uword pc,
+#if defined(DART_PRECOMPILED_RUNTIME)
+static const char* ImageName(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
+ intptr_t* offset) {
+ const Image vm_image(vm_instructions);
+ const Image isolate_image(isolate_instructions);
+ if (vm_image.contains(pc)) {
+ *offset = pc - vm_instructions;
+ return kVmSnapshotInstructionsAsmSymbol;
+ } else if (isolate_image.contains(pc)) {
+ *offset = pc - isolate_instructions;
+ return kIsolateSnapshotInstructionsAsmSymbol;
+ } else {
+ *offset = 0;
+ return "<unknown>";
+ }
+}
+#endif
+
+void SimulatorDebugger::PrintDartFrame(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
uword fp,
uword sp,
const Function& function,
@@ -257,22 +282,42 @@
script.GetTokenLocation(token_pos, &line, &column);
}
OS::PrintErr(
- "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc,
+ "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
func_name.ToCString(), url.ToCString(), line, column);
+#if defined(DART_PRECOMPILED_RUNTIME)
+ intptr_t offset;
+ auto const symbol_name =
+ ImageName(vm_instructions, isolate_instructions, pc, &offset);
+ OS::PrintErr(" %s+0x%" Px "", symbol_name, offset);
+#endif
+ OS::PrintErr("\n");
}
void SimulatorDebugger::PrintBacktrace() {
- StackFrameIterator frames(
- sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(),
- ValidationPolicy::kDontValidateFrames, Thread::Current(),
- StackFrameIterator::kNoCrossThreadIteration);
+ auto const T = Thread::Current();
+ auto const Z = T->zone();
+#if defined(DART_PRECOMPILED_RUNTIME)
+ auto const vm_instructions = reinterpret_cast<uword>(
+ Dart::vm_isolate()->group()->source()->snapshot_instructions);
+ auto const isolate_instructions = reinterpret_cast<uword>(
+ T->isolate_group()->source()->snapshot_instructions);
+ OS::PrintErr("vm_instructions=0x%" Px ", isolate_instructions=0x%" Px "\n",
+ vm_instructions, isolate_instructions);
+#else
+ const uword vm_instructions = 0;
+ const uword isolate_instructions = 0;
+#endif
+ StackFrameIterator frames(sim_->get_register(FP), sim_->get_register(SP),
+ sim_->get_pc(),
+ ValidationPolicy::kDontValidateFrames, T,
+ StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL);
- Function& function = Function::Handle();
- Function& inlined_function = Function::Handle();
- Code& code = Code::Handle();
- Code& unoptimized_code = Code::Handle();
+ Function& function = Function::Handle(Z);
+ Function& inlined_function = Function::Handle(Z);
+ Code& code = Code::Handle(Z);
+ Code& unoptimized_code = Code::Handle(Z);
while (frame != NULL) {
if (frame->IsDartFrame()) {
ASSERT(!frame->is_interpreted()); // Not yet supported.
@@ -291,24 +336,33 @@
it.Advance();
if (!it.Done()) {
PrintDartFrame(
- unoptimized_pc, frame->fp(), frame->sp(), inlined_function,
+ vm_instructions, isolate_instructions, unoptimized_pc,
+ frame->fp(), frame->sp(), inlined_function,
GetApproximateTokenIndex(unoptimized_code, unoptimized_pc),
true, true);
}
}
// Print the optimized inlining frame below.
}
- PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), function,
+ PrintDartFrame(vm_instructions, isolate_instructions, frame->pc(),
+ frame->fp(), frame->sp(), function,
GetApproximateTokenIndex(code, frame->pc()),
code.is_optimized(), false);
} else {
- OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
+ OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame",
frame->pc(), frame->fp(), frame->sp(),
frame->IsEntryFrame()
? "entry"
: frame->IsExitFrame()
? "exit"
: frame->IsStubFrame() ? "stub" : "invalid");
+#if defined(DART_PRECOMPILED_RUNTIME)
+ intptr_t offset;
+ auto const symbol_name = ImageName(vm_instructions, isolate_instructions,
+ frame->pc(), &offset);
+ OS::PrintErr(" %s+0x%" Px "", symbol_name, offset);
+#endif
+ OS::PrintErr("\n");
}
frame = frames.NextFrame();
}
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 456ab1c..d7af78b 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -15,6 +15,7 @@
#include "vm/compiler/assembler/disassembler.h"
#include "vm/constants.h"
+#include "vm/image_snapshot.h"
#include "vm/native_arguments.h"
#include "vm/os_thread.h"
#include "vm/stack_frame.h"
@@ -100,7 +101,9 @@
static TokenPosition GetApproximateTokenIndex(const Code& code, uword pc);
- static void PrintDartFrame(uword pc,
+ static void PrintDartFrame(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
uword fp,
uword sp,
const Function& function,
@@ -269,7 +272,29 @@
return token_pos;
}
-void SimulatorDebugger::PrintDartFrame(uword pc,
+#if defined(DART_PRECOMPILED_RUNTIME)
+static const char* ImageName(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
+ intptr_t* offset) {
+ const Image vm_image(vm_instructions);
+ const Image isolate_image(isolate_instructions);
+ if (vm_image.contains(pc)) {
+ *offset = pc - vm_instructions;
+ return kVmSnapshotInstructionsAsmSymbol;
+ } else if (isolate_image.contains(pc)) {
+ *offset = pc - isolate_instructions;
+ return kIsolateSnapshotInstructionsAsmSymbol;
+ } else {
+ *offset = 0;
+ return "<unknown>";
+ }
+}
+#endif
+
+void SimulatorDebugger::PrintDartFrame(uword vm_instructions,
+ uword isolate_instructions,
+ uword pc,
uword fp,
uword sp,
const Function& function,
@@ -285,22 +310,42 @@
script.GetTokenLocation(token_pos, &line, &column);
}
OS::PrintErr(
- "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")\n", pc,
+ "pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s%s (%s:%" Pd ":%" Pd ")", pc,
fp, sp, is_optimized ? (is_inlined ? "inlined " : "optimized ") : "",
func_name.ToCString(), url.ToCString(), line, column);
+#if defined(DART_PRECOMPILED_RUNTIME)
+ intptr_t offset;
+ auto const symbol_name =
+ ImageName(vm_instructions, isolate_instructions, pc, &offset);
+ OS::PrintErr(" %s+0x%" Px "", symbol_name, offset);
+#endif
+ OS::PrintErr("\n");
}
void SimulatorDebugger::PrintBacktrace() {
- StackFrameIterator frames(
- sim_->get_register(FP), sim_->get_register(SP), sim_->get_pc(),
- ValidationPolicy::kDontValidateFrames, Thread::Current(),
- StackFrameIterator::kNoCrossThreadIteration);
+ auto const T = Thread::Current();
+ auto const Z = T->zone();
+#if defined(DART_PRECOMPILED_RUNTIME)
+ auto const vm_instructions = reinterpret_cast<uword>(
+ Dart::vm_isolate()->group()->source()->snapshot_instructions);
+ auto const isolate_instructions = reinterpret_cast<uword>(
+ T->isolate_group()->source()->snapshot_instructions);
+ OS::PrintErr("vm_instructions=0x%" Px ", isolate_instructions=0x%" Px "\n",
+ vm_instructions, isolate_instructions);
+#else
+ const uword vm_instructions = 0;
+ const uword isolate_instructions = 0;
+#endif
+ StackFrameIterator frames(sim_->get_register(FP), sim_->get_register(SP),
+ sim_->get_pc(),
+ ValidationPolicy::kDontValidateFrames, T,
+ StackFrameIterator::kNoCrossThreadIteration);
StackFrame* frame = frames.NextFrame();
ASSERT(frame != NULL);
- Function& function = Function::Handle();
- Function& inlined_function = Function::Handle();
- Code& code = Code::Handle();
- Code& unoptimized_code = Code::Handle();
+ Function& function = Function::Handle(Z);
+ Function& inlined_function = Function::Handle(Z);
+ Code& code = Code::Handle(Z);
+ Code& unoptimized_code = Code::Handle(Z);
while (frame != NULL) {
if (frame->IsDartFrame()) {
ASSERT(!frame->is_interpreted()); // Not yet supported.
@@ -319,24 +364,33 @@
it.Advance();
if (!it.Done()) {
PrintDartFrame(
- unoptimized_pc, frame->fp(), frame->sp(), inlined_function,
+ vm_instructions, isolate_instructions, unoptimized_pc,
+ frame->fp(), frame->sp(), inlined_function,
GetApproximateTokenIndex(unoptimized_code, unoptimized_pc),
true, true);
}
}
// Print the optimized inlining frame below.
}
- PrintDartFrame(frame->pc(), frame->fp(), frame->sp(), function,
+ PrintDartFrame(vm_instructions, isolate_instructions, frame->pc(),
+ frame->fp(), frame->sp(), function,
GetApproximateTokenIndex(code, frame->pc()),
code.is_optimized(), false);
} else {
- OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame\n",
+ OS::PrintErr("pc=0x%" Px " fp=0x%" Px " sp=0x%" Px " %s frame",
frame->pc(), frame->fp(), frame->sp(),
frame->IsEntryFrame()
? "entry"
: frame->IsExitFrame()
? "exit"
: frame->IsStubFrame() ? "stub" : "invalid");
+#if defined(DART_PRECOMPILED_RUNTIME)
+ intptr_t offset;
+ auto const symbol_name = ImageName(vm_instructions, isolate_instructions,
+ frame->pc(), &offset);
+ OS::PrintErr(" %s+0x%" Px "", symbol_name, offset);
+#endif
+ OS::PrintErr("\n");
}
frame = frames.NextFrame();
}
diff --git a/runtime/vm/stub_code_test.cc b/runtime/vm/stub_code_test.cc
new file mode 100644
index 0000000..4b8649b
--- /dev/null
+++ b/runtime/vm/stub_code_test.cc
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#include "vm/object.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+// Add function to a class and that class to the class dictionary so that
+// frame walking can be used.
+const Function& RegisterFakeFunction(const char* name, const Code& code) {
+ Thread* thread = Thread::Current();
+ const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
+ const Script& script = Script::Handle();
+ const Library& lib = Library::Handle(Library::CoreLibrary());
+ const Class& owner_class = Class::Handle(
+ Class::New(lib, class_name, script, TokenPosition::kNoSource));
+ const String& function_name = String::ZoneHandle(Symbols::New(thread, name));
+ const Function& function = Function::ZoneHandle(Function::New(
+ function_name, FunctionLayout::kRegularFunction, true, false, false,
+ false, false, owner_class, TokenPosition::kMinSource));
+ const Array& functions = Array::Handle(Array::New(1));
+ functions.SetAt(0, function);
+ {
+ SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+ owner_class.SetFunctions(functions);
+ }
+ lib.AddClass(owner_class);
+ function.AttachCode(code);
+ return function;
+}
+
+} // namespace dart
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index f70a389..83569d7 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -436,6 +436,7 @@
"snapshot_test.cc",
"source_report_test.cc",
"stack_frame_test.cc",
+ "stub_code_test.cc",
"stub_code_arm64_test.cc",
"stub_code_arm_test.cc",
"stub_code_ia32_test.cc",
diff --git a/tools/VERSION b/tools/VERSION
index e5b1b55..6dfe295 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 244
+PRERELEASE 245
PRERELEASE_PATCH 0
\ No newline at end of file