9f49b47823
This is a major revamp of bytecode metadata format. Now bytecode has its own serialization mechanisms. This CL adds 'bytecode component' metadata, which contains bytecode object table and string table. All references from bytecode (constant pools) to libraries, classes, members, types and strings now have a new format. References to frequently used objects are represented as indices in object table, while rarely used objects are written inline. This allows VM to cache frequently used objects while reading bytecode. Representation of strings is aligned with VM - string characters are stored in separate pools of one-byte and two-byte strings. This allows VM to avoid UTF-8 decoding and extra copying. Closure declarations are now explicit. Type parameters no longer require enslosing scopes when reading/writing them. Benchmarks: GenKernelKernelReadAllBytecode (Intel Core i5) +29.84% GenKernelKernelReadAllBytecode (Intel Xeon) +28.74% Change-Id: I4b80009733a8f8c038264af74f97c4e094b9e311 Reviewed-on: https://dart-review.googlesource.com/c/85469 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com> Reviewed-by: Zach Anderson <zra@google.com>
105 lines
2.7 KiB
Dart
105 lines
2.7 KiB
Dart
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library vm.bytecode.source_positions;
|
|
|
|
import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;
|
|
|
|
/// Maintains mapping between bytecode instructions and source positions.
|
|
class SourcePositions {
|
|
final Map<int, int> mapping = <int, int>{}; // PC -> fileOffset
|
|
int _lastPc = 0;
|
|
int _lastOffset = 0;
|
|
|
|
SourcePositions();
|
|
|
|
void add(int pc, int fileOffset) {
|
|
assert(pc > _lastPc);
|
|
assert(fileOffset >= 0);
|
|
if (fileOffset != _lastOffset) {
|
|
mapping[pc] = fileOffset;
|
|
_lastPc = pc;
|
|
_lastOffset = fileOffset;
|
|
}
|
|
}
|
|
|
|
void writeContents(BufferedWriter writer) {
|
|
writer.writePackedUInt30(mapping.length);
|
|
final encodePC = new PackedUInt30DeltaEncoder();
|
|
final encodeOffset = new SLEB128DeltaEncoder();
|
|
mapping.forEach((int pc, int fileOffset) {
|
|
encodePC.write(writer, pc);
|
|
encodeOffset.write(writer, fileOffset);
|
|
});
|
|
}
|
|
|
|
void write(BufferedWriter writer) {
|
|
// TODO(alexmarkov): write source positions in a separate section
|
|
BufferedWriter contentsWriter = new BufferedWriter.fromWriter(writer);
|
|
writeContents(contentsWriter);
|
|
|
|
final contents = contentsWriter.takeBytes();
|
|
writer.writePackedUInt30(contents.length);
|
|
writer.writeBytes(contents);
|
|
}
|
|
|
|
SourcePositions.read(BufferedReader reader) {
|
|
reader.readPackedUInt30(); // Contents length in bytes.
|
|
final int length = reader.readPackedUInt30();
|
|
final decodePC = new PackedUInt30DeltaDecoder();
|
|
final decodeOffset = new SLEB128DeltaDecoder();
|
|
for (int i = 0; i < length; ++i) {
|
|
int pc = decodePC.read(reader);
|
|
int fileOffset = decodeOffset.read(reader);
|
|
add(pc, fileOffset);
|
|
}
|
|
}
|
|
|
|
@override
|
|
String toString() => mapping.toString();
|
|
|
|
Map<int, String> getBytecodeAnnotations() {
|
|
return mapping.map((int pc, int fileOffset) =>
|
|
new MapEntry(pc, 'source position $fileOffset'));
|
|
}
|
|
}
|
|
|
|
class PackedUInt30DeltaEncoder {
|
|
int _last = 0;
|
|
|
|
void write(BufferedWriter write, int value) {
|
|
write.writePackedUInt30(value - _last);
|
|
_last = value;
|
|
}
|
|
}
|
|
|
|
class PackedUInt30DeltaDecoder {
|
|
int _last = 0;
|
|
|
|
int read(BufferedReader reader) {
|
|
int value = reader.readPackedUInt30() + _last;
|
|
_last = value;
|
|
return value;
|
|
}
|
|
}
|
|
|
|
class SLEB128DeltaEncoder {
|
|
int _last = 0;
|
|
|
|
void write(BufferedWriter writer, int value) {
|
|
writer.writeSLEB128(value - _last);
|
|
_last = value;
|
|
}
|
|
}
|
|
|
|
class SLEB128DeltaDecoder {
|
|
int _last = 0;
|
|
|
|
int read(BufferedReader reader) {
|
|
int value = reader.readSLEB128() + _last;
|
|
_last = value;
|
|
return value;
|
|
}
|
|
}
|