blob: aae9218979f84eb9f980091528ffea6a2bedb4e0 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library vm.metadata.bytecode;
import 'package:kernel/ast.dart';
import '../bytecode/constant_pool.dart' show ConstantPool;
import '../bytecode/disassembler.dart' show BytecodeDisassembler;
import '../bytecode/exceptions.dart' show ExceptionsTable;
/// Metadata containing bytecode.
///
/// In kernel binary, bytecode metadata is encoded as following:
///
/// type BytecodeMetadata {
/// ConstantPool constantPool
/// List<Byte> bytecodes
/// ExceptionsTable exceptionsTable
/// List<ClosureBytecode> closures
/// }
///
/// type ClosureBytecode {
/// ConstantIndex closureFunction
/// List<Byte> bytecodes
/// ExceptionsTable exceptionsTable
/// }
///
/// Encoding of ExceptionsTable is described in
/// pkg/vm/lib/bytecode/exceptions.dart.
///
/// Encoding of ConstantPool is described in
/// pkg/vm/lib/bytecode/constant_pool.dart.
///
class BytecodeMetadata {
final ConstantPool constantPool;
final List<int> bytecodes;
final ExceptionsTable exceptionsTable;
final List<ClosureBytecode> closures;
BytecodeMetadata(
this.constantPool, this.bytecodes, this.exceptionsTable, this.closures);
// TODO(alexmarkov): Consider printing constant pool before bytecode.
@override
String toString() => "\n"
"Bytecode {\n"
"${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable)}}\n"
"$exceptionsTable"
"$constantPool"
"${closures.join('\n')}";
}
/// Bytecode of a nested function (closure).
/// Closures share the constant pool of a top-level member.
class ClosureBytecode {
final int closureFunctionConstantIndex;
final List<int> bytecodes;
final ExceptionsTable exceptionsTable;
ClosureBytecode(
this.closureFunctionConstantIndex, this.bytecodes, this.exceptionsTable);
void writeToBinary(BinarySink sink) {
sink.writeUInt30(closureFunctionConstantIndex);
sink.writeByteList(bytecodes);
exceptionsTable.writeToBinary(sink);
}
factory ClosureBytecode.readFromBinary(BinarySource source) {
final closureFunctionConstantIndex = source.readUInt();
final List<int> bytecodes = source.readByteList();
final exceptionsTable = new ExceptionsTable.readFromBinary(source);
return new ClosureBytecode(
closureFunctionConstantIndex, bytecodes, exceptionsTable);
}
@override
String toString() {
StringBuffer sb = new StringBuffer();
sb.writeln('Closure CP#$closureFunctionConstantIndex {');
sb.writeln(
new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable));
sb.writeln('}');
return sb.toString();
}
}
/// Repository for [BytecodeMetadata].
class BytecodeMetadataRepository extends MetadataRepository<BytecodeMetadata> {
@override
final String tag = 'vm.bytecode';
@override
final Map<TreeNode, BytecodeMetadata> mapping =
<TreeNode, BytecodeMetadata>{};
@override
void writeToBinary(BytecodeMetadata metadata, Node node, BinarySink sink) {
metadata.constantPool.writeToBinary(node, sink);
sink.writeByteList(metadata.bytecodes);
metadata.exceptionsTable.writeToBinary(sink);
sink.writeUInt30(metadata.closures.length);
metadata.closures.forEach((c) => c.writeToBinary(sink));
}
@override
BytecodeMetadata readFromBinary(Node node, BinarySource source) {
final ConstantPool constantPool =
new ConstantPool.readFromBinary(node, source);
final List<int> bytecodes = source.readByteList();
final exceptionsTable = new ExceptionsTable.readFromBinary(source);
final List<ClosureBytecode> closures = new List<ClosureBytecode>.generate(
source.readUInt(), (_) => new ClosureBytecode.readFromBinary(source));
return new BytecodeMetadata(
constantPool, bytecodes, exceptionsTable, closures);
}
}