| // 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; | 
 |  | 
 |   auto map = FindStackMapInGroup(group, pc, is_return_address, code_start, | 
 |                                  global_table); | 
 |   if (map == nullptr) { | 
 |     map = FindStackMapInGroup(Dart::vm_isolate_group(), pc, is_return_address, | 
 |                               code_start, global_table); | 
 |   } | 
 |   return map; | 
 | } | 
 |  | 
 | CodePtr ReversePc::FindCode(IsolateGroup* group, | 
 |                             uword pc, | 
 |                             bool is_return_address) { | 
 |   ASSERT(FLAG_precompiled_mode); | 
 |   NoSafepointScope no_safepoint; | 
 |  | 
 |   auto code_descriptor = FindCodeInGroup(group, pc, is_return_address); | 
 |   if (code_descriptor == Code::null()) { | 
 |     code_descriptor = | 
 |         FindCodeInGroup(Dart::vm_isolate_group(), pc, is_return_address); | 
 |   } | 
 |   return code_descriptor; | 
 | } | 
 |  | 
 | 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 |