mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:51:30 +00:00
e01457d138
Now, when writing an AOT snapshot in bare instructions mode, only the actual instructions in the RawInstructions payload are serialized instead of the entire RawInstructions object. Since there are no longer RawInstructions objects in these AOT snapshots, we also change how Code objects are serialized. Instead of just containing a reference to the RawInstructions object, we serialize two pieces of information: where the instructions payload for this Code object begins and whether there was a single entry for the instructions payload. (To save space, the single entry bit is serialized as the low order bit of the unchecked offset, which was already being serialized). While we also need the length of the instructions payload, we approximate it for all but the last Code object by subtracting the next Code object's payload start from this Code object's payload start. For the last Code object, we assume it extends to the end of the instructions image. Changes on flutter gallery in release mode: armv7: instructions size -2.70%, total size -1.73% armv8: instructions size -6.04%, total size -3.63% Fixes https://github.com/dart-lang/sdk/issues/38451. Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-linux-release-x64-try,vm-kernel-precomp-linux-release-simarm-try,vm-kernel-precomp-linux-release-simarm64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-precomp-android-release-arm64-try,vm-kernel-precomp-android-release-arm_x64-try,vm-kernel-precomp-mac-release-simarm64-try,vm-kernel-precomp-win-release-x64-try Change-Id: Ia0a5c4e5e47c956776dc62503da38ec55a143c04 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134325 Commit-Queue: Teagan Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
141 lines
4.5 KiB
C++
141 lines
4.5 KiB
C++
// 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].
|
|
//
|
|
// If [is_return_address] is true, then the PC may be immediately after the
|
|
// payload, if the last instruction is a call that is guaranteed not to
|
|
// return. Otherwise, the PC must be within the payload.
|
|
inline RawCode* Lookup(uword pc, bool is_return_address = false) {
|
|
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 if (!is_return_address && middle_pc == pc_offset) {
|
|
// This case should only happen if we have bare instruction payloads.
|
|
// Otherwise, the instruction payloads of two RawInstructions objects
|
|
// will never be immediately adjacent in memory due to the header of
|
|
// the second object.
|
|
ASSERT(FLAG_use_bare_instructions);
|
|
left = middle + 1;
|
|
break;
|
|
} 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, bool is_return_address = false) {
|
|
UNREACHABLE();
|
|
}
|
|
};
|
|
|
|
#endif // defined(DART_PRECOMPILED_RUNTIME
|
|
|
|
} // namespace dart
|
|
|
|
#endif // RUNTIME_VM_REVERSE_PC_LOOKUP_CACHE_H_
|