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 | |
11 | namespace dart { |
12 | |
13 | CodePtr 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 | |