| // 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 { | |
| CodePtr ReversePc::FindCodeInGroup(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; | |
| 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<InstructionsTablePtr>( | |
| tables->untag()->data()->untag()->element(i)); | |
| CodePtr code = InstructionsTable::FindCode(table, pc); | |
| if (code != Code::null()) { | |
| return code; | |
| } | |
| } | |
| #endif // defined(DART_PRECOMPILED_RUNTIME) | |
| return Code::null(); | |
| } | |
| const UntaggedCompressedStackMaps::Payload* ReversePc::FindStackMapInGroup( | |
| IsolateGroup* group, | |
| uword pc, | |
| bool is_return_address, | |
| uword* code_start, | |
| const UntaggedCompressedStackMaps::Payload** global_table) { | |
| #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<InstructionsTablePtr>( | |
| tables->untag()->data()->untag()->element(i)); | |
| auto map = InstructionsTable::FindStackMap(table, pc, code_start); | |
| if (map != nullptr) { | |
| // Take global table from the first table. | |
| table = static_cast<InstructionsTablePtr>( | |
| tables->untag()->data()->untag()->element(0)); | |
| *global_table = InstructionsTable::GetCanonicalStackMap(table); | |
| return map; | |
| } | |
| } | |
| #endif // defined(DART_PRECOMPILED_RUNTIME) | |
| *code_start = 0; | |
| return nullptr; | |
| } | |
| const UntaggedCompressedStackMaps::Payload* ReversePc::FindStackMap( | |
| IsolateGroup* group, | |
| uword pc, | |
| bool is_return_address, | |
| uword* code_start, | |
| const UntaggedCompressedStackMaps::Payload** global_table) { | |
| ASSERT(FLAG_precompiled_mode); | |
| NoSafepointScope no_safepoint; | |
| return FindStackMapInGroup(group, pc, is_return_address, code_start, | |
| global_table); | |
| } | |
| CodePtr ReversePc::FindCode(IsolateGroup* group, | |
| uword pc, | |
| bool is_return_address) { | |
| ASSERT(FLAG_precompiled_mode); | |
| NoSafepointScope no_safepoint; | |
| return FindCodeInGroup(group, pc, is_return_address); | |
| } | |
| CodePtr ReversePc::Lookup(IsolateGroup* group, | |
| uword pc, | |
| bool is_return_address) { | |
| ASSERT(FLAG_precompiled_mode); | |
| NoSafepointScope no_safepoint; | |
| return FindCode(group, pc, is_return_address); | |
| } | |
| } // namespace dart |