// Copyright (c) 2018, 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/reverse_pc_lookup_cache.h" #include "vm/isolate.h" #include "vm/object.h" #include "vm/object_store.h" #include "vm/stub_code.h" namespace dart { ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group, uword pc, bool is_return_address, uword* code_start) { #if defined(DART_PRECOMPILED_RUNTIME) // This can run in the middle of GC and must not allocate handles. NoSafepointScope no_safepoint; if (is_return_address) { pc--; } // This expected number of tables is low (one per loading unit), so we go // through them linearly. If this changes, would could sort the table list // during deserialization and binary search for the table. GrowableObjectArrayPtr tables = group->object_store()->instructions_tables(); intptr_t tables_length = Smi::Value(tables->untag()->length_); for (intptr_t i = 0; i < tables_length; i++) { InstructionsTablePtr table = static_cast( tables->untag()->data_->untag()->data()[i]); intptr_t index = InstructionsTable::FindEntry(table, pc); if (index >= 0) { *code_start = InstructionsTable::PayloadStartAt(table, index); return InstructionsTable::DescriptorAt(table, index); } } #endif // defined(DART_PRECOMPILED_RUNTIME) *code_start = 0; return Object::null(); } ObjectPtr ReversePc::FindCodeDescriptor(IsolateGroup* group, uword pc, bool is_return_address, uword* code_start) { ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions); NoSafepointScope no_safepoint; ObjectPtr code_descriptor = FindCodeDescriptorInGroup(group, pc, is_return_address, code_start); if (code_descriptor == Object::null()) { code_descriptor = FindCodeDescriptorInGroup(Dart::vm_isolate_group(), pc, is_return_address, code_start); } return code_descriptor; } CodePtr ReversePc::Lookup(IsolateGroup* group, uword pc, bool is_return_address) { ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions); NoSafepointScope no_safepoint; uword code_start; ObjectPtr code_descriptor = FindCodeDescriptor(group, pc, is_return_address, &code_start); if (code_descriptor != Object::null()) { if (!code_descriptor->IsCode()) { ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0); ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax); ASSERT(StubCode::UnknownDartCode().IsFunctionCode()); ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode()); code_descriptor = StubCode::UnknownDartCode().ptr(); } } return static_cast(code_descriptor); } 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; ObjectPtr code_descriptor = FindCodeDescriptor(group, pc, is_return_address, code_start); if (code_descriptor != Object::null()) { if (code_descriptor->IsCode()) { CodePtr code = static_cast(code_descriptor); ASSERT(*code_start == Code::PayloadStartOf(code)); return code->untag()->compressed_stackmaps(); } else { ASSERT(code_descriptor->IsCompressedStackMaps()); return static_cast(code_descriptor); } } *code_start = 0; return CompressedStackMaps::null(); } } // namespace dart