blob: dc7390a54054c9ce600bc172143f76b7d78bf060 [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"
#include "vm/stub_code.h"
namespace dart {
ObjectPtr ReversePc::FindCodeDescriptorInGroup(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
#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));
intptr_t index = InstructionsTable::FindEntry(table, pc);
if (index >= 0) {
*code_start = InstructionsTable::PayloadStartAt(table, index);
return InstructionsTable::DescriptorAt(table, index);
}
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
*code_start = 0;
return Object::null();
}
ObjectPtr ReversePc::FindCodeDescriptor(IsolateGroup* group,
uword pc,
bool is_return_address,
uword* code_start) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
ObjectPtr code_descriptor =
FindCodeDescriptorInGroup(group, pc, is_return_address, code_start);
if (code_descriptor == Object::null()) {
code_descriptor = FindCodeDescriptorInGroup(Dart::vm_isolate_group(), pc,
is_return_address, code_start);
}
return code_descriptor;
}
CodePtr ReversePc::Lookup(IsolateGroup* group,
uword pc,
bool is_return_address) {
ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
NoSafepointScope no_safepoint;
uword code_start;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, &code_start);
if (code_descriptor != Object::null()) {
if (!code_descriptor->IsCode()) {
ASSERT(StubCode::UnknownDartCode().PayloadStart() == 0);
ASSERT(StubCode::UnknownDartCode().Size() == kUwordMax);
ASSERT(StubCode::UnknownDartCode().IsFunctionCode());
ASSERT(StubCode::UnknownDartCode().IsUnknownDartCode());
code_descriptor = StubCode::UnknownDartCode().ptr();
}
}
return static_cast<CodePtr>(code_descriptor);
}
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;
ObjectPtr code_descriptor =
FindCodeDescriptor(group, pc, is_return_address, code_start);
if (code_descriptor != Object::null()) {
if (code_descriptor->IsCode()) {
CodePtr code = static_cast<CodePtr>(code_descriptor);
ASSERT(*code_start == Code::PayloadStartOf(code));
return code->untag()->compressed_stackmaps();
} else {
ASSERT(code_descriptor->IsCompressedStackMaps());
return static_cast<CompressedStackMapsPtr>(code_descriptor);
}
}
*code_start = 0;
return CompressedStackMaps::null();
}
} // namespace dart