mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 08:24:39 +00:00
Revert "[vm/aot] Remove object wrapping of bare instructions for AOT snapshots."
This reverts commit 7475c637c3
.
Reason for revert: Breakage on simarm_x64 (and thus arm_x64)
Original change's description:
> [vm/aot] Remove object wrapping of bare instructions for AOT snapshots.
>
> 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.66%, total size -1.68%
> armv8: instructions size -5.81%, total size -3.49%
>
> Fixes https://github.com/dart-lang/sdk/issues/38451.
>
> Change-Id: Ia458e8d99bae18f5c3b6e849df2519027f06f574
> 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
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/131067
> Commit-Queue: Teagan Strickland <sstrickl@google.com>
> Reviewed-by: Martin Kustermann <kustermann@google.com>
TBR=kustermann@google.com,rmacnak@google.com,sstrickl@google.com
Change-Id: If2c8ca6b0993211b2509b275af7ff11a8fa2baa3
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
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
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134322
Reviewed-by: Teagan Strickland <sstrickl@google.com>
Commit-Queue: Teagan Strickland <sstrickl@google.com>
This commit is contained in:
parent
592e59691b
commit
bb24f98616
|
@ -11,12 +11,7 @@ import "package:vm/v8_snapshot_profile.dart";
|
|||
|
||||
import 'use_flag_test_helper.dart';
|
||||
|
||||
test(
|
||||
{String dillPath,
|
||||
bool useAsm,
|
||||
bool useBare,
|
||||
bool stripFlag,
|
||||
bool stripUtil}) async {
|
||||
test({String dillPath, bool useAsm, bool stripFlag, bool stripUtil}) async {
|
||||
// The assembler may add extra unnecessary information to the compiled
|
||||
// snapshot whether or not we generate DWARF information in the assembly, so
|
||||
// we force the use of a utility when generating assembly.
|
||||
|
@ -28,7 +23,6 @@ test(
|
|||
|
||||
final tempDirPrefix = 'v8-snapshot-profile' +
|
||||
(useAsm ? '-assembly' : '-elf') +
|
||||
(useBare ? '-bare' : '-nonbare') +
|
||||
(stripFlag ? '-intstrip' : '') +
|
||||
(stripUtil ? '-extstrip' : '');
|
||||
|
||||
|
@ -38,7 +32,6 @@ test(
|
|||
final snapshotPath = path.join(tempDir, 'test.snap');
|
||||
final commonSnapshotArgs = [
|
||||
if (stripFlag) '--strip',
|
||||
useBare ? '--use-bare-instructions' : '--no-use-bare-instructions',
|
||||
"--write-v8-snapshot-profile-to=$profilePath",
|
||||
dillPath,
|
||||
];
|
||||
|
@ -78,7 +71,7 @@ test(
|
|||
// graph (in some cases the shallow size can legitimately be 0, e.g. for
|
||||
// "base objects").
|
||||
for (final int node in profile.nodes) {
|
||||
Expect.notEquals("Unknown", profile[node].type,
|
||||
Expect.notEquals(profile[node].type, "Unknown",
|
||||
"unknown node at ID ${profile[node].id}");
|
||||
}
|
||||
|
||||
|
@ -96,7 +89,6 @@ test(
|
|||
final actual = await File(strippedPath).length();
|
||||
final expected = profile.accountedBytes;
|
||||
|
||||
final bareUsed = useBare ? "bare" : "non-bare";
|
||||
final fileType = useAsm ? "assembly" : "ELF";
|
||||
String stripPrefix = "";
|
||||
if (stripFlag && stripUtil) {
|
||||
|
@ -108,7 +100,7 @@ test(
|
|||
}
|
||||
|
||||
Expect.approxEquals(expected, actual, 0.03 * actual,
|
||||
"failed on $bareUsed $stripPrefix$fileType snapshot type.");
|
||||
"failed on $stripPrefix$fileType snapshot type.");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -222,17 +214,7 @@ main() async {
|
|||
|
||||
// Test stripped ELF generation directly.
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: true,
|
||||
stripUtil: false,
|
||||
useAsm: false,
|
||||
useBare: false);
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: true,
|
||||
stripUtil: false,
|
||||
useAsm: false,
|
||||
useBare: true);
|
||||
dillPath: dillPath, stripFlag: true, stripUtil: false, useAsm: false);
|
||||
|
||||
// We neither generate assembly nor have a stripping utility on Windows.
|
||||
if (Platform.isWindows) {
|
||||
|
@ -246,17 +228,7 @@ main() async {
|
|||
} else {
|
||||
// Test unstripped ELF generation that is then stripped externally.
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: false,
|
||||
stripUtil: true,
|
||||
useAsm: false,
|
||||
useBare: false);
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: false,
|
||||
stripUtil: true,
|
||||
useAsm: false,
|
||||
useBare: true);
|
||||
dillPath: dillPath, stripFlag: false, stripUtil: true, useAsm: false);
|
||||
}
|
||||
|
||||
// TODO(sstrickl): Currently we can't assemble for SIMARM64 on MacOSX.
|
||||
|
@ -269,29 +241,9 @@ main() async {
|
|||
|
||||
// Test stripped assembly generation that is then compiled and stripped.
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: true,
|
||||
stripUtil: true,
|
||||
useAsm: true,
|
||||
useBare: false);
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: true,
|
||||
stripUtil: true,
|
||||
useAsm: true,
|
||||
useBare: true);
|
||||
dillPath: dillPath, stripFlag: true, stripUtil: true, useAsm: true);
|
||||
// Test unstripped assembly generation that is then compiled and stripped.
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: false,
|
||||
stripUtil: true,
|
||||
useAsm: true,
|
||||
useBare: false);
|
||||
await test(
|
||||
dillPath: dillPath,
|
||||
stripFlag: false,
|
||||
stripUtil: true,
|
||||
useAsm: true,
|
||||
useBare: true);
|
||||
dillPath: dillPath, stripFlag: false, stripUtil: true, useAsm: true);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace dart {
|
|||
V(Code) \
|
||||
V(Bytecode) \
|
||||
V(Instructions) \
|
||||
V(InstructionsSection) \
|
||||
V(ObjectPool) \
|
||||
V(PcDescriptors) \
|
||||
V(CodeSourceMap) \
|
||||
|
|
|
@ -1509,16 +1509,15 @@ class CodeSerializationCluster : public SerializationCluster {
|
|||
s->UnexpectedObject(code, "Disabled code");
|
||||
}
|
||||
|
||||
s->WriteInstructions(code->ptr()->instructions_,
|
||||
code->ptr()->unchecked_offset_, code);
|
||||
s->WriteInstructions(code->ptr()->instructions_, code);
|
||||
s->WriteUnsigned(code->ptr()->unchecked_offset_);
|
||||
if (kind == Snapshot::kFullJIT) {
|
||||
// TODO(rmacnak): Fix references to disabled code before serializing.
|
||||
// For now, we may write the FixCallersTarget or equivalent stub. This
|
||||
// will cause a fixup if this code is called.
|
||||
const uint32_t active_unchecked_offset =
|
||||
code->ptr()->unchecked_entry_point_ - code->ptr()->entry_point_;
|
||||
s->WriteInstructions(code->ptr()->active_instructions_,
|
||||
active_unchecked_offset, code);
|
||||
s->WriteInstructions(code->ptr()->active_instructions_, code);
|
||||
s->WriteUnsigned(code->ptr()->unchecked_entry_point_ -
|
||||
code->ptr()->entry_point_);
|
||||
}
|
||||
|
||||
WriteField(code, object_pool_);
|
||||
|
@ -1599,10 +1598,24 @@ class CodeDeserializationCluster : public DeserializationCluster {
|
|||
|
||||
void ReadFill(Deserializer* d) {
|
||||
for (intptr_t id = start_index_; id < stop_index_; id++) {
|
||||
auto const code = reinterpret_cast<RawCode*>(d->Ref(id));
|
||||
RawCode* code = reinterpret_cast<RawCode*>(d->Ref(id));
|
||||
Deserializer::InitializeHeader(code, kCodeCid, Code::InstanceSize(0));
|
||||
|
||||
d->ReadInstructions(code);
|
||||
RawInstructions* instr = d->ReadInstructions();
|
||||
uint32_t unchecked_offset = d->ReadUnsigned();
|
||||
|
||||
code->ptr()->instructions_ = instr;
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
code->ptr()->unchecked_offset_ = unchecked_offset;
|
||||
if (d->kind() == Snapshot::kFullJIT) {
|
||||
instr = d->ReadInstructions();
|
||||
unchecked_offset = d->ReadUnsigned();
|
||||
}
|
||||
code->ptr()->active_instructions_ = instr;
|
||||
#endif // !DART_PRECOMPILED_RUNTIME
|
||||
|
||||
Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
|
||||
|
||||
code->ptr()->object_pool_ =
|
||||
reinterpret_cast<RawObjectPool*>(d->ReadRef());
|
||||
|
@ -1638,32 +1651,7 @@ class CodeDeserializationCluster : public DeserializationCluster {
|
|||
#endif
|
||||
|
||||
code->ptr()->state_bits_ = d->Read<int32_t>();
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (FLAG_use_bare_instructions && id != start_index_) {
|
||||
// The following assumes that ReadInstructions put the offset of the
|
||||
// entry point from the payload start into instructions_length_. We
|
||||
// use this to calculate the length of the previous payload.
|
||||
RawCode* prev = reinterpret_cast<RawCode*>(d->Ref(id - 1));
|
||||
const uword prev_payload_start =
|
||||
prev->ptr()->entry_point_ - prev->ptr()->instructions_length_;
|
||||
const uword curr_payload_start =
|
||||
code->ptr()->entry_point_ - code->ptr()->instructions_length_;
|
||||
prev->ptr()->instructions_length_ =
|
||||
curr_payload_start - prev_payload_start;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (FLAG_use_bare_instructions) {
|
||||
// Since there is no following Code object, we assume that the last Code
|
||||
// object ends at the end of the instructions snapshot.
|
||||
auto const code = reinterpret_cast<RawCode*>(d->Ref(stop_index_ - 1));
|
||||
const uword curr_payload_start =
|
||||
code->ptr()->entry_point_ - code->ptr()->instructions_length_;
|
||||
code->ptr()->instructions_length_ =
|
||||
d->GetBareInstructionsEnd() - curr_payload_start;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
||||
|
@ -4687,9 +4675,7 @@ SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
|
|||
}
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
void Serializer::WriteInstructions(RawInstructions* instr,
|
||||
uint32_t unchecked_offset,
|
||||
RawCode* code) {
|
||||
void Serializer::WriteInstructions(RawInstructions* instr, RawCode* code) {
|
||||
ASSERT(code != Code::null());
|
||||
|
||||
const intptr_t offset = image_writer_->GetTextOffsetFor(instr, code);
|
||||
|
@ -4698,17 +4684,6 @@ void Serializer::WriteInstructions(RawInstructions* instr,
|
|||
UnexpectedObject(code, "Expected instructions to reuse");
|
||||
}
|
||||
Write<uint32_t>(offset);
|
||||
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
|
||||
// When writing only instruction payloads, we also need to serialize
|
||||
// whether there was a single entry. We add this as the low order bit
|
||||
// in the unchecked_offset.
|
||||
ASSERT(unchecked_offset <= kMaxInt32);
|
||||
const uint32_t payload_info =
|
||||
(unchecked_offset << 1) | (Code::HasMonomorphicEntry(code) ? 0x1 : 0x0);
|
||||
WriteUnsigned(payload_info);
|
||||
} else {
|
||||
WriteUnsigned(unchecked_offset);
|
||||
}
|
||||
|
||||
// If offset < 0, it's pointing to a shared instruction. We don't profile
|
||||
// references to shared text/data (since they don't consume any space). Of
|
||||
|
@ -5448,74 +5423,11 @@ RawApiError* FullSnapshotReader::ConvertToApiError(char* message) {
|
|||
return ApiError::New(msg, Heap::kOld);
|
||||
}
|
||||
|
||||
void Deserializer::ReadInstructions(RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
if (FLAG_use_bare_instructions) {
|
||||
const uint32_t bare_offset = Read<uint32_t>();
|
||||
const uword payload_start =
|
||||
image_reader_->GetBareInstructionsAt(bare_offset);
|
||||
const uint32_t payload_info = ReadUnsigned();
|
||||
const uint32_t unchecked_offset = payload_info >> 1;
|
||||
const bool has_monomorphic_entrypoint = (payload_info & 0x1) == 0x1;
|
||||
|
||||
const uword entry_offset = has_monomorphic_entrypoint
|
||||
? Instructions::kPolymorphicEntryOffsetAOT
|
||||
: 0;
|
||||
const uword monomorphic_entry_offset =
|
||||
has_monomorphic_entrypoint ? Instructions::kMonomorphicEntryOffsetAOT
|
||||
: 0;
|
||||
|
||||
const uword entry_point = payload_start + entry_offset;
|
||||
const uword monomorphic_entry_point =
|
||||
payload_start + monomorphic_entry_offset;
|
||||
|
||||
code->ptr()->instructions_ = Instructions::null();
|
||||
code->ptr()->entry_point_ = entry_point;
|
||||
code->ptr()->unchecked_entry_point_ = entry_point + unchecked_offset;
|
||||
code->ptr()->monomorphic_entry_point_ = monomorphic_entry_point;
|
||||
code->ptr()->monomorphic_unchecked_entry_point_ =
|
||||
monomorphic_entry_point + unchecked_offset;
|
||||
// We don't serialize the length of the instructions payload. Instead, the
|
||||
// deserializer calculates an approximate length (may include padding)
|
||||
// by subtracting the payload offset of the next Code object (if any)
|
||||
// from this one. (For the last Code object, we assume its serialization
|
||||
// extends to the end of the instructions image.)
|
||||
//
|
||||
// Since the Code object doesn't include a field for the payload start,
|
||||
// we store the entry_offset (calculated above) in instructions_length_
|
||||
// for now, and subtract it from entry_point_ later after reading the
|
||||
// next Code object.
|
||||
ASSERT(entry_offset <= kMaxUint32);
|
||||
code->ptr()->instructions_length_ = entry_offset;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint32_t offset = Read<uint32_t>();
|
||||
RawInstructions* instr = image_reader_->GetInstructionsAt(offset);
|
||||
uint32_t unchecked_offset = ReadUnsigned();
|
||||
|
||||
code->ptr()->instructions_ = instr;
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
code->ptr()->instructions_length_ = Instructions::Size(instr);
|
||||
#else
|
||||
code->ptr()->unchecked_offset_ = unchecked_offset;
|
||||
if (kind() == Snapshot::kFullJIT) {
|
||||
const uint32_t active_offset = Read<uint32_t>();
|
||||
instr = image_reader_->GetInstructionsAt(active_offset);
|
||||
unchecked_offset = ReadUnsigned();
|
||||
}
|
||||
code->ptr()->active_instructions_ = instr;
|
||||
#endif
|
||||
Code::InitializeCachedEntryPointsFrom(code, instr, unchecked_offset);
|
||||
RawInstructions* Deserializer::ReadInstructions() {
|
||||
uint32_t offset = Read<uint32_t>();
|
||||
return image_reader_->GetInstructionsAt(offset);
|
||||
}
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
uword Deserializer::GetBareInstructionsEnd() {
|
||||
return image_reader_->GetBareInstructionsEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
RawObject* Deserializer::GetObjectAt(uint32_t offset) const {
|
||||
return image_reader_->GetObjectAt(offset);
|
||||
}
|
||||
|
|
|
@ -358,9 +358,7 @@ class Serializer : public ThreadStackResource {
|
|||
Write<int32_t>(cid);
|
||||
}
|
||||
|
||||
void WriteInstructions(RawInstructions* instr,
|
||||
uint32_t unchecked_offset,
|
||||
RawCode* code);
|
||||
void WriteInstructions(RawInstructions* instr, RawCode* code);
|
||||
uint32_t GetDataOffset(RawObject* object) const;
|
||||
void TraceDataOffset(uint32_t offset);
|
||||
intptr_t GetDataSize() const;
|
||||
|
@ -561,8 +559,7 @@ class Deserializer : public ThreadStackResource {
|
|||
return Read<int32_t>();
|
||||
}
|
||||
|
||||
ONLY_IN_PRECOMPILED(uword GetBareInstructionsEnd());
|
||||
void ReadInstructions(RawCode* code);
|
||||
RawInstructions* ReadInstructions();
|
||||
RawObject* GetObjectAt(uint32_t offset) const;
|
||||
|
||||
void SkipHeader() { stream_.SetPosition(Snapshot::kHeaderSize); }
|
||||
|
|
|
@ -303,7 +303,7 @@ class AssemblerBase : public StackResource {
|
|||
explicit AssemblerBase(ObjectPoolBuilder* object_pool_builder)
|
||||
: StackResource(ThreadState::Current()),
|
||||
prologue_offset_(-1),
|
||||
has_monomorphic_entry_(false),
|
||||
has_single_entry_point_(true),
|
||||
object_pool_builder_(object_pool_builder) {}
|
||||
virtual ~AssemblerBase();
|
||||
|
||||
|
@ -315,7 +315,7 @@ class AssemblerBase : public StackResource {
|
|||
ObjectPoolBuilder& object_pool_builder() { return *object_pool_builder_; }
|
||||
|
||||
intptr_t prologue_offset() const { return prologue_offset_; }
|
||||
bool has_monomorphic_entry() const { return has_monomorphic_entry_; }
|
||||
bool has_single_entry_point() const { return has_single_entry_point_; }
|
||||
|
||||
void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
|
||||
static bool EmittingComments();
|
||||
|
@ -370,7 +370,7 @@ class AssemblerBase : public StackResource {
|
|||
protected:
|
||||
AssemblerBuffer buffer_; // Contains position independent code.
|
||||
int32_t prologue_offset_;
|
||||
bool has_monomorphic_entry_;
|
||||
bool has_single_entry_point_;
|
||||
|
||||
intptr_t unchecked_entry_offset_ = 0;
|
||||
|
||||
|
|
|
@ -3437,7 +3437,7 @@ void Assembler::LeaveStubFrame() {
|
|||
// R0 receiver, R9 ICData entries array
|
||||
// Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryJIT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
#if defined(TESTING) || defined(DEBUG)
|
||||
bool saved_use_far_branches = use_far_branches();
|
||||
set_use_far_branches(false);
|
||||
|
@ -3473,7 +3473,7 @@ void Assembler::MonomorphicCheckedEntryJIT() {
|
|||
// R0 receiver, R9 guarded cid as Smi.
|
||||
// Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryAOT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
#if defined(TESTING) || defined(DEBUG)
|
||||
bool saved_use_far_branches = use_far_branches();
|
||||
set_use_far_branches(false);
|
||||
|
@ -3498,7 +3498,7 @@ void Assembler::MonomorphicCheckedEntryAOT() {
|
|||
}
|
||||
|
||||
void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
|
||||
bkpt(0);
|
||||
}
|
||||
|
|
|
@ -1532,7 +1532,7 @@ void Assembler::LeaveStubFrame() {
|
|||
// R0 receiver, R5 ICData entries array
|
||||
// Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryJIT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
const bool saved_use_far_branches = use_far_branches();
|
||||
set_use_far_branches(false);
|
||||
const intptr_t start = CodeSize();
|
||||
|
@ -1569,7 +1569,7 @@ void Assembler::MonomorphicCheckedEntryJIT() {
|
|||
// R0 receiver, R5 guarded cid as Smi.
|
||||
// Preserve R4 (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryAOT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
bool saved_use_far_branches = use_far_branches();
|
||||
set_use_far_branches(false);
|
||||
|
||||
|
@ -1595,7 +1595,7 @@ void Assembler::MonomorphicCheckedEntryAOT() {
|
|||
}
|
||||
|
||||
void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
|
||||
brk(0);
|
||||
}
|
||||
|
|
|
@ -2117,7 +2117,7 @@ void Assembler::EmitEntryFrameVerification() {
|
|||
// EBX receiver, ECX ICData entries array
|
||||
// Preserve EDX (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryJIT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
intptr_t start = CodeSize();
|
||||
Label have_cid, miss;
|
||||
Bind(&miss);
|
||||
|
@ -2156,7 +2156,7 @@ void Assembler::MonomorphicCheckedEntryAOT() {
|
|||
}
|
||||
|
||||
void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
|
||||
int3();
|
||||
}
|
||||
|
|
|
@ -1798,7 +1798,7 @@ void Assembler::LeaveStubFrame() {
|
|||
// RDX receiver, RBX ICData entries array
|
||||
// Preserve R10 (ARGS_DESC_REG), not required today, but maybe later.
|
||||
void Assembler::MonomorphicCheckedEntryJIT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
intptr_t start = CodeSize();
|
||||
Label have_cid, miss;
|
||||
Bind(&miss);
|
||||
|
@ -1831,7 +1831,7 @@ void Assembler::MonomorphicCheckedEntryJIT() {
|
|||
}
|
||||
|
||||
void Assembler::MonomorphicCheckedEntryAOT() {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
intptr_t start = CodeSize();
|
||||
Label have_cid, miss;
|
||||
Bind(&miss);
|
||||
|
@ -1862,7 +1862,7 @@ void Assembler::MonomorphicCheckedEntryAOT() {
|
|||
}
|
||||
|
||||
void Assembler::BranchOnMonomorphicCheckedEntryJIT(Label* label) {
|
||||
has_monomorphic_entry_ = true;
|
||||
has_single_entry_point_ = false;
|
||||
while (CodeSize() < target::Instructions::kMonomorphicEntryOffsetJIT) {
|
||||
int3();
|
||||
}
|
||||
|
|
|
@ -258,7 +258,8 @@ void Disassembler::DisassembleCodeHelper(const char* function_fullname,
|
|||
PcDescriptors::Handle(zone, code.pc_descriptors());
|
||||
THR_Print("%s}\n", descriptors.ToCString());
|
||||
|
||||
const uword start = code.PayloadStart();
|
||||
const auto& instructions = Instructions::Handle(code.instructions());
|
||||
const uword start = instructions.PayloadStart();
|
||||
const uword base = FLAG_disassemble_relative ? 0 : start;
|
||||
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
|
|
@ -157,7 +157,8 @@ void CodeRelocator::FindInstructionAndCallLimits() {
|
|||
offset_into_target = call.distance();
|
||||
}
|
||||
|
||||
const uword destination_payload = destination_.PayloadStart();
|
||||
const uword destination_payload =
|
||||
Instructions::PayloadStart(destination_.instructions());
|
||||
const uword entry_point = call_entry_point == Code::kUncheckedEntry
|
||||
? destination_.UncheckedEntryPoint()
|
||||
: destination_.EntryPoint();
|
||||
|
@ -271,16 +272,17 @@ void CodeRelocator::ScanCallTargets(const Code& code,
|
|||
offset_into_target = call.distance();
|
||||
}
|
||||
|
||||
const uword destination_payload = destination_.PayloadStart();
|
||||
const uword destination_payload =
|
||||
Instructions::PayloadStart(destination_.instructions());
|
||||
const uword entry_point = call_entry_point == Code::kUncheckedEntry
|
||||
? destination_.UncheckedEntryPoint()
|
||||
: destination_.EntryPoint();
|
||||
|
||||
offset_into_target += (entry_point - destination_payload);
|
||||
|
||||
const intptr_t text_offset =
|
||||
code_text_offset + AdjustPayloadOffset(call_instruction_offset);
|
||||
|
||||
const intptr_t text_offset = code_text_offset +
|
||||
compiler::target::Instructions::HeaderSize() +
|
||||
call_instruction_offset;
|
||||
UnresolvedCall unresolved_call(code.raw(), call_instruction_offset,
|
||||
text_offset, destination_.raw(),
|
||||
offset_into_target);
|
||||
|
@ -366,12 +368,12 @@ void CodeRelocator::ResolveCallToDestination(UnresolvedCall* unresolved_call,
|
|||
const intptr_t call_text_offset = unresolved_call->text_offset;
|
||||
const intptr_t call_offset = unresolved_call->call_offset;
|
||||
|
||||
auto caller = Code::InstructionsOf(unresolved_call->caller);
|
||||
const int32_t distance = destination_text - call_text_offset;
|
||||
{
|
||||
auto const caller = unresolved_call->caller;
|
||||
uword addr = Code::PayloadStartOf(caller) + call_offset;
|
||||
uword addr = Instructions::PayloadStart(caller) + call_offset;
|
||||
if (FLAG_write_protect_code) {
|
||||
addr -= HeapPage::Of(Code::InstructionsOf(caller))->AliasOffset();
|
||||
addr -= HeapPage::Of(caller)->AliasOffset();
|
||||
}
|
||||
PcRelativeCallPattern call(addr);
|
||||
ASSERT(call.IsValid());
|
||||
|
@ -508,15 +510,9 @@ void CodeRelocator::BuildTrampolinesForAlmostOutOfRangeCalls() {
|
|||
intptr_t CodeRelocator::FindDestinationInText(
|
||||
const RawInstructions* destination,
|
||||
intptr_t offset_into_target) {
|
||||
auto const destination_offset = text_offsets_.LookupValue(destination);
|
||||
return destination_offset + AdjustPayloadOffset(offset_into_target);
|
||||
}
|
||||
|
||||
intptr_t CodeRelocator::AdjustPayloadOffset(intptr_t payload_offset) {
|
||||
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
|
||||
return payload_offset;
|
||||
}
|
||||
return compiler::target::Instructions::HeaderSize() + payload_offset;
|
||||
auto destination_offset = text_offsets_.LookupValue(destination);
|
||||
return destination_offset + compiler::target::Instructions::HeaderSize() +
|
||||
offset_into_target;
|
||||
}
|
||||
|
||||
#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
|
||||
|
|
|
@ -178,8 +178,6 @@ class CodeRelocator : public StackResource {
|
|||
intptr_t FindDestinationInText(const RawInstructions* destination,
|
||||
intptr_t offset_into_target);
|
||||
|
||||
static intptr_t AdjustPayloadOffset(intptr_t payload_offset);
|
||||
|
||||
bool IsTargetInRangeFor(UnresolvedCall* unresolved_call,
|
||||
intptr_t target_text_offset);
|
||||
|
||||
|
|
|
@ -513,11 +513,6 @@ const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;
|
|||
|
||||
const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
|
||||
|
||||
word InstructionsSection::HeaderSize() {
|
||||
return Utils::RoundUp(InstructionsSection::UnalignedHeaderSize(),
|
||||
target::kWordSize);
|
||||
}
|
||||
|
||||
word Instructions::HeaderSize() {
|
||||
return Utils::RoundUp(Instructions::UnalignedHeaderSize(), target::kWordSize);
|
||||
}
|
||||
|
@ -916,10 +911,6 @@ word MonomorphicSmiableCall::NextFieldOffset() {
|
|||
return -kWordSize;
|
||||
}
|
||||
|
||||
word InstructionsSection::NextFieldOffset() {
|
||||
return -kWordSize;
|
||||
}
|
||||
|
||||
word Instructions::NextFieldOffset() {
|
||||
return -kWordSize;
|
||||
}
|
||||
|
|
|
@ -1063,14 +1063,6 @@ class ClassTable : public AllStatic {
|
|||
static const word kSizeOfClassPairLog2;
|
||||
};
|
||||
|
||||
class InstructionsSection : public AllStatic {
|
||||
public:
|
||||
static word HeaderSize();
|
||||
static word UnalignedHeaderSize();
|
||||
static word InstanceSize();
|
||||
static word NextFieldOffset();
|
||||
};
|
||||
|
||||
class Instructions : public AllStatic {
|
||||
public:
|
||||
static const word kMonomorphicEntryOffsetJIT;
|
||||
|
|
|
@ -415,10 +415,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -878,10 +874,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -1334,10 +1326,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -1798,10 +1786,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -2254,10 +2238,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -2711,10 +2691,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -3161,10 +3137,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -3619,10 +3591,6 @@ static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
|
|||
static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
|
||||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
|
||||
|
@ -4111,10 +4079,6 @@ static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -4617,10 +4581,6 @@ static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
|
|||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -5127,10 +5087,6 @@ static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
|
|||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -5593,7 +5549,7 @@ static constexpr dart::compiler::target::word AOT_Capability_InstanceSize = 16;
|
|||
static constexpr dart::compiler::target::word AOT_Class_InstanceSize = 112;
|
||||
static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
|
||||
static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
|
||||
static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 64;
|
||||
static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 60;
|
||||
static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
|
||||
8;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -5626,10 +5582,6 @@ static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
|
|||
static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 8;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -6125,10 +6077,6 @@ static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
|
|||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
@ -6628,10 +6576,6 @@ static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
|
|||
12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_Instructions_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_InstanceSize = 12;
|
||||
static constexpr dart::compiler::target::word
|
||||
AOT_InstructionsSection_UnalignedHeaderSize = 12;
|
||||
static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
|
||||
static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
|
||||
static constexpr dart::compiler::target::word
|
||||
|
|
|
@ -286,8 +286,6 @@
|
|||
SIZEOF(Instance, InstanceSize, RawInstance) \
|
||||
SIZEOF(Instructions, InstanceSize, RawInstructions) \
|
||||
SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions) \
|
||||
SIZEOF(InstructionsSection, InstanceSize, RawInstructionsSection) \
|
||||
SIZEOF(InstructionsSection, UnalignedHeaderSize, RawInstructionsSection) \
|
||||
SIZEOF(Int32x4, InstanceSize, RawInt32x4) \
|
||||
SIZEOF(Integer, InstanceSize, RawInteger) \
|
||||
SIZEOF(KernelProgramInfo, InstanceSize, RawKernelProgramInfo) \
|
||||
|
|
|
@ -78,12 +78,6 @@ const intptr_t kDefaultMaxOldGenHeapSize = (kWordSize <= 4) ? 1536 : 30720;
|
|||
#define NOT_IN_PRECOMPILED(code) code
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
#define ONLY_IN_PRECOMPILED(code) code
|
||||
#else
|
||||
#define ONLY_IN_PRECOMPILED(code)
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
|
||||
defined(TARGET_ARCH_X64)
|
||||
#define ONLY_IN_ARM_ARM64_X64(code) code
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "vm/image_snapshot.h"
|
||||
|
||||
#include "platform/assert.h"
|
||||
#include "vm/class_id.h"
|
||||
#include "vm/compiler/backend/code_statistics.h"
|
||||
#include "vm/compiler/runtime_api.h"
|
||||
#include "vm/dwarf.h"
|
||||
|
@ -136,25 +135,6 @@ int32_t ImageWriter::GetTextOffsetFor(RawInstructions* instructions,
|
|||
return offset;
|
||||
}
|
||||
|
||||
static intptr_t InstructionsSizeInSnapshot(RawInstructions* raw) {
|
||||
if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
|
||||
// Currently, we align bare instruction payloads on 4 byte boundaries.
|
||||
//
|
||||
// If we later decide to align on larger boundaries to put entries at the
|
||||
// start of cache lines, make sure to account for entry points that are
|
||||
// _not_ at the start of the payload.
|
||||
return Utils::RoundUp(Instructions::Size(raw),
|
||||
ImageWriter::kBareInstructionsAlignment);
|
||||
}
|
||||
#if defined(IS_SIMARM_X64)
|
||||
return Utils::RoundUp(
|
||||
compiler::target::Instructions::HeaderSize() + Instructions::Size(raw),
|
||||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
#else
|
||||
return raw->HeapSize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(IS_SIMARM_X64)
|
||||
static intptr_t CompressedStackMapsSizeInSnapshot(intptr_t payload_size) {
|
||||
// We do not need to round the non-payload size up to a word boundary because
|
||||
|
@ -191,6 +171,11 @@ static intptr_t PcDescriptorsSizeInSnapshot(intptr_t len) {
|
|||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
}
|
||||
|
||||
static intptr_t InstructionsSizeInSnapshot(intptr_t len) {
|
||||
return Utils::RoundUp(compiler::target::Instructions::HeaderSize() + len,
|
||||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
}
|
||||
|
||||
intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
|
||||
const classid_t cid = raw_object->GetClassId();
|
||||
|
||||
|
@ -216,7 +201,7 @@ intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
|
|||
}
|
||||
case kInstructionsCid: {
|
||||
RawInstructions* raw_insns = static_cast<RawInstructions*>(raw_object);
|
||||
return InstructionsSizeInSnapshot(raw_insns);
|
||||
return InstructionsSizeInSnapshot(Instructions::Size(raw_insns));
|
||||
}
|
||||
default: {
|
||||
const Class& clazz = Class::Handle(Object::Handle(raw_object).clazz());
|
||||
|
@ -226,13 +211,8 @@ intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
|
|||
}
|
||||
}
|
||||
#else // defined(IS_SIMARM_X64)
|
||||
intptr_t ImageWriter::SizeInSnapshot(RawObject* raw) {
|
||||
switch (raw->GetClassId()) {
|
||||
case kInstructionsCid:
|
||||
return InstructionsSizeInSnapshot(static_cast<RawInstructions*>(raw));
|
||||
default:
|
||||
return raw->HeapSize();
|
||||
}
|
||||
intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
|
||||
return raw_object->HeapSize();
|
||||
}
|
||||
#endif // defined(IS_SIMARM_X64)
|
||||
|
||||
|
@ -576,9 +556,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
#else
|
||||
Zone* zone = Thread::Current()->zone();
|
||||
|
||||
const bool bare_instruction_payloads =
|
||||
FLAG_precompiled_mode && FLAG_use_bare_instructions;
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
const char* bss_symbol =
|
||||
vm ? "_kDartVmSnapshotBss" : "_kDartIsolateSnapshotBss";
|
||||
|
@ -595,14 +572,13 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
// Start snapshot at page boundary.
|
||||
ASSERT(VirtualMemory::PageSize() >= kMaxObjectAlignment);
|
||||
Align(VirtualMemory::PageSize());
|
||||
assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
|
||||
assembly_stream_.Print("%s:\n", instructions_symbol);
|
||||
|
||||
// This head also provides the gap to make the instructions snapshot
|
||||
// look like a HeapPage.
|
||||
const intptr_t image_size = Utils::RoundUp(
|
||||
next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
WriteWordLiteralText(image_size);
|
||||
intptr_t instructions_length = next_text_offset_;
|
||||
WriteWordLiteralText(instructions_length);
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
assembly_stream_.Print("%s %s - %s\n", kLiteralPrefix, bss_symbol,
|
||||
|
@ -616,43 +592,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
WriteWordLiteralText(0);
|
||||
}
|
||||
|
||||
if (bare_instruction_payloads) {
|
||||
const intptr_t image_payload_length = image_size - Image::kHeaderSize;
|
||||
// Add the RawInstructionsSection header.
|
||||
uword marked_tags = 0;
|
||||
marked_tags = RawObject::OldBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::SizeTag::update(image_payload_length, marked_tags);
|
||||
marked_tags =
|
||||
RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
|
||||
|
||||
WriteWordLiteralText(marked_tags);
|
||||
// Calculated using next_text_offset_, which doesn't include post-payload
|
||||
// padding to object alignment.
|
||||
const intptr_t instructions_length =
|
||||
next_text_offset_ - Image::kHeaderSize -
|
||||
compiler::target::InstructionsSection::HeaderSize();
|
||||
WriteWordLiteralText(instructions_length);
|
||||
|
||||
if (profile_writer_ != nullptr) {
|
||||
const intptr_t offset = Image::kHeaderSize;
|
||||
const intptr_t non_instruction_bytes =
|
||||
compiler::target::InstructionsSection::HeaderSize();
|
||||
profile_writer_->SetObjectTypeAndName({offset_space_, offset},
|
||||
"InstructionsSection",
|
||||
/*name=*/nullptr);
|
||||
profile_writer_->AttributeBytesTo({offset_space_, offset},
|
||||
non_instruction_bytes);
|
||||
profile_writer_->AddRoot({offset_space_, offset});
|
||||
}
|
||||
}
|
||||
|
||||
const intptr_t section_headers_size =
|
||||
Image::kHeaderSize +
|
||||
(bare_instruction_payloads
|
||||
? compiler::target::InstructionsSection::HeaderSize()
|
||||
: 0);
|
||||
|
||||
FrameUnwindPrologue();
|
||||
|
||||
PcDescriptors& descriptors = PcDescriptors::Handle(zone);
|
||||
|
@ -665,19 +604,9 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
const bool is_trampoline = data.trampoline_bytes != nullptr;
|
||||
ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
|
||||
|
||||
if (bare_instruction_payloads && profile_writer_ != nullptr) {
|
||||
const intptr_t instructions_sections_offset = Image::kHeaderSize;
|
||||
const intptr_t offset = section_headers_size + text_offset;
|
||||
profile_writer_->AttributeReferenceTo(
|
||||
{offset_space_, instructions_sections_offset},
|
||||
{{offset_space_, offset},
|
||||
V8SnapshotProfileWriter::Reference::kElement,
|
||||
text_offset});
|
||||
}
|
||||
|
||||
if (is_trampoline) {
|
||||
if (profile_writer_ != nullptr) {
|
||||
const intptr_t offset = section_headers_size + text_offset;
|
||||
const intptr_t offset = Image::kHeaderSize + text_offset;
|
||||
profile_writer_->SetObjectTypeAndName({offset_space_, offset},
|
||||
"Trampolines",
|
||||
/*name=*/nullptr);
|
||||
|
@ -700,7 +629,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
descriptors = data.code_->pc_descriptors();
|
||||
|
||||
if (profile_writer_ != nullptr) {
|
||||
const intptr_t offset = section_headers_size + text_offset;
|
||||
const intptr_t offset = Image::kHeaderSize + text_offset;
|
||||
profile_writer_->SetObjectTypeAndName({offset_space_, offset},
|
||||
"Instructions",
|
||||
/*name=*/nullptr);
|
||||
|
@ -708,12 +637,9 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
SizeInSnapshot(insns.raw()));
|
||||
}
|
||||
|
||||
const uword payload_start = insns.PayloadStart();
|
||||
|
||||
// 1. Write from the object start to the payload start. This includes the
|
||||
// object header and the fixed fields. Not written for AOT snapshots using
|
||||
// bare instructions.
|
||||
if (!bare_instruction_payloads) {
|
||||
// object header and the fixed fields.
|
||||
{
|
||||
NoSafepointScope no_safepoint;
|
||||
|
||||
// Write Instructions with the mark and read-only bits set.
|
||||
|
@ -730,7 +656,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
#endif
|
||||
|
||||
#if defined(IS_SIMARM_X64)
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.Size());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
WriteWordLiteralText(marked_tags);
|
||||
text_offset += sizeof(compiler::target::uword);
|
||||
|
@ -738,6 +664,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
text_offset += sizeof(compiler::target::uword);
|
||||
#else // defined(IS_SIMARM_X64)
|
||||
uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
|
||||
uword payload_start = insns.PayloadStart();
|
||||
WriteWordLiteralText(marked_tags);
|
||||
object_start += sizeof(uword);
|
||||
text_offset += sizeof(uword);
|
||||
|
@ -756,7 +683,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
}
|
||||
if (debug_dwarf_ != nullptr) {
|
||||
auto const virtual_address =
|
||||
debug_segment_base + section_headers_size + text_offset;
|
||||
debug_segment_base + Image::kHeaderSize + text_offset;
|
||||
debug_dwarf_->AddCode(code, virtual_address);
|
||||
}
|
||||
#endif
|
||||
|
@ -765,29 +692,19 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
assembly_stream_.Print("%s:\n", namer.AssemblyNameFor(dwarf_index, code));
|
||||
|
||||
{
|
||||
// 3. Write from the payload start to payload end. For AOT snapshots
|
||||
// with bare instructions, this is the only part serialized.
|
||||
// 3. Write from the payload start to payload end.
|
||||
NoSafepointScope no_safepoint;
|
||||
assert(kBareInstructionsAlignment <=
|
||||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
const auto payload_align = bare_instruction_payloads
|
||||
? kBareInstructionsAlignment
|
||||
: sizeof(compiler::target::uword);
|
||||
const uword payload_size = Utils::RoundUp(insns.Size(), payload_align);
|
||||
const uword payload_start = insns.PayloadStart();
|
||||
const uword payload_size =
|
||||
Utils::RoundUp(insns.Size(), sizeof(compiler::target::uword));
|
||||
const uword payload_end = payload_start + payload_size;
|
||||
|
||||
ASSERT(Utils::IsAligned(text_offset, payload_align));
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
PcDescriptors::Iterator iterator(descriptors,
|
||||
RawPcDescriptors::kBSSRelocation);
|
||||
uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
|
||||
|
||||
// We only generate BSS relocations that are word-sized and at
|
||||
// word-aligned offsets in the payload.
|
||||
auto const possible_relocations_end =
|
||||
Utils::RoundDown(payload_end, sizeof(compiler::target::uword));
|
||||
for (uword cursor = payload_start; cursor < possible_relocations_end;
|
||||
for (uword cursor = payload_start; cursor < payload_end;
|
||||
cursor += sizeof(compiler::target::uword)) {
|
||||
compiler::target::uword data =
|
||||
*reinterpret_cast<compiler::target::uword*>(cursor);
|
||||
|
@ -799,8 +716,6 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
WriteWordLiteralText(data);
|
||||
}
|
||||
}
|
||||
assert(next_reloc_offset != (possible_relocations_end - payload_start));
|
||||
WriteByteSequence(possible_relocations_end, payload_end);
|
||||
text_offset += payload_size;
|
||||
#else
|
||||
text_offset += WriteByteSequence(payload_start, payload_end);
|
||||
|
@ -808,43 +723,26 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
// 4. Write from the payload end to object end. Note we can't simply copy
|
||||
// from the object because the host object may have less alignment filler
|
||||
// than the target object in the cross-word case. Not written for AOT
|
||||
// snapshots using bare instructions.
|
||||
if (!bare_instruction_payloads) {
|
||||
uword unaligned_size =
|
||||
compiler::target::Instructions::HeaderSize() + payload_size;
|
||||
uword alignment_size =
|
||||
Utils::RoundUp(
|
||||
unaligned_size,
|
||||
compiler::target::ObjectAlignment::kObjectAlignment) -
|
||||
unaligned_size;
|
||||
while (alignment_size > 0) {
|
||||
WriteWordLiteralText(
|
||||
compiler::Assembler::GetBreakInstructionFiller());
|
||||
alignment_size -= sizeof(compiler::target::uword);
|
||||
text_offset += sizeof(compiler::target::uword);
|
||||
}
|
||||
|
||||
ASSERT(kWordSize != compiler::target::kWordSize ||
|
||||
(text_offset - instr_start) == insns.raw()->HeapSize());
|
||||
// than the target object in the cross-word case.
|
||||
uword unaligned_size =
|
||||
compiler::target::Instructions::HeaderSize() + payload_size;
|
||||
uword alignment_size =
|
||||
Utils::RoundUp(unaligned_size,
|
||||
compiler::target::ObjectAlignment::kObjectAlignment) -
|
||||
unaligned_size;
|
||||
while (alignment_size > 0) {
|
||||
WriteWordLiteralText(compiler::Assembler::GetBreakInstructionFiller());
|
||||
alignment_size -= sizeof(compiler::target::uword);
|
||||
text_offset += sizeof(compiler::target::uword);
|
||||
}
|
||||
|
||||
ASSERT(kWordSize != compiler::target::kWordSize ||
|
||||
(text_offset - instr_start) == insns.raw()->HeapSize());
|
||||
}
|
||||
|
||||
ASSERT((text_offset - instr_start) == SizeInSnapshot(insns.raw()));
|
||||
}
|
||||
|
||||
// Should be a no-op unless writing bare instruction payloads, in which case
|
||||
// we need to add post-payload padding to the object alignment.
|
||||
text_offset +=
|
||||
Align(compiler::target::ObjectAlignment::kObjectAlignment, text_offset);
|
||||
|
||||
ASSERT(Image::kHeaderSize +
|
||||
(bare_instruction_payloads
|
||||
? compiler::target::InstructionsSection::HeaderSize()
|
||||
: 0) +
|
||||
text_offset ==
|
||||
image_size);
|
||||
|
||||
FrameUnwindEpilogue();
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
|
@ -865,7 +763,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
// we can pass nullptr for the bytes of the section/segment.
|
||||
auto const debug_segment_base2 =
|
||||
debug_dwarf_->elf()->AddText(instructions_symbol, /*bytes=*/nullptr,
|
||||
section_headers_size + text_offset);
|
||||
Image::kHeaderSize + text_offset);
|
||||
ASSERT(debug_segment_base2 == debug_segment_base);
|
||||
}
|
||||
|
||||
|
@ -890,7 +788,7 @@ void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
const char* data_symbol =
|
||||
vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData";
|
||||
assembly_stream_.Print(".globl %s\n", data_symbol);
|
||||
Align(kMaxObjectAlignment);
|
||||
assembly_stream_.Print(".balign %" Pd ", 0\n", kMaxObjectAlignment);
|
||||
assembly_stream_.Print("%s:\n", data_symbol);
|
||||
uword buffer = reinterpret_cast<uword>(clustered_stream->buffer());
|
||||
intptr_t length = clustered_stream->bytes_written();
|
||||
|
@ -976,33 +874,13 @@ void AssemblyImageWriter::FrameUnwindEpilogue() {
|
|||
}
|
||||
|
||||
intptr_t AssemblyImageWriter::WriteByteSequence(uword start, uword end) {
|
||||
assert(end >= start);
|
||||
auto const end_of_words =
|
||||
Utils::RoundDown(end, sizeof(compiler::target::uword));
|
||||
for (auto cursor = reinterpret_cast<compiler::target::uword*>(start);
|
||||
cursor < reinterpret_cast<compiler::target::uword*>(end_of_words);
|
||||
cursor++) {
|
||||
for (auto* cursor = reinterpret_cast<compiler::target::uword*>(start);
|
||||
cursor < reinterpret_cast<compiler::target::uword*>(end); cursor++) {
|
||||
WriteWordLiteralText(*cursor);
|
||||
}
|
||||
if (end != end_of_words) {
|
||||
auto start_of_rest = reinterpret_cast<const uint8_t*>(end_of_words);
|
||||
assembly_stream_.Print(".byte ");
|
||||
for (auto cursor = start_of_rest;
|
||||
cursor < reinterpret_cast<const uint8_t*>(end); cursor++) {
|
||||
if (cursor != start_of_rest) assembly_stream_.Print(", ");
|
||||
assembly_stream_.Print("0x%0.2" Px "", *cursor);
|
||||
}
|
||||
assembly_stream_.Print("\n");
|
||||
}
|
||||
return end - start;
|
||||
}
|
||||
|
||||
intptr_t AssemblyImageWriter::Align(intptr_t alignment, uword position) {
|
||||
const uword next_position = Utils::RoundUp(position, alignment);
|
||||
assembly_stream_.Print(".balign %" Pd ", 0\n", alignment);
|
||||
return next_position - position;
|
||||
}
|
||||
|
||||
BlobImageWriter::BlobImageWriter(Thread* thread,
|
||||
uint8_t** instructions_blob_buffer,
|
||||
ReAlloc alloc,
|
||||
|
@ -1034,9 +912,7 @@ intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) {
|
|||
}
|
||||
|
||||
void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
||||
const bool bare_instruction_payloads =
|
||||
FLAG_precompiled_mode && FLAG_use_bare_instructions;
|
||||
|
||||
const intptr_t instructions_length = next_text_offset_;
|
||||
#ifdef DART_PRECOMPILER
|
||||
intptr_t segment_base = 0;
|
||||
if (elf_ != nullptr) {
|
||||
|
@ -1050,9 +926,7 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
// This header provides the gap to make the instructions snapshot look like a
|
||||
// HeapPage.
|
||||
const intptr_t image_size = Utils::RoundUp(
|
||||
next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
instructions_blob_stream_.WriteTargetWord(image_size);
|
||||
instructions_blob_stream_.WriteTargetWord(instructions_length);
|
||||
#if defined(DART_PRECOMPILER)
|
||||
instructions_blob_stream_.WriteTargetWord(
|
||||
elf_ != nullptr ? bss_base_ - segment_base : 0);
|
||||
|
@ -1065,36 +939,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
instructions_blob_stream_.WriteTargetWord(0);
|
||||
}
|
||||
|
||||
if (bare_instruction_payloads) {
|
||||
const intptr_t image_payload_length = image_size - Image::kHeaderSize;
|
||||
// Add the RawInstructionsSection header.
|
||||
uword marked_tags = 0;
|
||||
marked_tags = RawObject::OldBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::OldAndNotRememberedBit::update(true, marked_tags);
|
||||
marked_tags = RawObject::SizeTag::update(image_payload_length, marked_tags);
|
||||
marked_tags =
|
||||
RawObject::ClassIdTag::update(kInstructionsSectionCid, marked_tags);
|
||||
|
||||
instructions_blob_stream_.WriteTargetWord(marked_tags);
|
||||
// Uses next_text_offset_ to avoid any post-payload padding.
|
||||
const intptr_t instructions_length =
|
||||
next_text_offset_ - Image::kHeaderSize -
|
||||
compiler::target::InstructionsSection::HeaderSize();
|
||||
instructions_blob_stream_.WriteTargetWord(instructions_length);
|
||||
|
||||
if (profile_writer_ != nullptr) {
|
||||
const intptr_t offset = Image::kHeaderSize;
|
||||
const intptr_t non_instruction_bytes =
|
||||
compiler::target::InstructionsSection::HeaderSize();
|
||||
profile_writer_->SetObjectTypeAndName({offset_space_, offset},
|
||||
"InstructionsSection",
|
||||
/*name=*/nullptr);
|
||||
profile_writer_->AttributeBytesTo({offset_space_, offset},
|
||||
non_instruction_bytes);
|
||||
profile_writer_->AddRoot({offset_space_, offset});
|
||||
}
|
||||
}
|
||||
|
||||
intptr_t text_offset = 0;
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
|
@ -1108,15 +952,6 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
const bool is_trampoline = data.trampoline_bytes != nullptr;
|
||||
ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
|
||||
|
||||
if (bare_instruction_payloads && profile_writer_ != nullptr) {
|
||||
const intptr_t instructions_sections_offset = Image::kHeaderSize;
|
||||
profile_writer_->AttributeReferenceTo(
|
||||
{offset_space_, instructions_sections_offset},
|
||||
{{offset_space_, instructions_blob_stream_.Position()},
|
||||
V8SnapshotProfileWriter::Reference::kElement,
|
||||
text_offset});
|
||||
}
|
||||
|
||||
if (is_trampoline) {
|
||||
const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
|
||||
const auto end = start + data.trampline_length;
|
||||
|
@ -1130,9 +965,17 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
|
||||
const Instructions& insns = *instructions_[i].insns_;
|
||||
AutoTraceImage(insns, 0, &this->instructions_blob_stream_);
|
||||
const uword payload_start = insns.PayloadStart();
|
||||
|
||||
ASSERT(Utils::IsAligned(payload_start, sizeof(compiler::target::uword)));
|
||||
uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
|
||||
uword payload_start = insns.PayloadStart();
|
||||
uword payload_size =
|
||||
Utils::RoundUp(
|
||||
compiler::target::Instructions::HeaderSize() + insns.Size(),
|
||||
compiler::target::ObjectAlignment::kObjectAlignment) -
|
||||
compiler::target::Instructions::HeaderSize();
|
||||
uword object_end = payload_start + payload_size;
|
||||
|
||||
ASSERT(Utils::IsAligned(payload_start, sizeof(uword)));
|
||||
|
||||
// Write Instructions with the mark and read-only bits set.
|
||||
uword marked_tags = insns.raw_ptr()->tags_;
|
||||
|
@ -1146,49 +989,32 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
|
||||
#endif
|
||||
|
||||
intptr_t payload_stream_start = 0;
|
||||
|
||||
#if defined(IS_SIMARM_X64)
|
||||
const intptr_t start_offset = instructions_blob_stream_.bytes_written();
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
|
||||
const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.Size());
|
||||
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
|
||||
|
||||
if (!bare_instruction_payloads) {
|
||||
instructions_blob_stream_.WriteTargetWord(marked_tags);
|
||||
instructions_blob_stream_.WriteFixed<uint32_t>(
|
||||
insns.raw_ptr()->size_and_flags_);
|
||||
} else {
|
||||
ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
|
||||
kBareInstructionsAlignment));
|
||||
}
|
||||
const intptr_t payload_stream_start = instructions_blob_stream_.Position();
|
||||
instructions_blob_stream_.WriteTargetWord(marked_tags);
|
||||
instructions_blob_stream_.WriteFixed<uint32_t>(
|
||||
insns.raw_ptr()->size_and_flags_);
|
||||
payload_stream_start = instructions_blob_stream_.Position();
|
||||
instructions_blob_stream_.WriteBytes(
|
||||
reinterpret_cast<const void*>(insns.PayloadStart()), insns.Size());
|
||||
const intptr_t alignment =
|
||||
bare_instruction_payloads
|
||||
? kBareInstructionsAlignment
|
||||
: compiler::target::ObjectAlignment::kObjectAlignment;
|
||||
instructions_blob_stream_.Align(alignment);
|
||||
instructions_blob_stream_.Align(
|
||||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
const intptr_t end_offset = instructions_blob_stream_.bytes_written();
|
||||
text_offset += (end_offset - start_offset);
|
||||
USE(object_start);
|
||||
USE(object_end);
|
||||
#else // defined(IS_SIMARM_X64)
|
||||
// Only payload is output in AOT snapshots.
|
||||
const uword header_size =
|
||||
bare_instruction_payloads
|
||||
? 0
|
||||
: compiler::target::Instructions::HeaderSize();
|
||||
const uword payload_size = SizeInSnapshot(insns.raw()) - header_size;
|
||||
const uword object_end = payload_start + payload_size;
|
||||
if (!bare_instruction_payloads) {
|
||||
uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
|
||||
instructions_blob_stream_.WriteWord(marked_tags);
|
||||
text_offset += sizeof(uword);
|
||||
object_start += sizeof(uword);
|
||||
text_offset += WriteByteSequence(object_start, payload_start);
|
||||
} else {
|
||||
ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
|
||||
kBareInstructionsAlignment));
|
||||
}
|
||||
const intptr_t payload_stream_start = instructions_blob_stream_.Position();
|
||||
text_offset += WriteByteSequence(payload_start, object_end);
|
||||
payload_stream_start = instructions_blob_stream_.Position() +
|
||||
(insns.PayloadStart() - object_start);
|
||||
|
||||
instructions_blob_stream_.WriteWord(marked_tags);
|
||||
text_offset += sizeof(uword);
|
||||
object_start += sizeof(uword);
|
||||
text_offset += WriteByteSequence(object_start, object_end);
|
||||
#endif
|
||||
|
||||
#if defined(DART_PRECOMPILER)
|
||||
|
@ -1250,12 +1076,7 @@ void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
|
|||
ImageWriter::SizeInSnapshot(insns.raw()));
|
||||
}
|
||||
|
||||
// Should be a no-op unless writing bare instruction payloads, in which case
|
||||
// we need to add post-payload padding to the object alignment.
|
||||
instructions_blob_stream_.Align(
|
||||
compiler::target::ObjectAlignment::kObjectAlignment);
|
||||
|
||||
ASSERT(instructions_blob_stream_.bytes_written() == image_size);
|
||||
ASSERT(instructions_blob_stream_.bytes_written() == instructions_length);
|
||||
|
||||
#ifdef DART_PRECOMPILER
|
||||
const char* instructions_symbol =
|
||||
|
@ -1293,18 +1114,6 @@ RawApiError* ImageReader::VerifyAlignment() const {
|
|||
return ApiError::null();
|
||||
}
|
||||
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
uword ImageReader::GetBareInstructionsAt(uint32_t offset) const {
|
||||
ASSERT(Utils::IsAligned(offset, ImageWriter::kBareInstructionsAlignment));
|
||||
return reinterpret_cast<uword>(instructions_image_) + offset;
|
||||
}
|
||||
|
||||
uword ImageReader::GetBareInstructionsEnd() const {
|
||||
Image image(instructions_image_);
|
||||
return reinterpret_cast<uword>(image.object_start()) + image.object_size();
|
||||
}
|
||||
#endif
|
||||
|
||||
RawInstructions* ImageReader::GetInstructionsAt(uint32_t offset) const {
|
||||
ASSERT(Utils::IsAligned(offset, kObjectAlignment));
|
||||
|
||||
|
|
|
@ -69,8 +69,6 @@ class ImageReader : public ZoneAllocated {
|
|||
|
||||
RawApiError* VerifyAlignment() const;
|
||||
|
||||
ONLY_IN_PRECOMPILED(uword GetBareInstructionsAt(uint32_t offset) const);
|
||||
ONLY_IN_PRECOMPILED(uword GetBareInstructionsEnd() const);
|
||||
RawInstructions* GetInstructionsAt(uint32_t offset) const;
|
||||
RawObject* GetObjectAt(uint32_t offset) const;
|
||||
|
||||
|
@ -155,9 +153,6 @@ class ImageWriter : public ValueObject {
|
|||
void ResetOffsets() {
|
||||
next_data_offset_ = Image::kHeaderSize;
|
||||
next_text_offset_ = Image::kHeaderSize;
|
||||
if (FLAG_use_bare_instructions && FLAG_precompiled_mode) {
|
||||
next_text_offset_ += compiler::target::InstructionsSection::HeaderSize();
|
||||
}
|
||||
objects_.Clear();
|
||||
instructions_.Clear();
|
||||
}
|
||||
|
@ -184,7 +179,6 @@ class ImageWriter : public ValueObject {
|
|||
void TraceInstructions(const Instructions& instructions);
|
||||
|
||||
static intptr_t SizeInSnapshot(RawObject* object);
|
||||
static const intptr_t kBareInstructionsAlignment = 4;
|
||||
|
||||
protected:
|
||||
void WriteROData(WriteStream* stream);
|
||||
|
@ -335,7 +329,6 @@ class AssemblyImageWriter : public ImageWriter {
|
|||
void FrameUnwindPrologue();
|
||||
void FrameUnwindEpilogue();
|
||||
intptr_t WriteByteSequence(uword start, uword end);
|
||||
intptr_t Align(intptr_t alignment, uword position = 0);
|
||||
|
||||
#if defined(TARGET_ARCH_IS_64_BIT)
|
||||
const char* kLiteralPrefix = ".quad";
|
||||
|
|
|
@ -150,8 +150,6 @@ RawClass* Object::kernel_program_info_class_ =
|
|||
RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::instructions_section_class_ =
|
||||
reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
RawClass* Object::code_source_map_class_ =
|
||||
|
@ -795,9 +793,6 @@ void Object::Init(Isolate* isolate) {
|
|||
cls = Class::New<Instructions, RTN::Instructions>(isolate);
|
||||
instructions_class_ = cls.raw();
|
||||
|
||||
cls = Class::New<InstructionsSection, RTN::InstructionsSection>(isolate);
|
||||
instructions_section_class_ = cls.raw();
|
||||
|
||||
cls = Class::New<ObjectPool, RTN::ObjectPool>(isolate);
|
||||
object_pool_class_ = cls.raw();
|
||||
|
||||
|
@ -1226,7 +1221,6 @@ void Object::Cleanup() {
|
|||
code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
bytecode_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
instructions_section_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
object_pool_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
code_source_map_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
||||
|
@ -1329,7 +1323,6 @@ void Object::FinalizeVMIsolate(Isolate* isolate) {
|
|||
SET_CLASS_NAME(code, Code);
|
||||
SET_CLASS_NAME(bytecode, Bytecode);
|
||||
SET_CLASS_NAME(instructions, Instructions);
|
||||
SET_CLASS_NAME(instructions_section, InstructionsSection);
|
||||
SET_CLASS_NAME(object_pool, ObjectPool);
|
||||
SET_CLASS_NAME(code_source_map, CodeSourceMap);
|
||||
SET_CLASS_NAME(pc_descriptors, PcDescriptors);
|
||||
|
@ -4543,8 +4536,6 @@ const char* Class::GenerateUserVisibleName() const {
|
|||
return Symbols::Bytecode().ToCString();
|
||||
case kInstructionsCid:
|
||||
return Symbols::Instructions().ToCString();
|
||||
case kInstructionsSectionCid:
|
||||
return Symbols::InstructionsSection().ToCString();
|
||||
case kObjectPoolCid:
|
||||
return Symbols::ObjectPool().ToCString();
|
||||
case kCodeSourceMapCid:
|
||||
|
@ -13117,7 +13108,7 @@ void Library::CheckFunctionFingerprints() {
|
|||
}
|
||||
#endif // defined(DEBUG) && !defined(DART_PRECOMPILED_RUNTIME).
|
||||
|
||||
RawInstructions* Instructions::New(intptr_t size, bool has_monomorphic_entry) {
|
||||
RawInstructions* Instructions::New(intptr_t size, bool has_single_entry_point) {
|
||||
ASSERT(size >= 0);
|
||||
ASSERT(Object::instructions_class() != Class::null());
|
||||
if (size < 0 || size > kMaxElements) {
|
||||
|
@ -13132,7 +13123,7 @@ RawInstructions* Instructions::New(intptr_t size, bool has_monomorphic_entry) {
|
|||
NoSafepointScope no_safepoint;
|
||||
result ^= raw;
|
||||
result.SetSize(size);
|
||||
result.SetHasMonomorphicEntry(has_monomorphic_entry);
|
||||
result.SetHasSingleEntryPoint(has_single_entry_point);
|
||||
result.set_stats(nullptr);
|
||||
}
|
||||
return result.raw();
|
||||
|
@ -13157,10 +13148,6 @@ void Instructions::set_stats(CodeStatistics* stats) const {
|
|||
#endif
|
||||
}
|
||||
|
||||
const char* InstructionsSection::ToCString() const {
|
||||
return "InstructionsSection";
|
||||
}
|
||||
|
||||
// Encode integer |value| in SLEB128 format and store into |data|.
|
||||
static void EncodeSLEB128(GrowableArray<uint8_t>* data, intptr_t value) {
|
||||
bool is_last_part = false;
|
||||
|
@ -15338,11 +15325,12 @@ void Code::Disassemble(DisassemblyFormatter* formatter) const {
|
|||
if (!FLAG_support_disassembler) {
|
||||
return;
|
||||
}
|
||||
const uword start = PayloadStart();
|
||||
const Instructions& instr = Instructions::Handle(instructions());
|
||||
uword start = instr.PayloadStart();
|
||||
if (formatter == NULL) {
|
||||
Disassembler::Disassemble(start, start + Size(), *this);
|
||||
Disassembler::Disassemble(start, start + instr.Size(), *this);
|
||||
} else {
|
||||
Disassembler::Disassemble(start, start + Size(), formatter, *this);
|
||||
Disassembler::Disassemble(start, start + instr.Size(), formatter, *this);
|
||||
}
|
||||
#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
|
||||
}
|
||||
|
@ -15482,7 +15470,7 @@ RawCode* Code::FinalizeCode(FlowGraphCompiler* compiler,
|
|||
assembler->GetSelfHandle() = code.raw();
|
||||
#endif
|
||||
Instructions& instrs = Instructions::ZoneHandle(Instructions::New(
|
||||
assembler->CodeSize(), assembler->has_monomorphic_entry()));
|
||||
assembler->CodeSize(), assembler->has_single_entry_point()));
|
||||
|
||||
{
|
||||
// Important: if GC is triggerred at any point between Instructions::New
|
||||
|
@ -15883,10 +15871,11 @@ void Code::DumpSourcePositions(bool relative_addresses) const {
|
|||
|
||||
bool Code::VerifyBSSRelocations() const {
|
||||
const auto& descriptors = PcDescriptors::Handle(pc_descriptors());
|
||||
const auto& insns = Instructions::Handle(instructions());
|
||||
PcDescriptors::Iterator iterator(descriptors,
|
||||
RawPcDescriptors::kBSSRelocation);
|
||||
while (iterator.MoveNext()) {
|
||||
const uword reloc = PayloadStart() + iterator.PcOffset();
|
||||
const uword reloc = insns.PayloadStart() + iterator.PcOffset();
|
||||
const word target = *reinterpret_cast<word*>(reloc);
|
||||
// The relocation is in its original unpatched form -- the addend
|
||||
// representing the target symbol itself.
|
||||
|
|
|
@ -482,9 +482,6 @@ class Object {
|
|||
static RawClass* code_class() { return code_class_; }
|
||||
static RawClass* bytecode_class() { return bytecode_class_; }
|
||||
static RawClass* instructions_class() { return instructions_class_; }
|
||||
static RawClass* instructions_section_class() {
|
||||
return instructions_section_class_;
|
||||
}
|
||||
static RawClass* object_pool_class() { return object_pool_class_; }
|
||||
static RawClass* pc_descriptors_class() { return pc_descriptors_class_; }
|
||||
static RawClass* code_source_map_class() { return code_source_map_class_; }
|
||||
|
@ -769,8 +766,6 @@ class Object {
|
|||
static RawClass* code_class_; // Class of the Code vm object.
|
||||
static RawClass* bytecode_class_; // Class of the Bytecode vm object.
|
||||
static RawClass* instructions_class_; // Class of the Instructions vm object.
|
||||
static RawClass*
|
||||
instructions_section_class_; // Class of InstructionsSection.
|
||||
static RawClass* object_pool_class_; // Class of the ObjectPool vm object.
|
||||
static RawClass* pc_descriptors_class_; // Class of PcDescriptors vm object.
|
||||
static RawClass* code_source_map_class_; // Class of CodeSourceMap vm object.
|
||||
|
@ -5057,13 +5052,21 @@ class Instructions : public Object {
|
|||
return SizeBits::decode(instr->ptr()->size_and_flags_);
|
||||
}
|
||||
|
||||
bool HasMonomorphicEntry() const {
|
||||
bool HasSingleEntryPoint() const {
|
||||
return FlagsBits::decode(raw_ptr()->size_and_flags_);
|
||||
}
|
||||
static bool HasMonomorphicEntry(const RawInstructions* instr) {
|
||||
static bool HasSingleEntryPoint(const RawInstructions* instr) {
|
||||
return FlagsBits::decode(instr->ptr()->size_and_flags_);
|
||||
}
|
||||
|
||||
static bool ContainsPc(RawInstructions* instruction, uword pc) {
|
||||
const uword offset = pc - PayloadStart(instruction);
|
||||
// We use <= instead of < here because the saved-pc can be outside the
|
||||
// instruction stream if the last instruction is a call we don't expect to
|
||||
// return (e.g. because it throws an exception).
|
||||
return offset <= static_cast<uword>(Size(instruction));
|
||||
}
|
||||
|
||||
uword PayloadStart() const { return PayloadStart(raw()); }
|
||||
uword MonomorphicEntryPoint() const { return MonomorphicEntryPoint(raw()); }
|
||||
uword EntryPoint() const { return EntryPoint(raw()); }
|
||||
|
@ -5099,7 +5102,7 @@ class Instructions : public Object {
|
|||
|
||||
static uword MonomorphicEntryPoint(const RawInstructions* instr) {
|
||||
uword entry = PayloadStart(instr);
|
||||
if (HasMonomorphicEntry(instr)) {
|
||||
if (!HasSingleEntryPoint(instr)) {
|
||||
entry += !FLAG_precompiled_mode ? kMonomorphicEntryOffsetJIT
|
||||
: kMonomorphicEntryOffsetAOT;
|
||||
}
|
||||
|
@ -5108,7 +5111,7 @@ class Instructions : public Object {
|
|||
|
||||
static uword EntryPoint(const RawInstructions* instr) {
|
||||
uword entry = PayloadStart(instr);
|
||||
if (HasMonomorphicEntry(instr)) {
|
||||
if (!HasSingleEntryPoint(instr)) {
|
||||
entry += !FLAG_precompiled_mode ? kPolymorphicEntryOffsetJIT
|
||||
: kPolymorphicEntryOffsetAOT;
|
||||
}
|
||||
|
@ -5158,7 +5161,7 @@ class Instructions : public Object {
|
|||
SizeBits::update(value, raw_ptr()->size_and_flags_));
|
||||
}
|
||||
|
||||
void SetHasMonomorphicEntry(bool value) const {
|
||||
void SetHasSingleEntryPoint(bool value) const {
|
||||
StoreNonPointer(&raw_ptr()->size_and_flags_,
|
||||
FlagsBits::update(value, raw_ptr()->size_and_flags_));
|
||||
}
|
||||
|
@ -5167,7 +5170,7 @@ class Instructions : public Object {
|
|||
// only be created using the Code::FinalizeCode method. This method creates
|
||||
// the RawInstruction and RawCode objects, sets up the pointer offsets
|
||||
// and links the two in a GC safe manner.
|
||||
static RawInstructions* New(intptr_t size, bool has_monomorphic_entry);
|
||||
static RawInstructions* New(intptr_t size, bool has_single_entry_point);
|
||||
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(Instructions, Object);
|
||||
friend class Class;
|
||||
|
@ -5177,34 +5180,6 @@ class Instructions : public Object {
|
|||
friend class ImageWriter;
|
||||
};
|
||||
|
||||
// Used only to provide memory accounting for the bare instruction payloads
|
||||
// we serialize, since they are no longer part of RawInstructions objects.
|
||||
class InstructionsSection : public Object {
|
||||
public:
|
||||
// Excludes HeaderSize().
|
||||
intptr_t Size() const { return raw_ptr()->payload_length_; }
|
||||
static intptr_t Size(const RawInstructionsSection* instr) {
|
||||
return instr->ptr()->payload_length_;
|
||||
}
|
||||
static intptr_t InstanceSize() {
|
||||
ASSERT(sizeof(RawInstructionsSection) ==
|
||||
OFFSET_OF_RETURNED_VALUE(RawInstructionsSection, data));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static intptr_t InstanceSize(intptr_t size) {
|
||||
return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
|
||||
}
|
||||
|
||||
static intptr_t HeaderSize() {
|
||||
return Utils::RoundUp(sizeof(RawInstructionsSection), kWordSize);
|
||||
}
|
||||
|
||||
private:
|
||||
FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object);
|
||||
friend class Class;
|
||||
};
|
||||
|
||||
class LocalVarDescriptors : public Object {
|
||||
public:
|
||||
intptr_t Length() const;
|
||||
|
@ -5580,6 +5555,11 @@ class Code : public Object {
|
|||
return code->ptr()->instructions_;
|
||||
}
|
||||
|
||||
// Returns the entry point of [InstructionsOf(code)].
|
||||
static uword EntryPointOf(const RawCode* code) {
|
||||
return Instructions::EntryPoint(InstructionsOf(code));
|
||||
}
|
||||
|
||||
static intptr_t saved_instructions_offset() {
|
||||
return OFFSET_OF(RawCode, instructions_);
|
||||
}
|
||||
|
@ -5629,38 +5609,12 @@ class Code : public Object {
|
|||
bool is_alive() const { return AliveBit::decode(raw_ptr()->state_bits_); }
|
||||
void set_is_alive(bool value) const;
|
||||
|
||||
bool HasMonomorphicEntry() const { return HasMonomorphicEntry(raw()); }
|
||||
static bool HasMonomorphicEntry(const RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return code->ptr()->entry_point_ != code->ptr()->monomorphic_entry_point_;
|
||||
#else
|
||||
return Instructions::HasMonomorphicEntry(InstructionsOf(code));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the payload start of [instructions()].
|
||||
uword PayloadStart() const { return PayloadStartOf(raw()); }
|
||||
static uword PayloadStartOf(const RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
const uword entry_offset = HasMonomorphicEntry(code)
|
||||
? Instructions::kPolymorphicEntryOffsetAOT
|
||||
: 0;
|
||||
return EntryPointOf(code) - entry_offset;
|
||||
#else
|
||||
return Instructions::PayloadStart(InstructionsOf(code));
|
||||
#endif
|
||||
uword PayloadStart() const {
|
||||
return Instructions::PayloadStart(instructions());
|
||||
}
|
||||
|
||||
// Returns the entry point of [instructions()].
|
||||
uword EntryPoint() const { return EntryPointOf(raw()); }
|
||||
static uword EntryPointOf(const RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return code->ptr()->entry_point_;
|
||||
#else
|
||||
return Instructions::EntryPoint(InstructionsOf(code));
|
||||
#endif
|
||||
}
|
||||
|
||||
uword EntryPoint() const { return Instructions::EntryPoint(instructions()); }
|
||||
// Returns the unchecked entry point of [instructions()].
|
||||
uword UncheckedEntryPoint() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
@ -5671,11 +5625,7 @@ class Code : public Object {
|
|||
}
|
||||
// Returns the monomorphic entry point of [instructions()].
|
||||
uword MonomorphicEntryPoint() const {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return raw_ptr()->monomorphic_entry_point_;
|
||||
#else
|
||||
return Instructions::MonomorphicEntryPoint(instructions());
|
||||
#endif
|
||||
}
|
||||
// Returns the unchecked monomorphic entry point of [instructions()].
|
||||
uword MonomorphicUncheckedEntryPoint() const {
|
||||
|
@ -5685,16 +5635,8 @@ class Code : public Object {
|
|||
return MonomorphicEntryPoint() + raw_ptr()->unchecked_offset_;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the size of [instructions()].
|
||||
intptr_t Size() const { return PayloadSizeOf(raw()); }
|
||||
static intptr_t PayloadSizeOf(const RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
return code->ptr()->instructions_length_;
|
||||
#else
|
||||
return Instructions::Size(InstructionsOf(code));
|
||||
#endif
|
||||
}
|
||||
intptr_t Size() const { return Instructions::Size(instructions()); }
|
||||
|
||||
RawObjectPool* GetObjectPool() const;
|
||||
// Returns whether the given PC address is in [instructions()].
|
||||
|
@ -5703,8 +5645,8 @@ class Code : public Object {
|
|||
}
|
||||
|
||||
// Returns whether the given PC address is in [InstructionsOf(code)].
|
||||
static bool ContainsInstructionAt(const RawCode* code, uword pc) {
|
||||
return RawCode::ContainsPC(code, pc);
|
||||
static bool ContainsInstructionAt(const RawCode* code, uword addr) {
|
||||
return Instructions::ContainsPc(InstructionsOf(code), addr);
|
||||
}
|
||||
|
||||
// Returns true if there is a debugger breakpoint set in this code object.
|
||||
|
@ -6108,13 +6050,11 @@ class Code : public Object {
|
|||
|
||||
// Returns the unchecked entry point offset for [instructions_].
|
||||
uint32_t UncheckedEntryPointOffset() const {
|
||||
return UncheckedEntryPointOffsetOf(raw());
|
||||
}
|
||||
static uint32_t UncheckedEntryPointOffsetOf(RawCode* code) {
|
||||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
UNREACHABLE();
|
||||
return raw_ptr()->unchecked_entry_point_ - raw_ptr()->entry_point_;
|
||||
#else
|
||||
return code->ptr()->unchecked_offset_;
|
||||
return raw_ptr()->unchecked_offset_;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -6152,7 +6092,6 @@ class Code : public Object {
|
|||
friend class FunctionSerializationCluster;
|
||||
friend class CodeSerializationCluster;
|
||||
friend class CodeDeserializationCluster;
|
||||
friend class Deserializer; // for InitializeCachedEntryPointsFrom
|
||||
friend class StubCode; // for set_object_pool
|
||||
friend class MegamorphicCacheTable; // for set_object_pool
|
||||
friend class CodePatcher; // for set_instructions
|
||||
|
|
|
@ -667,10 +667,6 @@ void Instructions::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
|||
}
|
||||
}
|
||||
|
||||
void InstructionsSection::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
Object::PrintJSONImpl(stream, ref);
|
||||
}
|
||||
|
||||
void ObjectPool::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
AddCommonObjectProperties(&jsobj, "Object", ref);
|
||||
|
|
|
@ -100,13 +100,6 @@ intptr_t RawObject::HeapSizeFromClass() const {
|
|||
instance_size = Instructions::InstanceSize(instructions_size);
|
||||
break;
|
||||
}
|
||||
case kInstructionsSectionCid: {
|
||||
const RawInstructionsSection* raw_section =
|
||||
reinterpret_cast<const RawInstructionsSection*>(this);
|
||||
intptr_t section_size = InstructionsSection::Size(raw_section);
|
||||
instance_size = InstructionsSection::InstanceSize(section_size);
|
||||
break;
|
||||
}
|
||||
case kContextCid: {
|
||||
const RawContext* raw_context = reinterpret_cast<const RawContext*>(this);
|
||||
intptr_t num_variables = raw_context->ptr()->num_variables_;
|
||||
|
@ -556,7 +549,6 @@ NULL_VISITOR(TransferableTypedData)
|
|||
REGULAR_VISITOR(Pointer)
|
||||
NULL_VISITOR(DynamicLibrary)
|
||||
VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
|
||||
VARIABLE_NULL_VISITOR(InstructionsSection, InstructionsSection::Size(raw_obj))
|
||||
VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->ptr()->length_)
|
||||
VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->ptr()->length_)
|
||||
VARIABLE_NULL_VISITOR(CompressedStackMaps, raw_obj->ptr()->payload_size())
|
||||
|
@ -572,12 +564,12 @@ UNREACHABLE_VISITOR(String)
|
|||
// Smi has no heap representation.
|
||||
UNREACHABLE_VISITOR(Smi)
|
||||
|
||||
bool RawCode::ContainsPC(const RawObject* raw_obj, uword pc) {
|
||||
if (!raw_obj->IsCode()) return false;
|
||||
auto const raw_code = static_cast<const RawCode*>(raw_obj);
|
||||
const uword start = Code::PayloadStartOf(raw_code);
|
||||
const uword size = Code::PayloadSizeOf(raw_code);
|
||||
return (pc - start) <= size; // pc may point just past last instruction.
|
||||
bool RawCode::ContainsPC(RawObject* raw_obj, uword pc) {
|
||||
if (raw_obj->IsCode()) {
|
||||
RawCode* raw_code = static_cast<RawCode*>(raw_obj);
|
||||
return RawInstructions::ContainsPC(raw_code->ptr()->instructions_, pc);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
intptr_t RawCode::VisitCodePointers(RawCode* raw_obj,
|
||||
|
@ -591,7 +583,8 @@ intptr_t RawCode::VisitCodePointers(RawCode* raw_obj,
|
|||
// instructions. The variable portion of a Code object describes where to
|
||||
// find those pointers for tracing.
|
||||
if (Code::AliveBit::decode(obj->state_bits_)) {
|
||||
uword entry_point = Code::PayloadStartOf(raw_obj);
|
||||
uword entry_point = reinterpret_cast<uword>(obj->instructions_->ptr()) +
|
||||
Instructions::HeaderSize();
|
||||
for (intptr_t i = 0; i < length; i++) {
|
||||
int32_t offset = obj->data()[i];
|
||||
visitor->VisitPointer(
|
||||
|
@ -633,13 +626,12 @@ intptr_t RawObjectPool::VisitObjectPoolPointers(RawObjectPool* raw_obj,
|
|||
return ObjectPool::InstanceSize(length);
|
||||
}
|
||||
|
||||
bool RawInstructions::ContainsPC(const RawInstructions* raw_instr, uword pc) {
|
||||
const uword start = Instructions::PayloadStart(raw_instr);
|
||||
const uword size = Instructions::Size(raw_instr);
|
||||
// We use <= instead of < here because the saved-pc can be outside the
|
||||
// instruction stream if the last instruction is a call we don't expect to
|
||||
// return (e.g. because it throws an exception).
|
||||
return (pc - start) <= size;
|
||||
bool RawInstructions::ContainsPC(RawInstructions* raw_instr, uword pc) {
|
||||
uword start_pc =
|
||||
reinterpret_cast<uword>(raw_instr->ptr()) + Instructions::HeaderSize();
|
||||
uword end_pc = start_pc + Instructions::Size(raw_instr);
|
||||
ASSERT(end_pc > start_pc);
|
||||
return (pc >= start_pc) && (pc < end_pc);
|
||||
}
|
||||
|
||||
intptr_t RawInstance::VisitInstancePointers(RawInstance* raw_obj,
|
||||
|
|
|
@ -1408,11 +1408,8 @@ class RawKernelProgramInfo : public RawObject {
|
|||
class RawCode : public RawObject {
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(Code);
|
||||
|
||||
// When in the precompiled runtime, there is no disabling of Code objects
|
||||
// and thus no active_instructions_ field. Thus, the entry point caches are
|
||||
// only set once during deserialization. If not using bare instructions,
|
||||
// the caches should match the entry points for instructions_.
|
||||
//
|
||||
// When in the precompiled runtime, there is no active_instructions_ field
|
||||
// and the entry point caches should contain entry points for instructions_.
|
||||
// Otherwise, they should contain entry points for active_instructions_.
|
||||
|
||||
uword entry_point_; // Accessed from generated code.
|
||||
|
@ -1500,14 +1497,12 @@ class RawCode : public RawObject {
|
|||
// Caches the unchecked entry point offset for instructions_, in case we need
|
||||
// to reset the active_instructions_ to instructions_.
|
||||
NOT_IN_PRECOMPILED(uint32_t unchecked_offset_);
|
||||
// Stores the instructions length when not using RawInstructions objects.
|
||||
ONLY_IN_PRECOMPILED(uint32_t instructions_length_);
|
||||
|
||||
// Variable length data follows here.
|
||||
int32_t* data() { OPEN_ARRAY_START(int32_t, int32_t); }
|
||||
const int32_t* data() const { OPEN_ARRAY_START(int32_t, int32_t); }
|
||||
|
||||
static bool ContainsPC(const RawObject* raw_obj, uword pc);
|
||||
static bool ContainsPC(RawObject* raw_obj, uword pc);
|
||||
|
||||
friend class Function;
|
||||
template <bool>
|
||||
|
@ -1589,7 +1584,7 @@ class RawInstructions : public RawObject {
|
|||
// Private helper function used while visiting stack frames. The
|
||||
// code which iterates over dart frames is also called during GC and
|
||||
// is not allowed to create handles.
|
||||
static bool ContainsPC(const RawInstructions* raw_instr, uword pc);
|
||||
static bool ContainsPC(RawInstructions* raw_instr, uword pc);
|
||||
|
||||
friend class RawCode;
|
||||
friend class RawFunction;
|
||||
|
@ -1604,19 +1599,6 @@ class RawInstructions : public RawObject {
|
|||
friend class BlobImageWriter;
|
||||
};
|
||||
|
||||
// Used only to provide memory accounting for the bare instruction payloads
|
||||
// we serialize, since they are no longer part of RawInstructions objects.
|
||||
class RawInstructionsSection : public RawObject {
|
||||
RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection);
|
||||
VISIT_NOTHING();
|
||||
|
||||
// Instructions section payload length in bytes.
|
||||
uint32_t payload_length_;
|
||||
|
||||
// Variable length data follows here.
|
||||
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
|
||||
};
|
||||
|
||||
class RawPcDescriptors : public RawObject {
|
||||
public:
|
||||
// The macro argument V is passed two arguments, the raw name of the enum value
|
||||
|
@ -2993,9 +2975,8 @@ inline bool RawObject::IsVariableSizeClassId(intptr_t index) {
|
|||
RawObject::IsTwoByteStringClassId(index) ||
|
||||
RawObject::IsTypedDataClassId(index) || (index == kContextCid) ||
|
||||
(index == kTypeArgumentsCid) || (index == kInstructionsCid) ||
|
||||
(index == kInstructionsSectionCid) || (index == kObjectPoolCid) ||
|
||||
(index == kPcDescriptorsCid) || (index == kCodeSourceMapCid) ||
|
||||
(index == kCompressedStackMapsCid) ||
|
||||
(index == kObjectPoolCid) || (index == kPcDescriptorsCid) ||
|
||||
(index == kCodeSourceMapCid) || (index == kCompressedStackMapsCid) ||
|
||||
(index == kLocalVarDescriptorsCid) ||
|
||||
(index == kExceptionHandlersCid) || (index == kCodeCid) ||
|
||||
(index == kContextScopeCid) || (index == kInstanceCid) ||
|
||||
|
|
|
@ -541,7 +541,6 @@ MESSAGE_SNAPSHOT_UNREACHABLE(Field);
|
|||
MESSAGE_SNAPSHOT_UNREACHABLE(Function);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(Library);
|
||||
MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
|
||||
|
|
|
@ -11,11 +11,13 @@ namespace dart {
|
|||
#if defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
static uword BeginPcFromCode(const RawCode* code) {
|
||||
return Code::PayloadStartOf(code);
|
||||
auto instr = Code::InstructionsOf(code);
|
||||
return Instructions::PayloadStart(instr);
|
||||
}
|
||||
|
||||
static uword EndPcFromCode(const RawCode* code) {
|
||||
return Code::PayloadStartOf(code) + Code::PayloadSizeOf(code);
|
||||
auto instr = Code::InstructionsOf(code);
|
||||
return Instructions::PayloadStart(instr) + Instructions::Size(instr);
|
||||
}
|
||||
|
||||
void ReversePcLookupCache::BuildAndAttachToIsolate(Isolate* isolate) {
|
||||
|
|
|
@ -66,11 +66,7 @@ class ReversePcLookupCache {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
inline RawCode* Lookup(uword pc) {
|
||||
NoSafepointScope no_safepoint_scope;
|
||||
|
||||
intptr_t left = 0;
|
||||
|
@ -85,14 +81,6 @@ class ReversePcLookupCache {
|
|||
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;
|
||||
}
|
||||
|
@ -128,9 +116,7 @@ class ReversePcLookupCache {
|
|||
|
||||
inline bool Contains(uword pc) { return false; }
|
||||
|
||||
inline RawCode* Lookup(uword pc, bool is_return_address = false) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
inline RawCode* Lookup(uword pc) { UNREACHABLE(); }
|
||||
};
|
||||
|
||||
#endif // defined(DART_PRECOMPILED_RUNTIME
|
||||
|
|
|
@ -126,7 +126,7 @@ bool StackFrame::IsBareInstructionsDartFrame() const {
|
|||
if (auto isolate = IsolateOfBareInstructionsFrame()) {
|
||||
Code code;
|
||||
auto rct = isolate->reverse_pc_lookup_cache();
|
||||
code = rct->Lookup(pc(), /*is_return_address=*/true);
|
||||
code = rct->Lookup(pc());
|
||||
|
||||
const intptr_t cid = code.owner()->GetClassId();
|
||||
ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
|
||||
|
@ -141,7 +141,7 @@ bool StackFrame::IsBareInstructionsStubFrame() const {
|
|||
if (auto isolate = IsolateOfBareInstructionsFrame()) {
|
||||
Code code;
|
||||
auto rct = isolate->reverse_pc_lookup_cache();
|
||||
code = rct->Lookup(pc(), /*is_return_address=*/true);
|
||||
code = rct->Lookup(pc());
|
||||
|
||||
const intptr_t cid = code.owner()->GetClassId();
|
||||
ASSERT(cid == kNullCid || cid == kClassCid || cid == kFunctionCid);
|
||||
|
@ -253,8 +253,7 @@ void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
|||
Code code;
|
||||
|
||||
if (auto isolate = IsolateOfBareInstructionsFrame()) {
|
||||
auto const rct = isolate->reverse_pc_lookup_cache();
|
||||
code = rct->Lookup(pc(), /*is_return_address=*/true);
|
||||
code = isolate->reverse_pc_lookup_cache()->Lookup(pc());
|
||||
} else {
|
||||
RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
|
||||
fp() + ((is_interpreted() ? kKBCPcMarkerSlotFromFp
|
||||
|
@ -388,8 +387,7 @@ RawCode* StackFrame::LookupDartCode() const {
|
|||
NoSafepointScope no_safepoint;
|
||||
#endif
|
||||
if (auto isolate = IsolateOfBareInstructionsFrame()) {
|
||||
auto const rct = isolate->reverse_pc_lookup_cache();
|
||||
return rct->Lookup(pc(), /*is_return_address=*/true);
|
||||
return isolate->reverse_pc_lookup_cache()->Lookup(pc());
|
||||
}
|
||||
|
||||
RawCode* code = GetCodeObject();
|
||||
|
@ -403,8 +401,7 @@ RawCode* StackFrame::LookupDartCode() const {
|
|||
RawCode* StackFrame::GetCodeObject() const {
|
||||
ASSERT(!is_interpreted());
|
||||
if (auto isolate = IsolateOfBareInstructionsFrame()) {
|
||||
auto const rct = isolate->reverse_pc_lookup_cache();
|
||||
return rct->Lookup(pc(), /*is_return_address=*/true);
|
||||
return isolate->reverse_pc_lookup_cache()->Lookup(pc());
|
||||
} else {
|
||||
RawObject* pc_marker = *(reinterpret_cast<RawObject**>(
|
||||
fp() + runtime_frame_layout.code_from_fp * kWordSize));
|
||||
|
|
|
@ -178,7 +178,6 @@ class ObjectPointerVisitor;
|
|||
V(IndexToken, "[]") \
|
||||
V(InitPrefix, "init:") \
|
||||
V(Instructions, "Instructions") \
|
||||
V(InstructionsSection, "InstructionsSection") \
|
||||
V(Int, "int") \
|
||||
V(Int16List, "Int16List") \
|
||||
V(Int32List, "Int32List") \
|
||||
|
|
Loading…
Reference in a new issue