1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/reverse_pc_lookup_cache.h"
6
7#include "vm/isolate.h"
8#include "vm/object.h"
9#include "vm/object_store.h"
10
11namespace dart {
12
13CodePtr ReversePc::Lookup(IsolateGroup* group,
14 uword pc,
15 bool is_return_address) {
16#if defined(DART_PRECOMPILED_RUNTIME)
17 // This can run in the middle of GC and must not allocate handles.
18 NoSafepointScope no_safepoint;
19
20 if (is_return_address) {
21 pc--;
22 }
23
24 // This expected number of tables is low, so we go through them linearly. If
25 // this changes, would could sort the table list during deserialization and
26 // binary search for the table.
27 GrowableObjectArrayPtr tables = group->object_store()->code_order_tables();
28 intptr_t tables_length = Smi::Value(tables->ptr()->length_);
29 for (intptr_t i = 0; i < tables_length; i++) {
30 ArrayPtr table =
31 static_cast<ArrayPtr>(tables->ptr()->data_->ptr()->data()[i]);
32 intptr_t lo = 0;
33 intptr_t hi = Smi::Value(table->ptr()->length_) - 1;
34
35 // Fast check if pc belongs to this table.
36 if (lo > hi) {
37 continue;
38 }
39 CodePtr first = static_cast<CodePtr>(table->ptr()->data()[lo]);
40 if (pc < Code::PayloadStartOf(first)) {
41 continue;
42 }
43 CodePtr last = static_cast<CodePtr>(table->ptr()->data()[hi]);
44 if (pc >= (Code::PayloadStartOf(last) + Code::PayloadSizeOf(last))) {
45 continue;
46 }
47
48 // Binary search within the table for the matching Code.
49 while (lo <= hi) {
50 intptr_t mid = (hi - lo + 1) / 2 + lo;
51 ASSERT(mid >= lo);
52 ASSERT(mid <= hi);
53 CodePtr code = static_cast<CodePtr>(table->ptr()->data()[mid]);
54 uword code_start = Code::PayloadStartOf(code);
55 uword code_end = code_start + Code::PayloadSizeOf(code);
56 if (pc < code_start) {
57 hi = mid - 1;
58 } else if (pc >= code_end) {
59 lo = mid + 1;
60 } else {
61 return code;
62 }
63 }
64 }
65#endif // defined(DART_PRECOMPILED_RUNTIME)
66
67 return Code::null();
68}
69
70} // namespace dart
71