blob: 70f06dff0023e47d7d0316f08949216745f268d1 [file] [log] [blame]
// 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"
namespace dart {
CodePtr ReversePc::LookupInGroup(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, 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()->code_order_tables();
intptr_t tables_length = Smi::Value(tables->untag()->length_);
for (intptr_t i = 0; i < tables_length; i++) {
ArrayPtr table =
static_cast<ArrayPtr>(tables->untag()->data_->untag()->data()[i]);
intptr_t lo = 0;
intptr_t hi = Smi::Value(table->untag()->length_) - 1;
// Fast check if pc belongs to this table.
if (lo > hi) {
continue;
}
CodePtr first = static_cast<CodePtr>(table->untag()->data()[lo]);
if (pc < Code::PayloadStartOf(first)) {
continue;
}
CodePtr last = static_cast<CodePtr>(table->untag()->data()[hi]);
if (pc >= (Code::PayloadStartOf(last) + Code::PayloadSizeOf(last))) {
continue;
}
// Binary search within the table for the matching Code.
while (lo <= hi) {
intptr_t mid = (hi - lo + 1) / 2 + lo;
ASSERT(mid >= lo);
ASSERT(mid <= hi);
CodePtr code = static_cast<CodePtr>(table->untag()->data()[mid]);
uword code_start = Code::PayloadStartOf(code);
uword code_end = code_start + Code::PayloadSizeOf(code);
if (pc < code_start) {
hi = mid - 1;
} else if (pc >= code_end) {
lo = mid + 1;
} else {
return code;
}
}
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
return Code::null();
}
CodePtr ReversePc::Lookup(IsolateGroup* group,
uword pc,
bool is_return_address) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
CodePtr code = LookupInGroup(group, pc, is_return_address);
if (code == Code::null()) {
code = LookupInGroup(Dart::vm_isolate_group(), pc, is_return_address);
}
return code;
}
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;
CodePtr code = Lookup(group, pc, is_return_address);
if (code != Code::null()) {
*code_start = Code::PayloadStartOf(code);
return code->untag()->compressed_stackmaps();
}
*code_start = 0;
return CompressedStackMaps::null();
}
} // namespace dart