diff --git a/pkg/kernel/lib/kernel.dart b/pkg/kernel/lib/kernel.dart index 48af8f45c6d..e3c04e1c633 100644 --- a/pkg/kernel/lib/kernel.dart +++ b/pkg/kernel/lib/kernel.dart @@ -66,9 +66,15 @@ void writeLibraryToText(Library library, {String path}) { } void writeProgramToText(Program program, - {String path, bool showExternal: false, bool showOffsets: false}) { + {String path, + bool showExternal: false, + bool showOffsets: false, + bool showMetadata: false}) { StringBuffer buffer = new StringBuffer(); - new Printer(buffer, showExternal: showExternal, showOffsets: showOffsets) + new Printer(buffer, + showExternal: showExternal, + showOffsets: showOffsets, + showMetadata: showMetadata) .writeProgramFile(program); if (path == null) { print(buffer); diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart index 449301e1d38..482e553c7d3 100644 --- a/pkg/kernel/lib/text/ast_to_text.dart +++ b/pkg/kernel/lib/text/ast_to_text.dart @@ -222,11 +222,13 @@ class Printer extends Visitor { final NameSystem syntheticNames; final StringSink sink; final Annotator annotator; + final Map> metadata; ImportTable importTable; int indentation = 0; int column = 0; bool showExternal; bool showOffsets; + bool showMetadata; static int SPACE = 0; static int WORD = 1; @@ -237,16 +239,19 @@ class Printer extends Visitor { {NameSystem syntheticNames, this.showExternal, this.showOffsets: false, + this.showMetadata: false, this.importTable, - this.annotator}) + this.annotator, + this.metadata}) : this.syntheticNames = syntheticNames ?? new NameSystem(); - Printer._inner(Printer parent, this.importTable) + Printer._inner(Printer parent, this.importTable, this.metadata) : sink = parent.sink, syntheticNames = parent.syntheticNames, annotator = parent.annotator, showExternal = parent.showExternal, - showOffsets = parent.showOffsets; + showOffsets = parent.showOffsets, + showMetadata = parent.showMetadata; bool shouldHighlight(Node node) { return false; @@ -387,7 +392,8 @@ class Printer extends Visitor { } endLine(); - var inner = new Printer._inner(this, imports); + var inner = + new Printer._inner(this, imports, library.enclosingProgram?.metadata); library.typedefs.forEach(inner.writeNode); library.classes.forEach(inner.writeNode); library.fields.forEach(inner.writeNode); @@ -396,7 +402,7 @@ class Printer extends Visitor { void writeProgramFile(Program program) { ImportTable imports = new ProgramImportTable(program); - var inner = new Printer._inner(this, imports); + var inner = new Printer._inner(this, imports, program.metadata); writeWord('main'); writeSpaced('='); inner.writeMemberReferenceFromReference(program.mainMethodName); @@ -504,6 +510,9 @@ class Printer extends Visitor { if (showOffsets && node is TreeNode) { writeWord("[${node.fileOffset}]"); } + if (showMetadata && node is TreeNode) { + writeMetadata(node); + } node.accept(this); @@ -519,6 +528,17 @@ class Printer extends Visitor { } } + void writeMetadata(TreeNode node) { + if (metadata != null) { + for (var md in metadata.values) { + final nodeMetadata = md.mapping[node]; + if (nodeMetadata != null) { + writeWord("[@${md.tag}=${nodeMetadata}]"); + } + } + } + } + void writeAnnotatedType(DartType type, String annotation) { writeType(type); if (annotation != null) { diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart new file mode 100644 index 00000000000..e2bbb61ea45 --- /dev/null +++ b/pkg/vm/bin/dump_kernel.dart @@ -0,0 +1,36 @@ +// Copyright (c) 2017, 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. + +import 'dart:io'; + +import 'package:kernel/kernel.dart' show Program, writeProgramToText; +import 'package:kernel/binary/ast_from_binary.dart' + show BinaryBuilderWithMetadata; + +import 'package:vm/metadata/direct_call.dart' show DirectCallMetadataRepository; + +final String _usage = ''' +Usage: dump_kernel input.dill output.txt +Dumps kernel binary file with VM-specific metadata. +'''; + +main(List arguments) async { + if (arguments.length != 2) { + print(_usage); + exit(1); + } + + final input = arguments[0]; + final output = arguments[1]; + + final program = new Program(); + + // Register VM-specific metadata. + program.addMetadataRepository(new DirectCallMetadataRepository()); + + final List bytes = new File(input).readAsBytesSync(); + new BinaryBuilderWithMetadata(bytes).readProgram(program); + + writeProgramToText(program, path: output, showMetadata: true); +} diff --git a/pkg/vm/lib/metadata/direct_call.dart b/pkg/vm/lib/metadata/direct_call.dart index 46f1fea5944..570e30354e4 100644 --- a/pkg/vm/lib/metadata/direct_call.dart +++ b/pkg/vm/lib/metadata/direct_call.dart @@ -8,10 +8,19 @@ import 'package:kernel/ast.dart'; /// Metadata for annotating method invocations converted to direct calls. class DirectCallMetadata { - final Member target; + final Reference _targetReference; final bool checkReceiverForNull; - DirectCallMetadata(this.target, this.checkReceiverForNull); + DirectCallMetadata(Member target, bool checkReceiverForNull) + : this.byReference(getMemberReference(target), checkReceiverForNull); + + DirectCallMetadata.byReference( + this._targetReference, this.checkReceiverForNull); + + Member get target => _targetReference.asMember; + + @override + String toString() => "${target}${checkReceiverForNull ? '??' : ''}"; } /// Repository for [DirectCallMetadata]. @@ -32,11 +41,12 @@ class DirectCallMetadataRepository @override DirectCallMetadata readFromBinary(BinarySource source) { - var target = source.readCanonicalNameReference()?.getReference()?.asMember; - if (target == null) { + final targetReference = source.readCanonicalNameReference()?.getReference(); + if (targetReference == null) { throw 'DirectCallMetadata should have a non-null target'; } - var checkReceiverForNull = (source.readByte() != 0); - return new DirectCallMetadata(target, checkReceiverForNull); + final checkReceiverForNull = (source.readByte() != 0); + return new DirectCallMetadata.byReference( + targetReference, checkReceiverForNull); } } diff --git a/pkg/vm/tool/dump_kernel b/pkg/vm/tool/dump_kernel new file mode 100755 index 00000000000..bd3dc31afd3 --- /dev/null +++ b/pkg/vm/tool/dump_kernel @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# Copyright (c) 2017, 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. + +# Script for dumping kernel files with VM-specific metadata. + +set -e + +function follow_links() { + file="$1" + while [ -h "$file" ]; do + # On Mac OS, readlink -f doesn't work. + file="$(readlink "$file")" + done + echo "$file" +} + +# Unlike $0, $BASH_SOURCE points to the absolute path of this file. +PROG_NAME="$(follow_links "$BASH_SOURCE")" + +# Handle the case where dart-sdk/bin has been symlinked to. +CUR_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" + +SDK_DIR="$CUR_DIR/../../.." + +if [[ `uname` == 'Darwin' ]]; then + OUT_DIR="$SDK_DIR/xcodebuild" +else + OUT_DIR="$SDK_DIR/out" +fi + +export DART_CONFIGURATION=${DART_CONFIGURATION:-ReleaseX64} +BIN_DIR="$OUT_DIR/$DART_CONFIGURATION" + +"$BIN_DIR"/dart "${SDK_DIR}/pkg/vm/bin/dump_kernel.dart" "$@"