Skip to content

Commit

Permalink
[VM] Bare instructions - Part 3: Add support for building a PC -> Cod…
Browse files Browse the repository at this point in the history
…e mapping table

This CL adds a [ReversePcLookupCache] which, based on a list of code
objects, builds up a binary searchable table for mapping PCs to Code
objects (where all the metadata is available, like stackmaps, ...).

This CL also adds stack walking support for "bare instruction" frames.

In a later part we will start emitting the sorted list of code objects
(via the new field in the object store) under a flag.

Issue #33274

Change-Id: I3c06c12bc0fb266dc1bd843a4a11b5208773151d
Reviewed-on: https://dart-review.googlesource.com/c/85746
Commit-Queue: Martin Kustermann <[email protected]>
Reviewed-by: Vyacheslav Egorov <[email protected]>
  • Loading branch information
mkustermann authored and [email protected] committed Dec 13, 2018
1 parent 7a968ae commit 2440a32
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 23 deletions.
7 changes: 6 additions & 1 deletion runtime/vm/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "vm/port.h"
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
#include "vm/reverse_pc_lookup_cache.h"
#include "vm/service.h"
#include "vm/service_event.h"
#include "vm/service_isolate.h"
Expand Down Expand Up @@ -946,7 +947,8 @@ Isolate::Isolate(const Dart_IsolateFlags& api_flags)
handler_info_cache_(),
catch_entry_moves_cache_(),
embedder_entry_points_(NULL),
obfuscation_map_(NULL) {
obfuscation_map_(NULL),
reverse_pc_lookup_cache_(nullptr) {
FlagsCopyFrom(api_flags);
SetErrorsFatal(true);
set_compilation_allowed(true);
Expand Down Expand Up @@ -974,6 +976,9 @@ Isolate::~Isolate() {
// RELEASE_ASSERT(reload_context_ == NULL);
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)

delete reverse_pc_lookup_cache_;
reverse_pc_lookup_cache_ = nullptr;

delete background_compiler_;
background_compiler_ = NULL;

Expand Down
14 changes: 14 additions & 0 deletions runtime/vm/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class RawInteger;
class RawFloat32x4;
class RawInt32x4;
class RawUserTag;
class ReversePcLookupCache;
class SafepointHandler;
class SampleBuffer;
class SendPort;
Expand Down Expand Up @@ -704,6 +705,17 @@ class Isolate : public BaseIsolate {
void set_obfuscation_map(const char** map) { obfuscation_map_ = map; }
const char** obfuscation_map() const { return obfuscation_map_; }

// Returns the pc -> code lookup cache object for this isolate.
ReversePcLookupCache* reverse_pc_lookup_cache() const {
return reverse_pc_lookup_cache_;
}

// Sets the pc -> code lookup cache object for this isolate.
void set_reverse_pc_lookup_cache(ReversePcLookupCache* table) {
ASSERT(reverse_pc_lookup_cache_ == nullptr);
reverse_pc_lookup_cache_ = table;
}

// Isolate-specific flag handling.
static void FlagsInitialize(Dart_IsolateFlags* api_flags);
void FlagsCopyTo(Dart_IsolateFlags* api_flags) const;
Expand Down Expand Up @@ -1006,6 +1018,8 @@ class Isolate : public BaseIsolate {
Dart_QualifiedFunctionName* embedder_entry_points_;
const char** obfuscation_map_;

ReversePcLookupCache* reverse_pc_lookup_cache_;

static Dart_IsolateCreateCallback create_callback_;
static Dart_IsolateShutdownCallback shutdown_callback_;
static Dart_IsolateCleanupCallback cleanup_callback_;
Expand Down
2 changes: 2 additions & 0 deletions runtime/vm/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -7947,6 +7947,8 @@ class Array : public Instance {
return memcmp(a->ptr()->data(), b->ptr()->data(), kWordSize * length) == 0;
}

static RawObject** DataOf(RawArray* array) { return array->ptr()->data(); }

RawObject* At(intptr_t index) const { return *ObjectAddr(index); }
void SetAt(intptr_t index, const Object& value) const {
// TODO(iposva): Add storing NoSafepointScope.
Expand Down
1 change: 1 addition & 0 deletions runtime/vm/object_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class ObjectPointerVisitor;
RW(Array, unique_dynamic_targets) \
RW(GrowableObjectArray, megamorphic_cache_table) \
RW(Code, build_method_extractor_code) \
RW(Array, code_order_table) \
R_(Code, megamorphic_miss_code) \
R_(Function, megamorphic_miss_function) \
RW(Array, obfuscation_map) \
Expand Down
56 changes: 56 additions & 0 deletions runtime/vm/reverse_pc_lookup_cache.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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"

namespace dart {

#if defined(DART_PRECOMPILED_RUNTIME)

static uword BeginPcFromCode(const RawCode* code) {
auto instr = Code::InstructionsOf(code);
return Instructions::PayloadStart(instr);
}

static uword EndPcFromCode(const RawCode* code) {
auto instr = Code::InstructionsOf(code);
return Instructions::PayloadStart(instr) + Instructions::Size(instr);
}

void ReversePcLookupCache::BuildAndAttachToIsolate(Isolate* isolate) {
auto object_store = isolate->object_store();
auto& array = Array::Handle(object_store->code_order_table());
if (!array.IsNull()) {
const intptr_t length = array.Length();
{
NoSafepointScope no_safepoint_scope;

const uword begin =
BeginPcFromCode(reinterpret_cast<RawCode*>(array.At(0)));
const uword end =
EndPcFromCode(reinterpret_cast<RawCode*>(array.At(length - 1)));

auto pc_array = new uint32_t[length];
for (intptr_t i = 0; i < length; i++) {
const auto end_pc =
EndPcFromCode(reinterpret_cast<RawCode*>(array.At(i)));
pc_array[i] = end_pc - begin;
}
#if defined(DEBUG)
for (intptr_t i = 1; i < length; i++) {
ASSERT(pc_array[i - 1] <= pc_array[i]);
}
#endif // defined(DEBUG)
auto cache =
new ReversePcLookupCache(isolate, pc_array, length, begin, end);
isolate->set_reverse_pc_lookup_cache(cache);
}
}
}

#endif // defined(DART_PRECOMPILED_RUNTIME)

} // namespace dart
126 changes: 126 additions & 0 deletions runtime/vm/reverse_pc_lookup_cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// 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.

#ifndef RUNTIME_VM_REVERSE_PC_LOOKUP_CACHE_H_
#define RUNTIME_VM_REVERSE_PC_LOOKUP_CACHE_H_

#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/object.h"
#include "vm/object_store.h"

namespace dart {

class Isolate;

#if defined(DART_PRECOMPILED_RUNTIME)

// A cache for looking up a Code object based on pc (currently the cache is
// implemented as a binary-searchable uint32 array)
//
// If an AOT snapshot was created with --use_bare_instructions the isolate's
// object store will contain a `code_order_table` - which is a sorted array
// of [Code] objects. The order is based on addresses of the code's
// instructions in memory.
//
// For a binary search we would need to touch O(log(array-size)) array entries,
// code objects and instruction objects.
//
// To avoid this we make another uint32 array which is initialized from the end
// PCs of the instructions (relative to the start pc of the first instruction
// object).
//
// We have the following invariants:
//
// BeginPcFromCode(code_array[0]) <= pc_array[0]
// pc_array[i] == EndPcFromCode(code_array[i])
// pc_array[i] <= pc_array[i+1]
//
// The lookup will then do a binary search in pc_array. The index can then be
// used in the `code_order_table` of the object store.
//
// WARNING: This class cannot do memory allocation or handle allocation!
class ReversePcLookupCache {
public:
ReversePcLookupCache(Isolate* isolate,
uint32_t* pc_array,
intptr_t length,
uword first_absolute_pc,
uword last_absolute_pc)
: isolate_(isolate),
pc_array_(pc_array),
length_(length),
first_absolute_pc_(first_absolute_pc),
last_absolute_pc_(last_absolute_pc) {}
~ReversePcLookupCache() { delete[] pc_array_; }

// Builds a [ReversePcLookupCache] and attaches it to the isolate (if
// `code_order_table` is non-`null`).
static void BuildAndAttachToIsolate(Isolate* isolate);

// Returns `true` if the given [pc] contains can be mapped to a [Code] object
// using this cache.
inline bool Contains(uword pc) {
return first_absolute_pc_ <= pc && pc <= last_absolute_pc_;
}

// Looks up the [Code] object from a given [pc].
inline RawCode* Lookup(uword pc) {
NoSafepointScope no_safepoint_scope;

intptr_t left = 0;
intptr_t right = length_ - 1;

ASSERT(first_absolute_pc_ <= pc && pc < last_absolute_pc_);
uint32_t pc_offset = static_cast<uint32_t>(pc - first_absolute_pc_);

while (left < right) {
intptr_t middle = left + (right - left) / 2;

uword middle_pc = pc_array_[middle];
if (middle_pc < pc_offset) {
left = middle + 1;
} else {
right = middle;
}
}

auto code_array = isolate_->object_store()->code_order_table();
auto raw_code = reinterpret_cast<RawCode*>(Array::DataOf(code_array)[left]);

#if defined(DEBUG)
ASSERT(raw_code->GetClassIdMayBeSmi() == kCodeCid);
ASSERT(Code::ContainsInstructionAt(raw_code, pc));
#endif

return raw_code;
}

private:
Isolate* isolate_;
uint32_t* pc_array_;
intptr_t length_;
uword first_absolute_pc_;
uword last_absolute_pc_;
};

#else // defined(DART_PRECOMPILED_RUNTIME

class ReversePcLookupCache {
public:
ReversePcLookupCache() {}
~ReversePcLookupCache() {}

static void BuildAndAttachToIsolate(Isolate* isolate) {}

inline bool Contains(uword pc) { return false; }

inline RawCode* Lookup(uword pc) { UNREACHABLE(); }
};

#endif // defined(DART_PRECOMPILED_RUNTIME

} // namespace dart

#endif // RUNTIME_VM_REVERSE_PC_LOOKUP_CACHE_H_
Loading

0 comments on commit 2440a32

Please sign in to comment.