diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc index 2c75f02b0ae..545a3d37589 100644 --- a/runtime/lib/stacktrace.cc +++ b/runtime/lib/stacktrace.cc @@ -18,25 +18,35 @@ DECLARE_FLAG(bool, show_invisible_frames); static const intptr_t kDefaultStackAllocation = 8; +static StackTracePtr CreateStackTraceObject( + Zone* zone, + const GrowableObjectArray& code_list, + const GrowableArray& pc_offset_list) { + const auto& code_array = + Array::Handle(zone, Array::MakeFixedLength(code_list)); + const auto& pc_offset_array = TypedData::Handle( + zone, TypedData::New(kUintPtrCid, pc_offset_list.length())); + { + NoSafepointScope no_safepoint; + memmove(pc_offset_array.DataAddr(0), pc_offset_list.data(), + pc_offset_list.length() * kWordSize); + } + return StackTrace::New(code_array, pc_offset_array); +} + static StackTracePtr CurrentSyncStackTraceLazy(Thread* thread, intptr_t skip_frames = 1) { Zone* zone = thread->zone(); const auto& code_array = GrowableObjectArray::ZoneHandle( zone, GrowableObjectArray::New(kDefaultStackAllocation)); - const auto& pc_offset_array = GrowableObjectArray::ZoneHandle( - zone, GrowableObjectArray::New(kDefaultStackAllocation)); + GrowableArray pc_offset_array; // Collect the frames. - StackTraceUtils::CollectFramesLazy(thread, code_array, pc_offset_array, + StackTraceUtils::CollectFramesLazy(thread, code_array, &pc_offset_array, skip_frames); - const auto& code_array_fixed = - Array::Handle(zone, Array::MakeFixedLength(code_array)); - const auto& pc_offset_array_fixed = - Array::Handle(zone, Array::MakeFixedLength(pc_offset_array)); - - return StackTrace::New(code_array_fixed, pc_offset_array_fixed); + return CreateStackTraceObject(zone, code_array, pc_offset_array); } static StackTracePtr CurrentSyncStackTrace(Thread* thread, @@ -51,8 +61,8 @@ static StackTracePtr CurrentSyncStackTrace(Thread* thread, // Allocate once. const Array& code_array = Array::ZoneHandle(zone, Array::New(stack_trace_length)); - const Array& pc_offset_array = - Array::ZoneHandle(zone, Array::New(stack_trace_length)); + const TypedData& pc_offset_array = TypedData::ZoneHandle( + zone, TypedData::New(kUintPtrCid, stack_trace_length)); // Collect the frames. const intptr_t collected_frames_count = StackTraceUtils::CollectFrames( @@ -89,7 +99,7 @@ DEFINE_NATIVE_ENTRY(StackTrace_current, 0, 0) { } static void AppendFrames(const GrowableObjectArray& code_list, - const GrowableObjectArray& pc_offset_list, + GrowableArray* pc_offset_list, int skip_frames) { Thread* thread = Thread::Current(); Zone* zone = thread->zone(); @@ -98,7 +108,6 @@ static void AppendFrames(const GrowableObjectArray& code_list, StackFrame* frame = frames.NextFrame(); ASSERT(frame != NULL); // We expect to find a dart invocation frame. Code& code = Code::Handle(zone); - Smi& offset = Smi::Handle(zone); for (; frame != NULL; frame = frames.NextFrame()) { if (!frame->IsDartFrame()) { continue; @@ -109,9 +118,9 @@ static void AppendFrames(const GrowableObjectArray& code_list, } code = frame->LookupDartCode(); - offset = Smi::New(frame->pc() - code.PayloadStart()); + const intptr_t pc_offset = frame->pc() - code.PayloadStart(); code_list.Add(code); - pc_offset_list.Add(offset); + pc_offset_list->Add(pc_offset); } } @@ -119,16 +128,14 @@ static void AppendFrames(const GrowableObjectArray& code_list, // // Skips the first skip_frames Dart frames. const StackTrace& GetCurrentStackTrace(int skip_frames) { + Zone* zone = Thread::Current()->zone(); const GrowableObjectArray& code_list = - GrowableObjectArray::Handle(GrowableObjectArray::New()); - const GrowableObjectArray& pc_offset_list = - GrowableObjectArray::Handle(GrowableObjectArray::New()); - AppendFrames(code_list, pc_offset_list, skip_frames); - const Array& code_array = Array::Handle(Array::MakeFixedLength(code_list)); - const Array& pc_offset_array = - Array::Handle(Array::MakeFixedLength(pc_offset_list)); - const StackTrace& stacktrace = - StackTrace::Handle(StackTrace::New(code_array, pc_offset_array)); + GrowableObjectArray::Handle(zone, GrowableObjectArray::New()); + GrowableArray pc_offset_list; + AppendFrames(code_list, &pc_offset_list, skip_frames); + + const StackTrace& stacktrace = StackTrace::Handle( + zone, CreateStackTraceObject(zone, code_list, pc_offset_list)); return stacktrace; } diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc index 0947b58f6c6..2fc53618a96 100644 --- a/runtime/vm/code_patcher_arm.cc +++ b/runtime/vm/code_patcher_arm.cc @@ -96,9 +96,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( const Code& caller_code, const Object& data, const Code& target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); call.SetData(data); call.SetTarget(target); } else { @@ -110,9 +109,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); return call.target_entry(); } else { SwitchableCallPattern call(return_address, caller_code); @@ -122,9 +120,8 @@ uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); return call.data(); } else { SwitchableCallPattern call(return_address, caller_code); diff --git a/runtime/vm/code_patcher_arm64.cc b/runtime/vm/code_patcher_arm64.cc index b7590dbfae8..c399fd1c77c 100644 --- a/runtime/vm/code_patcher_arm64.cc +++ b/runtime/vm/code_patcher_arm64.cc @@ -132,9 +132,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( const Code& caller_code, const Object& data, const Code& target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); call.SetData(data); call.SetTarget(target); } else { @@ -146,9 +145,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); return call.target_entry(); } else { SwitchableCallPattern call(return_address, caller_code); @@ -158,9 +156,8 @@ uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCallPattern call(return_address, caller_code); + BareSwitchableCallPattern call(return_address); return call.data(); } else { SwitchableCallPattern call(return_address, caller_code); diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc index 1ba005f311e..ce1d9f2c40e 100644 --- a/runtime/vm/code_patcher_x64.cc +++ b/runtime/vm/code_patcher_x64.cc @@ -220,10 +220,8 @@ class PoolPointerCall : public ValueObject { // call target.entry call stub.entry call stub.entry class SwitchableCallBase : public ValueObject { public: - explicit SwitchableCallBase(const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - target_index_(-1), - data_index_(-1) {} + explicit SwitchableCallBase(const ObjectPool& object_pool) + : object_pool_(object_pool), target_index_(-1), data_index_(-1) {} intptr_t data_index() const { return data_index_; } intptr_t target_index() const { return target_index_; } @@ -237,7 +235,7 @@ class SwitchableCallBase : public ValueObject { } protected: - ObjectPool& object_pool_; + const ObjectPool& object_pool_; intptr_t target_index_; intptr_t data_index_; @@ -251,8 +249,9 @@ class SwitchableCallBase : public ValueObject { // monomorphic function or a stub code. class SwitchableCall : public SwitchableCallBase { public: - SwitchableCall(uword return_address, const Code& code) - : SwitchableCallBase(code) { + SwitchableCall(uword return_address, const Code& caller_code) + : SwitchableCallBase(ObjectPool::Handle(caller_code.GetObjectPool())) { + ASSERT(caller_code.ContainsInstructionAt(return_address)); uword pc = return_address; // callq RCX @@ -333,11 +332,9 @@ class SwitchableCall : public SwitchableCallBase { // of the monomorphic function or a stub entry point. class BareSwitchableCall : public SwitchableCallBase { public: - BareSwitchableCall(uword return_address, const Code& code) - : SwitchableCallBase(code) { - object_pool_ = ObjectPool::RawCast( - IsolateGroup::Current()->object_store()->global_object_pool()); - + explicit BareSwitchableCall(uword return_address) + : SwitchableCallBase(ObjectPool::Handle( + IsolateGroup::Current()->object_store()->global_object_pool())) { uword pc = return_address; // callq RCX @@ -489,9 +486,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( const Code& caller_code, const Object& data, const Code& target) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCall call(return_address, caller_code); + BareSwitchableCall call(return_address); call.SetData(data); call.SetTarget(target); } else { @@ -503,9 +499,8 @@ void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped( uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCall call(return_address, caller_code); + BareSwitchableCall call(return_address); return call.target_entry(); } else { SwitchableCall call(return_address, caller_code); @@ -515,9 +510,8 @@ uword CodePatcher::GetSwitchableCallTargetEntryAt(uword return_address, ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address, const Code& caller_code) { - ASSERT(caller_code.ContainsInstructionAt(return_address)); if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - BareSwitchableCall call(return_address, caller_code); + BareSwitchableCall call(return_address); return call.data(); } else { SwitchableCall call(return_address, caller_code); diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc index 78ae30b24ba..9e19290dbd8 100644 --- a/runtime/vm/compiler/assembler/disassembler.cc +++ b/runtime/vm/compiler/assembler/disassembler.cc @@ -457,6 +457,9 @@ void Disassembler::DisassembleCodeHelper(const char* function_fullname, void Disassembler::DisassembleCode(const Function& function, const Code& code, bool optimized) { + if (code.IsUnknownDartCode()) { + return; + } TextBuffer buffer(128); const char* function_fullname = function.ToFullyQualifiedCString(); buffer.Printf("%s", Function::KindToCString(function.kind())); diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc index e08b5485b5d..c4ed1241b1f 100644 --- a/runtime/vm/compiler/stub_code_compiler.cc +++ b/runtime/vm/compiler/stub_code_compiler.cc @@ -796,6 +796,19 @@ void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub( GenerateRangeError(assembler, /*with_fpu_regs=*/true); } +void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( + Assembler* assembler) { + __ Breakpoint(); // Marker stub. +} + +void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { + __ Breakpoint(); // Marker stub. +} + +void StubCodeCompiler::GenerateUnknownDartCodeStub(Assembler* assembler) { + __ Breakpoint(); // Marker stub. +} + } // namespace compiler } // namespace dart diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc index 0dfaa61f67d..db3bb608699 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm.cc @@ -3291,15 +3291,6 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) { CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic))); } -void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( - Assembler* assembler) { - __ bkpt(0); -} - -void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { - __ bkpt(0); -} - void StubCodeCompiler::GenerateNotLoadedStub(Assembler* assembler) { __ EnterStubFrame(); __ CallRuntime(kNotLoadedRuntimeEntry, 0); diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc index 2bbe95e9423..e5f2d4e995a 100644 --- a/runtime/vm/compiler/stub_code_compiler_arm64.cc +++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc @@ -3435,15 +3435,6 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) { __ br(R1); } -void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( - Assembler* assembler) { - __ brk(0); -} - -void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { - __ brk(0); -} - void StubCodeCompiler::GenerateNotLoadedStub(Assembler* assembler) { __ EnterStubFrame(); __ CallRuntime(kNotLoadedRuntimeEntry, 0); diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc index 229be66d710..d96a18b10ca 100644 --- a/runtime/vm/compiler/stub_code_compiler_ia32.cc +++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc @@ -2788,15 +2788,6 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) { __ int3(); // AOT only. } -void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( - Assembler* assembler) { - __ int3(); // Marker stub. -} - -void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { - __ int3(); // Marker stub. -} - void StubCodeCompiler::GenerateNotLoadedStub(Assembler* assembler) { __ EnterStubFrame(); __ CallRuntime(kNotLoadedRuntimeEntry, 0); diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc index 175ed5db396..8c4bb238788 100644 --- a/runtime/vm/compiler/stub_code_compiler_x64.cc +++ b/runtime/vm/compiler/stub_code_compiler_x64.cc @@ -3365,15 +3365,6 @@ void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) { __ jmp(RCX); } -void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub( - Assembler* assembler) { - __ int3(); -} - -void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { - __ int3(); -} - void StubCodeCompiler::GenerateNotLoadedStub(Assembler* assembler) { __ EnterStubFrame(); __ CallRuntime(kNotLoadedRuntimeEntry, 0); diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index acf1abdaf2a..16cc361277e 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -1846,7 +1846,6 @@ DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() { Code& code = Code::Handle(zone); Code& inlined_code = Code::Handle(zone); Array& deopt_frame = Array::Handle(zone); - Smi& offset = Smi::Handle(zone); Function& function = Function::Handle(zone); constexpr intptr_t kDefaultStackAllocation = 8; @@ -1854,8 +1853,7 @@ DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() { const auto& code_array = GrowableObjectArray::ZoneHandle( zone, GrowableObjectArray::New(kDefaultStackAllocation)); - const auto& pc_offset_array = GrowableObjectArray::ZoneHandle( - zone, GrowableObjectArray::New(kDefaultStackAllocation)); + GrowableArray pc_offset_array(kDefaultStackAllocation); bool has_async = false; std::function on_sync_frame = [&](StackFrame* frame) { @@ -1864,7 +1862,7 @@ DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() { &inlined_code, &deopt_frame); }; - StackTraceUtils::CollectFramesLazy(thread, code_array, pc_offset_array, + StackTraceUtils::CollectFramesLazy(thread, code_array, &pc_offset_array, /*skip_frames=*/0, &on_sync_frame, &has_async); @@ -1900,8 +1898,8 @@ DebuggerStackTrace* Debugger::CollectAsyncLazyStackTrace() { continue; } - offset ^= pc_offset_array.At(i); - const uword absolute_pc = code.PayloadStart() + offset.Value(); + const uword pc_offset = pc_offset_array[i]; + const uword absolute_pc = code.PayloadStart() + pc_offset; stack_trace->AddAsyncCausalFrame(absolute_pc, code); } @@ -2136,8 +2134,7 @@ DebuggerStackTrace* Debugger::StackTraceFrom(const class StackTrace& ex_trace) { function = code.function(); if (function.is_visible()) { ASSERT(function.ptr() == code.function()); - uword pc = - code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i)); + uword pc = code.PayloadStart() + ex_trace.PcOffsetAtFrame(i); if (code.is_optimized() && ex_trace.expand_inlined()) { // Traverse inlined frames. for (InlinedFunctionsIterator it(code, pc); !it.Done(); diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc index a818df9259c..35df76376ae 100644 --- a/runtime/vm/dwarf.cc +++ b/runtime/vm/dwarf.cc @@ -146,7 +146,7 @@ void Dwarf::AddCode(const Code& orig_code, const char* name) { // Dwarf object (which is currently true). Otherwise, need to copy. code_to_name_.Insert({&code, name}); - if (code.IsFunctionCode()) { + if (code.IsFunctionCode() && !code.IsUnknownDartCode()) { const Function& function = Function::Handle(zone_, code.function()); AddFunction(function); } @@ -364,7 +364,7 @@ void Dwarf::WriteConcreteFunctions(DwarfWriteStream* stream) { for (intptr_t i = 0; i < codes_.length(); i++) { const Code& code = *(codes_[i]); RELEASE_ASSERT(!code.IsNull()); - if (!code.IsFunctionCode()) { + if (!code.IsFunctionCode() || code.IsUnknownDartCode()) { continue; } diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index e9464e3b647..1d767507c73 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -35,7 +35,7 @@ class StackTraceBuilder : public ValueObject { StackTraceBuilder() {} virtual ~StackTraceBuilder() {} - virtual void AddFrame(const Object& code, const Smi& offset) = 0; + virtual void AddFrame(const Object& code, uword pc_offset) = 0; }; class PreallocatedStackTraceBuilder : public StackTraceBuilder { @@ -50,7 +50,7 @@ class PreallocatedStackTraceBuilder : public StackTraceBuilder { } ~PreallocatedStackTraceBuilder() {} - virtual void AddFrame(const Object& code, const Smi& offset); + void AddFrame(const Object& code, uword pc_offset) override; private: static const int kNumTopframes = StackTrace::kPreallocatedStackdepth / 2; @@ -63,11 +63,10 @@ class PreallocatedStackTraceBuilder : public StackTraceBuilder { }; void PreallocatedStackTraceBuilder::AddFrame(const Object& code, - const Smi& offset) { + uword pc_offset) { if (cur_index_ >= StackTrace::kPreallocatedStackdepth) { // The number of frames is overflowing the preallocated stack trace object. Object& frame_code = Object::Handle(); - Smi& frame_offset = Smi::Handle(); intptr_t start = StackTrace::kPreallocatedStackdepth - (kNumTopframes - 1); intptr_t null_slot = start - 2; // We are going to drop one frame. @@ -80,20 +79,19 @@ void PreallocatedStackTraceBuilder::AddFrame(const Object& code, dropped_frames_++; } // Encode the number of dropped frames into the pc offset. - frame_offset = Smi::New(dropped_frames_); - stacktrace_.SetPcOffsetAtFrame(null_slot, frame_offset); + stacktrace_.SetPcOffsetAtFrame(null_slot, dropped_frames_); // Move frames one slot down so that we can accommodate the new frame. for (intptr_t i = start; i < StackTrace::kPreallocatedStackdepth; i++) { intptr_t prev = (i - 1); frame_code = stacktrace_.CodeAtFrame(i); - frame_offset = stacktrace_.PcOffsetAtFrame(i); + const uword frame_offset = stacktrace_.PcOffsetAtFrame(i); stacktrace_.SetCodeAtFrame(prev, frame_code); stacktrace_.SetPcOffsetAtFrame(prev, frame_offset); } cur_index_ = (StackTrace::kPreallocatedStackdepth - 1); } stacktrace_.SetCodeAtFrame(cur_index_, code); - stacktrace_.SetPcOffsetAtFrame(cur_index_, offset); + stacktrace_.SetPcOffsetAtFrame(cur_index_, pc_offset); cur_index_ += 1; } @@ -104,15 +102,14 @@ static void BuildStackTrace(StackTraceBuilder* builder) { StackFrame* frame = frames.NextFrame(); ASSERT(frame != NULL); // We expect to find a dart invocation frame. Code& code = Code::Handle(); - Smi& offset = Smi::Handle(); for (; frame != NULL; frame = frames.NextFrame()) { if (!frame->IsDartFrame()) { continue; } code = frame->LookupDartCode(); ASSERT(code.ContainsInstructionAt(frame->pc())); - offset = Smi::New(frame->pc() - code.PayloadStart()); - builder->AddFrame(code, offset); + const uword pc_offset = frame->pc() - code.PayloadStart(); + builder->AddFrame(code, pc_offset); } } diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc index c2b70142fc7..1c45ff9f685 100644 --- a/runtime/vm/instructions_arm.cc +++ b/runtime/vm/instructions_arm.cc @@ -263,10 +263,9 @@ void ICCallPattern::SetTargetCode(const Code& target_code) const { object_pool_.SetObjectAt(target_pool_index_, target_code); } -SwitchableCallPatternBase::SwitchableCallPatternBase(const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - data_pool_index_(-1), - target_pool_index_(-1) {} +SwitchableCallPatternBase::SwitchableCallPatternBase( + const ObjectPool& object_pool) + : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {} ObjectPtr SwitchableCallPatternBase::data() const { return object_pool_.ObjectAt(data_pool_index_); @@ -278,7 +277,7 @@ void SwitchableCallPatternBase::SetData(const Object& data) const { } SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) - : SwitchableCallPatternBase(code) { + : SwitchableCallPatternBase(ObjectPool::Handle(code.GetObjectPool())) { ASSERT(code.ContainsInstructionAt(pc)); // Last instruction: blx lr. ASSERT(*(reinterpret_cast(pc) - 1) == 0xe12fff3e); @@ -302,9 +301,9 @@ void SwitchableCallPattern::SetTarget(const Code& target) const { object_pool_.SetObjectAt(target_pool_index_, target); } -BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc, const Code& code) - : SwitchableCallPatternBase(code) { - ASSERT(code.ContainsInstructionAt(pc)); +BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc) + : SwitchableCallPatternBase(ObjectPool::Handle( + IsolateGroup::Current()->object_store()->global_object_pool())) { // Last instruction: blx lr. ASSERT(*(reinterpret_cast(pc) - 1) == 0xe12fff3e); diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h index 7b7b43bde3d..a1e1f9b3d5d 100644 --- a/runtime/vm/instructions_arm.h +++ b/runtime/vm/instructions_arm.h @@ -131,7 +131,7 @@ class NativeCallPattern : public ValueObject { // call target.entry call stub.entry call stub.entry class SwitchableCallPatternBase : public ValueObject { public: - explicit SwitchableCallPatternBase(const Code& code); + explicit SwitchableCallPatternBase(const ObjectPool& object_pool); ObjectPtr data() const; void SetData(const Object& data) const; @@ -166,7 +166,7 @@ class SwitchableCallPattern : public SwitchableCallPatternBase { // of the monomorphic function or a stub entry point. class BareSwitchableCallPattern : public SwitchableCallPatternBase { public: - BareSwitchableCallPattern(uword pc, const Code& code); + explicit BareSwitchableCallPattern(uword pc); uword target_entry() const; void SetTarget(const Code& target) const; diff --git a/runtime/vm/instructions_arm64.cc b/runtime/vm/instructions_arm64.cc index a38a07ea9c6..d1935106a1d 100644 --- a/runtime/vm/instructions_arm64.cc +++ b/runtime/vm/instructions_arm64.cc @@ -397,10 +397,9 @@ void ICCallPattern::SetTargetCode(const Code& target) const { // No need to flush the instruction cache, since the code is not modified. } -SwitchableCallPatternBase::SwitchableCallPatternBase(const Code& code) - : object_pool_(ObjectPool::Handle(code.GetObjectPool())), - data_pool_index_(-1), - target_pool_index_(-1) {} +SwitchableCallPatternBase::SwitchableCallPatternBase( + const ObjectPool& object_pool) + : object_pool_(object_pool), data_pool_index_(-1), target_pool_index_(-1) {} ObjectPtr SwitchableCallPatternBase::data() const { return object_pool_.ObjectAt(data_pool_index_); @@ -412,7 +411,7 @@ void SwitchableCallPatternBase::SetData(const Object& data) const { } SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code) - : SwitchableCallPatternBase(code) { + : SwitchableCallPatternBase(ObjectPool::Handle(code.GetObjectPool())) { ASSERT(code.ContainsInstructionAt(pc)); // Last instruction: blr lr. ASSERT(*(reinterpret_cast(pc) - 1) == 0xd63f03c0); @@ -438,9 +437,9 @@ void SwitchableCallPattern::SetTarget(const Code& target) const { object_pool_.SetObjectAt(target_pool_index_, target); } -BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc, const Code& code) - : SwitchableCallPatternBase(code) { - ASSERT(code.ContainsInstructionAt(pc)); +BareSwitchableCallPattern::BareSwitchableCallPattern(uword pc) + : SwitchableCallPatternBase(ObjectPool::Handle( + IsolateGroup::Current()->object_store()->global_object_pool())) { // Last instruction: blr lr. ASSERT(*(reinterpret_cast(pc) - 1) == 0xd63f03c0); diff --git a/runtime/vm/instructions_arm64.h b/runtime/vm/instructions_arm64.h index ae755397827..b4505229436 100644 --- a/runtime/vm/instructions_arm64.h +++ b/runtime/vm/instructions_arm64.h @@ -141,7 +141,7 @@ class NativeCallPattern : public ValueObject { // call target.entry call stub.entry call stub.entry class SwitchableCallPatternBase : public ValueObject { public: - explicit SwitchableCallPatternBase(const Code& code); + explicit SwitchableCallPatternBase(const ObjectPool& object_pool); ObjectPtr data() const; void SetData(const Object& data) const; @@ -176,7 +176,7 @@ class SwitchableCallPattern : public SwitchableCallPatternBase { // of the monomorphic function or a stub entry point. class BareSwitchableCallPattern : public SwitchableCallPatternBase { public: - BareSwitchableCallPattern(uword pc, const Code& code); + explicit BareSwitchableCallPattern(uword pc); uword target_entry() const; void SetTarget(const Code& target) const; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 1186974ea44..286f4f17522 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -75,7 +75,7 @@ namespace dart { -DEFINE_FLAG(int, +DEFINE_FLAG(uint64_t, huge_method_cutoff_in_code_size, 200000, "Huge method cutoff in unoptimized code size (in bytes)."); @@ -1059,6 +1059,11 @@ void Object::Init(IsolateGroup* isolate_group) { cls.set_is_declaration_loaded(); cls.set_is_type_finalized(); + cls = Class::New(isolate_group); + cls.set_is_allocate_finalized(); + cls.set_is_declaration_loaded(); + cls.set_is_type_finalized(); + cls = dynamic_class_; *dynamic_type_ = Type::New(cls, Object::null_type_arguments(), Nullability::kNullable); @@ -1365,6 +1370,12 @@ void Object::FinalizeVMIsolate(IsolateGroup* isolate_group) { cls = isolate_group->class_table()->At(kForwardingCorpse); cls.set_name(Symbols::ForwardingCorpse()); +#if defined(DART_PRECOMPILER) + const auto& function = + Function::Handle(StubCode::UnknownDartCode().function()); + function.set_name(Symbols::OptimizedOut()); +#endif // defined(DART_PRECOMPILER) + { ASSERT(isolate_group == Dart::vm_isolate_group()); Thread* thread = Thread::Current(); @@ -16773,7 +16784,8 @@ void Code::NotifyCodeObservers(const char* name, #endif // !defined(DART_PRECOMPILED_RUNTIME) bool Code::SlowFindRawCodeVisitor::FindObject(ObjectPtr raw_obj) const { - return UntaggedCode::ContainsPC(raw_obj, pc_); + return UntaggedCode::ContainsPC(raw_obj, pc_) && + !Code::IsUnknownDartCode(Code::RawCast(raw_obj)); } CodePtr Code::LookupCodeInIsolateGroup(IsolateGroup* isolate_group, uword pc) { @@ -16928,6 +16940,10 @@ bool Code::IsFunctionCode() const { return OwnerClassId() == kFunctionCid; } +bool Code::IsUnknownDartCode(CodePtr code) { + return code == StubCode::UnknownDartCode().ptr(); +} + void Code::DisableDartCode() const { SafepointOperationScope safepoint(Thread::Current()); ASSERT(IsFunctionCode()); @@ -17044,6 +17060,41 @@ void Code::DumpSourcePositions(bool relative_addresses) const { reader.DumpSourcePositions(relative_addresses ? 0 : PayloadStart()); } +bool Code::CanBeOmittedFromAOTSnapshot() const { + NoSafepointScope no_safepoint; + + // Code objects are stored in stack frames if not use_bare_instructions. + // Code objects are used by stack traces if not dwarf_stack_traces. + if (!FLAG_precompiled_mode || !FLAG_use_bare_instructions || + !FLAG_dwarf_stack_traces_mode) { + return false; + } + // Only omit Code objects corresponding to Dart functions. + if (!IsFunctionCode()) { + return false; + } + // Retain Code object if it has exception handlers or PC descriptors. + if ((exception_handlers() != Object::empty_exception_handlers().ptr()) || + (pc_descriptors() != Object::empty_descriptors().ptr())) { + return false; + } + if (!owner()->IsHeapObject()) { + // Can drop Code if precompiler dropped the Function and only left Smi + // classId. + return true; + } + // Retain Code objects corresponding to: + // * invisible functions (to filter them from stack traces); + // * async/async* closures (to construct async stacks). + // * native functions (to find native implementation). + const auto& func = Function::Handle(function()); + if (!func.is_visible() || func.is_native() || func.IsAsyncClosure() || + func.IsAsyncGenClosure()) { + return false; + } + return true; +} + intptr_t Context::GetLevel() const { intptr_t level = 0; Context& parent_ctx = Context::Handle(parent()); @@ -24666,15 +24717,17 @@ void StackTrace::SetCodeAtFrame(intptr_t frame_index, code_array.SetAt(frame_index, code); } -SmiPtr StackTrace::PcOffsetAtFrame(intptr_t frame_index) const { - const Array& pc_offset_array = Array::Handle(untag()->pc_offset_array()); - return static_cast(pc_offset_array.At(frame_index)); +uword StackTrace::PcOffsetAtFrame(intptr_t frame_index) const { + const TypedData& pc_offset_array = + TypedData::Handle(untag()->pc_offset_array()); + return pc_offset_array.GetUintPtr(frame_index * kWordSize); } void StackTrace::SetPcOffsetAtFrame(intptr_t frame_index, - const Smi& pc_offset) const { - const Array& pc_offset_array = Array::Handle(untag()->pc_offset_array()); - pc_offset_array.SetAt(frame_index, pc_offset); + uword pc_offset) const { + const TypedData& pc_offset_array = + TypedData::Handle(untag()->pc_offset_array()); + pc_offset_array.SetUintPtr(frame_index * kWordSize, pc_offset); } void StackTrace::set_async_link(const StackTrace& async_link) const { @@ -24685,7 +24738,7 @@ void StackTrace::set_code_array(const Array& code_array) const { untag()->set_code_array(code_array.ptr()); } -void StackTrace::set_pc_offset_array(const Array& pc_offset_array) const { +void StackTrace::set_pc_offset_array(const TypedData& pc_offset_array) const { untag()->set_pc_offset_array(pc_offset_array.ptr()); } @@ -24698,7 +24751,7 @@ bool StackTrace::expand_inlined() const { } StackTracePtr StackTrace::New(const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, Heap::Space space) { StackTrace& result = StackTrace::Handle(); { @@ -24715,7 +24768,7 @@ StackTracePtr StackTrace::New(const Array& code_array, } StackTracePtr StackTrace::New(const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, const StackTrace& async_link, bool skip_sync_start_in_parent_stack, Heap::Space space) { @@ -24902,9 +24955,8 @@ const char* StackTrace::ToCString() const { if ((i < (stack_trace.Length() - 1)) && (stack_trace.CodeAtFrame(i + 1) != Code::null())) { buffer.AddString("...\n...\n"); - ASSERT(stack_trace.PcOffsetAtFrame(i) != Smi::null()); // To account for gap frames. - frame_index += Smi::Value(stack_trace.PcOffsetAtFrame(i)); + frame_index += stack_trace.PcOffsetAtFrame(i); } continue; } @@ -24917,7 +24969,7 @@ const char* StackTrace::ToCString() const { continue; } - intptr_t pc_offset = Smi::Value(stack_trace.PcOffsetAtFrame(i)); + const uword pc_offset = stack_trace.PcOffsetAtFrame(i); ASSERT(code_object.IsCode()); code ^= code_object.ptr(); ASSERT(code.IsFunctionCode()); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 5cf9f6cfb1b..33d8942b732 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5970,6 +5970,7 @@ class Code : public Object { uword PayloadStart() const { return PayloadStartOf(ptr()); } static uword PayloadStartOf(const CodePtr code) { #if defined(DART_PRECOMPILED_RUNTIME) + if (IsUnknownDartCode(code)) return 0; const uword entry_offset = HasMonomorphicEntry(code) ? Instructions::kPolymorphicEntryOffsetAOT : 0; @@ -6015,9 +6016,10 @@ class Code : public Object { } // Returns the size of [instructions()]. - intptr_t Size() const { return PayloadSizeOf(ptr()); } - static intptr_t PayloadSizeOf(const CodePtr code) { + uword Size() const { return PayloadSizeOf(ptr()); } + static uword PayloadSizeOf(const CodePtr code) { #if defined(DART_PRECOMPILED_RUNTIME) + if (IsUnknownDartCode(code)) return kUwordMax; return code->untag()->instructions_length_; #else return Instructions::Size(InstructionsOf(code)); @@ -6347,6 +6349,11 @@ class Code : public Object { bool IsTypeTestStubCode() const; bool IsFunctionCode() const; + // Returns true if this Code object represents + // Dart function code without any additional information. + bool IsUnknownDartCode() const { return IsUnknownDartCode(ptr()); } + static bool IsUnknownDartCode(CodePtr code); + void DisableDartCode() const; void DisableStubCode() const; @@ -6371,6 +6378,11 @@ class Code : public Object { untag()->set_object_pool(object_pool); } + // Returns true if given Code object can be omitted from + // the AOT snapshot (when corresponding instructions are + // included). + bool CanBeOmittedFromAOTSnapshot() const; + private: void set_state_bits(intptr_t bits) const; @@ -10803,9 +10815,9 @@ class StackTrace : public Instance { ObjectPtr CodeAtFrame(intptr_t frame_index) const; void SetCodeAtFrame(intptr_t frame_index, const Object& code) const; - ArrayPtr pc_offset_array() const { return untag()->pc_offset_array(); } - SmiPtr PcOffsetAtFrame(intptr_t frame_index) const; - void SetPcOffsetAtFrame(intptr_t frame_index, const Smi& pc_offset) const; + TypedDataPtr pc_offset_array() const { return untag()->pc_offset_array(); } + uword PcOffsetAtFrame(intptr_t frame_index) const; + void SetPcOffsetAtFrame(intptr_t frame_index, uword pc_offset) const; bool skip_sync_start_in_parent_stack() const; void set_skip_sync_start_in_parent_stack(bool value) const; @@ -10828,18 +10840,18 @@ class StackTrace : public Instance { return RoundedAllocationSize(sizeof(UntaggedStackTrace)); } static StackTracePtr New(const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, Heap::Space space = Heap::kNew); static StackTracePtr New(const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, const StackTrace& async_link, bool skip_sync_start_in_parent_stack, Heap::Space space = Heap::kNew); private: void set_code_array(const Array& code_array) const; - void set_pc_offset_array(const Array& pc_offset_array) const; + void set_pc_offset_array(const TypedData& pc_offset_array) const; bool expand_inlined() const; FINAL_HEAP_OBJECT_IMPLEMENTATION(StackTrace, Instance); diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc index 8fc322a687b..0b7cd00270c 100644 --- a/runtime/vm/object_graph.cc +++ b/runtime/vm/object_graph.cc @@ -963,7 +963,11 @@ class Pass2Visitor : public ObjectVisitor, ScrubAndWriteUtf8(static_cast(obj)->untag()->name_); } else if (cid == kCodeCid) { ObjectPtr owner = static_cast(obj)->untag()->owner_; - if (owner->IsFunction()) { + if (!owner->IsHeapObject()) { + // Precompiler removed owner object from the snapshot, + // only leaving Smi classId. + writer_->WriteUnsigned(kNoData); + } else if (owner->IsFunction()) { writer_->WriteUnsigned(kNameData); ScrubAndWriteUtf8(static_cast(owner)->untag()->name_); } else if (owner->IsClass()) { diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc index feb4803e2c2..57343da7109 100644 --- a/runtime/vm/object_store.cc +++ b/runtime/vm/object_store.cc @@ -53,8 +53,9 @@ void IsolateObjectStore::PrintToJSONObject(JSONObject* jsobj) { static StackTracePtr CreatePreallocatedStackTrace(Zone* zone) { const Array& code_array = Array::Handle( zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld)); - const Array& pc_offset_array = Array::Handle( - zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld)); + const TypedData& pc_offset_array = TypedData::Handle( + zone, TypedData::New(kUintPtrCid, StackTrace::kPreallocatedStackdepth, + Heap::kOld)); const StackTrace& stack_trace = StackTrace::Handle(zone, StackTrace::New(code_array, pc_offset_array)); // Expansion of inlined functions requires additional memory at run time, diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc index f0d9d2cff8a..684d7f3b16f 100644 --- a/runtime/vm/profiler.cc +++ b/runtime/vm/profiler.cc @@ -1410,7 +1410,7 @@ class CodeLookupTableBuilder : public ObjectVisitor { ~CodeLookupTableBuilder() {} void VisitObject(ObjectPtr raw_obj) { - if (raw_obj->IsCode()) { + if (raw_obj->IsCode() && !Code::IsUnknownDartCode(Code::RawCast(raw_obj))) { table_->Add(Code::Handle(Code::RawCast(raw_obj))); } } diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc index 599885b6d80..0ba5912b214 100644 --- a/runtime/vm/profiler_service.cc +++ b/runtime/vm/profiler_service.cc @@ -70,6 +70,9 @@ const char* ProfileFunction::ResolvedScriptUrl() const { return NULL; } const Script& script = Script::Handle(function_.script()); + if (script.IsNull()) { + return NULL; + } const String& uri = String::Handle(script.resolved_url()); if (uri.IsNull()) { return NULL; diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc index d4e62d2d79c..40f1a09d6f4 100644 --- a/runtime/vm/profiler_test.cc +++ b/runtime/vm/profiler_test.cc @@ -2288,7 +2288,7 @@ static void InsertFakeSample(SampleBuffer* sample_buffer, uword* pc_offsets) { static uword FindPCForTokenPosition(const Code& code, TokenPosition tp) { GrowableArray functions; GrowableArray token_positions; - for (intptr_t pc_offset = 0; pc_offset < code.Size(); pc_offset++) { + for (uword pc_offset = 0; pc_offset < code.Size(); pc_offset++) { code.GetInlinedFunctionsAtInstruction(pc_offset, &functions, &token_positions); if (token_positions[0] == tp) { diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 1ac32d00615..160185c5f04 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -2835,10 +2835,18 @@ COMPILE_ASSERT(sizeof(UntaggedFloat64x2) == 24); // Define an aliases for intptr_t. #if defined(ARCH_IS_32_BIT) #define kIntPtrCid kTypedDataInt32ArrayCid +#define GetIntPtr GetInt32 #define SetIntPtr SetInt32 +#define kUintPtrCid kTypedDataUint32ArrayCid +#define GetUintPtr GetUint32 +#define SetUintPtr SetUint32 #elif defined(ARCH_IS_64_BIT) #define kIntPtrCid kTypedDataInt64ArrayCid +#define GetIntPtr GetInt64 #define SetIntPtr SetInt64 +#define kUintPtrCid kTypedDataUint64ArrayCid +#define GetUintPtr GetUint64 +#define SetUintPtr SetUint64 #else #error Architecture is not 32-bit or 64-bit. #endif // ARCH_IS_32_BIT @@ -2917,7 +2925,8 @@ class UntaggedStackTrace : public UntaggedInstance { async_link); // Link to parent async stack trace. POINTER_FIELD(ArrayPtr, code_array); // Code object for each frame in the stack trace. - POINTER_FIELD(ArrayPtr, pc_offset_array); // Offset of PC for each frame. + POINTER_FIELD(TypedDataPtr, pc_offset_array); // Offset of PC for each frame. + VISIT_TO(ObjectPtr, pc_offset_array) ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); } diff --git a/runtime/vm/reverse_pc_lookup_cache.cc b/runtime/vm/reverse_pc_lookup_cache.cc index dad884952b4..70f06dff002 100644 --- a/runtime/vm/reverse_pc_lookup_cache.cc +++ b/runtime/vm/reverse_pc_lookup_cache.cc @@ -10,9 +10,9 @@ namespace dart { -CodePtr ReversePc::Lookup(IsolateGroup* group, - uword pc, - bool is_return_address) { +CodePtr ReversePc::LookupInGroup(IsolateGroup* group, + uword pc, + bool is_return_address) { #if defined(DART_PRECOMPILED_RUNTIME) // This can run in the middle of GC and must not allocate handles. NoSafepointScope no_safepoint; @@ -67,4 +67,35 @@ CodePtr ReversePc::Lookup(IsolateGroup* group, return Code::null(); } +CodePtr ReversePc::Lookup(IsolateGroup* group, + uword pc, + bool is_return_address) { + ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions); + NoSafepointScope no_safepoint; + + CodePtr code = LookupInGroup(group, pc, is_return_address); + if (code == Code::null()) { + code = LookupInGroup(Dart::vm_isolate_group(), pc, is_return_address); + } + return code; +} + +CompressedStackMapsPtr ReversePc::FindCompressedStackMaps( + IsolateGroup* group, + uword pc, + bool is_return_address, + uword* code_start) { + ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions); + NoSafepointScope no_safepoint; + + CodePtr code = Lookup(group, pc, is_return_address); + if (code != Code::null()) { + *code_start = Code::PayloadStartOf(code); + return code->untag()->compressed_stackmaps(); + } + + *code_start = 0; + return CompressedStackMaps::null(); +} + } // namespace dart diff --git a/runtime/vm/reverse_pc_lookup_cache.h b/runtime/vm/reverse_pc_lookup_cache.h index 8c45bb1b3cf..9eb0558457c 100644 --- a/runtime/vm/reverse_pc_lookup_cache.h +++ b/runtime/vm/reverse_pc_lookup_cache.h @@ -13,11 +13,28 @@ namespace dart { class IsolateGroup; +// This class provides mechanism to find Code and CompressedStackMaps +// objects corresponding to the given PC. +// Can only be used in AOT runtime with bare instructions. class ReversePc : public AllStatic { public: - static CodePtr Lookup(IsolateGroup* group, - uword pc, - bool is_return_address = false); + // Looks for Code object corresponding to |pc| in the + // given isolate |group| and vm isolate group. + static CodePtr Lookup(IsolateGroup* group, uword pc, bool is_return_address); + + // Looks for CompressedStackMaps corresponding to |pc| in the + // given isolate |group| and vm isolate group. + // Sets |code_start| to the beginning of the instructions corresponding + // to |pc| (like Code::PayloadStart()). + static CompressedStackMapsPtr FindCompressedStackMaps(IsolateGroup* group, + uword pc, + bool is_return_address, + uword* code_start); + + private: + static CodePtr LookupInGroup(IsolateGroup* group, + uword pc, + bool is_return_address); }; } // namespace dart diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc index c078398cb46..7dec0a88906 100644 --- a/runtime/vm/service_test.cc +++ b/runtime/vm/service_test.cc @@ -259,7 +259,7 @@ ISOLATE_UNIT_TEST_CASE(Service_Code) { // Use the entry of the code object as it's reference. uword entry = code_c.PayloadStart(); int64_t compile_timestamp = code_c.compile_timestamp(); - EXPECT_GT(code_c.Size(), 16); + EXPECT_GT(code_c.Size(), 16u); uword last = entry + code_c.Size(); // Build a mock message handler and wrap it in a dart port. diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc index 51c1722e539..037e70df656 100644 --- a/runtime/vm/stack_frame.cc +++ b/runtime/vm/stack_frame.cc @@ -105,6 +105,9 @@ void UntaggedFrame::Init() { } bool StackFrame::IsBareInstructionsDartFrame() const { + if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) { + return false; + } NoSafepointScope no_safepoint; Code code; @@ -115,18 +118,14 @@ bool StackFrame::IsBareInstructionsDartFrame() const { ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); return cid == kFunctionCid; } - code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(), - /*is_return_address=*/true); - if (!code.IsNull()) { - auto const cid = code.OwnerClassId(); - ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); - return cid == kFunctionCid; - } return false; } bool StackFrame::IsBareInstructionsStubFrame() const { + if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) { + return false; + } NoSafepointScope no_safepoint; Code code; @@ -137,13 +136,6 @@ bool StackFrame::IsBareInstructionsStubFrame() const { ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); return cid == kNullCid || cid == kClassCid; } - code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(), - /*is_return_address=*/true); - if (!code.IsNull()) { - auto const cid = code.OwnerClassId(); - ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid); - return cid == kNullCid || cid == kClassCid; - } return false; } @@ -225,9 +217,13 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { // helper functions to the raw object interface. NoSafepointScope no_safepoint; Code code; + CompressedStackMaps maps; + uword code_start; if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - code = GetCodeObject(); + maps = ReversePc::FindCompressedStackMaps(isolate_group(), pc(), + /*is_return_address=*/true, + &code_start); } else { ObjectPtr pc_marker = *(reinterpret_cast( fp() + (runtime_frame_layout.code_from_fp * kWordSize))); @@ -236,23 +232,23 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { visitor->VisitPointer(&pc_marker); if (pc_marker->IsHeapObject() && (pc_marker->GetClassId() == kCodeCid)) { code ^= pc_marker; + code_start = code.PayloadStart(); + maps = code.compressed_stackmaps(); + ASSERT(!maps.IsNull()); } else { ASSERT(pc_marker == Object::null()); } } - if (!code.IsNull()) { + if (!maps.IsNull()) { // Optimized frames have a stack map. We need to visit the frame based // on the stack map. - CompressedStackMaps maps; - maps = code.compressed_stackmaps(); CompressedStackMaps global_table; global_table = isolate_group()->object_store()->canonicalized_stack_map_entries(); CompressedStackMaps::Iterator it(maps, global_table); - const uword start = code.PayloadStart(); - const uint32_t pc_offset = pc() - start; + const uint32_t pc_offset = pc() - code_start; if (it.Find(pc_offset)) { ObjectPtr* first = reinterpret_cast(sp()); ObjectPtr* last = reinterpret_cast( @@ -305,8 +301,14 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) { // unoptimized code, code with no stack map information at all, or the entry // to an osr function. In each of these cases, all stack slots contain // tagged pointers, so fall through. - ASSERT(!code.is_optimized() || maps.IsNull() || - (pc_offset == code.EntryPoint() - code.PayloadStart())); +#if defined(DEBUG) + if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { + ASSERT(IsStubFrame()); + } else { + ASSERT(!code.is_optimized() || + (pc_offset == code.EntryPoint() - code.PayloadStart())); + } +#endif // defined(DEBUG) } // For normal unoptimized Dart frames and Stub frames each slot @@ -348,15 +350,23 @@ CodePtr StackFrame::LookupDartCode() const { CodePtr StackFrame::GetCodeObject() const { #if defined(DART_PRECOMPILED_RUNTIME) if (FLAG_precompiled_mode && FLAG_use_bare_instructions) { - CodePtr code = ReversePc::Lookup(isolate_group(), pc(), - /*is_return_address=*/true); - if (code != Code::null()) { - return code; - } - code = ReversePc::Lookup(Dart::vm_isolate_group(), pc(), + NoSafepointScope no_safepoint; + Code code; + code = ReversePc::Lookup(isolate_group(), pc(), /*is_return_address=*/true); - if (code != Code::null()) { - return code; + if (!code.IsNull()) { + // This is needed in order to test stack traces with the future + // behavior of ReversePc::Lookup which will return + // StubCode::UnknownDartCode() if code object is omitted from + // the snapshot. + if (FLAG_dwarf_stack_traces_mode && code.CanBeOmittedFromAOTSnapshot()) { + ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0); + ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax); + ASSERT(StubCode::UnknownDartCode().IsFunctionCode()); + ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode()); + return StubCode::UnknownDartCode().ptr(); + } + return code.ptr(); } UNREACHABLE(); } diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc index e392260d76b..f20026959c5 100644 --- a/runtime/vm/stack_trace.cc +++ b/runtime/vm/stack_trace.cc @@ -429,19 +429,17 @@ ClosurePtr StackTraceUtils::ClosureFromFrameFunction( void StackTraceUtils::UnwindAwaiterChain( Zone* zone, const GrowableObjectArray& code_array, - const GrowableObjectArray& pc_offset_array, + GrowableArray* pc_offset_array, CallerClosureFinder* caller_closure_finder, const Closure& leaf_closure) { auto& code = Code::Handle(zone); auto& function = Function::Handle(zone); auto& closure = Closure::Handle(zone, leaf_closure.ptr()); auto& pc_descs = PcDescriptors::Handle(zone); - auto& offset = Smi::Handle(zone); // Inject async suspension marker. code_array.Add(StubCode::AsynchronousGapMarker()); - offset = Smi::New(0); - pc_offset_array.Add(offset); + pc_offset_array->Add(0); // Traverse the trail of async futures all the way up. for (; !closure.IsNull(); @@ -455,23 +453,22 @@ void StackTraceUtils::UnwindAwaiterChain( RELEASE_ASSERT(!code.IsNull()); code_array.Add(code); pc_descs = code.pc_descriptors(); - offset = Smi::New(FindPcOffset(pc_descs, GetYieldIndex(closure))); + const intptr_t pc_offset = FindPcOffset(pc_descs, GetYieldIndex(closure)); // Unlike other sources of PC offsets, the offset may be 0 here if we // reach a non-async closure receiving the yielded value. - ASSERT(offset.Value() >= 0); - pc_offset_array.Add(offset); + ASSERT(pc_offset >= 0); + pc_offset_array->Add(pc_offset); // Inject async suspension marker. code_array.Add(StubCode::AsynchronousGapMarker()); - offset = Smi::New(0); - pc_offset_array.Add(offset); + pc_offset_array->Add(0); } } void StackTraceUtils::CollectFramesLazy( Thread* thread, const GrowableObjectArray& code_array, - const GrowableObjectArray& pc_offset_array, + GrowableArray* pc_offset_array, int skip_frames, std::function* on_sync_frames, bool* has_async) { @@ -489,7 +486,6 @@ void StackTraceUtils::CollectFramesLazy( } auto& code = Code::Handle(zone); - auto& offset = Smi::Handle(zone); auto& closure = Closure::Handle(zone); CallerClosureFinder caller_closure_finder(zone); @@ -513,10 +509,9 @@ void StackTraceUtils::CollectFramesLazy( // Add the current synchronous frame. code = frame->LookupDartCode(); code_array.Add(code); - const intptr_t pc_offset = frame->pc() - code.PayloadStart(); + const uword pc_offset = frame->pc() - code.PayloadStart(); ASSERT(pc_offset > 0 && pc_offset <= code.Size()); - offset = Smi::New(pc_offset); - pc_offset_array.Add(offset); + pc_offset_array->Add(pc_offset); // Callback for sync frame. if (on_sync_frames != nullptr) { (*on_sync_frames)(frame); @@ -593,7 +588,7 @@ intptr_t StackTraceUtils::CountFrames(Thread* thread, intptr_t StackTraceUtils::CollectFrames(Thread* thread, const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, intptr_t array_offset, intptr_t count, int skip_frames) { @@ -602,7 +597,6 @@ intptr_t StackTraceUtils::CollectFrames(Thread* thread, StackFrame* frame = frames.NextFrame(); ASSERT(frame != NULL); // We expect to find a dart invocation frame. Code& code = Code::Handle(zone); - Smi& offset = Smi::Handle(zone); intptr_t collected_frames_count = 0; for (; (frame != NULL) && (collected_frames_count < count); frame = frames.NextFrame()) { @@ -611,9 +605,9 @@ intptr_t StackTraceUtils::CollectFrames(Thread* thread, continue; } code = frame->LookupDartCode(); - offset = Smi::New(frame->pc() - code.PayloadStart()); + const intptr_t pc_offset = frame->pc() - code.PayloadStart(); code_array.SetAt(array_offset, code); - pc_offset_array.SetAt(array_offset, offset); + pc_offset_array.SetUintPtr(array_offset * kWordSize, pc_offset); array_offset++; collected_frames_count++; } diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h index a08221f4f25..c2eb02abc24 100644 --- a/runtime/vm/stack_trace.h +++ b/runtime/vm/stack_trace.h @@ -107,7 +107,7 @@ class StackTraceUtils : public AllStatic { static void UnwindAwaiterChain(Zone* zone, const GrowableObjectArray& code_array, - const GrowableObjectArray& pc_offset_array, + GrowableArray* pc_offset_array, CallerClosureFinder* caller_closure_finder, const Closure& leaf_closure); @@ -130,7 +130,7 @@ class StackTraceUtils : public AllStatic { static void CollectFramesLazy( Thread* thread, const GrowableObjectArray& code_array, - const GrowableObjectArray& pc_offset_array, + GrowableArray* pc_offset_array, int skip_frames, std::function* on_sync_frames = nullptr, bool* has_async = nullptr); @@ -151,7 +151,7 @@ class StackTraceUtils : public AllStatic { /// Returns the number of frames collected. static intptr_t CollectFrames(Thread* thread, const Array& code_array, - const Array& pc_offset_array, + const TypedData& pc_offset_array, intptr_t array_offset, intptr_t count, int skip_frames); diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc index e41c6421a09..a78d1b0e8ef 100644 --- a/runtime/vm/stub_code.cc +++ b/runtime/vm/stub_code.cc @@ -60,6 +60,30 @@ void StubCode::Init() { for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) { entries_[i].code->set_object_pool(object_pool.ptr()); } + +#if defined(DART_PRECOMPILER) + { + // Set Function owner for UnknownDartCode stub so it pretends to + // be a Dart code. + Zone* zone = Thread::Current()->zone(); + const auto& signature = FunctionType::Handle(zone, FunctionType::New()); + auto& owner = Object::Handle(zone); + owner = Object::void_class(); + ASSERT(!owner.IsNull()); + owner = Function::New(signature, Object::null_string(), + UntaggedFunction::kRegularFunction, + /*is_static=*/true, + /*is_const=*/false, + /*is_abstract=*/false, + /*is_external=*/false, + /*is_native=*/false, owner, TokenPosition::kNoSource); + StubCode::UnknownDartCode().set_owner(owner); + StubCode::UnknownDartCode().set_exception_handlers( + Object::empty_exception_handlers()); + StubCode::UnknownDartCode().set_pc_descriptors(Object::empty_descriptors()); + ASSERT(StubCode::UnknownDartCode().IsFunctionCode()); + } +#endif // defined(DART_PRECOMPILER) } #undef STUB_CODE_GENERATE diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h index c08bfd6052b..d99a661bc1f 100644 --- a/runtime/vm/stub_code_list.h +++ b/runtime/vm/stub_code_list.h @@ -128,7 +128,8 @@ namespace dart { V(InstantiateTypeArguments) \ V(InstantiateTypeArgumentsMayShareInstantiatorTA) \ V(InstantiateTypeArgumentsMayShareFunctionTA) \ - V(NoSuchMethodDispatcher) + V(NoSuchMethodDispatcher) \ + V(UnknownDartCode) } // namespace dart