diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart index 20ad6adb9f7..77ea7b95634 100644 --- a/pkg/front_end/lib/src/api_unstable/vm.dart +++ b/pkg/front_end/lib/src/api_unstable/vm.dart @@ -40,7 +40,8 @@ export '../fasta/fasta_codes.dart' templateFfiTypeInvalid, templateFfiTypeMismatch, templateFfiTypeUnsized, - templateFfiFieldInitializer; + templateFfiFieldInitializer, + templateIllegalRecursiveType; export '../fasta/hybrid_file_system.dart' show HybridFileSystem; diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart index eb1291a9c35..b25813bf132 100644 --- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart +++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart @@ -4276,6 +4276,29 @@ Message _withArgumentsIllegalMixinDueToConstructorsCause(String name) { arguments: {'name': name}); } +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Template templateIllegalRecursiveType = + const Template( + messageTemplate: r"""Illegal recursive type '#type'.""", + withArguments: _withArgumentsIllegalRecursiveType); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +const Code codeIllegalRecursiveType = + const Code( + "IllegalRecursiveType", + templateIllegalRecursiveType, +); + +// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. +Message _withArgumentsIllegalRecursiveType(DartType _type) { + TypeLabeler labeler = new TypeLabeler(); + List typeParts = labeler.labelType(_type); + String type = typeParts.join(); + return new Message(codeIllegalRecursiveType, + message: """Illegal recursive type '${type}'.""" + labeler.originMessages, + arguments: {'type': _type}); +} + // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE. const Code codeIllegalSyncGeneratorReturnType = messageIllegalSyncGeneratorReturnType; diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status index db100bb106e..8f99626bb72 100644 --- a/pkg/front_end/messages.status +++ b/pkg/front_end/messages.status @@ -280,6 +280,9 @@ IllegalAssignmentToNonAssignable/script1: Fail IllegalAsyncGeneratorVoidReturnType/analyzerCode: Fail # The analyzer doesn't report this error. IllegalMixin/example: Fail IllegalMixinDueToConstructors/example: Fail +IllegalRecursiveType/analyzerCode: Fail +IllegalRecursiveType/part_wrapped_script: Fail +IllegalRecursiveType/script: Fail IllegalSyncGeneratorVoidReturnType/analyzerCode: Fail # The analyzer doesn't report this error. ImplementsBeforeExtends/part_wrapped_script: Fail ImplementsBeforeExtends/script: Fail diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml index 8f8a623a547..d2b0dac35ca 100644 --- a/pkg/front_end/messages.yaml +++ b/pkg/front_end/messages.yaml @@ -3560,3 +3560,9 @@ BadTypeVariableInSupertype: script: > class A {} class B extends A {} + +IllegalRecursiveType: + template: "Illegal recursive type '#type'." + script: > + class Base {} + class Derived extends Base>> {} diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart index 4685f798c47..fc076559df1 100644 --- a/pkg/vm/bin/kernel_service.dart +++ b/pkg/vm/bin/kernel_service.dart @@ -145,12 +145,13 @@ abstract class Compiler { if (options.bytecode && errors.isEmpty) { await runWithFrontEndCompilerContext(script, options, component, () { - // TODO(alexmarkov): disable source positions and local variables - // in VM PRODUCT mode. + // TODO(alexmarkov): disable source positions, local variables info + // and source files in VM PRODUCT mode. generateBytecode(component, environmentDefines: options.environmentDefines, emitSourcePositions: true, - emitLocalVarInfo: true); + emitLocalVarInfo: true, + emitSourceFiles: true); }); } diff --git a/pkg/vm/lib/bytecode/ast_remover.dart b/pkg/vm/lib/bytecode/ast_remover.dart deleted file mode 100644 index e7a28d1b1c9..00000000000 --- a/pkg/vm/lib/bytecode/ast_remover.dart +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright (c) 2019, 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.ast_remover; - -import 'package:kernel/ast.dart' hide MapEntry; -import '../metadata/bytecode.dart'; - -/// Drops kernel AST for members with bytecode. -/// Can preserve removed AST and restore it if needed. -class ASTRemover extends Transformer { - final BytecodeMetadataRepository metadata; - final stashes = {}; - - ASTRemover(Component component) - : metadata = component.metadata[new BytecodeMetadataRepository().tag] { - stashes[component] = new _ComponentStash(component.mainMethod, - new Map>.from(component.metadata)); - component.mainMethod = null; - component.metadata.removeWhere((tag, md) => tag != metadata.tag); - } - - @override - visitLibrary(Library node) { - stashes[node] = new _LibraryStash( - new List.from(node.annotations), - new List.from(node.fields), - new List.from(node.procedures), - new List.from(node.additionalExports)); - - node.annotations.clear(); - node.fields.clear(); - node.procedures.clear(); - node.additionalExports.clear(); - - super.visitLibrary(node); - - return node; - } - - @override - visitLibraryDependency(LibraryDependency node) { - stashes[node] = new _LibraryDependencyStash( - new List.from(node.annotations)); - - node.annotations.clear(); - - super.visitLibraryDependency(node); - - return node; - } - - // Still referenced from function types which may appear in class supertypes. - @override - visitTypedef(Typedef node) { - stashes[node] = new _TypedefStash(node.annotations); - - node.annotations = const []; - - super.visitTypedef(node); - - // TODO(alexmarkov): fix Typedef visitor to visit these fields. - transformList(node.positionalParameters, this, node); - transformList(node.namedParameters, this, node); - - return node; - } - - // May appear in typedefs. - @override - visitVariableDeclaration(VariableDeclaration node) { - stashes[node] = new _VariableDeclarationStash(node.annotations); - - node.annotations = const []; - - super.visitVariableDeclaration(node); - - return node; - } - - @override - visitClass(Class node) { - stashes[node] = new _ClassStash( - node.annotations, - new List.from(node.fields), - new List.from(node.procedures), - new List.from(node.constructors)); - - node.annotations = const []; - node.fields.clear(); - node.procedures.clear(); - node.constructors.clear(); - - super.visitClass(node); - - return node; - } - - void restoreAST() { - stashes.forEach((Node node, _Stash stash) { - if (node is Component) { - _ComponentStash componentStash = stash as _ComponentStash; - node.mainMethod = componentStash.mainMethod; - node.metadata.addAll(componentStash.metadata); - } else if (node is Library) { - _LibraryStash libraryStash = stash as _LibraryStash; - node.annotations.addAll(libraryStash.annotations); - node.fields.addAll(libraryStash.fields); - node.procedures.addAll(libraryStash.procedures); - node.additionalExports.addAll(libraryStash.additionalExports); - } else if (node is LibraryDependency) { - _LibraryDependencyStash libraryDependencyStash = - stash as _LibraryDependencyStash; - node.annotations.addAll(libraryDependencyStash.annotations); - } else if (node is Typedef) { - _TypedefStash typedefStash = stash as _TypedefStash; - node.annotations = typedefStash.annotations; - } else if (node is VariableDeclaration) { - _VariableDeclarationStash variableDeclarationStash = - stash as _VariableDeclarationStash; - node.annotations = variableDeclarationStash.annotations; - } else if (node is Class) { - _ClassStash classStash = stash as _ClassStash; - node.annotations = classStash.annotations; - node.fields.addAll(classStash.fields); - node.procedures.addAll(classStash.procedures); - node.constructors.addAll(classStash.constructors); - } else { - throw 'Unexpected ${node.runtimeType} $node'; - } - }); - } -} - -abstract class _Stash {} - -class _ClassStash extends _Stash { - final List annotations; - final List fields; - final List procedures; - final List constructors; - - _ClassStash( - this.annotations, this.fields, this.procedures, this.constructors); -} - -class _LibraryStash extends _Stash { - final List annotations; - final List fields; - final List procedures; - final List additionalExports; - - _LibraryStash( - this.annotations, this.fields, this.procedures, this.additionalExports); -} - -class _LibraryDependencyStash extends _Stash { - final List annotations; - - _LibraryDependencyStash(this.annotations); -} - -class _TypedefStash extends _Stash { - final List annotations; - - _TypedefStash(this.annotations); -} - -class _VariableDeclarationStash extends _Stash { - final List annotations; - - _VariableDeclarationStash(this.annotations); -} - -class _ComponentStash extends _Stash { - final Procedure mainMethod; - final Map> metadata; - - _ComponentStash(this.mainMethod, this.metadata); -} diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart index db9fa7198b0..5f2dd85a541 100644 --- a/pkg/vm/lib/bytecode/bytecode_serialization.dart +++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart @@ -234,6 +234,11 @@ class BufferedReader { return linkReader.get(offset); } + ForwardReference readLinkOffsetAsForwardReference() { + final offset = readPackedUInt30(); + return new ForwardReference(offset, linkReader); + } + void align(int alignment) { assert(alignment & (alignment - 1) == 0); _pos = ((_pos + alignment - 1) & -alignment); @@ -455,6 +460,16 @@ class LinkReader { } } +// Placeholder for an object which will be read in future. +class ForwardReference { + final int offset; + final LinkReader linkReader; + + ForwardReference(this.offset, this.linkReader); + + T get() => linkReader.get(offset); +} + class NamedEntryStatistics { final String name; int size = 0; @@ -471,7 +486,15 @@ class BytecodeSizeStatistics { static int objectTableSize = 0; static int objectTableEntriesCount = 0; static int stringTableSize = 0; + static int librariesSize = 0; + static int classesSize = 0; static int membersSize = 0; + static int codeSize = 0; + static int sourcePositionsSize = 0; + static int sourceFilesSize = 0; + static int lineStartsSize = 0; + static int localVariablesSize = 0; + static int annotationsSize = 0; static int constantPoolSize = 0; static int instructionsSize = 0; static List constantPoolStats = @@ -483,7 +506,15 @@ class BytecodeSizeStatistics { objectTableSize = 0; objectTableEntriesCount = 0; stringTableSize = 0; + librariesSize = 0; + classesSize = 0; membersSize = 0; + codeSize = 0; + sourcePositionsSize = 0; + sourceFilesSize = 0; + lineStartsSize = 0; + localVariablesSize = 0; + annotationsSize = 0; constantPoolSize = 0; instructionsSize = 0; constantPoolStats = []; @@ -499,7 +530,15 @@ class BytecodeSizeStatistics { print(" - $entry"); } print(" - string table: $stringTableSize"); - print(" Bytecode members: $membersSize"); + print(" Libraries: $librariesSize"); + print(" Classes: $classesSize"); + print(" Members: $membersSize"); + print(" Source positions: $sourcePositionsSize"); + print(" Source files: $sourceFilesSize"); + print(" Line starts: $lineStartsSize"); + print(" Local variables: $localVariablesSize"); + print(" Annotations: $annotationsSize"); + print(" Code: $codeSize"); print(" - constant pool: $constantPoolSize"); for (var entry in constantPoolStats) { print(" - $entry"); diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart index 351a3e7448e..244e8008ca1 100644 --- a/pkg/vm/lib/bytecode/dbc.dart +++ b/pkg/vm/lib/bytecode/dbc.dart @@ -10,7 +10,7 @@ library vm.bytecode.dbc; /// Before bumping current bytecode version format, make sure that /// all users have switched to a VM which is able to consume new /// version of bytecode. -const int currentBytecodeFormatVersion = 9; +const int currentBytecodeFormatVersion = 10; /// Version of experimental / bleeding edge bytecode format. /// Produced by bytecode generator when --use-future-bytecode-format diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart index 1d8cfc53eb1..58827b6ebf0 100644 --- a/pkg/vm/lib/bytecode/declarations.dart +++ b/pkg/vm/lib/bytecode/declarations.dart @@ -14,7 +14,250 @@ import 'disassembler.dart' show BytecodeDisassembler; import 'exceptions.dart' show ExceptionsTable; import 'local_variable_table.dart' show LocalVariableTable; import 'object_table.dart' show ObjectTable, ObjectHandle, NameAndType; -import 'source_positions.dart' show SourcePositions; +import 'source_positions.dart' show LineStarts, SourcePositions; + +class LibraryDeclaration { + static const usesDartMirrorsFlag = 1 << 0; + static const usesDartFfiFlag = 1 << 1; + + ObjectHandle importUri; + final int flags; + final ObjectHandle name; + final ObjectHandle script; + final List classes; + + LibraryDeclaration( + this.importUri, this.flags, this.name, this.script, this.classes); + + void write(BufferedWriter writer) { + final start = writer.offset; + writer.writePackedUInt30(flags); + writer.writePackedObject(name); + writer.writePackedObject(script); + writer.writePackedUInt30(classes.length); + for (var cls in classes) { + writer.writePackedObject(cls.name); + writer.writeLinkOffset(cls); + } + BytecodeSizeStatistics.librariesSize += (writer.offset - start); + } + + factory LibraryDeclaration.read(BufferedReader reader) { + final flags = reader.readPackedUInt30(); + final name = reader.readPackedObject(); + final script = reader.readPackedObject(); + final classes = + List.generate(reader.readPackedUInt30(), (_) { + final className = reader.readPackedObject(); + return reader.readLinkOffset()..name = className; + }); + return new LibraryDeclaration(null, flags, name, script, classes); + } + + @override + String toString() { + final StringBuffer sb = new StringBuffer(); + sb.writeln('Library $importUri'); + sb.writeln(' name $name'); + sb.writeln(' script $script'); + if ((flags & usesDartMirrorsFlag) != 0) { + sb.writeln(' uses dart:mirrors'); + } + if ((flags & usesDartFfiFlag) != 0) { + sb.writeln(' uses dart:ffi'); + } + sb.writeln(); + for (var cls in classes) { + sb.write(cls); + } + return sb.toString(); + } +} + +class ClassDeclaration { + static const isAbstractFlag = 1 << 0; + static const isEnumFlag = 1 << 1; + static const hasTypeParamsFlag = 1 << 2; + static const hasTypeArgumentsFlag = 1 << 3; + static const isTransformedMixinApplicationFlag = 1 << 4; + static const hasSourcePositionsFlag = 1 << 5; + static const hasAnnotationsFlag = 1 << 6; + static const hasPragmaFlag = 1 << 7; + + ObjectHandle name; + final int flags; + final ObjectHandle script; + final int position; + final int endPosition; + final TypeParametersDeclaration typeParameters; + final int numTypeArguments; + final ObjectHandle superType; + final List interfaces; + final Members members; + final ObjectHandle annotations; + + ClassDeclaration( + this.name, + this.flags, + this.script, + this.position, + this.endPosition, + this.typeParameters, + this.numTypeArguments, + this.superType, + this.interfaces, + this.members, + this.annotations); + + void write(BufferedWriter writer) { + final start = writer.offset; + writer.writePackedUInt30(flags); + writer.writePackedObject(script); + + if ((flags & hasSourcePositionsFlag) != 0) { + writer.writePackedUInt30(position + 1); + writer.writePackedUInt30(endPosition + 1); + } + if ((flags & hasTypeArgumentsFlag) != 0) { + writer.writePackedUInt30(numTypeArguments); + } + if ((flags & hasTypeParamsFlag) != 0) { + typeParameters.write(writer); + } + writer.writePackedObject(superType); + writer.writePackedList(interfaces); + if ((flags & hasAnnotationsFlag) != 0) { + writer.writeLinkOffset(annotations); + } + writer.writeLinkOffset(members); + BytecodeSizeStatistics.classesSize += (writer.offset - start); + } + + factory ClassDeclaration.read(BufferedReader reader) { + final flags = reader.readPackedUInt30(); + final script = reader.readPackedObject(); + final position = ((flags & hasSourcePositionsFlag) != 0) + ? reader.readPackedUInt30() - 1 + : TreeNode.noOffset; + final endPosition = ((flags & hasSourcePositionsFlag) != 0) + ? reader.readPackedUInt30() - 1 + : TreeNode.noOffset; + final numTypeArguments = + ((flags & hasTypeArgumentsFlag) != 0) ? reader.readPackedUInt30() : 0; + final typeParameters = ((flags & hasTypeParamsFlag) != 0) + ? new TypeParametersDeclaration.read(reader) + : null; + final superType = reader.readPackedObject(); + final interfaces = reader.readPackedList(); + final annotations = ((flags & hasAnnotationsFlag) != 0) + ? reader.readLinkOffset() + : null; + final members = reader.readLinkOffset(); + return new ClassDeclaration( + null, + flags, + script, + position, + endPosition, + typeParameters, + numTypeArguments, + superType, + interfaces, + members, + annotations); + } + + @override + String toString() { + final StringBuffer sb = new StringBuffer(); + sb.write('Class $name, script = $script'); + if ((flags & isAbstractFlag) != 0) { + sb.write(', abstract'); + } + if ((flags & isEnumFlag) != 0) { + sb.write(', enum'); + } + if ((flags & isTransformedMixinApplicationFlag) != 0) { + sb.write(', mixin-application'); + } + if ((flags & hasPragmaFlag) != 0) { + sb.write(', has-pragma'); + } + if ((flags & hasSourcePositionsFlag) != 0) { + sb.write(', pos = $position, end-pos = $endPosition'); + } + sb.writeln(); + if ((flags & hasTypeParamsFlag) != 0) { + sb.write(' type-params $typeParameters (args: $numTypeArguments)\n'); + } + if (superType != null) { + sb.write(' extends $superType\n'); + } + if (interfaces.isNotEmpty) { + sb.write(' implements $interfaces\n'); + } + if ((flags & hasAnnotationsFlag) != 0) { + sb.write(' annotations $annotations\n'); + } + sb.writeln(); + sb.write(members.toString()); + return sb.toString(); + } +} + +class SourceFile { + static const hasLineStartsFlag = 1 << 0; + static const hasSourceFlag = 1 << 1; + + int flags; + final ObjectHandle importUri; + final LineStarts lineStarts; + final String source; + + SourceFile(this.importUri, this.lineStarts, this.source) { + flags = 0; + if (lineStarts != null) { + flags |= hasLineStartsFlag; + } + if (source != null && source != '') { + flags |= hasSourceFlag; + } + } + + void write(BufferedWriter writer) { + writer.writePackedUInt30(flags); + writer.writePackedObject(importUri); + if ((flags & hasLineStartsFlag) != 0) { + writer.writeLinkOffset(lineStarts); + } + if ((flags & hasSourceFlag) != 0) { + writer.writePackedStringReference(source); + } + } + + factory SourceFile.read(BufferedReader reader) { + final flags = reader.readPackedUInt30(); + final importUri = reader.readPackedObject(); + final lineStarts = ((flags & hasLineStartsFlag) != 0) + ? reader.readLinkOffset() + : null; + final source = ((flags & hasSourceFlag) != 0) + ? reader.readPackedStringReference() + : null; + return new SourceFile(importUri, lineStarts, source); + } + + @override + String toString() { + final StringBuffer sb = new StringBuffer(); + sb.writeln('SourceFile $importUri'); + sb.writeln('------------------------------------------------'); + sb.write(source); + sb.writeln('------------------------------------------------'); + sb.writeln(lineStarts); + return sb.toString(); + } +} class Members { final List fields; @@ -36,6 +279,7 @@ class Members { } void write(BufferedWriter writer) { + final start = writer.offset; writer.writePackedUInt30(countFunctions()); writer.writePackedUInt30(fields.length); for (var field in fields) { @@ -45,6 +289,7 @@ class Members { for (var func in functions) { func.write(writer); } + BytecodeSizeStatistics.membersSize += (writer.offset - start); } factory Members.read(BufferedReader reader) { @@ -57,11 +302,8 @@ class Members { } @override - String toString() => "\n" - "Members {\n" - "${fields.join('\n')}\n" - "${functions.join('\n')}" - "}\n"; + String toString() => "${fields.join('\n')}\n" + "${functions.join('\n')}"; } class FieldDeclaration { @@ -164,7 +406,7 @@ class FieldDeclaration { @override String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuffer sb = new StringBuffer(); sb.write('Field $name, type = $type'); if ((flags & hasGetterFlag) != 0) { sb.write(', getter = $getterName'); @@ -195,7 +437,7 @@ class FieldDeclaration { } sb.writeln(); if ((flags & hasInitializerFlag) != 0) { - sb.write(' initializer $initializerCode\n'); + sb.write(' initializer\n$initializerCode\n'); } else { sb.write(' value = $value\n'); } @@ -341,7 +583,7 @@ class FunctionDeclaration { @override String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuffer sb = new StringBuffer(); sb.write('Function $name'); if ((flags & isConstructorFlag) != 0) { sb.write(', constructor'); @@ -571,7 +813,7 @@ class Code { if (hasClosures) { closures.forEach((c) => c.code.write(writer)); } - BytecodeSizeStatistics.membersSize += (writer.offset - start); + BytecodeSizeStatistics.codeSize += (writer.offset - start); } factory Code.read(BufferedReader reader) { @@ -625,8 +867,7 @@ class Code { // TODO(alexmarkov): Consider printing constant pool before bytecode. @override - String toString() => "\n" - "Bytecode {\n" + String toString() => "Bytecode {\n" "${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [ hasSourcePositions ? sourcePositions.getBytecodeAnnotations() @@ -761,7 +1002,7 @@ class ClosureDeclaration { @override String toString() { - StringBuffer sb = new StringBuffer(); + final StringBuffer sb = new StringBuffer(); sb.write('Closure $parent::$name'); if (position != TreeNode.noOffset) { sb.write(' pos = $position, end-pos = $endPosition'); @@ -850,7 +1091,7 @@ class ClosureCode { String toString() { StringBuffer sb = new StringBuffer(); sb.writeln('ClosureCode {'); - sb.writeln(new BytecodeDisassembler() + sb.write(new BytecodeDisassembler() .disassemble(bytecodes, exceptionsTable, annotations: [ hasSourcePositions ? sourcePositions.getBytecodeAnnotations() @@ -876,7 +1117,7 @@ class _Section { class Component { static const int magicValue = 0x44424332; // 'DBC2' - static const int numSections = 8; + static const int numSections = 13; static const int sectionAlignment = 4; // UInt32 magic, version, numSections x (numItems, offset) @@ -885,11 +1126,16 @@ class Component { int version; StringTable stringTable; ObjectTable objectTable; - List members = []; - List codes = []; - List sourcePositions = []; - List localVariables = []; - List annotations = []; + final List libraries = []; + final List classes = []; + final List members = []; + final List codes = []; + final List sourcePositions = []; + final List lineStarts = []; + final List sourceFiles = []; + final Map uriToSource = {}; + final List localVariables = []; + final List annotations = []; ObjectHandle mainLibrary; Component(this.version) @@ -902,58 +1148,96 @@ class Component { // Write sections to their own buffers in reverse order as section may // reference data structures from successor sections by offsets. - final BufferedWriter annotationsWriter = - new BufferedWriter.fromWriter(writer); + final annotationsWriter = new BufferedWriter.fromWriter(writer); for (var annot in annotations) { writer.linkWriter.put(annot, annotationsWriter.offset); annotationsWriter.writePackedObject(annot); } + BytecodeSizeStatistics.annotationsSize += annotationsWriter.offset; - final BufferedWriter localVariablesWriter = - new BufferedWriter.fromWriter(writer); + final localVariablesWriter = new BufferedWriter.fromWriter(writer); for (var lv in localVariables) { writer.linkWriter.put(lv, localVariablesWriter.offset); lv.write(localVariablesWriter); } + BytecodeSizeStatistics.localVariablesSize += localVariablesWriter.offset; - final BufferedWriter sourcePositionsWriter = - new BufferedWriter.fromWriter(writer); + final lineStartsWriter = new BufferedWriter.fromWriter(writer); + for (var ls in lineStarts) { + writer.linkWriter.put(ls, lineStartsWriter.offset); + ls.write(lineStartsWriter); + } + BytecodeSizeStatistics.lineStartsSize += lineStartsWriter.offset; + + final sourceFilesWriter = new BufferedWriter.fromWriter(writer); + for (var sf in sourceFiles) { + writer.linkWriter.put(sf, sourceFilesWriter.offset); + sf.write(sourceFilesWriter); + } + BytecodeSizeStatistics.sourceFilesSize += sourceFilesWriter.offset; + + final sourcePositionsWriter = new BufferedWriter.fromWriter(writer); for (var sp in sourcePositions) { writer.linkWriter.put(sp, sourcePositionsWriter.offset); sp.write(sourcePositionsWriter); } + BytecodeSizeStatistics.sourcePositionsSize += sourcePositionsWriter.offset; - final BufferedWriter codesWriter = new BufferedWriter.fromWriter(writer); + final codesWriter = new BufferedWriter.fromWriter(writer); for (var code in codes) { writer.linkWriter.put(code, codesWriter.offset); code.write(codesWriter); } - final BufferedWriter membersWriter = new BufferedWriter.fromWriter(writer); + final membersWriter = new BufferedWriter.fromWriter(writer); for (var m in members) { writer.linkWriter.put(m, membersWriter.offset); m.write(membersWriter); } + final classesWriter = new BufferedWriter.fromWriter(writer); + for (var cls in classes) { + writer.linkWriter.put(cls, classesWriter.offset); + cls.write(classesWriter); + } + + final librariesWriter = new BufferedWriter.fromWriter(writer); + for (var library in libraries) { + writer.linkWriter.put(library, librariesWriter.offset); + library.write(librariesWriter); + } + + final libraryIndexWriter = new BufferedWriter.fromWriter(writer); + for (var library in libraries) { + libraryIndexWriter.writePackedObject(library.importUri); + libraryIndexWriter.writeLinkOffset(library); + } + BytecodeSizeStatistics.librariesSize += libraryIndexWriter.offset; + BufferedWriter mainWriter; if (mainLibrary != null) { mainWriter = new BufferedWriter.fromWriter(writer); mainWriter.writePackedObject(mainLibrary); } - final BufferedWriter objectsWriter = new BufferedWriter.fromWriter(writer); + final objectsWriter = new BufferedWriter.fromWriter(writer); objectTable.write(objectsWriter); - final BufferedWriter stringsWriter = new BufferedWriter.fromWriter(writer); + final stringsWriter = new BufferedWriter.fromWriter(writer); stringTable.write(stringsWriter); List<_Section> sections = [ new _Section(0, stringsWriter), new _Section(0, objectsWriter), new _Section(0, mainWriter), + new _Section(libraries.length, libraryIndexWriter), + new _Section(libraries.length, librariesWriter), + new _Section(classes.length, classesWriter), new _Section(members.length, membersWriter), new _Section(codes.length, codesWriter), new _Section(sourcePositions.length, sourcePositionsWriter), + new _Section(sourceFiles.length, sourceFilesWriter), + new _Section(lineStarts.length, lineStartsWriter), new _Section(localVariables.length, localVariablesWriter), new _Section(annotations.length, annotationsWriter), ]; @@ -1014,6 +1298,15 @@ class Component { reader.readUInt32(); final mainOffset = reader.readUInt32(); + final librariesNum = reader.readUInt32(); + final libraryIndexOffset = reader.readUInt32(); + + reader.readUInt32(); + final librariesOffset = reader.readUInt32(); + + final classesNum = reader.readUInt32(); + final classesOffset = reader.readUInt32(); + final membersNum = reader.readUInt32(); final membersOffset = reader.readUInt32(); @@ -1023,6 +1316,12 @@ class Component { final sourcePositionsNum = reader.readUInt32(); final sourcePositionsOffset = reader.readUInt32(); + final sourceFilesNum = reader.readUInt32(); + final sourceFilesOffset = reader.readUInt32(); + + final lineStartsNum = reader.readUInt32(); + final lineStartsOffset = reader.readUInt32(); + final localVariablesNum = reader.readUInt32(); final localVariablesOffset = reader.readUInt32(); @@ -1049,6 +1348,24 @@ class Component { annotations.add(annot); } + final lineStartsStart = start + lineStartsOffset; + reader.offset = lineStartsStart; + for (int i = 0; i < lineStartsNum; ++i) { + int offset = reader.offset - lineStartsStart; + LineStarts ls = new LineStarts.read(reader); + reader.linkReader.setOffset(ls, offset); + lineStarts.add(ls); + } + + final sourceFilesStart = start + sourceFilesOffset; + reader.offset = sourceFilesStart; + for (int i = 0; i < sourceFilesNum; ++i) { + int offset = reader.offset - sourceFilesStart; + SourceFile sf = new SourceFile.read(reader); + reader.linkReader.setOffset(sf, offset); + sourceFiles.add(sf); + } + final sourcePositionsStart = start + sourcePositionsOffset; reader.offset = sourcePositionsStart; for (int i = 0; i < sourcePositionsNum; ++i) { @@ -1085,22 +1402,58 @@ class Component { members.add(m); } + final classesStart = start + classesOffset; + reader.offset = classesStart; + for (int i = 0; i < classesNum; ++i) { + int offset = reader.offset - classesStart; + ClassDeclaration cls = new ClassDeclaration.read(reader); + reader.linkReader.setOffset(cls, offset); + classes.add(cls); + } + + final librariesStart = start + librariesOffset; + reader.offset = librariesStart; + for (int i = 0; i < librariesNum; ++i) { + int offset = reader.offset - librariesStart; + LibraryDeclaration library = new LibraryDeclaration.read(reader); + reader.linkReader.setOffset(library, offset); + libraries.add(library); + } + + final libraryIndexStart = start + libraryIndexOffset; + reader.offset = libraryIndexStart; + for (int i = 0; i < librariesNum; ++i) { + final importUri = reader.readPackedObject(); + final library = reader.readLinkOffset(); + library.importUri = importUri; + } + if (mainOffset != 0) { reader.offset = start + mainOffset; mainLibrary = reader.readPackedObject(); } } - String toString() => "\n" - "Bytecode" - " (version: " - "${version == currentBytecodeFormatVersion ? 'stable' : version == futureBytecodeFormatVersion ? 'future' : "v$version"}" - ")\n" -// "$objectTable\n" -// "$stringTable\n" - "${mainLibrary != null ? 'Main library: $mainLibrary\n' : ''}" -// "${members.join('\n')}\n" - ; + @override + String toString() { + final StringBuffer sb = new StringBuffer(); + sb.write("Bytecode (version: "); + if (version == currentBytecodeFormatVersion) { + sb.write("stable"); + } else if (version == futureBytecodeFormatVersion) { + sb.write("future"); + } else { + sb.write("v$version"); + } + sb.writeln(")"); + if (mainLibrary != null) { + sb.writeln("Main library: $mainLibrary"); + } + for (var library in libraries) { + sb.write(library); + } + return sb.toString(); + } } void _writeBytecodeInstructions(BufferedWriter writer, List bytecodes) { diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart index ba4f75eab2b..01426c5e532 100644 --- a/pkg/vm/lib/bytecode/gen_bytecode.dart +++ b/pkg/vm/lib/bytecode/gen_bytecode.dart @@ -8,6 +8,8 @@ library vm.bytecode.gen_bytecode; // explicitly once constant-update-2018 is shipped. import 'package:front_end/src/api_prototype/constant_evaluator.dart' show ConstantEvaluator, EvaluationEnvironment, ErrorReporter; +import 'package:front_end/src/api_unstable/vm.dart' + show CompilerContext, Severity, templateIllegalRecursiveType; import 'package:kernel/ast.dart' hide MapEntry, Component, FunctionDeclaration; import 'package:kernel/ast.dart' as ast show Component, FunctionDeclaration; @@ -38,12 +40,15 @@ import 'generics.dart' import 'local_variable_table.dart' show LocalVariableTable; import 'local_vars.dart' show LocalVariables; import 'nullability_detector.dart' show NullabilityDetector; -import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType; +import 'object_table.dart' + show ObjectHandle, ObjectTable, NameAndType, topLevelClassName; import 'recognized_methods.dart' show RecognizedMethods; -import 'source_positions.dart' show SourcePositions; +import 'recursive_types_validator.dart' show IllegalRecursiveTypeException; +import 'source_positions.dart' show LineStarts, SourcePositions; import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors; import '../metadata/bytecode.dart'; +import 'dart:convert' show utf8; import 'dart:math' as math; // This symbol is used as the name in assert assignable's to indicate it comes @@ -55,6 +60,7 @@ void generateBytecode( ast.Component component, { bool enableAsserts: true, bool emitSourcePositions: false, + bool emitSourceFiles: false, bool emitLocalVarInfo: false, bool emitAnnotations: false, bool omitAssertSourcePositions: false, @@ -73,22 +79,29 @@ void generateBytecode( final constantsBackend = new VmConstantsBackend(coreTypes); final errorReporter = new ForwardConstantEvaluationErrors(); libraries ??= component.libraries; - final bytecodeGenerator = new BytecodeGenerator( - component, - coreTypes, - hierarchy, - typeEnvironment, - constantsBackend, - environmentDefines, - enableAsserts, - emitSourcePositions, - emitLocalVarInfo, - emitAnnotations, - omitAssertSourcePositions, - useFutureBytecodeFormat, - errorReporter); - for (var library in libraries) { - bytecodeGenerator.visitLibrary(library); + try { + final bytecodeGenerator = new BytecodeGenerator( + component, + coreTypes, + hierarchy, + typeEnvironment, + constantsBackend, + environmentDefines, + enableAsserts, + emitSourcePositions, + emitSourceFiles, + emitLocalVarInfo, + emitAnnotations, + omitAssertSourcePositions, + useFutureBytecodeFormat, + errorReporter); + for (var library in libraries) { + bytecodeGenerator.visitLibrary(library); + } + } on IllegalRecursiveTypeException catch (e) { + CompilerContext.current.options.report( + templateIllegalRecursiveType.withArguments(e.type).withoutLocation(), + Severity.error); } } @@ -100,6 +113,7 @@ class BytecodeGenerator extends RecursiveVisitor { final Map environmentDefines; final bool enableAsserts; final bool emitSourcePositions; + final bool emitSourceFiles; final bool emitLocalVarInfo; final bool emitAnnotations; final bool omitAssertSourcePositions; @@ -108,11 +122,13 @@ class BytecodeGenerator extends RecursiveVisitor { final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository(); final RecognizedMethods recognizedMethods; final int formatVersion; + final Map astUriToSource; StringTable stringTable; ObjectTable objectTable; Component bytecodeComponent; NullabilityDetector nullabilityDetector; + List classDeclarations; List fieldDeclarations; List functionDeclarations; Class enclosingClass; @@ -152,6 +168,7 @@ class BytecodeGenerator extends RecursiveVisitor { this.environmentDefines, this.enableAsserts, this.emitSourcePositions, + this.emitSourceFiles, this.emitLocalVarInfo, this.emitAnnotations, this.omitAssertSourcePositions, @@ -160,14 +177,13 @@ class BytecodeGenerator extends RecursiveVisitor { : recognizedMethods = new RecognizedMethods(typeEnvironment), formatVersion = useFutureBytecodeFormat ? futureBytecodeFormatVersion - : currentBytecodeFormatVersion { + : currentBytecodeFormatVersion, + astUriToSource = component.uriToSource { nullabilityDetector = new NullabilityDetector(recognizedMethods); component.addMetadataRepository(metadata); bytecodeComponent = new Component(formatVersion); - metadata.bytecodeComponent = bytecodeComponent; - metadata.mapping[component] = - new ComponentBytecodeMetadata(bytecodeComponent); + metadata.mapping[component] = new BytecodeMetadata(bytecodeComponent); stringTable = bytecodeComponent.stringTable; objectTable = bytecodeComponent.objectTable; @@ -185,12 +201,20 @@ class BytecodeGenerator extends RecursiveVisitor { return; } - visitList(node.classes, this); - startMembers(); visitList(node.procedures, this); visitList(node.fields, this); - endMembers(node); + final members = endMembers(node); + + classDeclarations = [ + getTopLevelClassDeclaration(node, members) + ]; + + visitList(node.classes, this); + + bytecodeComponent.libraries + .add(getLibraryDeclaration(node, classDeclarations)); + classDeclarations = null; } @override @@ -199,7 +223,9 @@ class BytecodeGenerator extends RecursiveVisitor { visitList(node.constructors, this); visitList(node.procedures, this); visitList(node.fields, this); - endMembers(node); + final members = endMembers(node); + + classDeclarations.add(getClassDeclaration(node, members)); } void startMembers() { @@ -207,13 +233,159 @@ class BytecodeGenerator extends RecursiveVisitor { functionDeclarations = []; } - void endMembers(TreeNode node) { + Members endMembers(TreeNode node) { final members = new Members(fieldDeclarations, functionDeclarations); bytecodeComponent.members.add(members); - metadata.mapping[node] = new MembersBytecodeMetadata(members); - fieldDeclarations = null; functionDeclarations = null; + return members; + } + + ObjectHandle getScript(Uri uri, bool includeSource) { + SourceFile source; + if (includeSource && (emitSourceFiles || emitSourcePositions)) { + source = bytecodeComponent.uriToSource[uri]; + if (source == null) { + final astSource = astUriToSource[uri]; + if (astSource != null) { + final importUri = + objectTable.getNameHandle(null, astSource.importUri.toString()); + LineStarts lineStarts; + if (emitSourcePositions) { + lineStarts = new LineStarts(astSource.lineStarts); + bytecodeComponent.lineStarts.add(lineStarts); + } + String text = ''; + if (emitSourceFiles) { + text = astSource.cachedText ?? + utf8.decode(astSource.source, allowMalformed: true); + } + source = new SourceFile(importUri, lineStarts, text); + bytecodeComponent.sourceFiles.add(source); + bytecodeComponent.uriToSource[uri] = source; + } + } + } + return objectTable.getScriptHandle(uri, source); + } + + LibraryDeclaration getLibraryDeclaration( + Library library, List classes) { + final importUri = + objectTable.getNameHandle(null, library.importUri.toString()); + int flags = 0; + for (var dependency in library.dependencies) { + final targetLibrary = dependency.targetLibrary; + assert(targetLibrary != null); + if (targetLibrary == coreTypes.mirrorsLibrary) { + flags |= LibraryDeclaration.usesDartMirrorsFlag; + } else if (targetLibrary == dartFfiLibrary) { + flags |= LibraryDeclaration.usesDartFfiFlag; + } + } + final name = objectTable.getNameHandle(null, library.name ?? ''); + final script = getScript(library.fileUri, true); + return new LibraryDeclaration(importUri, flags, name, script, classes); + } + + ClassDeclaration getClassDeclaration(Class cls, Members members) { + int flags = 0; + if (cls.isAbstract) { + flags |= ClassDeclaration.isAbstractFlag; + } + if (cls.isEnum) { + flags |= ClassDeclaration.isEnumFlag; + } + int numTypeArguments = 0; + TypeParametersDeclaration typeParameters; + if (hasInstantiatorTypeArguments(cls)) { + flags |= ClassDeclaration.hasTypeArgumentsFlag; + numTypeArguments = flattenInstantiatorTypeArguments( + cls, + cls.typeParameters + .map((tp) => new TypeParameterType(tp)) + .toList()) + .length; + assert(numTypeArguments > 0); + if (cls.typeParameters.isNotEmpty) { + flags |= ClassDeclaration.hasTypeParamsFlag; + typeParameters = getTypeParametersDeclaration(cls.typeParameters); + } + } + if (cls.isEliminatedMixin) { + flags |= ClassDeclaration.isTransformedMixinApplicationFlag; + } + int position = TreeNode.noOffset; + int endPosition = TreeNode.noOffset; + if (emitSourcePositions && cls.fileOffset != TreeNode.noOffset) { + flags |= ClassDeclaration.hasSourcePositionsFlag; + position = cls.fileOffset; + endPosition = cls.fileEndOffset; + } + Annotations annotations = getAnnotations(cls.annotations); + if (annotations.object != null) { + flags |= ClassDeclaration.hasAnnotationsFlag; + if (annotations.hasPragma) { + flags |= ClassDeclaration.hasPragmaFlag; + } + } + + final nameHandle = objectTable.getNameHandle( + cls.name.startsWith('_') ? cls.enclosingLibrary : null, cls.name); + final script = getScript(cls.fileUri, !cls.isAnonymousMixin); + final superType = objectTable.getHandle(cls.supertype?.asInterfaceType); + final interfaces = objectTable.getHandles( + cls.implementedTypes.map((t) => t.asInterfaceType).toList()); + + final classDeclaration = new ClassDeclaration( + nameHandle, + flags, + script, + position, + endPosition, + typeParameters, + numTypeArguments, + superType, + interfaces, + members, + annotations.object); + bytecodeComponent.classes.add(classDeclaration); + return classDeclaration; + } + + ClassDeclaration getTopLevelClassDeclaration( + Library library, Members members) { + int flags = 0; + int position = TreeNode.noOffset; + if (emitSourcePositions && library.fileOffset != TreeNode.noOffset) { + flags |= ClassDeclaration.hasSourcePositionsFlag; + position = library.fileOffset; + } + Annotations annotations = getAnnotations(library.annotations); + if (annotations.object != null) { + flags |= ClassDeclaration.hasAnnotationsFlag; + if (annotations.hasPragma) { + flags |= ClassDeclaration.hasPragmaFlag; + } + } + + final nameHandle = objectTable.getNameHandle(null, topLevelClassName); + final script = getScript(library.fileUri, true); + + final classDeclaration = new ClassDeclaration( + nameHandle, + flags, + script, + position, + /* endPosition */ TreeNode.noOffset, + /* typeParameters */ null, + /* numTypeArguments */ 0, + /* superType */ null, + /* interfaces */ const [], + members, + annotations.object); + bytecodeComponent.classes.add(classDeclaration); + return classDeclaration; } bool _isPragma(Constant annotation) => @@ -224,7 +396,14 @@ class BytecodeGenerator extends RecursiveVisitor { if (nodes.isEmpty) { return const Annotations(null, false); } + final savedConstantEvaluator = constantEvaluator; + if (constantEvaluator == null) { + constantEvaluator = new ConstantEvaluator(constantsBackend, + environmentDefines, typeEnvironment, enableAsserts, errorReporter) + ..env = new EvaluationEnvironment(); + } List constants = nodes.map(_evaluateConstantExpression).toList(); + constantEvaluator = savedConstantEvaluator; bool hasPragma = constants.any(_isPragma); if (!emitAnnotations) { if (hasPragma) { @@ -673,6 +852,10 @@ class BytecodeGenerator extends RecursiveVisitor { _asyncAwaitCompleterGetFuture ??= libraryIndex.getMember( 'dart:async', '_AsyncAwaitCompleter', 'get:future'); + Library _dartFfiLibrary; + Library get dartFfiLibrary => + _dartFfiLibrary ??= libraryIndex.tryGetLibrary('dart:ffi'); + void _recordSourcePosition(int fileOffset) { if (emitSourcePositions) { asm.currentSourcePosition = fileOffset; @@ -3535,3 +3718,15 @@ class Annotations { const Annotations(this.object, this.hasPragma); } + +ast.Component createFreshComponentWithBytecode(ast.Component component) { + final newComponent = new ast.Component(); + final newRepository = new BytecodeMetadataRepository(); + newComponent.addMetadataRepository(newRepository); + + final oldRepository = component.metadata[newRepository.tag]; + final metadata = oldRepository.mapping[component]; + newRepository.mapping[newComponent] = metadata; + + return newComponent; +} diff --git a/pkg/vm/lib/bytecode/generics.dart b/pkg/vm/lib/bytecode/generics.dart index 4e795d6975e..91f8a70e245 100644 --- a/pkg/vm/lib/bytecode/generics.dart +++ b/pkg/vm/lib/bytecode/generics.dart @@ -152,93 +152,6 @@ class FindFreeTypeParametersVisitor extends DartTypeVisitor { } } -/// Returns true if the given type is recursive after its type arguments -/// are flattened. -bool isRecursiveAfterFlattening(InterfaceType type) { - final visitor = new IsRecursiveAfterFlatteningVisitor(); - visitor.visit(type); - return visitor.isRecursive(type); -} - -class IsRecursiveAfterFlatteningVisitor extends DartTypeVisitor { - Set _visited = new Set(); - List _stack = []; - Set _recursive; - - bool isRecursive(DartType type) => - _recursive != null && _recursive.contains(type); - - void visit(DartType type) { - if (!_visited.add(type)) { - _recordRecursiveType(type); - return; - } - _stack.add(type); - - type.accept(this); - - _stack.removeLast(); - _visited.remove(type); - } - - void _recordRecursiveType(DartType type) { - final int start = _stack.lastIndexOf(type); - final recursive = (_recursive ??= new Set()); - for (int i = start; i < _stack.length; ++i) { - recursive.add(_stack[i]); - } - } - - @override - void defaultDartType(DartType node) => - throw 'Unexpected type ${node.runtimeType} $node'; - - @override - void visitInvalidType(InvalidType node) {} - - @override - void visitDynamicType(DynamicType node) {} - - @override - void visitVoidType(VoidType node) {} - - @override - void visitBottomType(BottomType node) {} - - @override - void visitTypeParameterType(TypeParameterType node) {} - - @override - void visitInterfaceType(InterfaceType node) { - for (var typeArg in node.typeArguments) { - visit(typeArg); - } - if (isRecursive(node)) { - return; - } - final flatTypeArgs = - flattenInstantiatorTypeArguments(node.classNode, node.typeArguments); - for (var typeArg in flatTypeArgs.getRange( - 0, flatTypeArgs.length - node.typeArguments.length)) { - visit(typeArg); - } - } - - @override - void visitTypedefType(TypedefType node) => visit(node.unalias); - - @override - void visitFunctionType(FunctionType node) { - for (var p in node.positionalParameters) { - visit(p); - } - for (var p in node.namedParameters) { - visit(p.type); - } - visit(node.returnType); - } -} - /// Returns static type of [expr]. DartType getStaticType(Expression expr, TypeEnvironment typeEnvironment) { // TODO(dartbug.com/34496): Remove this try/catch once diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart index 80324cc4a5e..be1a7eda399 100644 --- a/pkg/vm/lib/bytecode/object_table.dart +++ b/pkg/vm/lib/bytecode/object_table.dart @@ -13,6 +13,7 @@ import 'bytecode_serialization.dart' BufferedReader, BytecodeObject, BytecodeSizeStatistics, + ForwardReference, NamedEntryStatistics, doubleToIntBits, intBitsToDouble, @@ -20,8 +21,9 @@ import 'bytecode_serialization.dart' ObjectWriter, StringWriter; import 'generics.dart' - show getInstantiatorTypeArguments, isRecursiveAfterFlattening; -import 'declarations.dart' show TypeParametersDeclaration; + show getInstantiatorTypeArguments, hasInstantiatorTypeArguments; +import 'declarations.dart' show SourceFile, TypeParametersDeclaration; +import 'recursive_types_validator.dart' show RecursiveTypesValidator; /* @@ -29,47 +31,43 @@ Bytecode object table is encoded in the following way (using notation from pkg/kernel/binary.md): type ObjectTable { - UInt numEntries; - UInt contentsSize; + UInt numEntries - // Occupies contentsSize bytes. - ObjectContents objects[numEntries] + // Total size of ‘objects’ in bytes. + UInt objectsSize - UInt objectOffsets[numEntries] + ObjectContents[numEntries] objects + + // Offsets relative to ‘objects’. + UInt[numEntries] objectOffsets } + // Either reference to an object in object table, or object contents -// written inline. +// written inline (determined by bit 0). PackedObject = ObjectReference | ObjectContents type ObjectReference { // Bit 0 (reference bit): 1 // Bits 1+: index in object table - UInt reference(1) + UInt reference } type ObjectContents { // Bit 0 (reference bit): 0 // Bits 1-4: object kind // Bits 5+ object flags - UInt header(0) + UInt header } -// Reference to a string in string table. -type PackedString { - // Bit 0: set for two byte string - // Bits 1+: index in string table - UInt indexAndKind() -} - -// Invalid object table entry (at index 0). +// Invalid/null object (always present at index 0). type InvalidObject extends ObjectContents { kind = 0; } type Library extends ObjectContents { kind = 1; - PackedString importUri; + PackedObject importUri; } type Class extends ObjectContents { @@ -93,50 +91,6 @@ type Closure extends ObjectContents { UInt closureIndex; } -type SimpleType extends ObjectContents { - kind = 5; - flags = (isDynamic, isVoid); - PackedObject class; -} - -type TypeParameter extends ObjectContents { - kind = 6; - // Class, Member or Closure declaring this type parameter. - // Invalid if declared by function type. - PackedObject parent; - UInt indexInParent; -} - -type GenericType extends ObjectContents { - kind = 7; - PackedObject class; - List typeArgs; -} - -type FunctionType extends ObjectContents { - kind = 8; - flags = (hasOptionalPositionalParams, hasOptionalNamedParams, hasTypeParams) - - if hasTypeParams - UInt numTypeParameters - PackedObject[numTypeParameters] typeParameterNames - PackedObject[numTypeParameters] typeParameterBounds - - UInt numParameters - - if hasOptionalPositionalParams || hasOptionalNamedParams - UInt numRequiredParameters - - Type[] positionalParameters - NameAndType[] namedParameters - PackedObject returnType -} - -type NameAndType { - PackedObject name; - PackedObject type; -} - type Name extends ObjectContents { kind = 9; @@ -154,12 +108,6 @@ type TypeArguments extends ObjectContents { List args; } -type FinalizedGenericType extends ObjectContents { - kind = 11; - PackedObject class; - PackedObject typeArgs; -} - abstract type ConstObject extends ObjectContents { kind = 12; flags = constantTag (4 bits) @@ -181,7 +129,7 @@ type ConstInt extends ConstValue { type ConstDouble extends ConstValue { kind = 12 constantTag (flags) = 3 - // double bits are converted to int + // double bits are reinterpreted as 64-bit int SLEB128 value; } @@ -223,11 +171,110 @@ type ArgDesc extends ObjectContents { UInt numArguments - if hasTypeArgs - UInt numTypeArguments + if hasTypeArgs + UInt numTypeArguments - if hasNamedArgs - List argNames; + if hasNamedArgs + List argNames; +} + +type Script extends ObjectContents { + kind = 14 + flags = (hasSourceFile) + PackedObject uri + if hasSourceFile + UInt sourceFileOffset +} + +abstract type Type extends ObjectContents { + kind = 15 + flags = typeTag (4 bits) +} + +type DynamicType extends Type { + kind = 15 + typeTag (flags) = 1 +} + +type VoidType extends Type { + kind = 15 + typeTag (flags) = 2 +} + +// SimpleType can be used only for types without instantiator type arguments. +type SimpleType extends Type { + kind = 15 + typeTag (flags) = 3 + PackedObject class +} + +type TypeParameter extends Type { + kind = 15 + typeTag (flags) = 4 + // Class, Member or Closure declaring this type parameter. + // Null (Invalid) if declared by function type. + PackedObject parent + UInt indexInParent +} + +// Non-recursive finalized generic type. +type GenericType extends Type { + kind = 15 + typeTag (flags) = 5 + PackedObject class + // Flattened type arguments vector. + PackedObject typeArgs +} + +// Recursive finalized generic type. +type RecursiveGenericType extends Type { + kind = 15 + typeTag (flags) = 6 + // This id is used to reference recursive types using RecursiveTypeRef. + // Type should be declared using RecursiveGenericType before it can be referenced. + // The root type should have zero recursiveId. + UInt recursiveId + PackedObject class + // Flattened type arguments vector. + PackedObject typeArgs +} + +type RecursiveTypeRef extends Type { + kind = 15 + typeTag (flags) = 7 + UInt recursiveId +} + +type FunctionType extends Type { + kind = 15 + typeTag (flags) = 8 + + UInt functionTypeFlags(hasOptionalPositionalParams, + hasOptionalNamedParams, + hasTypeParams) + + if hasTypeParams + TypeParametersDeclaration typeParameters + + UInt numParameters + + if hasOptionalPositionalParams || hasOptionalNamedParams + UInt numRequiredParameters + + Type[] positionalParameters + NameAndType[] namedParameters + PackedObject returnType +} + +type TypeParametersDeclaration { + UInt numTypeParameters + PackedObject[numTypeParameters] typeParameterNames + PackedObject[numTypeParameters] typeParameterBounds +} + +type NameAndType { + PackedObject name; + PackedObject type; } */ @@ -238,15 +285,17 @@ enum ObjectKind { kClass, kMember, kClosure, - kSimpleType, - kTypeParameter, - kGenericType, - kFunctionType, + kUnused1, + kUnused2, + kUnused3, + kUnused4, kName, kTypeArguments, - kFinalizedGenericType, + kUnused5, kConstObject, kArgDesc, + kScript, + kType, } enum ConstTag { @@ -261,6 +310,21 @@ enum ConstTag { kTearOffInstantiation, } +enum TypeTag { + kInvalid, + kDynamic, + kVoid, + kSimpleType, + kTypeParameter, + kGenericType, + kRecursiveGenericType, + kRecursiveTypeRef, + kFunctionType, +} + +/// Name of artificial class containing top-level members of a library. +const String topLevelClassName = ''; + String objectKindToString(ObjectKind kind) => kind.toString().substring('ObjectKind.k'.length); @@ -315,7 +379,7 @@ abstract class ObjectHandle extends BytecodeObject { bool get isCacheable => true; - factory ObjectHandle._empty(ObjectKind kind) { + factory ObjectHandle._empty(ObjectKind kind, int flags) { switch (kind) { case ObjectKind.kInvalid: return new _InvalidHandle(); @@ -327,24 +391,44 @@ abstract class ObjectHandle extends BytecodeObject { return new _MemberHandle._empty(); case ObjectKind.kClosure: return new _ClosureHandle._empty(); - case ObjectKind.kSimpleType: - return new _SimpleTypeHandle._empty(); - case ObjectKind.kGenericType: - return new _GenericTypeHandle._empty(); - case ObjectKind.kTypeParameter: - return new _TypeParameterHandle._empty(); - case ObjectKind.kFunctionType: - return new _FunctionTypeHandle._empty(); case ObjectKind.kName: return new _NameHandle._empty(); case ObjectKind.kTypeArguments: return new _TypeArgumentsHandle._empty(); - case ObjectKind.kFinalizedGenericType: - return new _FinalizedGenericTypeHandle._empty(); case ObjectKind.kConstObject: return new _ConstObjectHandle._empty(); case ObjectKind.kArgDesc: return new _ArgDescHandle._empty(); + case ObjectKind.kScript: + return new _ScriptHandle._empty(); + case ObjectKind.kType: + switch (TypeTag.values[flags ~/ flagBit0]) { + case TypeTag.kInvalid: + break; + case TypeTag.kDynamic: + return new _DynamicTypeHandle(); + case TypeTag.kVoid: + return new _VoidTypeHandle(); + case TypeTag.kSimpleType: + return new _SimpleTypeHandle._empty(); + case TypeTag.kTypeParameter: + return new _TypeParameterHandle._empty(); + case TypeTag.kGenericType: + return new _GenericTypeHandle._empty(); + case TypeTag.kRecursiveGenericType: + return new _RecursiveGenericTypeHandle._empty(); + case TypeTag.kRecursiveTypeRef: + return new _RecursiveTypeRefHandle._empty(); + case TypeTag.kFunctionType: + return new _FunctionTypeHandle._empty(); + } + throw 'Unexpected type tag $flags'; + case ObjectKind.kUnused1: + case ObjectKind.kUnused2: + case ObjectKind.kUnused3: + case ObjectKind.kUnused4: + case ObjectKind.kUnused5: + break; } throw 'Unexpected object kind $kind'; } @@ -361,8 +445,9 @@ abstract class ObjectHandle extends BytecodeObject { factory ObjectHandle._read(BufferedReader reader, int header) { assert((header & referenceBit) == 0); final ObjectKind kind = _getKindFromHeader(header); - final obj = new ObjectHandle._empty(kind); - obj.flags = _getFlagsFromHeader(header); + final int flags = _getFlagsFromHeader(header); + final obj = new ObjectHandle._empty(kind, flags); + obj.flags = flags; obj.readContents(reader); return obj; } @@ -391,7 +476,7 @@ class _InvalidHandle extends ObjectHandle { } class _LibraryHandle extends ObjectHandle { - String uri; + _NameHandle uri; _LibraryHandle._empty(); @@ -402,17 +487,17 @@ class _LibraryHandle extends ObjectHandle { @override void writeContents(BufferedWriter writer) { - writer.writePackedStringReference(uri); + writer.writePackedObject(uri); } @override void readContents(BufferedReader reader) { - uri = reader.readPackedStringReference(); + uri = reader.readPackedObject(); } @override - void indexStrings(StringWriter strings) { - strings.put(uri); + void accountUsesForObjectCopies(int numCopies) { + uri._useCount += numCopies; } @override @@ -422,13 +507,10 @@ class _LibraryHandle extends ObjectHandle { bool operator ==(other) => other is _LibraryHandle && this.uri == other.uri; @override - String toString() => uri; + String toString() => uri.name; } class _ClassHandle extends ObjectHandle { - /// Name of artificial class containing top-level members of a library. - static const String topLevelClassName = ''; - _LibraryHandle library; _NameHandle name; @@ -578,33 +660,69 @@ class _ClosureHandle extends ObjectHandle { String toString() => '$enclosingMember::Closure/$closureIndex'; } -abstract class _TypeHandle extends ObjectHandle {} +abstract class _TypeHandle extends ObjectHandle { + final TypeTag tag; -class _SimpleTypeHandle extends _TypeHandle { - static const int flagIsDynamic = ObjectHandle.flagBit0; - static const int flagIsVoid = ObjectHandle.flagBit1; - - _ClassHandle class_; - int _flags = 0; - - _SimpleTypeHandle._empty(); - - _SimpleTypeHandle(this.class_); - - _SimpleTypeHandle._dynamic() : _flags = flagIsDynamic; - - _SimpleTypeHandle._void() : _flags = flagIsVoid; + _TypeHandle(this.tag); @override - ObjectKind get kind => ObjectKind.kSimpleType; + ObjectKind get kind => ObjectKind.kType; @override - int get flags => _flags; + int get flags => tag.index * ObjectHandle.flagBit0; @override set flags(int value) { - _flags = value; + if (value != flags) { + throw 'Unable to set flags for _TypeHandle (they are occupied by type tag)'; + } } +} + +class _DynamicTypeHandle extends _TypeHandle { + _DynamicTypeHandle() : super(TypeTag.kDynamic); + + @override + void writeContents(BufferedWriter writer) {} + + @override + void readContents(BufferedReader reader) {} + + @override + int get hashCode => 2029; + + @override + bool operator ==(other) => other is _DynamicTypeHandle; + + @override + String toString() => 'dynamic'; +} + +class _VoidTypeHandle extends _TypeHandle { + _VoidTypeHandle() : super(TypeTag.kVoid); + + @override + void writeContents(BufferedWriter writer) {} + + @override + void readContents(BufferedReader reader) {} + + @override + int get hashCode => 2039; + + @override + bool operator ==(other) => other is _VoidTypeHandle; + + @override + String toString() => 'void'; +} + +class _SimpleTypeHandle extends _TypeHandle { + _ClassHandle class_; + + _SimpleTypeHandle._empty() : super(TypeTag.kSimpleType); + + _SimpleTypeHandle(this.class_) : super(TypeTag.kSimpleType); @override void writeContents(BufferedWriter writer) { @@ -624,29 +742,24 @@ class _SimpleTypeHandle extends _TypeHandle { } @override - int get hashCode => class_.hashCode + _flags + 11; + int get hashCode => class_.hashCode + 11; @override bool operator ==(other) => - other is _SimpleTypeHandle && - this.class_ == other.class_ && - this._flags == other._flags; + other is _SimpleTypeHandle && this.class_ == other.class_; @override - String toString() { - if ((_flags & flagIsDynamic) != 0) return 'dynamic'; - if ((_flags & flagIsVoid) != 0) return 'void'; - return '$class_'; - } + String toString() => '$class_'; } class _TypeParameterHandle extends _TypeHandle { ObjectHandle parent; int indexInParent; - _TypeParameterHandle._empty(); + _TypeParameterHandle._empty() : super(TypeTag.kTypeParameter); - _TypeParameterHandle(this.parent, this.indexInParent) { + _TypeParameterHandle(this.parent, this.indexInParent) + : super(TypeTag.kTypeParameter) { assert(parent is _ClassHandle || parent is _MemberHandle || parent is _ClosureHandle || @@ -654,9 +767,6 @@ class _TypeParameterHandle extends _TypeHandle { assert(indexInParent >= 0); } - @override - ObjectKind get kind => ObjectKind.kTypeParameter; - @override bool get isCacheable => (parent != null); @@ -694,46 +804,122 @@ class _TypeParameterHandle extends _TypeHandle { class _GenericTypeHandle extends _TypeHandle { _ClassHandle class_; - List<_TypeHandle> typeArgs; + _TypeArgumentsHandle typeArgs; - _GenericTypeHandle._empty(); + _GenericTypeHandle._empty() : super(TypeTag.kGenericType); - _GenericTypeHandle(this.class_, this.typeArgs); - - @override - ObjectKind get kind => ObjectKind.kGenericType; + _GenericTypeHandle(this.class_, this.typeArgs) : super(TypeTag.kGenericType); @override void writeContents(BufferedWriter writer) { writer.writePackedObject(class_); - writer.writePackedList(typeArgs); + writer.writePackedObject(typeArgs); } @override void readContents(BufferedReader reader) { class_ = reader.readPackedObject(); - typeArgs = reader.readPackedList<_TypeHandle>(); + typeArgs = reader.readPackedObject(); } @override void accountUsesForObjectCopies(int numCopies) { class_._useCount += numCopies; - typeArgs.forEach((t) { - t._useCount += numCopies; - }); + if (typeArgs != null) { + typeArgs._useCount += numCopies; + } } @override - int get hashCode => _combineHashes(class_.hashCode, listHashCode(typeArgs)); + int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode); @override bool operator ==(other) => other is _GenericTypeHandle && this.class_ == other.class_ && - listEquals(this.typeArgs, other.typeArgs); + this.typeArgs == other.typeArgs; @override - String toString() => '$class_ < ${typeArgs.join(', ')} >'; + String toString() => '$class_ $typeArgs'; +} + +class _RecursiveGenericTypeHandle extends _TypeHandle { + int id; + _ClassHandle class_; + _TypeArgumentsHandle typeArgs; + + _RecursiveGenericTypeHandle._empty() : super(TypeTag.kRecursiveGenericType); + + _RecursiveGenericTypeHandle(this.id, this.class_, this.typeArgs) + : super(TypeTag.kRecursiveGenericType); + + @override + bool get isCacheable => (id == 0); + + @override + void writeContents(BufferedWriter writer) { + writer.writePackedUInt30(id); + writer.writePackedObject(class_); + writer.writePackedObject(typeArgs); + } + + @override + void readContents(BufferedReader reader) { + id = reader.readPackedUInt30(); + class_ = reader.readPackedObject(); + typeArgs = reader.readPackedObject(); + } + + @override + void accountUsesForObjectCopies(int numCopies) { + class_._useCount += numCopies; + if (typeArgs != null) { + typeArgs._useCount += numCopies; + } + } + + @override + int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode); + + @override + bool operator ==(other) => + other is _RecursiveGenericTypeHandle && + this.class_ == other.class_ && + this.typeArgs == other.typeArgs; + + @override + String toString() => '(recursive #$id) $class_ $typeArgs'; +} + +class _RecursiveTypeRefHandle extends _TypeHandle { + int id; + + _RecursiveTypeRefHandle._empty() : super(TypeTag.kRecursiveTypeRef); + + _RecursiveTypeRefHandle(this.id) : super(TypeTag.kRecursiveTypeRef); + + @override + bool get isCacheable => false; + + @override + void writeContents(BufferedWriter writer) { + writer.writePackedUInt30(id); + } + + @override + void readContents(BufferedReader reader) { + id = reader.readPackedUInt30(); + } + + @override + int get hashCode => id; + + @override + bool operator ==(other) => + other is _RecursiveTypeRefHandle && this.id == other.id; + + @override + String toString() => 'recursive-ref #$id'; } class NameAndType { @@ -756,52 +942,44 @@ class NameAndType { } class _FunctionTypeHandle extends _TypeHandle { - static const int flagHasOptionalPositionalParams = ObjectHandle.flagBit0; - static const int flagHasOptionalNamedParams = ObjectHandle.flagBit1; - static const int flagHasTypeParams = ObjectHandle.flagBit2; + static const int flagHasOptionalPositionalParams = 1 << 0; + static const int flagHasOptionalNamedParams = 1 << 1; + static const int flagHasTypeParams = 1 << 2; - int _flags = 0; + int functionTypeFlags = 0; List typeParams; int numRequiredParams; List<_TypeHandle> positionalParams; List namedParams; _TypeHandle returnType; - _FunctionTypeHandle._empty(); + _FunctionTypeHandle._empty() : super(TypeTag.kFunctionType); _FunctionTypeHandle(this.typeParams, this.numRequiredParams, - this.positionalParams, this.namedParams, this.returnType) { + this.positionalParams, this.namedParams, this.returnType) + : super(TypeTag.kFunctionType) { assert(numRequiredParams <= positionalParams.length + namedParams.length); if (numRequiredParams < positionalParams.length) { assert(namedParams.isEmpty); - _flags |= flagHasOptionalPositionalParams; + functionTypeFlags |= flagHasOptionalPositionalParams; } if (namedParams.isNotEmpty) { assert(numRequiredParams == positionalParams.length); - _flags |= flagHasOptionalNamedParams; + functionTypeFlags |= flagHasOptionalNamedParams; } if (typeParams.isNotEmpty) { - _flags |= flagHasTypeParams; + functionTypeFlags |= flagHasTypeParams; } } - @override - int get flags => _flags; - - @override - set flags(int value) { - _flags = value; - } - - ObjectKind get kind => ObjectKind.kFunctionType; - @override void writeContents(BufferedWriter writer) { - if ((_flags & flagHasTypeParams) != 0) { + writer.writePackedUInt30(functionTypeFlags); + if ((functionTypeFlags & flagHasTypeParams) != 0) { new TypeParametersDeclaration(typeParams).write(writer); } writer.writePackedUInt30(positionalParams.length + namedParams.length); - if (_flags & + if (functionTypeFlags & (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) != 0) { writer.writePackedUInt30(numRequiredParams); @@ -818,19 +996,21 @@ class _FunctionTypeHandle extends _TypeHandle { @override void readContents(BufferedReader reader) { - if ((_flags & flagHasTypeParams) != 0) { + functionTypeFlags = reader.readPackedUInt30(); + if ((functionTypeFlags & flagHasTypeParams) != 0) { typeParams = new TypeParametersDeclaration.read(reader).typeParams; } else { typeParams = const []; } final int numParams = reader.readPackedUInt30(); numRequiredParams = numParams; - if ((_flags & + if ((functionTypeFlags & (flagHasOptionalPositionalParams | flagHasOptionalNamedParams)) != 0) { numRequiredParams = reader.readPackedUInt30(); } - final bool hasNamedParams = (_flags & flagHasOptionalNamedParams) != 0; + final bool hasNamedParams = + (functionTypeFlags & flagHasOptionalNamedParams) != 0; positionalParams = new List<_TypeHandle>.generate( hasNamedParams ? numRequiredParams : numParams, (_) => reader.readPackedObject()); @@ -856,6 +1036,24 @@ class _FunctionTypeHandle extends _TypeHandle { }); } + @override + bool get isCacheable { + for (var param in positionalParams) { + if (!param.isCacheable) { + return false; + } + } + for (var param in namedParams) { + if (!param.type.isCacheable) { + return false; + } + } + if (!returnType.isCacheable) { + return false; + } + return true; + } + @override int get hashCode { int hash = listHashCode(typeParams); @@ -988,50 +1186,6 @@ class _TypeArgumentsHandle extends ObjectHandle { String toString() => '< ${args.join(', ')} >'; } -class _FinalizedGenericTypeHandle extends _TypeHandle { - _ClassHandle class_; - _TypeArgumentsHandle typeArgs; - - _FinalizedGenericTypeHandle._empty(); - - _FinalizedGenericTypeHandle(this.class_, this.typeArgs); - - @override - ObjectKind get kind => ObjectKind.kFinalizedGenericType; - - @override - void writeContents(BufferedWriter writer) { - writer.writePackedObject(class_); - writer.writePackedObject(typeArgs); - } - - @override - void readContents(BufferedReader reader) { - class_ = reader.readPackedObject(); - typeArgs = reader.readPackedObject(); - } - - @override - void accountUsesForObjectCopies(int numCopies) { - class_._useCount += numCopies; - if (typeArgs != null) { - typeArgs._useCount += numCopies; - } - } - - @override - int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode); - - @override - bool operator ==(other) => - other is _FinalizedGenericTypeHandle && - this.class_ == other.class_ && - this.typeArgs == other.typeArgs; - - @override - String toString() => '$class_ $typeArgs'; -} - class _ConstObjectHandle extends ObjectHandle { ConstTag tag; dynamic value; @@ -1274,7 +1428,7 @@ class _ConstObjectHandle extends ObjectHandle { } } -class _ArgDescHandle extends _TypeHandle { +class _ArgDescHandle extends ObjectHandle { static const int flagHasNamedArgs = ObjectHandle.flagBit0; static const int flagHasTypeArgs = ObjectHandle.flagBit1; @@ -1351,6 +1505,75 @@ class _ArgDescHandle extends _TypeHandle { 'ArgDesc num-args $numArguments, num-type-args $numTypeArguments, names $argNames'; } +class _ScriptHandle extends ObjectHandle { + static const int flagHasSourceFile = ObjectHandle.flagBit0; + + int _flags = 0; + ObjectHandle uri; + SourceFile _source; + ForwardReference _sourceForwardReference; + + _ScriptHandle._empty(); + + _ScriptHandle(this.uri, this._source) { + if (_source != null) { + _flags |= flagHasSourceFile; + } + } + + @override + ObjectKind get kind => ObjectKind.kScript; + + @override + int get flags => _flags; + + @override + set flags(int value) { + _flags = value; + } + + SourceFile get source { + // Unwrap forward reference on the first access. + if (_sourceForwardReference != null) { + _source = _sourceForwardReference.get(); + _sourceForwardReference = null; + } + return _source; + } + + set source(SourceFile sourceFile) { + _source = sourceFile; + } + + @override + void writeContents(BufferedWriter writer) { + writer.writePackedObject(uri); + if ((_flags & flagHasSourceFile) != 0) { + writer.writeLinkOffset(source); + } + } + + @override + void readContents(BufferedReader reader) { + uri = reader.readPackedObject(); + if ((_flags & flagHasSourceFile) != 0) { + // Script handles in the object table may be read before source files, + // so use forwarding reference here. + _sourceForwardReference = + reader.readLinkOffsetAsForwardReference(); + } + } + + @override + int get hashCode => uri.hashCode; + + @override + bool operator ==(other) => other is _ScriptHandle && this.uri == other.uri; + + @override + String toString() => "$uri"; +} + class ObjectTable implements ObjectWriter, ObjectReader { /// Object is added to an index table if it is used more than this /// number of times. @@ -1367,8 +1590,8 @@ class ObjectTable implements ObjectWriter, ObjectReader { _NodeVisitor _nodeVisitor; ObjectTable() { - _dynamicType = getOrAddObject(new _SimpleTypeHandle._dynamic()); - _voidType = getOrAddObject(new _SimpleTypeHandle._void()); + _dynamicType = getOrAddObject(new _DynamicTypeHandle()); + _voidType = getOrAddObject(new _VoidTypeHandle()); _nodeVisitor = new _NodeVisitor(this); } @@ -1417,6 +1640,7 @@ class ObjectTable implements ObjectWriter, ObjectReader { } ObjectHandle getNameHandle(Library library, String name) { + assert(name != null); final libraryHandle = library != null ? getHandle(library) : null; return getOrAddObject(new _NameHandle(libraryHandle, name)); } @@ -1427,6 +1651,12 @@ class ObjectTable implements ObjectWriter, ObjectReader { name.library, mangleSelectorName(name.name, isGetter, isSetter)); } + ObjectHandle getTopLevelClassHandle(Library library) { + final libraryHandle = getHandle(library); + final name = getNameHandle(null, topLevelClassName); + return getOrAddObject(new _ClassHandle(libraryHandle, name)); + } + ObjectHandle getMemberHandle(Member member, {bool isGetter: false, bool isSetter: false}) { final parent = member.parent; @@ -1434,9 +1664,7 @@ class ObjectTable implements ObjectWriter, ObjectReader { if (parent is Class) { classHandle = getHandle(parent); } else if (parent is Library) { - final library = getHandle(parent); - final name = getNameHandle(null, _ClassHandle.topLevelClassName); - classHandle = getOrAddObject(new _ClassHandle(library, name)); + classHandle = getTopLevelClassHandle(parent); } else { throw "Unexpected Member's parent ${parent.runtimeType} $parent"; } @@ -1484,6 +1712,15 @@ class ObjectTable implements ObjectWriter, ObjectReader { new List.from(args.named.map((ne) => ne.name))); } + ObjectHandle getScriptHandle(Uri uri, SourceFile source) { + ObjectHandle uriHandle = getNameHandle(null, uri.toString()); + _ScriptHandle handle = getOrAddObject(new _ScriptHandle(uriHandle, source)); + if (handle.source == null && source != null) { + handle.source = source; + } + return handle; + } + void declareClosure( FunctionNode function, Member enclosingMember, int closureIndex) { final handle = getOrAddObject( @@ -1635,6 +1872,8 @@ class ObjectTable implements ObjectWriter, ObjectReader { class _NodeVisitor extends Visitor { final ObjectTable objectTable; final _typeParameters = {}; + final Map _recursiveTypeIds = {}; + final recursiveTypesValidator = new RecursiveTypesValidator(); _NodeVisitor(this.objectTable); @@ -1643,8 +1882,10 @@ class _NodeVisitor extends Visitor { throw 'Unexpected node ${node.runtimeType} $node'; @override - ObjectHandle visitLibrary(Library node) => - objectTable.getOrAddObject(new _LibraryHandle(node.importUri.toString())); + ObjectHandle visitLibrary(Library node) { + final uri = objectTable.getNameHandle(null, node.importUri.toString()); + return objectTable.getOrAddObject(new _LibraryHandle(uri)); + } @override ObjectHandle visitClass(Class node) { @@ -1670,14 +1911,11 @@ class _NodeVisitor extends Visitor { @override ObjectHandle visitInterfaceType(InterfaceType node) { final classHandle = objectTable.getHandle(node.classNode); - if (node.typeArguments.isEmpty) { + if (!hasInstantiatorTypeArguments(node.classNode)) { return objectTable.getOrAddObject(new _SimpleTypeHandle(classHandle)); } - // In order to save loading time, generic types are written out in - // finalized form, if possible. - // - // Object table serialization/deserialization cannot handle cycles between - // objects. Non-finalized types are not recursive, but finalization of + + // Non-finalized types are not recursive, but finalization of // generic types includes flattening of type arguments and types could // become recursive. Consider the following example: // @@ -1687,27 +1925,41 @@ class _NodeVisitor extends Visitor { // Foo is not recursive, but finalized type is recursive: // Foo* = Foo [ Base [ Foo* ], int ] // - // Recursive types are very rare, so object table includes such types in - // non-finalized form. + // Object table serialization/deserialization cannot handle cycles between + // objects, so recursive types require extra care when serializing. + // Back references to the already serialized types are represented as + // _RecursiveTypeRefHandle objects, which are only valid in the context + // of enclosing top-level _RecursiveGenericType. // - // VM handles recursive types by introducing placeholder - // TypeRef objects. Also, VM ensures that recursive types are contractive - // (e.g. their fully finalized representation should be finite). - // - if (!isRecursiveAfterFlattening(node)) { - List instantiatorArgs = - getInstantiatorTypeArguments(node.classNode, node.typeArguments); - ObjectHandle typeArgsHandle = - objectTable.getTypeArgumentsHandle(instantiatorArgs); - return objectTable.getOrAddObject( - new _FinalizedGenericTypeHandle(classHandle, typeArgsHandle)); - } else { - final List<_TypeHandle> typeArgs = node.typeArguments - .map((t) => objectTable.getHandle(t) as _TypeHandle) - .toList(); + int recursiveId = _recursiveTypeIds[node]; + if (recursiveId != null) { return objectTable - .getOrAddObject(new _GenericTypeHandle(classHandle, typeArgs)); + .getOrAddObject(new _RecursiveTypeRefHandle(recursiveId)); } + + recursiveTypesValidator.validateType(node); + + final isRecursive = recursiveTypesValidator.isRecursive(node); + if (isRecursive) { + recursiveId = _recursiveTypeIds.length; + _recursiveTypeIds[node] = recursiveId; + } + + List instantiatorArgs = + getInstantiatorTypeArguments(node.classNode, node.typeArguments); + ObjectHandle typeArgsHandle = + objectTable.getTypeArgumentsHandle(instantiatorArgs); + + final result = objectTable.getOrAddObject(isRecursive + ? new _RecursiveGenericTypeHandle( + recursiveId, classHandle, typeArgsHandle) + : new _GenericTypeHandle(classHandle, typeArgsHandle)); + + if (isRecursive) { + _recursiveTypeIds.remove(node); + } + + return result; } @override diff --git a/pkg/vm/lib/bytecode/recursive_types_validator.dart b/pkg/vm/lib/bytecode/recursive_types_validator.dart new file mode 100644 index 00000000000..acaa020b626 --- /dev/null +++ b/pkg/vm/lib/bytecode/recursive_types_validator.dart @@ -0,0 +1,175 @@ +// Copyright (c) 2019, 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.recursive_types_validator; + +import 'package:kernel/ast.dart' hide MapEntry; +import 'package:kernel/type_algebra.dart' show Substitution; + +import 'generics.dart' + show flattenInstantiatorTypeArguments, hasFreeTypeParameters; + +/// Detect recursive types and validates that finalized (flattened) +/// representation of generic types is valid (finite). +class RecursiveTypesValidator { + final Set _validatedTypes = {}; + final Set _recursiveTypes = {}; + final Set _validatedClases = {}; + + /// Validates [type]. + void validateType(DartType type) { + if (!isValidated(type)) { + final visitor = new _RecursiveTypesVisitor(this); + visitor.visit(type); + _validatedTypes.addAll(visitor.validated); + _recursiveTypes.addAll(visitor.recursive); + } + } + + bool isValidated(DartType type) => _validatedTypes.contains(type); + + /// Returns true if [type] is recursive. + /// Should be called only after validating [type]. + bool isRecursive(DartType type) { + assert(isValidated(type)); + return _recursiveTypes.contains(type); + } + + void validateClass(Class cls) { + if (_validatedClases.add(cls)) { + try { + validateType(cls.thisType); + } on IllegalRecursiveTypeException catch (e) { + _validatedClases.remove(cls); + throw e; + } + } + } +} + +class IllegalRecursiveTypeException { + final DartType type; + IllegalRecursiveTypeException(this.type); +} + +class _RecursiveTypesVisitor extends DartTypeVisitor { + final RecursiveTypesValidator validator; + final Set validated = {}; + final Set recursive = {}; + final Set _visited = new Set(); + final List _stack = []; + + _RecursiveTypesVisitor(this.validator); + + void visit(DartType type) { + if (validator.isValidated(type)) { + return; + } + + if (!_visited.add(type)) { + final int start = _stack.lastIndexOf(type); + _verifyRecursiveType(start, type); + for (int i = start; i < _stack.length; ++i) { + recursive.add(_stack[i]); + } + return; + } + + _stack.add(type); + + type.accept(this); + + _stack.removeLast(); + _visited.remove(type); + + validated.add(type); + } + + @override + void defaultDartType(DartType node) => + throw 'Unexpected type ${node.runtimeType} $node'; + + @override + void visitInvalidType(InvalidType node) {} + + @override + void visitDynamicType(DynamicType node) {} + + @override + void visitVoidType(VoidType node) {} + + @override + void visitBottomType(BottomType node) {} + + @override + void visitTypeParameterType(TypeParameterType node) {} + + @override + void visitInterfaceType(InterfaceType node) { + // Validate class declaration type separately + // to avoid failures due to types in the current _stack. + validator.validateClass(node.classNode); + + for (var typeArg in node.typeArguments) { + visit(typeArg); + } + final flatTypeArgs = + flattenInstantiatorTypeArguments(node.classNode, node.typeArguments); + for (var typeArg in flatTypeArgs.getRange( + 0, flatTypeArgs.length - node.typeArguments.length)) { + visit(typeArg); + } + } + + @override + void visitTypedefType(TypedefType node) => visit(node.unalias); + + @override + void visitFunctionType(FunctionType node) { + for (var p in node.positionalParameters) { + visit(p); + } + for (var p in node.namedParameters) { + visit(p.type); + } + visit(node.returnType); + } + + void _verifyRecursiveType(int start, DartType type) { + if (type is InterfaceType) { + if (!hasFreeTypeParameters(type.typeArguments)) { + return; + } + + for (int i = start + 1; i < _stack.length; ++i) { + final other = _stack[i]; + if (other is InterfaceType && + other.classNode == type.classNode && + hasFreeTypeParameters(other.typeArguments)) { + if (!listEquals(_eraseTypeParameters(type.typeArguments), + _eraseTypeParameters(other.typeArguments))) { + throw IllegalRecursiveTypeException(type); + } + } + } + } else { + throw 'Unexpected recursive type ${type.runtimeType} $type'; + } + } + + List _eraseTypeParameters(List typeArgs) { + return typeArgs + .map((DartType t) => + const _EraseTypeParametersToDynamic().substituteType(t)) + .toList(); + } +} + +class _EraseTypeParametersToDynamic extends Substitution { + const _EraseTypeParametersToDynamic(); + + DartType getSubstitute(TypeParameter parameter, bool upperBound) { + return const DynamicType(); + } +} diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart index f0bef3dd5f4..af5853467a6 100644 --- a/pkg/vm/lib/bytecode/source_positions.dart +++ b/pkg/vm/lib/bytecode/source_positions.dart @@ -60,3 +60,29 @@ class SourcePositions { new MapEntry(pc, 'source position $fileOffset')); } } + +/// Keeps file offsets of line starts. This information is used to +/// decode source positions to line/column. +class LineStarts { + final List lineStarts; + + LineStarts(this.lineStarts); + + void write(BufferedWriter writer) { + writer.writePackedUInt30(lineStarts.length); + final encodeLineStarts = new PackedUInt30DeltaEncoder(); + for (int lineStart in lineStarts) { + encodeLineStarts.write(writer, lineStart); + } + } + + factory LineStarts.read(BufferedReader reader) { + final decodeLineStarts = new PackedUInt30DeltaDecoder(); + final lineStarts = new List.generate( + reader.readPackedUInt30(), (_) => decodeLineStarts.read(reader)); + return new LineStarts(lineStarts); + } + + @override + String toString() => 'Line starts: $lineStarts'; +} diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart index 0dd2962bba9..8402ef83f36 100644 --- a/pkg/vm/lib/kernel_front_end.dart +++ b/pkg/vm/lib/kernel_front_end.dart @@ -45,9 +45,9 @@ import 'package:kernel/core_types.dart' show CoreTypes; import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget; import 'package:kernel/vm/constants_native_effects.dart' as vm_constants; -import 'bytecode/ast_remover.dart' show ASTRemover; import 'bytecode/bytecode_serialization.dart' show BytecodeSizeStatistics; -import 'bytecode/gen_bytecode.dart' show generateBytecode; +import 'bytecode/gen_bytecode.dart' + show generateBytecode, createFreshComponentWithBytecode; import 'constants_error_reporter.dart' show ForwardConstantEvaluationErrors; import 'target/install.dart' show installAdditionalTargets; @@ -306,7 +306,7 @@ Future compileToKernel(Uri source, CompilerOptions options, options.onDiagnostic = errorDetector; setVMEnvironmentDefines(environmentDefines, options); - final component = await kernelForProgram(source, options); + Component component = await kernelForProgram(source, options); // Run global transformations only if component is correct. if (aot && component != null) { @@ -327,6 +327,7 @@ Future compileToKernel(Uri source, CompilerOptions options, generateBytecode(component, enableAsserts: enableAsserts, emitSourcePositions: emitBytecodeSourcePositions, + emitSourceFiles: options.embedSourceText, emitLocalVarInfo: emitBytecodeLocalVarInfo, emitAnnotations: emitBytecodeAnnotations, useFutureBytecodeFormat: useFutureBytecodeFormat, @@ -334,7 +335,7 @@ Future compileToKernel(Uri source, CompilerOptions options, }); if (dropAST) { - new ASTRemover(component).visitComponent(component); + component = createFreshComponentWithBytecode(component); } } @@ -717,7 +718,7 @@ Future writeOutputSplitByPackages( component.problemsAsJson = null; } - ASTRemover astRemover; + Component partComponent = component; if (genBytecode) { final List libraries = component.libraries .where((lib) => packageFor(lib) == package) @@ -727,26 +728,21 @@ Future writeOutputSplitByPackages( hierarchy: hierarchy, enableAsserts: enableAsserts, emitSourcePositions: emitBytecodeSourcePositions, + emitSourceFiles: compilerOptions.embedSourceText, emitLocalVarInfo: emitBytecodeLocalVarInfo, emitAnnotations: emitBytecodeAnnotations, useFutureBytecodeFormat: useFutureBytecodeFormat, environmentDefines: environmentDefines); if (dropAST) { - astRemover = new ASTRemover(component); - for (var library in libraries) { - astRemover.visitLibrary(library); - } + partComponent = createFreshComponentWithBytecode(component); } } final BinaryPrinter printer = new LimitedBinaryPrinter(sink, (lib) => packageFor(lib) == package, false /* excludeUriToSource */); - printer.writeComponentFile(component); + printer.writeComponentFile(partComponent); - if (genBytecode && dropAST) { - astRemover.restoreAST(); - } component.mainMethod = main; component.problemsAsJson = problems; diff --git a/pkg/vm/lib/metadata/bytecode.dart b/pkg/vm/lib/metadata/bytecode.dart index 6b18d0e8bb2..97e250cbc95 100644 --- a/pkg/vm/lib/metadata/bytecode.dart +++ b/pkg/vm/lib/metadata/bytecode.dart @@ -6,53 +6,26 @@ library vm.metadata.bytecode; import 'package:kernel/ast.dart' show BinarySink, BinarySource, MetadataRepository, Node, TreeNode; -import 'package:kernel/ast.dart' as ast show Component; import '../bytecode/bytecode_serialization.dart' show BufferedWriter, BufferedReader, LinkWriter, LinkReader; -import '../bytecode/declarations.dart' show Component, Members; +import '../bytecode/declarations.dart' show Component; -abstract class BytecodeMetadata { - void write(BufferedWriter writer); -} - -class MembersBytecodeMetadata extends BytecodeMetadata { - final Members members; - - MembersBytecodeMetadata(this.members); - - @override - void write(BufferedWriter writer) { - writer.writeLinkOffset(members); - } - - factory MembersBytecodeMetadata.read(BufferedReader reader) { - return new MembersBytecodeMetadata(reader.readLinkOffset()); - } - - @override - String toString() => "\n" - "MembersBytecodeMetadata {\n" - "$members\n" - "}\n"; -} - -class ComponentBytecodeMetadata extends BytecodeMetadata { +class BytecodeMetadata { final Component component; - ComponentBytecodeMetadata(this.component); + BytecodeMetadata(this.component); - @override void write(BufferedWriter writer) { component.write(writer); } - factory ComponentBytecodeMetadata.read(BufferedReader reader) { - return new ComponentBytecodeMetadata(new Component.read(reader)); + factory BytecodeMetadata.read(BufferedReader reader) { + return new BytecodeMetadata(new Component.read(reader)); } @override String toString() => "\n" - "ComponentBytecodeMetadata {\n" + "BytecodeMetadata {\n" "$component\n" "}\n"; } @@ -66,19 +39,10 @@ class BytecodeMetadataRepository extends MetadataRepository { final Map mapping = {}; - Component bytecodeComponent; - LinkWriter linkWriter; - LinkReader linkReader; - @override void writeToBinary(BytecodeMetadata metadata, Node node, BinarySink sink) { - if (node is ast.Component) { - bytecodeComponent = (metadata as ComponentBytecodeMetadata).component; - linkWriter = new LinkWriter(); - } else { - assert(bytecodeComponent != null); - assert(linkWriter != null); - } + final bytecodeComponent = metadata.component; + final linkWriter = new LinkWriter(); final writer = new BufferedWriter( bytecodeComponent.version, bytecodeComponent.stringTable, @@ -91,22 +55,10 @@ class BytecodeMetadataRepository extends MetadataRepository { @override BytecodeMetadata readFromBinary(Node node, BinarySource source) { - if (node is ast.Component) { - linkReader = new LinkReader(); - final reader = new BufferedReader( - -1, null, null, linkReader, source.bytes, - baseOffset: source.currentOffset); - bytecodeComponent = new Component.read(reader); - return new ComponentBytecodeMetadata(bytecodeComponent); - } else { - final reader = new BufferedReader( - bytecodeComponent.version, - bytecodeComponent.stringTable, - bytecodeComponent.objectTable, - linkReader, - source.bytes, - baseOffset: source.currentOffset); - return new MembersBytecodeMetadata.read(reader); - } + final linkReader = new LinkReader(); + final reader = new BufferedReader(-1, null, null, linkReader, source.bytes, + baseOffset: source.currentOffset); + final bytecodeComponent = new Component.read(reader); + return new BytecodeMetadata(bytecodeComponent); } } diff --git a/pkg/vm/test/bytecode/generics_test.dart b/pkg/vm/test/bytecode/recursive_types_validator_test.dart similarity index 59% rename from pkg/vm/test/bytecode/generics_test.dart rename to pkg/vm/test/bytecode/recursive_types_validator_test.dart index 6b0a75f5813..44c4522c7a6 100644 --- a/pkg/vm/test/bytecode/generics_test.dart +++ b/pkg/vm/test/bytecode/recursive_types_validator_test.dart @@ -6,13 +6,16 @@ import 'package:kernel/ast.dart'; import 'package:kernel/core_types.dart' show CoreTypes; import 'package:kernel/testing/mock_sdk_component.dart'; import 'package:test/test.dart'; -import 'package:vm/bytecode/generics.dart'; +import 'package:expect/expect.dart'; +import 'package:vm/bytecode/recursive_types_validator.dart'; main() { Library lib; Supertype objectSuper; DartType intType; + DartType doubleType; Class base; + RecursiveTypesValidator validator; Class addClass(String name, List typeParameters) { Class cls = new Class( @@ -27,6 +30,7 @@ main() { CoreTypes coreTypes = new CoreTypes(component); objectSuper = coreTypes.objectClass.asThisSupertype; intType = new InterfaceType(coreTypes.intClass); + doubleType = new InterfaceType(coreTypes.doubleClass); // Add the test library. lib = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'lib'); @@ -35,11 +39,13 @@ main() { // class Base base = addClass('Base', [new TypeParameter('T')]); + + validator = new RecursiveTypesValidator(); }); tearDown(() {}); - test('isRecursiveAfterFlattening-00', () async { + test('simple-recursive-type', () async { // class Derived extends Base> TypeParameter t = new TypeParameter('T'); Class derived = addClass('Derived', [t]); @@ -48,11 +54,14 @@ main() { DartType derivedOfInt = new InterfaceType(derived, [intType]); derived.supertype = new Supertype(base, [derivedOfT]); - expect(isRecursiveAfterFlattening(derivedOfT), isTrue); - expect(isRecursiveAfterFlattening(derivedOfInt), isTrue); + validator.validateType(derivedOfT); + Expect.isTrue(validator.isRecursive(derivedOfT)); + + validator.validateType(derivedOfInt); + Expect.isTrue(validator.isRecursive(derivedOfInt)); }); - test('isRecursiveAfterFlattening-01', () async { + test('recursive-type-extends-instantiated', () async { // class Derived extends Base>> TypeParameter t = new TypeParameter('T'); Class derived = addClass('Derived', [t]); @@ -62,11 +71,15 @@ main() { DartType derivedOfDerivedOfInt = new InterfaceType(derived, [derivedOfInt]); derived.supertype = new Supertype(base, [derivedOfDerivedOfInt]); - expect(isRecursiveAfterFlattening(derivedOfT), isFalse); - expect(isRecursiveAfterFlattening(derivedOfInt), isTrue); + validator.validateType(derivedOfT); + validator.validateType(derivedOfInt); + + Expect.isFalse(validator.isRecursive(derivedOfT)); + Expect.isTrue(validator.isRecursive(derivedOfInt)); + Expect.isTrue(validator.isRecursive(derivedOfDerivedOfInt)); }); - test('isRecursiveAfterFlattening-02', () async { + test('recursive-non-contractive-type', () async { // class Derived extends Base>> TypeParameter t = new TypeParameter('T'); Class derived = addClass('Derived', [t]); @@ -76,11 +89,18 @@ main() { DartType derivedOfDerivedOfT = new InterfaceType(derived, [derivedOfT]); derived.supertype = new Supertype(base, [derivedOfDerivedOfT]); - expect(isRecursiveAfterFlattening(derivedOfT), isTrue); - expect(isRecursiveAfterFlattening(derivedOfInt), isTrue); + Expect.throws(() { + validator.validateType(derivedOfT); + }); + Expect.throws(() { + validator.validateType(derivedOfDerivedOfT); + }); + Expect.throws(() { + validator.validateType(derivedOfInt); + }); }); - test('isRecursiveAfterFlattening-03', () async { + test('mutually-recursive-types', () async { // class Derived1 extends Base> // class Derived2 extends Base> TypeParameter u = new TypeParameter('U'); @@ -105,9 +125,40 @@ main() { new InterfaceType(derived2, [new TypeParameterType(v)]); DartType derived2OfInt = new InterfaceType(derived2, [intType]); - expect(isRecursiveAfterFlattening(derived1OfU), isTrue); - expect(isRecursiveAfterFlattening(derived1OfInt), isTrue); - expect(isRecursiveAfterFlattening(derived2OfV), isTrue); - expect(isRecursiveAfterFlattening(derived2OfInt), isTrue); + validator.validateType(derived1OfU); + Expect.isTrue(validator.isRecursive(derived1OfU)); + + validator.validateType(derived1OfInt); + Expect.isTrue(validator.isRecursive(derived1OfInt)); + + validator.validateType(derived2OfV); + Expect.isTrue(validator.isRecursive(derived2OfV)); + + validator.validateType(derived2OfInt); + Expect.isTrue(validator.isRecursive(derived2OfInt)); + }); + + test('recursive-two-type-params', () async { + // class F {} + // class E extends F, Q2> {} + TypeParameter p1 = new TypeParameter('P1'); + TypeParameter p2 = new TypeParameter('P2'); + Class f = addClass('F', [p1, p2]); + + TypeParameter q1 = new TypeParameter('Q1'); + TypeParameter q2 = new TypeParameter('Q2'); + Class e = addClass('E', [q1, q2]); + + DartType eOfQ1Int = + new InterfaceType(e, [new TypeParameterType(q1), intType]); + e.supertype = new Supertype(f, [eOfQ1Int, new TypeParameterType(q2)]); + + DartType eOfIntDouble = new InterfaceType(e, [intType, doubleType]); + + validator.validateType(eOfIntDouble); + validator.validateType(e.thisType); + + Expect.isFalse(validator.isRecursive(eOfIntDouble)); + Expect.isFalse(validator.isRecursive(e.thisType)); }); } diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect index 8bfc0e93fe2..e1323cb11ac 100644 --- a/pkg/vm/testcases/bytecode/asserts.dart.expect +++ b/pkg/vm/testcases/bytecode/asserts.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'test1', static, reflectable, debuggable parameters [dart:core::bool 'condition'] (required: 1) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -42,7 +40,6 @@ Function 'test2', static, reflectable, debuggable parameters [FunctionType () -> dart:core::bool 'condition', FunctionType () -> dart:core::String 'message'] (required: 2) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -74,7 +71,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -84,7 +80,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect index 480548208a0..32e7ee9a9b0 100644 --- a/pkg/vm/testcases/bytecode/async.dart.expect +++ b/pkg/vm/testcases/bytecode/async.dart.expect @@ -1,17 +1,16 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Field 'asyncInFieldInitializer', type = FunctionType (dart:async::Future < dart:core::int >) -> dart:async::Future < dart:core::Null >, getter = 'get:asyncInFieldInitializer', reflectable, static - initializer + initializer Bytecode { Entry 3 CheckStack 0 @@ -167,7 +166,6 @@ ClosureCode { LoadContextVar 0, 1 InterfaceCall CP#37, 1 ReturnTOS - } Closure #lib::asyncInFieldInitializer (field)::Closure/0::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic @@ -255,7 +253,6 @@ L1: LoadContextVar 0, 6 PopLocal r4 Jump L4 - } @@ -263,7 +260,6 @@ Function 'foo', static, reflectable, async parameters [] (required: 0) return-type dart:async::Future < dart:core::int > - Bytecode { Entry 7 CheckStack 0 @@ -420,7 +416,6 @@ L3: ReturnTOS L1: Trap - } @@ -428,7 +423,6 @@ Function 'simpleAsyncAwait', static, reflectable, async parameters [dart:async::Future < dart:core::int > 'a', dart:async::Future < dart:core::int > 'b'] (required: 2) return-type dart:async::Future < dart:core::int > - Bytecode { Entry 4 CheckStack 0 @@ -677,7 +671,6 @@ L1: PushInt 1 JumpIfEqStrict L6 Jump L7 - } @@ -685,7 +678,6 @@ Function 'loops', static, reflectable, async parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:async::Future < dart:core::int > - Bytecode { Entry 4 CheckStack 0 @@ -1058,7 +1050,6 @@ L1: LoadContextVar 0, 6 PopLocal r4 Jump L11 - } @@ -1066,7 +1057,6 @@ Function 'tryCatchRethrow', static, reflectable, async parameters [dart:async::Future < dart:core::int > 'a', dart:async::Future < dart:core::int > 'b', dart:async::Future < dart:core::int > 'c'] (required: 3) return-type dart:async::Future < dart:core::int > - Bytecode { Entry 4 CheckStack 0 @@ -1637,7 +1627,6 @@ L1: PushInt 4 JumpIfEqStrict L16 Jump L17 - } @@ -1645,7 +1634,6 @@ Function 'closure', static, reflectable, debuggable parameters [dart:async::Future < dart:core::int > 'a'] (required: 1) return-type dynamic - Bytecode { Entry 4 CheckStack 0 @@ -1808,7 +1796,6 @@ ClosureCode { LoadContextVar 1, 0 InterfaceCall CP#37, 1 ReturnTOS - } Closure #lib::closure::Closure/0::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic @@ -1966,7 +1953,6 @@ L1: LoadContextVar 1, 5 PopLocal r4 Jump L6 - } @@ -1974,7 +1960,6 @@ Function 'testAssert', static, reflectable, async parameters [dart:async::Future < dart:core::int > 'a'] (required: 1) return-type dart:async::Future < dart:core::int > - Bytecode { Entry 4 CheckStack 0 @@ -2198,7 +2183,6 @@ L1: LoadContextVar 0, 6 PopLocal r4 Jump L6 - } @@ -2206,7 +2190,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -2216,7 +2199,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect index e80bb9bbc48..bfa93146b06 100644 --- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect +++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect @@ -1,15 +1,14 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Field '_stdinFD', type = dart:core::int, reflectable, static value = const 0 @@ -29,7 +28,6 @@ Function '_printString', static, reflectable, debuggable, native 'Builtin_PrintS parameters [dart:core::String 's'] (required: 1) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -46,7 +44,6 @@ Function '_print', static, reflectable, debuggable parameters [dynamic 'arg'] (required: 1) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -69,7 +66,6 @@ Function '_getPrintClosure', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -85,7 +81,6 @@ Function '_setScheduleImmediateClosure', static, reflectable, debuggable parameters [FunctionType (FunctionType () -> void) -> void 'closure'] (required: 1) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -103,7 +98,6 @@ Function '_setStdioFDs', static, reflectable, debuggable parameters [dart:core::int 'stdin', dart:core::int 'stdout', dart:core::int 'stderr'] (required: 3) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -127,7 +121,6 @@ Function '_scriptUri', static, reflectable, debuggable parameters [] (required: 0) return-type dart:core::Uri - Bytecode { Entry 2 CheckStack 0 @@ -198,7 +191,6 @@ Function '_setupHooks', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -219,7 +211,6 @@ Function 'get:stdin', getter, static, reflectable, debuggable parameters [] (required: 0) return-type #lib::Stdin - Bytecode { Entry 2 CheckStack 0 @@ -257,7 +248,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -267,16 +257,9 @@ Bytecode { ConstantPool { } -} +Class '_ScheduleImmediate', script = '#lib' + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - - typedef _ScheduleImmediateClosure = (() → void) → void; -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field '_closure', type = FunctionType (FunctionType () -> void) -> void, reflectable, static value = null @@ -284,7 +267,6 @@ Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::_ScheduleImmediate - Bytecode { Entry 0 CheckStack 0 @@ -299,19 +281,10 @@ ConstantPool { [1] = Reserved } -} +Class '_NamespaceImpl', script = '#lib' + extends dart:core::Object + implements [#lib::_Namespace] -} -] class _ScheduleImmediate extends dart.core::Object { - static field (() → void) → void _closure = null; - synthetic constructor •() → #lib::_ScheduleImmediate - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field '_cachedNamespace', type = #lib::_NamespaceImpl, reflectable, static value = null @@ -319,7 +292,6 @@ Function '_', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::_NamespaceImpl - Bytecode { Entry 0 CheckStack 0 @@ -339,7 +311,6 @@ Function '_create', static, reflectable, debuggable, native 'Namespace_Create' parameters [#lib::_NamespaceImpl 'namespace', dynamic 'n'] (required: 2) return-type #lib::_NamespaceImpl - Bytecode { Entry 0 CheckStack 0 @@ -357,7 +328,6 @@ Function '_getPointer', static, reflectable, debuggable, native 'Namespace_GetPo parameters [#lib::_NamespaceImpl 'namespace'] (required: 1) return-type dart:core::int - Bytecode { Entry 0 CheckStack 0 @@ -374,7 +344,6 @@ Function '_getDefault', static, reflectable, debuggable, native 'Namespace_GetDe parameters [] (required: 0) return-type dart:core::int - Bytecode { Entry 0 CheckStack 0 @@ -390,7 +359,6 @@ Function '_setupNamespace', static, reflectable, debuggable parameters [dynamic 'namespace'] (required: 1) return-type void - Bytecode { Entry 2 CheckStack 0 @@ -419,7 +387,6 @@ Function 'get:_namespace', getter, static, reflectable, debuggable parameters [] (required: 0) return-type #lib::_NamespaceImpl - Bytecode { Entry 2 CheckStack 0 @@ -456,7 +423,6 @@ Function 'get:_namespacePointer', getter, static, reflectable, debuggable parameters [] (required: 0) return-type dart:core::int - Bytecode { Entry 0 CheckStack 0 @@ -471,42 +437,14 @@ ConstantPool { [3] = Reserved } -} +Class '_Namespace', script = '#lib' + extends dart:core::Object -} -] class _NamespaceImpl extends dart.core::Object implements #lib::_Namespace { - static field #lib::_NamespaceImpl _cachedNamespace = null; - constructor _() → #lib::_NamespaceImpl - : super dart.core::Object::•() - ; - @dart._internal::ExternalName::•("Namespace_Create") - external static method _create(#lib::_NamespaceImpl namespace, dynamic n) → #lib::_NamespaceImpl; - @dart._internal::ExternalName::•("Namespace_GetPointer") - external static method _getPointer(#lib::_NamespaceImpl namespace) → dart.core::int; - @dart._internal::ExternalName::•("Namespace_GetDefault") - external static method _getDefault() → dart.core::int; - static method _setupNamespace(dynamic namespace) → void { - #lib::_NamespaceImpl::_cachedNamespace = #lib::_NamespaceImpl::_create(new #lib::_NamespaceImpl::_(), namespace); - } - static get _namespace() → #lib::_NamespaceImpl { - if(#lib::_NamespaceImpl::_cachedNamespace.{dart.core::Object::==}(null)) { - #lib::_NamespaceImpl::_cachedNamespace = #lib::_NamespaceImpl::_create(new #lib::_NamespaceImpl::_(), #lib::_NamespaceImpl::_getDefault()); - } - return #lib::_NamespaceImpl::_cachedNamespace; - } - static get _namespacePointer() → dart.core::int - return #lib::_NamespaceImpl::_getPointer(#lib::_NamespaceImpl::_namespace); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::_Namespace - Bytecode { Entry 0 CheckStack 0 @@ -526,7 +464,6 @@ Function '_setupNamespace', static, reflectable, debuggable parameters [dynamic 'namespace'] (required: 1) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -546,7 +483,6 @@ Function 'get:_namespace', getter, static, reflectable, debuggable parameters [] (required: 0) return-type #lib::_Namespace - Bytecode { Entry 0 CheckStack 0 @@ -563,7 +499,6 @@ Function 'get:_namespacePointer', getter, static, reflectable, debuggable parameters [] (required: 0) return-type dart:core::int - Bytecode { Entry 0 CheckStack 0 @@ -575,25 +510,9 @@ ConstantPool { [1] = Reserved } -} +Class 'VMLibraryHooks', script = '#lib' + extends dart:core::Object -} -] class _Namespace extends dart.core::Object { - synthetic constructor •() → #lib::_Namespace - : super dart.core::Object::•() - ; - static method _setupNamespace(dynamic namespace) → void { - #lib::_NamespaceImpl::_setupNamespace(namespace); - } - static get _namespace() → #lib::_Namespace - return #lib::_NamespaceImpl::_namespace; - static get _namespacePointer() → dart.core::int - return #lib::_NamespaceImpl::_namespacePointer; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'timerFactory', type = dynamic, reflectable, static value = null @@ -631,7 +550,6 @@ Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::VMLibraryHooks - Bytecode { Entry 0 CheckStack 0 @@ -651,7 +569,6 @@ Function 'set:platformScript', setter, static, reflectable, debuggable parameters [dynamic 'f'] (required: 1) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -672,7 +589,6 @@ Function 'get:platformScript', getter, static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -708,10 +624,111 @@ ConstantPool { [3] = ICData dynamic target-name 'call', arg-desc CP#2 } +Class 'Stdin', script = '#lib' + extends dart:core::Object + + +Function '', constructor, reflectable + parameters [] (required: 0) + return-type #lib::Stdin + +Bytecode { + Entry 0 + CheckStack 0 + Push FP[-5] + DirectCall CP#0, 1 + Drop1 + PushNull + ReturnTOS +} +ConstantPool { + [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = Reserved } +Class '_StdIOUtils', script = '#lib' + extends dart:core::Object + + +Function '', constructor, reflectable + parameters [] (required: 0) + return-type #lib::_StdIOUtils + +Bytecode { + Entry 0 + CheckStack 0 + Push FP[-5] + DirectCall CP#0, 1 + Drop1 + PushNull + ReturnTOS } -] class VMLibraryHooks extends dart.core::Object { +ConstantPool { + [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] + [1] = Reserved +} + + +Function '_getStdioInputStream', static, reflectable, debuggable + parameters [dart:core::int 'fd'] (required: 1) + return-type #lib::Stdin + +Bytecode { + Entry 0 + CheckStack 0 + PushNull + ReturnTOS +} +ConstantPool { +} + + +} +]library #lib from "#lib" as #lib { + + typedef _ScheduleImmediateClosure = (() → void) → void; + class _ScheduleImmediate extends dart.core::Object { + static field (() → void) → void _closure = null; + synthetic constructor •() → #lib::_ScheduleImmediate + : super dart.core::Object::•() + ; + } + class _NamespaceImpl extends dart.core::Object implements #lib::_Namespace { + static field #lib::_NamespaceImpl _cachedNamespace = null; + constructor _() → #lib::_NamespaceImpl + : super dart.core::Object::•() + ; + @dart._internal::ExternalName::•("Namespace_Create") + external static method _create(#lib::_NamespaceImpl namespace, dynamic n) → #lib::_NamespaceImpl; + @dart._internal::ExternalName::•("Namespace_GetPointer") + external static method _getPointer(#lib::_NamespaceImpl namespace) → dart.core::int; + @dart._internal::ExternalName::•("Namespace_GetDefault") + external static method _getDefault() → dart.core::int; + static method _setupNamespace(dynamic namespace) → void { + #lib::_NamespaceImpl::_cachedNamespace = #lib::_NamespaceImpl::_create(new #lib::_NamespaceImpl::_(), namespace); + } + static get _namespace() → #lib::_NamespaceImpl { + if(#lib::_NamespaceImpl::_cachedNamespace.{dart.core::Object::==}(null)) { + #lib::_NamespaceImpl::_cachedNamespace = #lib::_NamespaceImpl::_create(new #lib::_NamespaceImpl::_(), #lib::_NamespaceImpl::_getDefault()); + } + return #lib::_NamespaceImpl::_cachedNamespace; + } + static get _namespacePointer() → dart.core::int + return #lib::_NamespaceImpl::_getPointer(#lib::_NamespaceImpl::_namespace); + } + class _Namespace extends dart.core::Object { + synthetic constructor •() → #lib::_Namespace + : super dart.core::Object::•() + ; + static method _setupNamespace(dynamic namespace) → void { + #lib::_NamespaceImpl::_setupNamespace(namespace); + } + static get _namespace() → #lib::_Namespace + return #lib::_NamespaceImpl::_namespace; + static get _namespacePointer() → dart.core::int + return #lib::_NamespaceImpl::_namespacePointer; + } + class VMLibraryHooks extends dart.core::Object { static field dynamic timerFactory = null; static field dynamic eventHandlerSendData = null; static field dynamic timerMillisecondClock = null; @@ -737,81 +754,12 @@ ConstantPool { return #lib::VMLibraryHooks::_cachedScript; } } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { - -Function '', constructor, reflectable - parameters [] (required: 0) - return-type #lib::Stdin - - -Bytecode { - Entry 0 - CheckStack 0 - Push FP[-5] - DirectCall CP#0, 1 - Drop1 - PushNull - ReturnTOS -} -ConstantPool { - [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] - [1] = Reserved -} - -} - -} -] class Stdin extends dart.core::Object { + class Stdin extends dart.core::Object { synthetic constructor •() → #lib::Stdin : super dart.core::Object::•() ; } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { - -Function '', constructor, reflectable - parameters [] (required: 0) - return-type #lib::_StdIOUtils - - -Bytecode { - Entry 0 - CheckStack 0 - Push FP[-5] - DirectCall CP#0, 1 - Drop1 - PushNull - ReturnTOS -} -ConstantPool { - [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names [] - [1] = Reserved -} - - -Function '_getStdioInputStream', static, reflectable, debuggable - parameters [dart:core::int 'fd'] (required: 1) - return-type #lib::Stdin - - -Bytecode { - Entry 0 - CheckStack 0 - PushNull - ReturnTOS -} -ConstantPool { -} - -} - -} -] class _StdIOUtils extends dart.core::Object { + class _StdIOUtils extends dart.core::Object { synthetic constructor •() → #lib::_StdIOUtils : super dart.core::Object::•() ; diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect index 465e333115b..2932382f81f 100644 --- a/pkg/vm/testcases/bytecode/closures.dart.expect +++ b/pkg/vm/testcases/bytecode/closures.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'simpleClosure', static, reflectable, debuggable parameters [] (required: 0) return-type dart:core::int - Bytecode { Entry 4 CheckStack 0 @@ -92,7 +90,6 @@ ClosureCode { StoreContextVar 0, 0 PushNull ReturnTOS - } @@ -101,7 +98,6 @@ Function 'callWithArgs', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 2 CheckStack 0 @@ -187,7 +183,6 @@ Function 'callA', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -241,7 +236,6 @@ Function 'testPartialInstantiation', static, reflectable, debuggable parameters [] (required: 0) return-type FunctionType (dart:core::int) -> dynamic - Bytecode { Entry 7 CheckStack 0 @@ -351,7 +345,6 @@ L2: Drop1 PushNull ReturnTOS - } @@ -359,7 +352,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -369,22 +361,14 @@ Bytecode { ConstantPool { } -} +Class 'C1', script = '#lib' + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - - typedef IntFunc = (dart.core::int) → dynamic; -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C1 - Bytecode { Entry 0 CheckStack 0 @@ -399,24 +383,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C2', script = '#lib' + extends dart:core::Object -} -] class C1 extends dart.core::Object { - synthetic constructor •() → #lib::C1 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C2 - Bytecode { Entry 0 CheckStack 0 @@ -431,24 +405,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C3', script = '#lib' + extends dart:core::Object -} -] class C2 extends dart.core::Object { - synthetic constructor •() → #lib::C2 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C3 - Bytecode { Entry 0 CheckStack 0 @@ -463,24 +427,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C4', script = '#lib' + extends dart:core::Object -} -] class C3 extends dart.core::Object { - synthetic constructor •() → #lib::C3 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C4 - Bytecode { Entry 0 CheckStack 0 @@ -495,24 +449,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C5', script = '#lib' + extends dart:core::Object -} -] class C4 extends dart.core::Object { - synthetic constructor •() → #lib::C4 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C5 - Bytecode { Entry 0 CheckStack 0 @@ -527,24 +471,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C6', script = '#lib' + extends dart:core::Object -} -] class C5 extends dart.core::Object { - synthetic constructor •() → #lib::C5 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C6 - Bytecode { Entry 0 CheckStack 0 @@ -559,24 +493,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C7', script = '#lib' + extends dart:core::Object -} -] class C6 extends dart.core::Object { - synthetic constructor •() → #lib::C6 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C7 - Bytecode { Entry 0 CheckStack 0 @@ -591,24 +515,14 @@ ConstantPool { [1] = Reserved } -} +Class 'C8', script = '#lib' + extends dart:core::Object -} -] class C7 extends dart.core::Object { - synthetic constructor •() → #lib::C7 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C8 - Bytecode { Entry 0 CheckStack 0 @@ -623,24 +537,15 @@ ConstantPool { [1] = Reserved } -} +Class 'A', script = '#lib' + type-params (args: 2) + extends dart:core::Object -} -] class C8 extends dart.core::Object { - synthetic constructor •() → #lib::C8 - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::A < #lib::A::TypeParam/0, #lib::A::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -661,7 +566,6 @@ Function 'foo', reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 5 CheckStack 0 @@ -804,7 +708,6 @@ L2: Drop1 PushNull ReturnTOS - } Closure #lib::A::foo::Closure/0::'nested2' () -> void @@ -856,7 +759,6 @@ L2: Drop1 PushNull ReturnTOS - } Closure #lib::A::foo::Closure/1::'' () -> dart:core::Null @@ -939,36 +841,11 @@ ClosureCode { Drop1 PushNull ReturnTOS - } -} +Class 'B', script = '#lib' + extends dart:core::Object -} -] class A extends dart.core::Object { - synthetic constructor •() → #lib::A<#lib::A::T1, #lib::A::T2> - : super dart.core::Object::•() - ; - method foo() → void { - function nested1() → void { - function nested2() → void { - () → dart.core::Null nested3 = () → dart.core::Null { - dart.core::print([#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]); - #lib::callWithArgs<#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8>(); - }; - [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] nested3.call(); - } - [@vm.call-site-attributes.metadata=receiverType:() → void] nested2.call<#lib::C7, #lib::C8>(); - [@vm.call-site-attributes.metadata=receiverType:() → void] nested2.call, dart.core::List<#lib::C8>>(); - } - [@vm.call-site-attributes.metadata=receiverType:() → void] nested1.call<#lib::C5, #lib::C6>(); - [@vm.call-site-attributes.metadata=receiverType:() → void] nested1.call, dart.core::List<#lib::C6>>(); - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'foo', type = dart:core::int, getter = 'get:foo', setter = 'set:foo', reflectable value = null @@ -976,7 +853,6 @@ Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::B - Bytecode { Entry 0 CheckStack 0 @@ -997,7 +873,6 @@ Function 'topLevel', reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 5 CheckStack 0 @@ -1179,7 +1054,6 @@ ClosureCode { L1: PushNull ReturnTOS - } Closure #lib::B::topLevel::Closure/0::'closure2' () -> void @@ -1208,7 +1082,6 @@ ClosureCode { StoreContextVar 1, 1 PushNull ReturnTOS - } Closure #lib::B::topLevel::'' () -> dart:core::Null @@ -1226,61 +1099,16 @@ ClosureCode { Drop1 PushNull ReturnTOS - } -} +Class 'C', script = '#lib' + extends dart:core::Object -} -] class B extends dart.core::Object { - field dart.core::int foo = null; - synthetic constructor •() → #lib::B - : super dart.core::Object::•() - ; - method topLevel() → void { - { - dart.core::int x = 1; - { - dart.core::int y = 2; - dart.core::int z = 3; - (dart.core::int) → dart.core::Null closure1 = (dart.core::int y) → dart.core::Null { - x = y.{dart.core::num::+}(1); - if(x.{dart.core::num::>}(5)) { - dart.core::int w = 4; - function closure2() → void { - z = x.{dart.core::num::+}(2); - w = this.{#lib::B::foo}.{dart.core::num::+}(y); - } - [@vm.call-site-attributes.metadata=receiverType:() → void] closure2.call(); - dart.core::print(w); - } - }; - [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(10); - [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(11); - dart.core::print(y); - dart.core::print(z); - } - dart.core::print(x); - } - { - dart.core::int x = 42; - () → dart.core::Null closure3 = () → dart.core::Null { - this.{#lib::B::foo} = x; - }; - [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] closure3.call(); - } - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C - Bytecode { Entry 0 CheckStack 0 @@ -1300,7 +1128,6 @@ Function 'testForLoop', reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 5 CheckStack 0 @@ -1436,7 +1263,6 @@ ClosureCode { LoadContextVar 0, 0 AddInt ReturnTOS - } Closure #lib::C::testForLoop::'' (dart:core::int ii) -> dart:core::Null @@ -1462,7 +1288,6 @@ ClosureCode { StoreContextVar 1, 0 PushNull ReturnTOS - } @@ -1470,7 +1295,6 @@ Function 'testForInLoop', reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type void - Bytecode { Entry 5 CheckStack 0 @@ -1561,47 +1385,17 @@ ClosureCode { StoreContextVar 0, 0 PushNull ReturnTOS - } -} +Class 'D', script = '#lib' + type-params (args: 1) + extends dart:core::Object -} -] class C extends dart.core::Object { - synthetic constructor •() → #lib::C - : super dart.core::Object::•() - ; - method testForLoop() → void { - dart.core::int delta = 0; - dart.core::List getI = []; - dart.core::List setI = []; - for (dart.core::int i = 0; i.{dart.core::num::<}(10); i = i.{dart.core::num::+}(1)) { - [@vm.call-site-attributes.metadata=receiverType:dart.core::List] getI.{dart.core::List::add}(() → dart.core::int => i.{dart.core::num::+}(delta)); - [@vm.call-site-attributes.metadata=receiverType:dart.core::List] setI.{dart.core::List::add}((dart.core::int ii) → dart.core::Null { - i = ii.{dart.core::num::+}(delta); - }); - } - } - method testForInLoop(dart.core::List list) → void { - for (dart.core::int i in list) { - () → dart.core::Null inc = () → dart.core::Null { - i = i.{dart.core::num::+}(1); - }; - [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] inc.call(); - dart.core::print(i); - } - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::D < #lib::D::TypeParam/0 > - Bytecode { Entry 0 CheckStack 0 @@ -1621,7 +1415,6 @@ Function 'foo', reflectable, debuggable parameters [#lib::D::TypeParam/0 't'] (required: 1) return-type dynamic - Bytecode { Entry 3 CheckStack 0 @@ -1688,7 +1481,6 @@ ClosureCode { Push r0 LoadContextVar 0, 0 ReturnTOS - } @@ -1696,7 +1488,6 @@ Function 'bar', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 3 CheckStack 0 @@ -1777,7 +1568,6 @@ ClosureCode { Drop1 PushNull ReturnTOS - } Closure #lib::D::bar::Closure/0::'inner' () -> dart:core::Null @@ -1789,13 +1579,138 @@ ClosureCode { PopLocal r0 PushNull ReturnTOS - } -} } -] class D extends dart.core::Object { +]library #lib from "#lib" as #lib { + + typedef IntFunc = (dart.core::int) → dynamic; + class C1 extends dart.core::Object { + synthetic constructor •() → #lib::C1 + : super dart.core::Object::•() + ; + } + class C2 extends dart.core::Object { + synthetic constructor •() → #lib::C2 + : super dart.core::Object::•() + ; + } + class C3 extends dart.core::Object { + synthetic constructor •() → #lib::C3 + : super dart.core::Object::•() + ; + } + class C4 extends dart.core::Object { + synthetic constructor •() → #lib::C4 + : super dart.core::Object::•() + ; + } + class C5 extends dart.core::Object { + synthetic constructor •() → #lib::C5 + : super dart.core::Object::•() + ; + } + class C6 extends dart.core::Object { + synthetic constructor •() → #lib::C6 + : super dart.core::Object::•() + ; + } + class C7 extends dart.core::Object { + synthetic constructor •() → #lib::C7 + : super dart.core::Object::•() + ; + } + class C8 extends dart.core::Object { + synthetic constructor •() → #lib::C8 + : super dart.core::Object::•() + ; + } + class A extends dart.core::Object { + synthetic constructor •() → #lib::A<#lib::A::T1, #lib::A::T2> + : super dart.core::Object::•() + ; + method foo() → void { + function nested1() → void { + function nested2() → void { + () → dart.core::Null nested3 = () → dart.core::Null { + dart.core::print([#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]); + #lib::callWithArgs<#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8>(); + }; + [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] nested3.call(); + } + [@vm.call-site-attributes.metadata=receiverType:() → void] nested2.call<#lib::C7, #lib::C8>(); + [@vm.call-site-attributes.metadata=receiverType:() → void] nested2.call, dart.core::List<#lib::C8>>(); + } + [@vm.call-site-attributes.metadata=receiverType:() → void] nested1.call<#lib::C5, #lib::C6>(); + [@vm.call-site-attributes.metadata=receiverType:() → void] nested1.call, dart.core::List<#lib::C6>>(); + } + } + class B extends dart.core::Object { + field dart.core::int foo = null; + synthetic constructor •() → #lib::B + : super dart.core::Object::•() + ; + method topLevel() → void { + { + dart.core::int x = 1; + { + dart.core::int y = 2; + dart.core::int z = 3; + (dart.core::int) → dart.core::Null closure1 = (dart.core::int y) → dart.core::Null { + x = y.{dart.core::num::+}(1); + if(x.{dart.core::num::>}(5)) { + dart.core::int w = 4; + function closure2() → void { + z = x.{dart.core::num::+}(2); + w = this.{#lib::B::foo}.{dart.core::num::+}(y); + } + [@vm.call-site-attributes.metadata=receiverType:() → void] closure2.call(); + dart.core::print(w); + } + }; + [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(10); + [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(11); + dart.core::print(y); + dart.core::print(z); + } + dart.core::print(x); + } + { + dart.core::int x = 42; + () → dart.core::Null closure3 = () → dart.core::Null { + this.{#lib::B::foo} = x; + }; + [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] closure3.call(); + } + } + } + class C extends dart.core::Object { + synthetic constructor •() → #lib::C + : super dart.core::Object::•() + ; + method testForLoop() → void { + dart.core::int delta = 0; + dart.core::List getI = []; + dart.core::List setI = []; + for (dart.core::int i = 0; i.{dart.core::num::<}(10); i = i.{dart.core::num::+}(1)) { + [@vm.call-site-attributes.metadata=receiverType:dart.core::List] getI.{dart.core::List::add}(() → dart.core::int => i.{dart.core::num::+}(delta)); + [@vm.call-site-attributes.metadata=receiverType:dart.core::List] setI.{dart.core::List::add}((dart.core::int ii) → dart.core::Null { + i = ii.{dart.core::num::+}(delta); + }); + } + } + method testForInLoop(dart.core::List list) → void { + for (dart.core::int i in list) { + () → dart.core::Null inc = () → dart.core::Null { + i = i.{dart.core::num::+}(1); + }; + [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] inc.call(); + dart.core::print(i); + } + } + } + class D extends dart.core::Object { synthetic constructor •() → #lib::D<#lib::D::T> : super dart.core::Object::•() ; diff --git a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect index f4ef7c3b248..a3a1685986a 100644 --- a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect +++ b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'callDeferred', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -37,7 +35,6 @@ Function 'testLoadLibrary', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -55,7 +52,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -65,7 +61,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect index ee724e8f57b..a2d144202d9 100644 --- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect +++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -25,15 +23,9 @@ Bytecode { ConstantPool { } -} +Class 'A', script = '#lib' + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'foo1', type = dart:core::int, getter = 'get:foo1', setter = 'set:foo1', reflectable value = null @@ -53,7 +45,6 @@ Function '', constructor, reflectable, debuggable parameters [dart:core::int 'foo4'] (required: 1) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -92,7 +83,6 @@ Function 'constr2', constructor, reflectable, debuggable parameters [dart:core::int 'x', dart:core::int 'y'] (required: 2) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -133,7 +123,6 @@ Function 'redirecting1', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -154,7 +143,6 @@ Function 'redirecting2', constructor, reflectable, debuggable parameters [dart:core::int 'a', dart:core::int 'b', dart:core::int 'c'] (required: 3) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -173,32 +161,9 @@ ConstantPool { [1] = Reserved } -} +Class 'B', script = '#lib' + extends #lib::A -} -] class A extends dart.core::Object { - field dart.core::int foo1; - field dart.core::int foo2 = null; - field dart.core::int foo3 = 42; - field dart.core::int foo4; - field dart.core::int foo5 = 43; - constructor •(dart.core::int foo4) → #lib::A - : #lib::A::foo1 = null, #lib::A::foo4 = foo4, #lib::A::foo5 = 44, super dart.core::Object::•() - ; - constructor constr2(dart.core::int x, dart.core::int y) → #lib::A - : #lib::A::foo4 = null, #lib::A::foo1 = x, #lib::A::foo5 = y.{dart.core::num::+}(1), super dart.core::Object::•() - ; - constructor redirecting1() → #lib::A - : this #lib::A::•(45) - ; - constructor redirecting2(dart.core::int a, dart.core::int b, dart.core::int c) → #lib::A - : this #lib::A::constr2(a, b.{dart.core::num::*}(c)) - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'foo6', type = dart:core::int, getter = 'get:foo6', setter = 'set:foo6', reflectable value = const 46 @@ -212,7 +177,6 @@ Function '', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::B - Bytecode { Entry 0 CheckStack 0 @@ -238,7 +202,6 @@ Function 'c2', constructor, reflectable, debuggable parameters [dart:core::int 'i', dart:core::int 'j'] (required: 2) return-type #lib::B - Bytecode { Entry 0 CheckStack 0 @@ -264,10 +227,30 @@ ConstantPool { [3] = Reserved } -} } -] class B extends #lib::A { +]library #lib from "#lib" as #lib { + + class A extends dart.core::Object { + field dart.core::int foo1; + field dart.core::int foo2 = null; + field dart.core::int foo3 = 42; + field dart.core::int foo4; + field dart.core::int foo5 = 43; + constructor •(dart.core::int foo4) → #lib::A + : #lib::A::foo1 = null, #lib::A::foo4 = foo4, #lib::A::foo5 = 44, super dart.core::Object::•() + ; + constructor constr2(dart.core::int x, dart.core::int y) → #lib::A + : #lib::A::foo4 = null, #lib::A::foo1 = x, #lib::A::foo5 = y.{dart.core::num::+}(1), super dart.core::Object::•() + ; + constructor redirecting1() → #lib::A + : this #lib::A::•(45) + ; + constructor redirecting2(dart.core::int a, dart.core::int b, dart.core::int c) → #lib::A + : this #lib::A::constr2(a, b.{dart.core::num::*}(c)) + ; + } + class B extends #lib::A { field dart.core::int foo6 = 46; static field dart.core::int foo7 = 47; static const field dart.core::int foo8 = 48; diff --git a/pkg/vm/testcases/bytecode/hello.dart.expect b/pkg/vm/testcases/bytecode/hello.dart.expect index aa15b420b4c..12f2f553f69 100644 --- a/pkg/vm/testcases/bytecode/hello.dart.expect +++ b/pkg/vm/testcases/bytecode/hello.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -31,7 +29,6 @@ ConstantPool { [2] = Reserved } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect index 7243ab28a58..eadce662b9d 100644 --- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect +++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'foo1', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -39,7 +37,6 @@ Function 'foo2', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -81,7 +78,6 @@ Function 'foo3', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 2 CheckStack 0 @@ -111,7 +107,6 @@ Function 'foo4', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -132,7 +127,6 @@ Function 'foo5', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -158,7 +152,6 @@ Function 'foo6', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -178,7 +171,6 @@ Function 'foo7', static, reflectable, debuggable parameters [dart:core::int 'n'] (required: 1) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -198,7 +190,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -222,15 +213,10 @@ ConstantPool { [6] = Reserved } -} +Class 'Base', script = '#lib' + type-params (args: 2) + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 't1', type = #lib::Base::TypeParam/0, getter = 'get:t1', setter = 'set:t1', reflectable value = null @@ -241,7 +227,6 @@ Function '', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::Base < #lib::Base::TypeParam/0, #lib::Base::TypeParam/1 > - Bytecode { Entry 1 CheckStack 0 @@ -295,26 +280,13 @@ ConstantPool { [10] = Reserved } -} +Class 'A', script = '#lib' + extends #lib::Base < dart:core::int, dart:core::String > -} -] class Base extends dart.core::Object { - generic-covariant-impl field #lib::Base::T1 t1 = null; - generic-covariant-impl field #lib::Base::T2 t2 = null; - constructor •() → #lib::Base<#lib::Base::T1, #lib::Base::T2> - : super dart.core::Object::•() { - dart.core::print("Base: ${#lib::Base::T1}, ${#lib::Base::T2}"); - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable, debuggable parameters [dart:core::String 's'] (required: 1) - return-type #lib::A - + return-type #lib::A < dart:core::int, dart:core::String > Bytecode { Entry 0 @@ -330,24 +302,15 @@ ConstantPool { [1] = Reserved } -} +Class 'B', script = '#lib' + type-params (args: 3) + extends #lib::Base < dart:core::List < #lib::B::TypeParam/0 >, dart:core::String > -} -] class A extends #lib::Base { - constructor •(dart.core::String s) → #lib::A - : super #lib::Base::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::B < dart:core::List < #lib::B::TypeParam/0 >, dart:core::String, #lib::B::TypeParam/0 > - Bytecode { Entry 1 CheckStack 0 @@ -387,25 +350,14 @@ ConstantPool { [8] = Reserved } -} +Class 'C', script = '#lib' + extends dart:core::Object -} -] class B extends #lib::Base, dart.core::String> { - constructor •() → #lib::B<#lib::B::T> - : super #lib::Base::•() { - dart.core::print("B: ${#lib::B::T}"); - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable, debuggable parameters [dart:core::String 's'] (required: 1) return-type #lib::C - Bytecode { Entry 1 CheckStack 0 @@ -440,25 +392,15 @@ ConstantPool { [6] = Reserved } -} +Class 'E', script = '#lib' + type-params (args: 2) + extends dart:core::Object -} -] class C extends dart.core::Object { - constructor •(dart.core::String s) → #lib::C - : super dart.core::Object::•() { - dart.core::print("C: ${s}"); - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::E < #lib::E::TypeParam/0, #lib::E::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -478,7 +420,6 @@ Function 'test_reuse1', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -493,26 +434,15 @@ ConstantPool { [2] = Reserved } -} +Class 'F', script = '#lib' + type-params (args: 4) + extends #lib::E < dart:core::String, dart:core::List < #lib::F::TypeParam/1 > > -} -] class E extends dart.core::Object { - synthetic constructor •() → #lib::E<#lib::E::K, #lib::E::V> - : super dart.core::Object::•() - ; - method test_reuse1() → dynamic - return dart.core::Map::•<#lib::E::K, #lib::E::V>(); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::F < dart:core::String, dart:core::List < #lib::F::TypeParam/1 >, #lib::F::TypeParam/0, #lib::F::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -532,7 +462,6 @@ Function 'test_reuse2', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -547,26 +476,15 @@ ConstantPool { [2] = Reserved } -} +Class 'G', script = '#lib' + type-params (args: 2) + extends dart:core::Object -} -] class F extends #lib::E> { - synthetic constructor •() → #lib::F<#lib::F::K, #lib::F::V> - : super #lib::E::•() - ; - method test_reuse2() → dynamic - return dart.core::Map::•>(); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable, debuggable parameters [] (required: 0) return-type #lib::G < #lib::G::TypeParam/0, #lib::G::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -587,7 +505,6 @@ Function 'test_factory', factory, static, reflectable, debuggable parameters [] (required: 0) return-type #lib::G < #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1 > - Bytecode { Entry 1 CheckStack 0 @@ -609,26 +526,15 @@ ConstantPool { [3] = Reserved } -} +Class 'H', script = '#lib' + type-params (args: 5) + extends #lib::G < #lib::H::TypeParam/1, #lib::H::TypeParam/2 > -} -] class G extends dart.core::Object { - constructor •() → #lib::G<#lib::G::K, #lib::G::V> - : super dart.core::Object::•() - ; - static factory test_factory() → #lib::G<#lib::G::test_factory::K, #lib::G::test_factory::V> - return new #lib::H::•(); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::H < #lib::H::TypeParam/1, #lib::H::TypeParam/2, #lib::H::TypeParam/0, #lib::H::TypeParam/1, #lib::H::TypeParam/2 > - Bytecode { Entry 0 CheckStack 0 @@ -643,24 +549,14 @@ ConstantPool { [1] = Reserved } -} +Class 'I', script = '#lib' + extends dart:core::Object -} -] class H extends #lib::G<#lib::H::P2, #lib::H::P3> { - synthetic constructor •() → #lib::H<#lib::H::P1, #lib::H::P2, #lib::H::P3> - : super #lib::G::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable, debuggable parameters [dynamic 'param'] (required: 1) return-type #lib::I - Bytecode { Entry 0 CheckStack 0 @@ -680,7 +576,6 @@ Function 'test_factory2', factory, static, has-optional-named-params, reflectabl parameters [dynamic 'param'] (required: 0) return-type #lib::I - Bytecode { EntryOptional 1, 0, 1 LoadConstant r1, CP#0 @@ -703,26 +598,14 @@ ConstantPool { [4] = Reserved } -} +Class 'J', script = '#lib' + extends dart:core::Object -} -] class I extends dart.core::Object { - constructor •(dynamic param) → #lib::I - : super dart.core::Object::•() - ; - static factory test_factory2({dynamic param = null}) → #lib::I - return new #lib::I::•(param); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', factory, static, reflectable, debuggable, native 'agent_J' parameters [] (required: 0) return-type #lib::J - Bytecode { Entry 0 CheckStack 0 @@ -734,24 +617,16 @@ ConstantPool { [0] = NativeEntry agent_J } -} +Class 'K', script = '#lib', abstract + type-params (args: 2) + extends dart:core::Object -} -] class J extends dart.core::Object { - @dart._internal::ExternalName::•("agent_J") - external static factory •() → #lib::J; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', factory, static, reflectable, debuggable type-params parameters [] (required: 0) return-type #lib::K < #lib::K:: (constructor)::TypeParam/0, #lib::K:: (constructor)::TypeParam/1 > - Bytecode { Entry 1 CheckStack 0 @@ -770,23 +645,16 @@ ConstantPool { [2] = Reserved } -} +Class 'TestTypeArgReuse', script = '#lib' + type-params (args: 2) + extends #lib::Base < #lib::TestTypeArgReuse::TypeParam/0, #lib::TestTypeArgReuse::TypeParam/1 > + implements [#lib::K < #lib::TestTypeArgReuse::TypeParam/0, #lib::TestTypeArgReuse::TypeParam/1 >] -} -] abstract class K extends dart.core::Object { - static factory •() → #lib::K<#lib::K::•::A, #lib::K::•::B> - return new #lib::TestTypeArgReuse::•<#lib::K::•::A, #lib::K::•::B>(); - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::TestTypeArgReuse < #lib::TestTypeArgReuse::TypeParam/0, #lib::TestTypeArgReuse::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -801,10 +669,77 @@ ConstantPool { [1] = Reserved } -} } -] class TestTypeArgReuse

extends #lib::Base<#lib::TestTypeArgReuse::P, #lib::TestTypeArgReuse::Q> implements #lib::K<#lib::TestTypeArgReuse::P, #lib::TestTypeArgReuse::Q> { +]library #lib from "#lib" as #lib { + + class Base extends dart.core::Object { + generic-covariant-impl field #lib::Base::T1 t1 = null; + generic-covariant-impl field #lib::Base::T2 t2 = null; + constructor •() → #lib::Base<#lib::Base::T1, #lib::Base::T2> + : super dart.core::Object::•() { + dart.core::print("Base: ${#lib::Base::T1}, ${#lib::Base::T2}"); + } + } + class A extends #lib::Base { + constructor •(dart.core::String s) → #lib::A + : super #lib::Base::•() + ; + } + class B extends #lib::Base, dart.core::String> { + constructor •() → #lib::B<#lib::B::T> + : super #lib::Base::•() { + dart.core::print("B: ${#lib::B::T}"); + } + } + class C extends dart.core::Object { + constructor •(dart.core::String s) → #lib::C + : super dart.core::Object::•() { + dart.core::print("C: ${s}"); + } + } + class E extends dart.core::Object { + synthetic constructor •() → #lib::E<#lib::E::K, #lib::E::V> + : super dart.core::Object::•() + ; + method test_reuse1() → dynamic + return dart.core::Map::•<#lib::E::K, #lib::E::V>(); + } + class F extends #lib::E> { + synthetic constructor •() → #lib::F<#lib::F::K, #lib::F::V> + : super #lib::E::•() + ; + method test_reuse2() → dynamic + return dart.core::Map::•>(); + } + class G extends dart.core::Object { + constructor •() → #lib::G<#lib::G::K, #lib::G::V> + : super dart.core::Object::•() + ; + static factory test_factory() → #lib::G<#lib::G::test_factory::K, #lib::G::test_factory::V> + return new #lib::H::•(); + } + class H extends #lib::G<#lib::H::P2, #lib::H::P3> { + synthetic constructor •() → #lib::H<#lib::H::P1, #lib::H::P2, #lib::H::P3> + : super #lib::G::•() + ; + } + class I extends dart.core::Object { + constructor •(dynamic param) → #lib::I + : super dart.core::Object::•() + ; + static factory test_factory2({dynamic param = null}) → #lib::I + return new #lib::I::•(param); + } + class J extends dart.core::Object { + @dart._internal::ExternalName::•("agent_J") + external static factory •() → #lib::J; + } + abstract class K extends dart.core::Object { + static factory •() → #lib::K<#lib::K::•::A, #lib::K::•::B> + return new #lib::TestTypeArgReuse::•<#lib::K::•::A, #lib::K::•::B>(); + } + class TestTypeArgReuse

extends #lib::Base<#lib::TestTypeArgReuse::P, #lib::TestTypeArgReuse::Q> implements #lib::K<#lib::TestTypeArgReuse::P, #lib::TestTypeArgReuse::Q> { synthetic constructor •() → #lib::TestTypeArgReuse<#lib::TestTypeArgReuse::P, #lib::TestTypeArgReuse::Q> : super #lib::Base::•() ; diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect index 290438ee1e4..0785aa497ab 100644 --- a/pkg/vm/testcases/bytecode/literals.dart.expect +++ b/pkg/vm/testcases/bytecode/literals.dart.expect @@ -1,17 +1,16 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Field 'c1', type = #lib::A, getter = 'get:c1', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -30,7 +29,7 @@ Field 'c3', type = dart:core::int, reflectable, static, const, final value = const 6 Field 'c4', type = #lib::C, getter = 'get:c4', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -43,7 +42,7 @@ ConstantPool { Field 'c5', type = #lib::D, getter = 'get:c5', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -62,7 +61,6 @@ Function 'test_constants1', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -98,7 +96,6 @@ Function 'test_constants2', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -138,7 +135,6 @@ Function 'test_list_literal', static, reflectable, debuggable parameters [dart:core::int 'a'] (required: 1) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -207,7 +203,6 @@ Function 'test_map_literal', static, reflectable, debuggable parameters [dart:core::int 'a', dart:core::int 'b', #lib::test_map_literal::TypeParam/0 'c'] (required: 3) return-type void - Bytecode { Entry 2 CheckStack 0 @@ -310,7 +305,6 @@ Function 'test_symbol', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -336,7 +330,6 @@ Function 'test_type_literal', static, reflectable, debuggable parameters [] (required: 0) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -364,7 +357,6 @@ Function 'testGenericConstInstance', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -380,7 +372,6 @@ Function 'testGenericFunctionTypeLiteral', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -396,7 +387,6 @@ Function 'testFieldWithDoubleLiteralInitializer', static, reflectable, debuggabl parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -413,7 +403,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -423,16 +412,9 @@ Bytecode { ConstantPool { } -} +Class 'A', script = '#lib', enum + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - - typedef GenericFunctionType = (X) → X; -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'index', type = dart:core::int, getter = 'get:index', reflectable, final value = null @@ -440,7 +422,7 @@ Field '_name', type = dart:core::String, getter = 'get:_name', reflectable, fina value = null Field 'values', type = dart:core::List < #lib::A >, getter = 'get:values', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -453,7 +435,7 @@ ConstantPool { Field 'elem1', type = #lib::A, getter = 'get:elem1', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -466,7 +448,7 @@ ConstantPool { Field 'elem2', type = #lib::A, getter = 'get:elem2', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -479,7 +461,7 @@ ConstantPool { Field 'elem3', type = #lib::A, getter = 'get:elem3', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -492,7 +474,7 @@ ConstantPool { Field 'elem4', type = #lib::A, getter = 'get:elem4', reflectable, static, const, final - initializer + initializer Bytecode { Entry 0 CheckStack 0 @@ -508,7 +490,6 @@ Function '', constructor, const, reflectable, debuggable parameters [dart:core::int 'index', dart:core::String '_name'] (required: 2) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -538,7 +519,6 @@ Function 'toString', reflectable, debuggable parameters [] (required: 0) return-type dart:core::String - Bytecode { Entry 0 CheckStack 0 @@ -551,27 +531,9 @@ ConstantPool { [1] = Reserved } -} +Class 'B', script = '#lib' + extends dart:core::Object -} -] class A extends dart.core::Object { - final field dart.core::int index; - final field dart.core::String _name; - static const field dart.core::List<#lib::A> values = const <#lib::A>[#lib::A::elem1, #lib::A::elem2, #lib::A::elem3, #lib::A::elem4]; - static const field #lib::A elem1 = const #lib::A::•(0, "A.elem1"); - static const field #lib::A elem2 = const #lib::A::•(1, "A.elem2"); - static const field #lib::A elem3 = const #lib::A::•(2, "A.elem3"); - static const field #lib::A elem4 = const #lib::A::•(3, "A.elem4"); - const constructor •(dart.core::int index, dart.core::String _name) → #lib::A - : #lib::A::index = index, #lib::A::_name = _name, super dart.core::Object::•() - ; - method toString() → dart.core::String - return this.{=#lib::A::_name}; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'i', type = dart:core::int, getter = 'get:i', reflectable, final value = null @@ -579,7 +541,6 @@ Function '', constructor, const, reflectable, debuggable parameters [dart:core::int 'i'] (required: 1) return-type #lib::B - Bytecode { Entry 0 CheckStack 0 @@ -599,19 +560,9 @@ ConstantPool { [3] = Reserved } -} +Class 'C', script = '#lib' + extends #lib::B -} -] class B extends dart.core::Object { - final field dart.core::int i; - const constructor •(dart.core::int i) → #lib::B - : #lib::B::i = i, super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'j', type = dart:core::int, getter = 'get:j', reflectable, final value = null @@ -619,7 +570,6 @@ Function '', constructor, const, reflectable, debuggable parameters [dart:core::int 'a', dart:core::int 'b', dart:core::int 'c'] (required: 3) return-type #lib::C - Bytecode { Entry 0 CheckStack 0 @@ -644,19 +594,9 @@ ConstantPool { [3] = Reserved } -} +Class 'D', script = '#lib' + extends dart:core::Object -} -] class C extends #lib::B { - final field dart.core::int j; - const constructor •(dart.core::int a, dart.core::int b, dart.core::int c) → #lib::C - : #lib::C::j = a.{dart.core::num::+}(b), super #lib::B::•(c.{dart.core::num::*}(5)) - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'x', type = dynamic, getter = 'get:x', reflectable, final value = null @@ -667,7 +607,6 @@ Function '', constructor, const, has-optional-positional-params, reflectable, de parameters [dynamic 'x', dynamic 'y'] (required: 1) return-type #lib::D - Bytecode { EntryOptional 2, 1, 0 LoadConstant r2, CP#0 @@ -695,26 +634,15 @@ ConstantPool { [6] = Reserved } -} +Class 'E', script = '#lib' + type-params (args: 1) + extends dart:core::Object -} -] class D extends dart.core::Object { - final field dynamic x; - final field dynamic y; - const constructor •(dynamic x, [dynamic y = null]) → #lib::D - : #lib::D::x = x, #lib::D::y = y, super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, const, reflectable, debuggable parameters [] (required: 0) return-type #lib::E < #lib::E::TypeParam/0 > - Bytecode { Entry 0 CheckStack 0 @@ -729,24 +657,15 @@ ConstantPool { [1] = Reserved } -} +Class 'F', script = '#lib' + type-params (args: 3) + extends #lib::E < dart:core::Map < #lib::F::TypeParam/0, #lib::F::TypeParam/1 > > -} -] class E extends dart.core::Object { - const constructor •() → #lib::E<#lib::E::T> - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, const, reflectable, debuggable parameters [] (required: 0) return-type #lib::F < dart:core::Map < #lib::F::TypeParam/0, #lib::F::TypeParam/1 >, #lib::F::TypeParam/0, #lib::F::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -761,10 +680,50 @@ ConstantPool { [1] = Reserved } -} } -] class F

extends #lib::E> { +]library #lib from "#lib" as #lib { + + typedef GenericFunctionType = (X) → X; + class A extends dart.core::Object { + final field dart.core::int index; + final field dart.core::String _name; + static const field dart.core::List<#lib::A> values = const <#lib::A>[#lib::A::elem1, #lib::A::elem2, #lib::A::elem3, #lib::A::elem4]; + static const field #lib::A elem1 = const #lib::A::•(0, "A.elem1"); + static const field #lib::A elem2 = const #lib::A::•(1, "A.elem2"); + static const field #lib::A elem3 = const #lib::A::•(2, "A.elem3"); + static const field #lib::A elem4 = const #lib::A::•(3, "A.elem4"); + const constructor •(dart.core::int index, dart.core::String _name) → #lib::A + : #lib::A::index = index, #lib::A::_name = _name, super dart.core::Object::•() + ; + method toString() → dart.core::String + return this.{=#lib::A::_name}; + } + class B extends dart.core::Object { + final field dart.core::int i; + const constructor •(dart.core::int i) → #lib::B + : #lib::B::i = i, super dart.core::Object::•() + ; + } + class C extends #lib::B { + final field dart.core::int j; + const constructor •(dart.core::int a, dart.core::int b, dart.core::int c) → #lib::C + : #lib::C::j = a.{dart.core::num::+}(b), super #lib::B::•(c.{dart.core::num::*}(5)) + ; + } + class D extends dart.core::Object { + final field dynamic x; + final field dynamic y; + const constructor •(dynamic x, [dynamic y = null]) → #lib::D + : #lib::D::x = x, #lib::D::y = y, super dart.core::Object::•() + ; + } + class E extends dart.core::Object { + const constructor •() → #lib::E<#lib::E::T> + : super dart.core::Object::•() + ; + } + class F

extends #lib::E> { const constructor •() → #lib::F<#lib::F::P, #lib::F::Q> : super #lib::E::•() ; diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect index 99ac193e56c..da711c9d82f 100644 --- a/pkg/vm/testcases/bytecode/loops.dart.expect +++ b/pkg/vm/testcases/bytecode/loops.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'test_for', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -58,7 +56,6 @@ Function 'test_for_break', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -107,7 +104,6 @@ Function 'test_for_continue', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -158,7 +154,6 @@ Function 'test_while', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 4 CheckStack 0 @@ -203,7 +198,6 @@ Function 'test_do_while', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -243,7 +237,6 @@ Function 'test_for_in', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 3 CheckStack 0 @@ -283,7 +276,6 @@ Function 'test_for_in_with_outer_var', static, reflectable, debuggable parameters [dart:core::List < dart:core::int > 'list'] (required: 1) return-type dart:core::int - Bytecode { Entry 4 CheckStack 0 @@ -327,7 +319,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -337,7 +328,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect index 49156f26e7f..62dae5f933c 100644 --- a/pkg/vm/testcases/bytecode/optional_params.dart.expect +++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'foo1', static, has-optional-positional-params, reflectable, debuggable parameters [dynamic 'x', dynamic 'a', dynamic 'b'] (required: 1) return-type void - Bytecode { EntryOptional 1, 2, 0 LoadConstant r1, CP#0 @@ -87,7 +85,6 @@ Function 'foo2', static, has-optional-named-params, reflectable, debuggable parameters [dynamic 'y', dynamic 'z', dynamic 'c', dynamic 'a', dynamic 'b'] (required: 2) return-type void - Bytecode { EntryOptional 2, 0, 3 LoadConstant r2, CP#0 @@ -200,7 +197,6 @@ Function 'foo3', static, has-optional-named-params, reflectable, debuggable parameters [dynamic 'z', dynamic 'y', dart:core::bool 'a', dart:core::Map < #lib::foo3::TypeParam/0, #lib::foo3::TypeParam/1 > 'b'] (required: 2) return-type void - Bytecode { EntryOptional 2, 0, 2 LoadConstant r2, CP#0 @@ -239,7 +235,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -266,7 +261,6 @@ ConstantPool { [7] = Reserved } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect index 31ff703d32e..0ac58827fd6 100644 --- a/pkg/vm/testcases/bytecode/super_calls.dart.expect +++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -25,21 +23,14 @@ Bytecode { ConstantPool { } -} +Class 'Base1', script = '#lib' + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::Base1 - Bytecode { Entry 0 CheckStack 0 @@ -60,7 +51,6 @@ Function 'foo', reflectable, debuggable parameters [#lib::Base1::foo::TypeParam/0 'a1', dart:core::int 'a2'] (required: 2) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -76,7 +66,6 @@ Function 'get:bar', getter, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -91,7 +80,6 @@ Function 'set:bazz', setter, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type void - Bytecode { Entry 0 CheckStack 0 @@ -101,28 +89,14 @@ Bytecode { ConstantPool { } -} +Class 'A', script = '#lib' + extends #lib::Base1 -} -] class Base1 extends dart.core::Object { - synthetic constructor •() → #lib::Base1 - : super dart.core::Object::•() - ; - method foo(#lib::Base1::foo::T a1, dart.core::int a2) → void {} - get bar() → dynamic - return 42; - set bazz(dart.core::int x) → void {} - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::A - Bytecode { Entry 0 CheckStack 0 @@ -142,7 +116,6 @@ Function 'testSuperCall', reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -165,7 +138,6 @@ Function 'testSuperTearOff', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -183,7 +155,6 @@ Function 'testSuperGet', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -201,7 +172,6 @@ Function 'testSuperCallViaGetter', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -226,7 +196,6 @@ Function 'testSuperSet', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -242,35 +211,14 @@ ConstantPool { [1] = Reserved } -} +Class 'Base2', script = '#lib', abstract + extends dart:core::Object -} -] class A extends #lib::Base1 { - synthetic constructor •() → #lib::A - : super #lib::Base1::•() - ; - method testSuperCall(dart.core::int x) → dynamic - return super.{#lib::Base1::foo}("a1", 2); - method testSuperTearOff() → dynamic - return super.{#lib::Base1::foo}; - method testSuperGet() → dynamic - return super.{#lib::Base1::bar}; - method testSuperCallViaGetter() → dynamic - return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{#lib::Base1::bar}.call("param"); - method testSuperSet() → dynamic { - super.{#lib::Base1::bazz} = 3; - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::Base2 - Bytecode { Entry 0 CheckStack 0 @@ -298,27 +246,14 @@ Function 'get:bar', getter, abstract, reflectable, debuggable Function 'set:bazz', setter, abstract, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type void -} +Class 'B', script = '#lib', abstract + extends #lib::Base2 -} -] abstract class Base2 extends dart.core::Object { - synthetic constructor •() → #lib::Base2 - : super dart.core::Object::•() - ; - abstract method foo(dart.core::String a1, #lib::Base2::foo::T a2, dart.core::int a3) → void; - abstract get bar() → dynamic; - abstract set bazz(dart.core::int x) → void; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::B - Bytecode { Entry 0 CheckStack 0 @@ -338,7 +273,6 @@ Function 'testSuperCall', reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -392,7 +326,6 @@ Function 'testSuperTearOff', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -427,7 +360,6 @@ Function 'testSuperGet', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -462,7 +394,6 @@ Function 'testSuperCallViaGetter', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -504,7 +435,6 @@ Function 'testSuperSet', reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -540,10 +470,44 @@ ConstantPool { [6] = Reserved } -} } -] abstract class B extends #lib::Base2 { +]library #lib from "#lib" as #lib { + + class Base1 extends dart.core::Object { + synthetic constructor •() → #lib::Base1 + : super dart.core::Object::•() + ; + method foo(#lib::Base1::foo::T a1, dart.core::int a2) → void {} + get bar() → dynamic + return 42; + set bazz(dart.core::int x) → void {} + } + class A extends #lib::Base1 { + synthetic constructor •() → #lib::A + : super #lib::Base1::•() + ; + method testSuperCall(dart.core::int x) → dynamic + return super.{#lib::Base1::foo}("a1", 2); + method testSuperTearOff() → dynamic + return super.{#lib::Base1::foo}; + method testSuperGet() → dynamic + return super.{#lib::Base1::bar}; + method testSuperCallViaGetter() → dynamic + return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{#lib::Base1::bar}.call("param"); + method testSuperSet() → dynamic { + super.{#lib::Base1::bazz} = 3; + } + } + abstract class Base2 extends dart.core::Object { + synthetic constructor •() → #lib::Base2 + : super dart.core::Object::•() + ; + abstract method foo(dart.core::String a1, #lib::Base2::foo::T a2, dart.core::int a3) → void; + abstract get bar() → dynamic; + abstract set bazz(dart.core::int x) → void; + } + abstract class B extends #lib::Base2 { synthetic constructor •() → #lib::B : super #lib::Base2::•() ; diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect index 80a168240e8..bc8357fbe96 100644 --- a/pkg/vm/testcases/bytecode/switch.dart.expect +++ b/pkg/vm/testcases/bytecode/switch.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'foo1', static, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -62,7 +60,6 @@ Function 'foo2', static, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -120,7 +117,6 @@ Function 'foo3', static, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dart:core::int - Bytecode { Entry 2 CheckStack 0 @@ -178,7 +174,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -188,7 +183,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect index 3527e20788b..f1ef3d47395 100644 --- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect +++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect @@ -1,21 +1,19 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Function 'testTryCatch1', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 4 CheckStack 0 @@ -69,7 +67,6 @@ Function 'testTryCatch2', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 5 CheckStack 0 @@ -207,7 +204,6 @@ Function 'testTryCatch3', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 7 CheckStack 0 @@ -381,7 +377,6 @@ Try #0 handler: L1: PushNull ReturnTOS - } Closure #lib::testTryCatch3::'bar' () -> void @@ -443,7 +438,6 @@ L2: L1: PushNull ReturnTOS - } @@ -451,7 +445,6 @@ Function 'testRethrow', static, reflectable, debuggable parameters [dart:core::bool 'cond'] (required: 1) return-type dynamic - Bytecode { Entry 8 CheckStack 0 @@ -535,7 +528,6 @@ Function 'testTryFinally1', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 3 CheckStack 0 @@ -599,7 +591,6 @@ Function 'testTryFinally2', static, reflectable, debuggable parameters [dart:core::int 'x'] (required: 1) return-type dynamic - Bytecode { Entry 9 CheckStack 0 @@ -756,7 +747,6 @@ ClosureCode { Drop1 PushNull ReturnTOS - } @@ -764,7 +754,6 @@ Function 'testTryFinally3', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 6 CheckStack 0 @@ -944,7 +933,6 @@ L3: Drop1 PushInt 43 ReturnTOS - } @@ -952,7 +940,6 @@ Function 'testTryCatchFinally', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 5 CheckStack 0 @@ -1011,7 +998,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -1021,7 +1007,6 @@ Bytecode { ConstantPool { } -} } ]library #lib from "#lib" as #lib { diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect index ca572e87ea9..0e84cb2f457 100644 --- a/pkg/vm/testcases/bytecode/type_ops.dart.expect +++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect @@ -1,15 +1,14 @@ main = #lib::main; [@vm.bytecode= -ComponentBytecodeMetadata { - +BytecodeMetadata { Bytecode (version: stable) Main library: #lib +Library '#lib' + name '#lib' + script '#lib' -} -] [@vm.bytecode= -MembersBytecodeMetadata { +Class '', script = '#lib' -Members { Field 'globalVar', type = dart:core::List < dart:core::Iterable null >, reflectable, static value = null @@ -17,7 +16,6 @@ Function 'foo1', static, reflectable, debuggable parameters [dynamic 'x'] (required: 1) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -48,7 +46,7 @@ L2: ReturnTOS } ConstantPool { - [0] = Type #lib::B + [0] = Type #lib::B < dart:core::String > [1] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names [] [2] = Reserved [3] = ObjectRef '11' @@ -68,7 +66,6 @@ Function 'foo5', static, reflectable, debuggable parameters [dynamic 'x'] (required: 1) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -94,7 +91,6 @@ Function 'main', static, reflectable, debuggable parameters [] (required: 0) return-type dynamic - Bytecode { Entry 0 CheckStack 0 @@ -104,21 +100,15 @@ Bytecode { ConstantPool { } -} +Class 'A', script = '#lib' + type-params (args: 1) + extends dart:core::Object -} -]library #lib from "#lib" as #lib { - -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::A < #lib::A::TypeParam/0 > - Bytecode { Entry 0 CheckStack 0 @@ -133,23 +123,13 @@ ConstantPool { [1] = Reserved } -} +Class 'B', script = '#lib' + extends #lib::A < dart:core::String > -} -] class A extends dart.core::Object { - synthetic constructor •() → #lib::A<#lib::A::T> - : super dart.core::Object::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) - return-type #lib::B - + return-type #lib::B < dart:core::String > Bytecode { Entry 0 @@ -165,24 +145,15 @@ ConstantPool { [1] = Reserved } -} +Class 'C', script = '#lib' + type-params (args: 4) + extends #lib::B < dart:core::String > -} -] class B extends #lib::A { - synthetic constructor •() → #lib::B - : super #lib::A::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', constructor, reflectable parameters [] (required: 0) return-type #lib::C < dart:core::String, #lib::C::TypeParam/0, #lib::C::TypeParam/1, #lib::C::TypeParam/2 > - Bytecode { Entry 0 CheckStack 0 @@ -197,18 +168,10 @@ ConstantPool { [1] = Reserved } -} +Class 'D', script = '#lib' + type-params (args: 5) + extends #lib::C < dart:core::String, dart:core::int, #lib::D::TypeParam/1, #lib::D::TypeParam/0 > -} -] class C extends #lib::B { - synthetic constructor •() → #lib::C<#lib::C::T1, #lib::C::T2, #lib::C::T3> - : super #lib::B::•() - ; - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Field 'foo', type = dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >, getter = 'get:foo', setter = 'set:foo', reflectable value = null @@ -216,7 +179,6 @@ Function '', constructor, reflectable, debuggable parameters [dynamic 'tt'] (required: 1) return-type #lib::D < dart:core::String, dart:core::int, #lib::D::TypeParam/1, #lib::D::TypeParam/0, #lib::D::TypeParam/1 > - Bytecode { Entry 0 CheckStack 0 @@ -251,7 +213,6 @@ Function 'foo2', reflectable, debuggable parameters [dynamic 'y'] (required: 1) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -313,7 +274,6 @@ Function 'foo3', reflectable, debuggable parameters [dynamic 'z'] (required: 1) return-type dynamic - Bytecode { Entry 1 CheckStack 0 @@ -371,7 +331,6 @@ Function 'foo4', reflectable, debuggable parameters [dynamic 'w'] (required: 1) return-type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 > - Bytecode { Entry 2 CheckStack 0 @@ -416,48 +375,16 @@ ConstantPool { [7] = SubtypeTestCache } -} +Class 'E', script = '#lib' + type-params (args: 1) + extends dart:core::Object -} -] class D

extends #lib::C { - generic-covariant-impl field dart.core::Map<#lib::D::P, #lib::D::Q> foo; - constructor •(dynamic tt) → #lib::D<#lib::D::P, #lib::D::Q> - : #lib::D::foo = tt as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>, super #lib::C::•() - ; - method foo2(dynamic y) → dynamic { - if(y is #lib::A<#lib::D::P>) { - dart.core::print("21"); - } - if(y is #lib::C>) { - dart.core::print("22"); - } - [@vm.call-site-attributes.metadata=receiverType:#lib::D<#lib::D::P, #lib::D::Q>] this.{#lib::D::foo} = y as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>; - } - method foo3(dynamic z) → dynamic { - if(z is #lib::A<#lib::D::foo3::T1>) { - dart.core::print("31"); - } - if(z is #lib::C, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>) { - dart.core::print("32"); - } - return (z as dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>).{dart.core::Map::values}; - } - method foo4(dynamic w) → dart.core::Map<#lib::D::P, #lib::D::Q> { - dart.core::List> list = >[w as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>]; - return w as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>; - } - } -[@vm.bytecode= -MembersBytecodeMetadata { - -Members { Function '', factory, static, reflectable, debuggable type-params parameters [] (required: 0) return-type #lib::E < #lib::E:: (constructor)::TypeParam/0 > - Bytecode { Entry 0 CheckStack 0 @@ -473,7 +400,6 @@ Function 'foo6', reflectable, debuggable parameters [dart:core::Map < #lib::E::foo6::TypeParam/0, #lib::E::foo6::TypeParam/1 > 'map'] (required: 1) return-type void - Bytecode { Entry 1 CheckStack 0 @@ -504,10 +430,54 @@ ConstantPool { [4] = ObjectRef 'T' } -} } -] class E

extends dart.core::Object { +]library #lib from "#lib" as #lib { + + class A extends dart.core::Object { + synthetic constructor •() → #lib::A<#lib::A::T> + : super dart.core::Object::•() + ; + } + class B extends #lib::A { + synthetic constructor •() → #lib::B + : super #lib::A::•() + ; + } + class C extends #lib::B { + synthetic constructor •() → #lib::C<#lib::C::T1, #lib::C::T2, #lib::C::T3> + : super #lib::B::•() + ; + } + class D

extends #lib::C { + generic-covariant-impl field dart.core::Map<#lib::D::P, #lib::D::Q> foo; + constructor •(dynamic tt) → #lib::D<#lib::D::P, #lib::D::Q> + : #lib::D::foo = tt as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>, super #lib::C::•() + ; + method foo2(dynamic y) → dynamic { + if(y is #lib::A<#lib::D::P>) { + dart.core::print("21"); + } + if(y is #lib::C>) { + dart.core::print("22"); + } + [@vm.call-site-attributes.metadata=receiverType:#lib::D<#lib::D::P, #lib::D::Q>] this.{#lib::D::foo} = y as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>; + } + method foo3(dynamic z) → dynamic { + if(z is #lib::A<#lib::D::foo3::T1>) { + dart.core::print("31"); + } + if(z is #lib::C, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>) { + dart.core::print("32"); + } + return (z as dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>).{dart.core::Map::values}; + } + method foo4(dynamic w) → dart.core::Map<#lib::D::P, #lib::D::Q> { + dart.core::List> list = >[w as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>]; + return w as{TypeError} dart.core::Map<#lib::D::P, #lib::D::Q>; + } + } + class E

extends dart.core::Object { static factory •

() → #lib::E<#lib::E::•::P> return null; method foo6 = dart.core::List<#lib::E::P>>(dart.core::Map<#lib::E::foo6::T, #lib::E::foo6::U> map) → void {} diff --git a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart index 104d431f7e7..37071f97f4b 100644 --- a/runtime/tests/vm/dart/appjit_cha_deopt_test.dart +++ b/runtime/tests/vm/dart/appjit_cha_deopt_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. // OtherResources=appjit_cha_deopt_test_body.dart -// VMOptions=--optimization-counter-threshold=100 +// VMOptions=--optimization-counter-threshold=100 --deterministic // Verify that app-jit snapshot contains dependencies between classes and CHA // optimized code. diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc index 8c05417bd18..1b38ff7da4b 100644 --- a/runtime/vm/bootstrap.cc +++ b/runtime/vm/bootstrap.cc @@ -99,18 +99,10 @@ static RawError* BootstrapFromKernel(Thread* thread, // Load the bootstrap libraries in order (see object_store.h). Library& library = Library::Handle(zone); - String& dart_name = String::Handle(zone); for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) { ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index; library = isolate->object_store()->bootstrap_library(id); - dart_name = library.url(); - for (intptr_t j = 0; j < program->library_count(); ++j) { - const String& kernel_name = loader.LibraryUri(j); - if (kernel_name.Equals(dart_name)) { - loader.LoadLibrary(j); - break; - } - } + loader.LoadLibrary(library); } // Finish bootstrapping, including class finalization. @@ -125,8 +117,8 @@ static RawError* BootstrapFromKernel(Thread* thread, } // The builtin library should be registered with the VM. - dart_name = String::New("dart:_builtin"); - library = Library::LookupLibrary(thread, dart_name); + const auto& dart_builtin = String::Handle(zone, String::New("dart:_builtin")); + library = Library::LookupLibrary(thread, dart_builtin); isolate->object_store()->set_builtin_library(library); return Error::null(); diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc index 5b3fe6de69c..688f192e54a 100644 --- a/runtime/vm/class_finalizer.cc +++ b/runtime/vm/class_finalizer.cc @@ -1066,26 +1066,30 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) { } cls.set_is_type_finalized(); + RegisterClassInHierarchy(thread->zone(), cls); +} + +void ClassFinalizer::RegisterClassInHierarchy(Zone* zone, const Class& cls) { + auto& type = AbstractType::Handle(zone, cls.super_type()); + auto& other_cls = Class::Handle(zone); // Add this class to the direct subclasses of the superclass, unless the // superclass is Object. - if (!super_type.IsNull() && !super_type.IsObjectType()) { - ASSERT(!super_class.IsNull()); - super_class.AddDirectSubclass(cls); + if (!type.IsNull() && !type.IsObjectType()) { + other_cls = cls.SuperClass(); + ASSERT(!other_cls.IsNull()); + other_cls.AddDirectSubclass(cls); } // Add this class as an implementor to the implemented interface's type // classes. - Zone* zone = thread->zone(); - auto& interface_class = Class::Handle(zone); - const intptr_t mixin_index = cls.is_transformed_mixin_application() - ? interface_types.Length() - 1 - : -1; - for (intptr_t i = 0; i < interface_types.Length(); ++i) { - interface_type ^= interface_types.At(i); - interface_class = interface_type.type_class(); - MarkImplemented(thread->zone(), interface_class); - interface_class.AddDirectImplementor(cls, - /* is_mixin = */ i == mixin_index); + const auto& interfaces = Array::Handle(zone, cls.interfaces()); + const intptr_t mixin_index = + cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1; + for (intptr_t i = 0; i < interfaces.Length(); ++i) { + type ^= interfaces.At(i); + other_cls = type.type_class(); + MarkImplemented(zone, other_cls); + other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index); } } @@ -1113,9 +1117,14 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { #if !defined(DART_PRECOMPILED_RUNTIME) // If loading from a kernel, make sure that the class is fully loaded. - ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0)); + ASSERT(cls.IsTopLevel() || cls.is_declared_in_bytecode() || + (cls.kernel_offset() > 0)); if (!cls.is_loaded()) { - kernel::KernelLoader::FinishLoading(cls); + if (cls.is_declared_in_bytecode()) { + kernel::BytecodeReader::FinishClassLoading(cls); + } else { + kernel::KernelLoader::FinishLoading(cls); + } if (cls.is_finalized()) { return; } @@ -1180,6 +1189,14 @@ RawError* ClassFinalizer::LoadClassMembers(const Class& cls) { ASSERT(Thread::Current()->IsMutatorThread()); LongJumpScope jump; if (setjmp(*jump.Set()) == 0) { +#if !defined(DART_PRECOMPILED_RUNTIME) + if (!cls.is_declaration_loaded()) { + // Loading of class declaration can be postponed until needed + // if class comes from bytecode. + ASSERT(cls.is_declared_in_bytecode()); + kernel::BytecodeReader::LoadClassDeclaration(cls); + } +#endif // TODO(36584) : We expect is_type_finalized to be true for all classes // here, but with eager reading of the constant table we get into // situations where we see classes whose types have not been finalized yet, @@ -1241,7 +1258,7 @@ void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) { ->object_store() ->pending_unevaluated_const_fields()); - ASSERT(enum_cls.kernel_offset() > 0); + ASSERT(enum_cls.is_declared_in_bytecode() || enum_cls.kernel_offset() > 0); Error& error = Error::Handle(zone); for (intptr_t i = 0; i < fields.Length(); i++) { field = Field::RawCast(fields.At(i)); @@ -1419,7 +1436,7 @@ void ClassFinalizer::SortClasses() { continue; } cls = table->At(cid); - if (cls.is_patch()) { + if (cls.is_patch() || !cls.is_declaration_loaded()) { continue; } if (cls.SuperClass() == I->object_store()->object_class()) { diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h index 91292e99ec4..4a82e1c458c 100644 --- a/runtime/vm/class_finalizer.h +++ b/runtime/vm/class_finalizer.h @@ -57,6 +57,9 @@ class ClassFinalizer : public AllStatic { // is an anonymous top level class). static void FinalizeTypesInClass(const Class& cls); + // Register class in the lists of direct subclasses and direct implementors. + static void RegisterClassInHierarchy(Zone* zone, const Class& cls); + // Finalize the class including its fields and functions. static void FinalizeClass(const Class& cls); diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc index f8480910775..eade6cc6b73 100644 --- a/runtime/vm/clustered_snapshot.cc +++ b/runtime/vm/clustered_snapshot.cc @@ -178,7 +178,7 @@ class ClassSerializationCluster : public SerializationCluster { } s->WriteCid(class_id); if (s->kind() != Snapshot::kFullAOT) { - s->Write(cls->ptr()->kernel_offset_); + s->Write(cls->ptr()->binary_declaration_); } s->Write(cls->ptr()->instance_size_in_words_); s->Write(cls->ptr()->next_field_offset_in_words_); @@ -233,7 +233,7 @@ class ClassDeserializationCluster : public DeserializationCluster { cls->ptr()->id_ = class_id; #if !defined(DART_PRECOMPILED_RUNTIME) if (d->kind() != Snapshot::kFullAOT) { - cls->ptr()->kernel_offset_ = d->Read(); + cls->ptr()->binary_declaration_ = d->Read(); } #endif if (!RawObject::IsInternalVMdefinedClassId(class_id)) { @@ -264,7 +264,7 @@ class ClassDeserializationCluster : public DeserializationCluster { cls->ptr()->id_ = class_id; #if !defined(DART_PRECOMPILED_RUNTIME) if (d->kind() != Snapshot::kFullAOT) { - cls->ptr()->kernel_offset_ = d->Read(); + cls->ptr()->binary_declaration_ = d->Read(); } #endif cls->ptr()->instance_size_in_words_ = d->Read(); @@ -1176,7 +1176,7 @@ class LibrarySerializationCluster : public SerializationCluster { s->Write(lib->ptr()->is_dart_scheme_); s->Write(lib->ptr()->debuggable_); if (s->kind() != Snapshot::kFullAOT) { - s->Write(lib->ptr()->kernel_offset_); + s->Write(lib->ptr()->binary_declaration_); } } } @@ -1216,7 +1216,7 @@ class LibraryDeserializationCluster : public DeserializationCluster { lib->ptr()->is_in_fullsnapshot_ = true; #if !defined(DART_PRECOMPILED_RUNTIME) if (d->kind() != Snapshot::kFullAOT) { - lib->ptr()->kernel_offset_ = d->Read(); + lib->ptr()->binary_declaration_ = d->Read(); } #endif } @@ -1364,7 +1364,7 @@ class KernelProgramInfoDeserializationCluster : public DeserializationCluster { array = info.bytecode_component(); if (!array.IsNull()) { kernel::BytecodeReader::UseBytecodeVersion( - kernel::BytecodeComponentData(array).GetVersion()); + kernel::BytecodeComponentData(&array).GetVersion()); } } } diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc index 51b11021fa7..5d3ba7dff48 100644 --- a/runtime/vm/compiler/frontend/bytecode_reader.cc +++ b/runtime/vm/compiler/frontend/bytecode_reader.cc @@ -11,6 +11,7 @@ #include "vm/compiler/assembler/disassembler_kbc.h" #include "vm/compiler/frontend/bytecode_scope_builder.h" #include "vm/constants_kbc.h" +#include "vm/dart_api_impl.h" // For Api::IsFfiEnabled(). #include "vm/dart_entry.h" #include "vm/debugger.h" #include "vm/longjump.h" @@ -59,12 +60,14 @@ void BytecodeMetadataHelper::ParseBytecodeFunction( } BytecodeComponentData bytecode_component( - Array::Handle(helper_->zone_, GetBytecodeComponent())); + &Array::Handle(helper_->zone_, GetBytecodeComponent())); BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component); bytecode_reader.ParseBytecodeFunction(parsed_function, function); } +static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup support for old bytecode format versions"); bool BytecodeMetadataHelper::ReadMembers(intptr_t node_offset, const Class& cls, bool discard_fields) { @@ -80,18 +83,65 @@ bool BytecodeMetadataHelper::ReadMembers(intptr_t node_offset, ASSERT(Thread::Current()->IsMutatorThread()); BytecodeComponentData bytecode_component( - Array::Handle(helper_->zone_, GetBytecodeComponent())); + &Array::Handle(helper_->zone_, GetBytecodeComponent())); BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component); AlternativeReadingScope alt(&bytecode_reader.reader(), md_offset); - intptr_t members_offset = bytecode_reader.reader().ReadUInt(); + intptr_t members_offset = bytecode_component.GetMembersOffset() + + bytecode_reader.reader().ReadUInt(); - bytecode_reader.ReadMembers(cls, members_offset, discard_fields); + AlternativeReadingScope alt2(&bytecode_reader.reader(), members_offset); + + bytecode_reader.ReadMembers(cls, discard_fields); return true; } +bool BytecodeMetadataHelper::ReadLibraries() { + TIMELINE_DURATION(Thread::Current(), Compiler, + "BytecodeMetadataHelper::ReadLibraries"); + ASSERT(Thread::Current()->IsMutatorThread()); + + if (translation_helper_.GetBytecodeComponent() == Array::null()) { + return false; + } + + BytecodeComponentData bytecode_component( + &Array::Handle(helper_->zone_, GetBytecodeComponent())); + + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup condition"); + if (bytecode_component.GetVersion() < 10) { + return false; + } + + BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component); + AlternativeReadingScope alt(&bytecode_reader.reader(), + bytecode_component.GetLibraryIndexOffset()); + bytecode_reader.ReadLibraryDeclarations(bytecode_component.GetNumLibraries()); + return true; +} + +void BytecodeMetadataHelper::ReadLibrary(const Library& library) { + TIMELINE_DURATION(Thread::Current(), Compiler, + "BytecodeMetadataHelper::ReadLibrary"); + ASSERT(Thread::Current()->IsMutatorThread()); + ASSERT(!library.Loaded()); + + if (translation_helper_.GetBytecodeComponent() == Array::null()) { + return; + } + + BytecodeComponentData bytecode_component( + &Array::Handle(helper_->zone_, GetBytecodeComponent())); + BytecodeReaderHelper bytecode_reader(&H, active_class_, &bytecode_component); + AlternativeReadingScope alt(&bytecode_reader.reader(), + library.bytecode_offset()); + bytecode_reader.FindAndReadSpecificLibrary( + library, bytecode_component.GetNumLibraries()); +} + RawLibrary* BytecodeMetadataHelper::GetMainLibrary() { const intptr_t md_offset = GetComponentMetadataPayloadOffset(); if (md_offset < 0) { @@ -99,7 +149,7 @@ RawLibrary* BytecodeMetadataHelper::GetMainLibrary() { } BytecodeComponentData bytecode_component( - Array::Handle(helper_->zone_, GetBytecodeComponent())); + &Array::Handle(helper_->zone_, GetBytecodeComponent())); const intptr_t main_offset = bytecode_component.GetMainOffset(); if (main_offset == 0) { return Library::null(); @@ -976,6 +1026,23 @@ RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) { reader_.ReadUInt32(); // Skip main.numItems const intptr_t main_offset = start_offset + reader_.ReadUInt32(); + intptr_t num_libraries = 0; + intptr_t library_index_offset = 0; + intptr_t libraries_offset = 0; + intptr_t classes_offset = 0; + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup condition"); + if (version >= 10) { + num_libraries = reader_.ReadUInt32(); + library_index_offset = start_offset + reader_.ReadUInt32(); + + reader_.ReadUInt32(); // Skip libraries.numItems + libraries_offset = start_offset + reader_.ReadUInt32(); + + reader_.ReadUInt32(); // Skip classes.numItems + classes_offset = start_offset + reader_.ReadUInt32(); + } + reader_.ReadUInt32(); // Skip members.numItems const intptr_t members_offset = start_offset + reader_.ReadUInt32(); @@ -983,7 +1050,19 @@ RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) { const intptr_t codes_offset = start_offset + reader_.ReadUInt32(); reader_.ReadUInt32(); // Skip sourcePositions.numItems - const intptr_t sources_positions_offset = start_offset + reader_.ReadUInt32(); + const intptr_t source_positions_offset = start_offset + reader_.ReadUInt32(); + + intptr_t source_files_offset = 0; + intptr_t line_starts_offset = 0; + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup condition"); + if (version >= 10) { + reader_.ReadUInt32(); // Skip sourceFiles.numItems + source_files_offset = start_offset + reader_.ReadUInt32(); + + reader_.ReadUInt32(); // Skip lineStarts.numItems + line_starts_offset = start_offset + reader_.ReadUInt32(); + } intptr_t local_variables_offset = 0; static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 9, @@ -1012,14 +1091,16 @@ RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) { const intptr_t objects_contents_offset = reader_.offset(); reader_.set_offset(objects_contents_offset + objects_size); - const Array& bytecode_component_array = Array::Handle( + auto& bytecode_component_array = Array::Handle( Z, BytecodeComponentData::New( Z, version, num_objects, string_table_offset, strings_contents_offset, objects_contents_offset, main_offset, - members_offset, codes_offset, sources_positions_offset, + num_libraries, library_index_offset, libraries_offset, + classes_offset, members_offset, codes_offset, + source_positions_offset, source_files_offset, line_starts_offset, local_variables_offset, annotations_offset, Heap::kOld)); - BytecodeComponentData bytecode_component(bytecode_component_array); + BytecodeComponentData bytecode_component(&bytecode_component_array); // Read object offsets. Smi& offs = Smi::Handle(Z); @@ -1076,6 +1157,8 @@ RawString* BytecodeReaderHelper::ConstructorName(const Class& cls, RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { ASSERT(((header & kReferenceBit) == 0)); + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup obsolete object kinds"); // Must be in sync with enum ObjectKind in // pkg/vm/lib/bytecode/object_table.dart. enum ObjectKind { @@ -1084,15 +1167,17 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { kClass, kMember, kClosure, - kSimpleType, - kTypeParameter, - kGenericType, - kFunctionType, + kSimpleType, // obsolete in v10 + kTypeParameter, // obsolete in v10 + kGenericType, // obsolete in v10 + kFunctionType, // obsolete in v10 kName, kTypeArguments, - kFinalizedGenericType, + kFinalizedGenericType, // obsolete in v10 kConstObject, kArgDesc, + kScript, + kType, }; // Member flags, must be in sync with _MemberHandle constants in @@ -1105,6 +1190,8 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { const intptr_t kFlagIsDynamic = kFlagBit0; const intptr_t kFlagIsVoid = kFlagBit1; + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup old FunctionType flags"); // FunctionType flags, must be in sync with _FunctionTypeHandle constants in // pkg/vm/lib/bytecode/object_table.dart. const int kFlagHasOptionalPositionalParams = kFlagBit0; @@ -1116,6 +1203,10 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { const int kFlagHasNamedArgs = kFlagBit0; const int kFlagHasTypeArgs = kFlagBit1; + // Script flags, must be in sync with _ScriptHandle constants in + // pkg/vm/lib/bytecode/object_table.dart. + const int kFlagHasSourceFile = kFlagBit0; + const intptr_t kind = (header >> kKindShift) & kKindMask; const intptr_t flags = header & kFlagsMask; @@ -1124,7 +1215,14 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { UNREACHABLE(); break; case kLibrary: { - const String& uri = String::Handle(Z, ReadString()); + String& uri = String::Handle(Z); + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup condition"); + if (bytecode_component_->GetVersion() < 10) { + uri = ReadString(); + } else { + uri ^= ReadObject(); + } RawLibrary* library = Library::LookupLibrary(thread_, uri); if (library == Library::null()) { FATAL1("Unable to find library %s", uri.ToCString()); @@ -1135,9 +1233,15 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { const Library& library = Library::CheckedHandle(Z, ReadObject()); const String& class_name = String::CheckedHandle(Z, ReadObject()); if (class_name.raw() == Symbols::Empty().raw()) { - return library.toplevel_class(); + NoSafepointScope no_safepoint_scope(thread_); + RawClass* cls = library.toplevel_class(); + if (cls == Class::null()) { + FATAL1("Unable to find toplevel class %s", library.ToCString()); + } + return cls; } RawClass* cls = library.LookupClassAllowPrivate(class_name); + NoSafepointScope no_safepoint_scope(thread_); if (cls == Class::null()) { FATAL2("Unable to find class %s in %s", class_name.ToCString(), library.ToCString()); @@ -1149,6 +1253,7 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { String& name = String::CheckedHandle(Z, ReadObject()); if ((flags & kFlagIsField) != 0) { RawField* field = cls.LookupFieldAllowPrivate(name); + NoSafepointScope no_safepoint_scope(thread_); if (field == Field::null()) { FATAL2("Unable to find field %s in %s", name.ToCString(), cls.ToCString()); @@ -1164,6 +1269,10 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { return scoped_function_.raw(); } RawFunction* function = cls.LookupFunctionAllowPrivate(name); + { + // To verify that it's OK to hold raw function pointer at this point. + NoSafepointScope no_safepoint_scope(thread_); + } if (function == Function::null()) { // When requesting a getter, also return method extractors. if (Field::IsGetterName(name)) { @@ -1189,6 +1298,8 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { return closures_->At(closure_index); } case kSimpleType: { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup"); const Class& cls = Class::CheckedHandle(Z, ReadObject()); if ((flags & kFlagIsDynamic) != 0) { ASSERT(cls.IsNull()); @@ -1201,6 +1312,8 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { return cls.DeclarationType(); } case kTypeParameter: { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup"); Object& parent = Object::Handle(Z, ReadObject()); const intptr_t index_in_parent = reader_.ReadUInt(); TypeArguments& type_parameters = TypeArguments::Handle(Z); @@ -1228,14 +1341,18 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { return ClassFinalizer::FinalizeType(*active_class_->klass, type); } case kGenericType: { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup"); const Class& cls = Class::CheckedHandle(Z, ReadObject()); const TypeArguments& type_arguments = - TypeArguments::Handle(Z, ReadTypeArguments(Class::Handle(Z))); + TypeArguments::Handle(Z, ReadTypeArguments()); const Type& type = Type::Handle( Z, Type::New(cls, type_arguments, TokenPosition::kNoSource)); return ClassFinalizer::FinalizeType(*active_class_->klass, type); } case kFunctionType: { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup"); Function& signature_function = Function::ZoneHandle( Z, Function::NewSignatureFunction(*active_class_->klass, active_class_->enclosing != NULL @@ -1260,9 +1377,11 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { } } case kTypeArguments: { - return ReadTypeArguments(Class::Handle(Z)); + return ReadTypeArguments(); } case kFinalizedGenericType: { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup"); const Class& cls = Class::CheckedHandle(Z, ReadObject()); const TypeArguments& type_arguments = TypeArguments::CheckedHandle(Z, ReadObject()); @@ -1292,6 +1411,24 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { return ArgumentsDescriptor::New(num_type_args, num_arguments, array); } } + case kScript: { + const String& uri = String::CheckedHandle(Z, ReadObject()); + Script& script = Script::Handle(Z); + if ((flags & kFlagHasSourceFile) != 0) { + // TODO(alexmarkov): read source and line starts only when needed. + script = + ReadSourceFile(uri, bytecode_component_->GetSourceFilesOffset() + + reader_.ReadUInt()); + } else { + script = Script::New(uri, Object::null_string(), RawScript::kKernelTag); + } + script.set_kernel_program_info(H.GetKernelProgramInfo()); + return script.raw(); + } + case kType: { + const intptr_t tag = flags / kFlagBit0; + return ReadType(tag); + } default: UNREACHABLE(); } @@ -1409,6 +1546,140 @@ RawObject* BytecodeReaderHelper::ReadConstObject(intptr_t tag) { return Object::null(); } +RawObject* BytecodeReaderHelper::ReadType(intptr_t tag) { + // Must be in sync with enum TypeTag in + // pkg/vm/lib/bytecode/object_table.dart. + enum TypeTag { + kInvalid, + kDynamic, + kVoid, + kSimpleType, + kTypeParameter, + kGenericType, + kRecursiveGenericType, + kRecursiveTypeRef, + kFunctionType, + }; + + // FunctionType flags, must be in sync with _FunctionTypeHandle constants in + // pkg/vm/lib/bytecode/object_table.dart. + const int kFlagHasOptionalPositionalParams = 1 << 0; + const int kFlagHasOptionalNamedParams = 1 << 1; + const int kFlagHasTypeParams = 1 << 2; + + switch (tag) { + case kInvalid: + UNREACHABLE(); + break; + case kDynamic: + return AbstractType::dynamic_type().raw(); + case kVoid: + return AbstractType::void_type().raw(); + case kSimpleType: { + const Class& cls = Class::CheckedHandle(Z, ReadObject()); + if (!cls.is_declaration_loaded()) { + ASSERT(cls.is_declared_in_bytecode()); + BytecodeReader::LoadClassDeclaration(cls); + } + return cls.DeclarationType(); + } + case kTypeParameter: { + Object& parent = Object::Handle(Z, ReadObject()); + const intptr_t index_in_parent = reader_.ReadUInt(); + TypeArguments& type_parameters = TypeArguments::Handle(Z); + if (parent.IsClass()) { + type_parameters = Class::Cast(parent).type_parameters(); + } else if (parent.IsFunction()) { + if (Function::Cast(parent).IsFactory()) { + // For factory constructors VM uses type parameters of a class + // instead of constructor's type parameters. + parent = Function::Cast(parent).Owner(); + type_parameters = Class::Cast(parent).type_parameters(); + } else { + type_parameters = Function::Cast(parent).type_parameters(); + } + } else if (parent.IsNull()) { + ASSERT(function_type_type_parameters_ != nullptr); + type_parameters = function_type_type_parameters_->raw(); + } else { + UNREACHABLE(); + } + AbstractType& type = + AbstractType::Handle(Z, type_parameters.TypeAt(index_in_parent)); + // TODO(alexmarkov): skip type finalization + return ClassFinalizer::FinalizeType(*active_class_->klass, type); + } + case kGenericType: { + const Class& cls = Class::CheckedHandle(Z, ReadObject()); + if (!cls.is_declaration_loaded()) { + ASSERT(cls.is_declared_in_bytecode()); + BytecodeReader::LoadClassDeclaration(cls); + } + const TypeArguments& type_arguments = + TypeArguments::CheckedHandle(Z, ReadObject()); + const Type& type = Type::Handle( + Z, Type::New(cls, type_arguments, TokenPosition::kNoSource)); + type.SetIsFinalized(); + return type.Canonicalize(); + } + case kRecursiveGenericType: { + const intptr_t id = reader_.ReadUInt(); + const Class& cls = Class::CheckedHandle(Z, ReadObject()); + if (!cls.is_declaration_loaded()) { + ASSERT(cls.is_declared_in_bytecode()); + BytecodeReader::LoadClassDeclaration(cls); + } + const auto saved_pending_recursive_types = pending_recursive_types_; + if (id == 0) { + pending_recursive_types_ = &GrowableObjectArray::Handle( + Z, GrowableObjectArray::New(Heap::kOld)); + } + ASSERT(id == pending_recursive_types_->Length()); + const auto& type_ref = + TypeRef::Handle(Z, TypeRef::New(AbstractType::null_abstract_type())); + pending_recursive_types_->Add(type_ref); + + const TypeArguments& type_arguments = + TypeArguments::CheckedHandle(Z, ReadObject()); + + ASSERT(id == pending_recursive_types_->Length() - 1); + ASSERT(pending_recursive_types_->At(id) == type_ref.raw()); + pending_recursive_types_->SetLength(id); + pending_recursive_types_ = saved_pending_recursive_types; + + Type& type = Type::Handle( + Z, Type::New(cls, type_arguments, TokenPosition::kNoSource)); + type_ref.set_type(type); + type.SetIsFinalized(); + return type.Canonicalize(); + } + case kRecursiveTypeRef: { + const intptr_t id = reader_.ReadUInt(); + ASSERT(pending_recursive_types_ != nullptr); + ASSERT(pending_recursive_types_->Length() >= id); + return pending_recursive_types_->At(id); + } + case kFunctionType: { + const intptr_t flags = reader_.ReadUInt(); + Function& signature_function = Function::ZoneHandle( + Z, Function::NewSignatureFunction(*active_class_->klass, + active_class_->enclosing != NULL + ? *active_class_->enclosing + : Function::null_function(), + TokenPosition::kNoSource)); + // TODO(alexmarkov): skip type finalization + return ReadFunctionSignature( + signature_function, (flags & kFlagHasOptionalPositionalParams) != 0, + (flags & kFlagHasOptionalNamedParams) != 0, + (flags & kFlagHasTypeParams) != 0, + /* has_positional_param_names = */ false); + } + default: + UNREACHABLE(); + } + return Object::null(); +} + RawString* BytecodeReaderHelper::ReadString(bool is_canonical) { const int kFlagTwoByteString = 1; const int kHeaderFields = 2; @@ -1459,8 +1730,42 @@ RawString* BytecodeReaderHelper::ReadString(bool is_canonical) { } } -RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments( - const Class& instantiator) { +RawScript* BytecodeReaderHelper::ReadSourceFile(const String& uri, + intptr_t offset) { + // SourceFile flags, must be in sync with SourceFile constants in + // pkg/vm/lib/bytecode/declarations.dart. + const int kHasLineStartsFlag = 1 << 0; + const int kHasSourceFlag = 1 << 1; + + AlternativeReadingScope alt(&reader_, offset); + + const intptr_t flags = reader_.ReadUInt(); + const String& import_uri = String::CheckedHandle(Z, ReadObject()); + + TypedData& line_starts = TypedData::Handle(Z); + if ((flags & kHasLineStartsFlag) != 0) { + // TODO(alexmarkov): read line starts only when needed. + const intptr_t line_starts_offset = + bytecode_component_->GetLineStartsOffset() + reader_.ReadUInt(); + + AlternativeReadingScope alt(&reader_, line_starts_offset); + + const intptr_t num_line_starts = reader_.ReadUInt(); + line_starts = reader_.ReadLineStartsData(num_line_starts); + } + + String& source = String::Handle(Z); + if ((flags & kHasSourceFlag) != 0) { + source = ReadString(/* is_canonical = */ false); + } + + const Script& script = Script::Handle( + Z, Script::New(import_uri, uri, source, RawScript::kKernelTag)); + script.set_line_starts(line_starts); + return script.raw(); +} + +RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments() { const intptr_t length = reader_.ReadUInt(); TypeArguments& type_arguments = TypeArguments::ZoneHandle(Z, TypeArguments::New(length)); @@ -1469,36 +1774,14 @@ RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments( type ^= ReadObject(); type_arguments.SetTypeAt(i, type); } - - type_arguments = type_arguments.Canonicalize(); - - if (instantiator.IsNull()) { - return type_arguments.raw(); - } - - if (type_arguments.IsNull() && instantiator.NumTypeArguments() == length) { - return type_arguments.raw(); - } - - // We make a temporary [Type] object and use `ClassFinalizer::FinalizeType` to - // finalize the argument types. - // (This can for example make the [type_arguments] vector larger) - type = Type::New(instantiator, type_arguments, TokenPosition::kNoSource); - type = ClassFinalizer::FinalizeType(*active_class_->klass, type); - return type.arguments(); + return type_arguments.Canonicalize(); } -void BytecodeReaderHelper::ReadMembers(const Class& cls, - intptr_t members_offset, - bool discard_fields) { +void BytecodeReaderHelper::ReadMembers(const Class& cls, bool discard_fields) { ASSERT(Thread::Current()->IsMutatorThread()); ASSERT(cls.is_type_finalized()); ASSERT(!cls.is_loaded()); - const intptr_t offset = - bytecode_component_->GetMembersOffset() + members_offset; - AlternativeReadingScope alt_md(&reader_, offset); - const intptr_t num_functions = reader_.ReadUInt(); functions_ = &Array::Handle(Z, Array::New(num_functions, Heap::kOld)); function_index_ = 0; @@ -1917,6 +2200,263 @@ void BytecodeReaderHelper::ReadFunctionDeclarations(const Class& cls) { functions_ = nullptr; } +void BytecodeReaderHelper::ReadClassDeclaration(const Class& cls) { + // Class flags, must be in sync with ClassDeclaration constants in + // pkg/vm/lib/bytecode/declarations.dart. + const int kIsAbstractFlag = 1 << 0; + const int kIsEnumFlag = 1 << 1; + const int kHasTypeParamsFlag = 1 << 2; + const int kHasTypeArgumentsFlag = 1 << 3; + const int kIsTransformedMixinApplicationFlag = 1 << 4; + const int kHasSourcePositionsFlag = 1 << 5; + const int kHasAnnotationsFlag = 1 << 6; + const int kHasPragmaFlag = 1 << 7; + + // Class is allocated when reading library declaration in + // BytecodeReaderHelper::ReadLibraryDeclaration. + // Its cid is set in Class::New / Isolate::RegisterClass / + // ClassTable::Register, unless it was loaded for expression evaluation. + ASSERT(cls.is_declared_in_bytecode()); + ASSERT(!cls.is_declaration_loaded()); + + const intptr_t flags = reader_.ReadUInt(); + const bool has_pragma = (flags & kHasPragmaFlag) != 0; + + // Set early to enable access to type_parameters(). + cls.set_is_declaration_loaded(); + + const auto& script = Script::CheckedHandle(Z, ReadObject()); + cls.set_script(script); + + TokenPosition position = TokenPosition::kNoSource; + if ((flags & kHasSourcePositionsFlag) != 0) { + position = reader_.ReadPosition(); + reader_.ReadPosition(); // end_position + cls.set_token_pos(position); + } + + cls.set_has_pragma(has_pragma); + + if ((flags & kIsAbstractFlag) != 0) { + cls.set_is_abstract(); + } + if ((flags & kIsEnumFlag) != 0) { + cls.set_is_enum_class(); + } + if ((flags & kIsTransformedMixinApplicationFlag) != 0) { + cls.set_is_transformed_mixin_application(); + } + + intptr_t num_type_arguments = 0; + if ((flags & kHasTypeArgumentsFlag) != 0) { + num_type_arguments = reader_.ReadUInt(); + } + cls.set_num_type_arguments(num_type_arguments); + + if ((flags & kHasTypeParamsFlag) != 0) { + ReadTypeParametersDeclaration(cls, Function::null_function()); + } + + auto& type = AbstractType::CheckedHandle(Z, ReadObject()); + cls.set_super_type(type); + + const intptr_t num_interfaces = reader_.ReadUInt(); + if (num_interfaces > 0) { + const auto& interfaces = + Array::Handle(Z, Array::New(num_interfaces, Heap::kOld)); + for (intptr_t i = 0; i < num_interfaces; ++i) { + type ^= ReadObject(); + interfaces.SetAt(i, type); + } + cls.set_interfaces(interfaces); + } + + if ((flags & kHasAnnotationsFlag) != 0) { + intptr_t annotations_offset = + reader_.ReadUInt() + bytecode_component_->GetAnnotationsOffset(); + ASSERT(annotations_offset > 0); + + if (FLAG_enable_mirrors || has_pragma) { + const auto& library = Library::Handle(Z, cls.library()); + if (cls.IsTopLevel()) { + ASSERT(!has_pragma); + library.AddLibraryMetadata(cls, TokenPosition::kNoSource, 0, + annotations_offset); + } else { + const auto& top_level_class = + Class::Handle(Z, library.toplevel_class()); + + library.AddClassMetadata(cls, top_level_class, TokenPosition::kNoSource, + 0, annotations_offset); + if (has_pragma) { + // TODO(alexmarkov): read annotations right away using + // annotations_offset. + NoOOBMessageScope no_msg_scope(thread_); + NoReloadScope no_reload_scope(thread_->isolate(), thread_); + library.GetMetadata(cls); + } + } + } + } + + const intptr_t members_offset = reader_.ReadUInt(); + cls.set_bytecode_offset(members_offset + + bytecode_component_->GetMembersOffset()); + + // All types are finalized if loading from bytecode. + cls.set_is_type_finalized(); + + // TODO(alexmarkov): move this to class finalization. + ClassFinalizer::RegisterClassInHierarchy(Z, cls); +} + +void BytecodeReaderHelper::ReadLibraryDeclaration(const Library& library, + bool lookup_classes) { + // Library flags, must be in sync with LibraryDeclaration constants in + // pkg/vm/lib/bytecode/declarations.dart. + const int kUsesDartMirrorsFlag = 1 << 0; + const int kUsesDartFfiFlag = 1 << 1; + + ASSERT(library.is_declared_in_bytecode()); + ASSERT(!library.Loaded()); + ASSERT(library.toplevel_class() == Object::null()); + + // TODO(alexmarkov): fill in library.owned_scripts. + // + // TODO(alexmarkov): figure out if we need to finish class loading immediately + // in case of 'loading_native_wrappers_library_ ' or '!register_class'. + // + // TODO(alexmarkov): support native extension libraries. + // + + const intptr_t flags = reader_.ReadUInt(); + if (((flags & kUsesDartMirrorsFlag) != 0) && !FLAG_enable_mirrors) { + H.ReportError("import of dart:mirrors with --enable-mirrors=false"); + } + if (((flags & kUsesDartFfiFlag) != 0) && !Api::IsFfiEnabled()) { + H.ReportError("import of dart:ffi with --enable-ffi=false"); + } + + auto& name = String::CheckedHandle(Z, ReadObject()); + library.SetName(name); + + const auto& script = Script::CheckedHandle(Z, ReadObject()); + + // The bootstrapper will take care of creating the native wrapper classes, + // but we will add the synthetic constructors to them here. + if (name.raw() == + Symbols::Symbol(Symbols::kDartNativeWrappersLibNameId).raw()) { + ASSERT(library.LoadInProgress()); + loading_native_wrappers_library_ = true; + } else { + loading_native_wrappers_library_ = false; + library.SetLoadInProgress(); + } + + const bool register_class = !IsExpressionEvaluationLibrary(library); + + const intptr_t num_classes = reader_.ReadUInt(); + ASSERT(num_classes > 0); + auto& cls = Class::Handle(Z); + + for (intptr_t i = 0; i < num_classes; ++i) { + name ^= ReadObject(); + const intptr_t class_offset = + bytecode_component_->GetClassesOffset() + reader_.ReadUInt(); + + if (i == 0) { + ASSERT(name.raw() == Symbols::Empty().raw()); + cls = Class::New(library, Symbols::TopLevel(), script, + TokenPosition::kNoSource, register_class); + if (register_class) { + library.set_toplevel_class(cls); + } + } else { + if (lookup_classes) { + cls = library.LookupClassAllowPrivate(name); + } + if (lookup_classes && !cls.IsNull()) { + ASSERT(!cls.is_declaration_loaded()); + cls.set_script(script); + } else { + cls = Class::New(library, name, script, TokenPosition::kNoSource, + register_class); + if (register_class) { + library.AddClass(cls); + } + } + } + + cls.set_is_declared_in_bytecode(true); + cls.set_bytecode_offset(class_offset); + } + + ASSERT(!library.Loaded()); + library.SetLoaded(); + + loading_native_wrappers_library_ = false; +} + +void BytecodeReaderHelper::ReadLibraryDeclarations(intptr_t num_libraries) { + auto& library = Library::Handle(Z); + auto& uri = String::Handle(Z); + + for (intptr_t i = 0; i < num_libraries; ++i) { + uri ^= ReadObject(); + const intptr_t library_offset = + bytecode_component_->GetLibrariesOffset() + reader_.ReadUInt(); + + if (!FLAG_precompiled_mode && !I->should_load_vmservice()) { + if (uri.raw() == Symbols::DartVMServiceIO().raw()) { + continue; + } + } + + bool lookup_classes = true; + library = Library::LookupLibrary(thread_, uri); + if (library.IsNull()) { + lookup_classes = false; + library = Library::New(uri); + + if (uri.raw() == Symbols::EvalSourceUri().raw()) { + ASSERT(expression_evaluation_library_ == nullptr); + expression_evaluation_library_ = &Library::Handle(Z, library.raw()); + } else { + library.Register(thread_); + } + } + + if (library.Loaded()) { + continue; + } + + library.set_is_declared_in_bytecode(true); + library.set_bytecode_offset(library_offset); + + AlternativeReadingScope alt(&reader_, library_offset); + ReadLibraryDeclaration(library, lookup_classes); + } +} + +void BytecodeReaderHelper::FindAndReadSpecificLibrary(const Library& library, + intptr_t num_libraries) { + auto& uri = String::Handle(Z); + for (intptr_t i = 0; i < num_libraries; ++i) { + uri ^= ReadObject(); + const intptr_t library_offset = + bytecode_component_->GetLibrariesOffset() + reader_.ReadUInt(); + + if (uri.raw() == library.url()) { + library.set_is_declared_in_bytecode(true); + library.set_bytecode_offset(library_offset); + + AlternativeReadingScope alt(&reader_, library_offset); + ReadLibraryDeclaration(library, /* lookup_classes = */ true); + return; + } + } +} + void BytecodeReaderHelper::ReadParameterCovariance( const Function& function, BitVector* is_covariant, @@ -2153,6 +2693,22 @@ intptr_t BytecodeComponentData::GetMainOffset() const { return Smi::Value(Smi::RawCast(data_.At(kMainOffset))); } +intptr_t BytecodeComponentData::GetNumLibraries() const { + return Smi::Value(Smi::RawCast(data_.At(kNumLibraries))); +} + +intptr_t BytecodeComponentData::GetLibraryIndexOffset() const { + return Smi::Value(Smi::RawCast(data_.At(kLibraryIndexOffset))); +} + +intptr_t BytecodeComponentData::GetLibrariesOffset() const { + return Smi::Value(Smi::RawCast(data_.At(kLibrariesOffset))); +} + +intptr_t BytecodeComponentData::GetClassesOffset() const { + return Smi::Value(Smi::RawCast(data_.At(kClassesOffset))); +} + intptr_t BytecodeComponentData::GetMembersOffset() const { return Smi::Value(Smi::RawCast(data_.At(kMembersOffset))); } @@ -2165,6 +2721,14 @@ intptr_t BytecodeComponentData::GetSourcePositionsOffset() const { return Smi::Value(Smi::RawCast(data_.At(kSourcePositionsOffset))); } +intptr_t BytecodeComponentData::GetSourceFilesOffset() const { + return Smi::Value(Smi::RawCast(data_.At(kSourceFilesOffset))); +} + +intptr_t BytecodeComponentData::GetLineStartsOffset() const { + return Smi::Value(Smi::RawCast(data_.At(kLineStartsOffset))); +} + intptr_t BytecodeComponentData::GetLocalVariablesOffset() const { return Smi::Value(Smi::RawCast(data_.At(kLocalVariablesOffset))); } @@ -2188,9 +2752,15 @@ RawArray* BytecodeComponentData::New(Zone* zone, intptr_t strings_contents_offset, intptr_t objects_contents_offset, intptr_t main_offset, + intptr_t num_libraries, + intptr_t library_index_offset, + intptr_t libraries_offset, + intptr_t classes_offset, intptr_t members_offset, intptr_t codes_offset, intptr_t source_positions_offset, + intptr_t source_files_offset, + intptr_t line_starts_offset, intptr_t local_variables_offset, intptr_t annotations_offset, Heap::Space space) { @@ -2213,6 +2783,18 @@ RawArray* BytecodeComponentData::New(Zone* zone, smi_handle = Smi::New(main_offset); data.SetAt(kMainOffset, smi_handle); + smi_handle = Smi::New(num_libraries); + data.SetAt(kNumLibraries, smi_handle); + + smi_handle = Smi::New(library_index_offset); + data.SetAt(kLibraryIndexOffset, smi_handle); + + smi_handle = Smi::New(libraries_offset); + data.SetAt(kLibrariesOffset, smi_handle); + + smi_handle = Smi::New(classes_offset); + data.SetAt(kClassesOffset, smi_handle); + smi_handle = Smi::New(members_offset); data.SetAt(kMembersOffset, smi_handle); @@ -2222,6 +2804,12 @@ RawArray* BytecodeComponentData::New(Zone* zone, smi_handle = Smi::New(source_positions_offset); data.SetAt(kSourcePositionsOffset, smi_handle); + smi_handle = Smi::New(source_files_offset); + data.SetAt(kSourceFilesOffset, smi_handle); + + smi_handle = Smi::New(line_starts_offset); + data.SetAt(kLineStartsOffset, smi_handle); + smi_handle = Smi::New(local_variables_offset); data.SetAt(kLocalVariablesOffset, smi_handle); @@ -2303,7 +2891,7 @@ RawError* BytecodeReader::ReadFunctionBytecode(Thread* thread, ActiveClass active_class; BytecodeComponentData bytecode_component( - Array::Handle(zone, translation_helper.GetBytecodeComponent())); + &Array::Handle(zone, translation_helper.GetBytecodeComponent())); ASSERT(!bytecode_component.IsNull()); BytecodeReaderHelper bytecode_reader( &translation_helper, &active_class, &bytecode_component); @@ -2343,7 +2931,7 @@ RawError* BytecodeReader::ReadFunctionBytecode(Thread* thread, zone); BytecodeComponentData bytecode_component( - Array::Handle(zone, translation_helper.GetBytecodeComponent())); + &Array::Handle(zone, translation_helper.GetBytecodeComponent())); ASSERT(!bytecode_component.IsNull()); BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class, &bytecode_component); @@ -2371,7 +2959,7 @@ RawObject* BytecodeReader::ReadAnnotation(const Field& annotation_field) { ActiveClass active_class; BytecodeComponentData bytecode_component( - Array::Handle(zone, translation_helper.GetBytecodeComponent())); + &Array::Handle(zone, translation_helper.GetBytecodeComponent())); ASSERT(!bytecode_component.IsNull()); BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class, &bytecode_component); @@ -2382,6 +2970,65 @@ RawObject* BytecodeReader::ReadAnnotation(const Field& annotation_field) { return bytecode_reader.ReadObject(); } +void BytecodeReader::LoadClassDeclaration(const Class& cls) { + TIMELINE_DURATION(Thread::Current(), Compiler, + "BytecodeReader::LoadClassDeclaration"); + + ASSERT(cls.is_declared_in_bytecode()); + ASSERT(!cls.is_declaration_loaded()); + + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + ASSERT(thread->IsMutatorThread()); + + const Script& script = Script::Handle(zone, cls.script()); + TranslationHelper translation_helper(thread); + translation_helper.InitFromScript(script); + + ActiveClass active_class; + ActiveClassScope active_class_scope(&active_class, &cls); + + BytecodeComponentData bytecode_component( + &Array::Handle(zone, translation_helper.GetBytecodeComponent())); + ASSERT(!bytecode_component.IsNull()); + BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class, + &bytecode_component); + + AlternativeReadingScope alt(&bytecode_reader.reader(), cls.bytecode_offset()); + + bytecode_reader.ReadClassDeclaration(cls); +} + +void BytecodeReader::FinishClassLoading(const Class& cls) { + ASSERT(cls.is_declared_in_bytecode()); + + Thread* thread = Thread::Current(); + Zone* zone = thread->zone(); + ASSERT(thread->IsMutatorThread()); + + const Script& script = Script::Handle(zone, cls.script()); + TranslationHelper translation_helper(thread); + translation_helper.InitFromScript(script); + + ActiveClass active_class; + ActiveClassScope active_class_scope(&active_class, &cls); + + BytecodeComponentData bytecode_component( + &Array::Handle(zone, translation_helper.GetBytecodeComponent())); + ASSERT(!bytecode_component.IsNull()); + BytecodeReaderHelper bytecode_reader(&translation_helper, &active_class, + &bytecode_component); + + AlternativeReadingScope alt(&bytecode_reader.reader(), cls.bytecode_offset()); + + // If this is a dart:internal.ClassID class ignore field declarations + // contained in the Kernel file and instead inject our own const + // fields. + const bool discard_fields = cls.InjectCIDFields(); + + bytecode_reader.ReadMembers(cls, discard_fields); +} + #if !defined(PRODUCT) RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors( Zone* zone, diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h index 830bf95da79..1a8440cbc60 100644 --- a/runtime/vm/compiler/frontend/bytecode_reader.h +++ b/runtime/vm/compiler/frontend/bytecode_reader.h @@ -25,13 +25,18 @@ class BytecodeMetadataHelper : public MetadataHelper { ActiveClass* active_class); void ParseBytecodeFunction(ParsedFunction* parsed_function); - void ParseBytecodeImplicitClosureFunction(ParsedFunction* parsed_function); // Reads members associated with given [node_offset] and fills in [cls]. // Discards fields if [discard_fields] is true. // Returns true if class members are loaded. bool ReadMembers(intptr_t node_offset, const Class& cls, bool discard_fields); + // Read all library declarations. + bool ReadLibraries(); + + // Read specific library declaration. + void ReadLibrary(const Library& library); + RawLibrary* GetMainLibrary(); RawArray* GetBytecodeComponent(); @@ -56,12 +61,15 @@ class BytecodeReaderHelper : public ValueObject { RawArray* CreateForwarderChecks(const Function& function); - void ReadMembers(const Class& cls, - intptr_t members_offset, - bool discard_fields); + void ReadMembers(const Class& cls, bool discard_fields); void ReadFieldDeclarations(const Class& cls, bool discard_fields); void ReadFunctionDeclarations(const Class& cls); + void ReadClassDeclaration(const Class& cls); + void ReadLibraryDeclaration(const Library& library, bool lookup_classes); + void ReadLibraryDeclarations(intptr_t num_libraries); + void FindAndReadSpecificLibrary(const Library& library, + intptr_t num_libraries); void ParseBytecodeFunction(ParsedFunction* parsed_function, const Function& function); @@ -186,13 +194,20 @@ class BytecodeReaderHelper : public ValueObject { RawObject* ReadObjectContents(uint32_t header); RawObject* ReadConstObject(intptr_t tag); + RawObject* ReadType(intptr_t tag); RawString* ReadString(bool is_canonical = true); - RawTypeArguments* ReadTypeArguments(const Class& instantiator); + RawScript* ReadSourceFile(const String& uri, intptr_t offset); + RawTypeArguments* ReadTypeArguments(); RawPatchClass* GetPatchClass(const Class& cls, const Script& script); void ParseForwarderFunction(ParsedFunction* parsed_function, const Function& function, const Function& target); + bool IsExpressionEvaluationLibrary(const Library& library) const { + return expression_evaluation_library_ != nullptr && + expression_evaluation_library_->raw() == library.raw(); + } + Reader reader_; TranslationHelper& translation_helper_; ActiveClass* const active_class_; @@ -201,12 +216,15 @@ class BytecodeReaderHelper : public ValueObject { BytecodeComponentData* const bytecode_component_; Array* closures_ = nullptr; const TypeArguments* function_type_type_parameters_ = nullptr; + GrowableObjectArray* pending_recursive_types_ = nullptr; PatchClass* patch_class_ = nullptr; Array* functions_ = nullptr; intptr_t function_index_ = 0; Function& scoped_function_; String& scoped_function_name_; Class& scoped_function_class_; + Library* expression_evaluation_library_ = nullptr; + bool loading_native_wrappers_library_ = false; DISALLOW_COPY_AND_ASSIGN(BytecodeReaderHelper); }; @@ -219,24 +237,38 @@ class BytecodeComponentData : ValueObject { kStringsContentsOffset, kObjectsContentsOffset, kMainOffset, + kNumLibraries, + kLibraryIndexOffset, + kLibrariesOffset, + kClassesOffset, kMembersOffset, kCodesOffset, kSourcePositionsOffset, + kSourceFilesOffset, + kLineStartsOffset, kLocalVariablesOffset, kAnnotationsOffset, kNumFields }; - explicit BytecodeComponentData(const Array& data) : data_(data) {} + explicit BytecodeComponentData(Array* data) : data_(*data) {} + + void Init(const Array& data) { data_ = data.raw(); } intptr_t GetVersion() const; intptr_t GetStringsHeaderOffset() const; intptr_t GetStringsContentsOffset() const; intptr_t GetObjectsContentsOffset() const; intptr_t GetMainOffset() const; + intptr_t GetNumLibraries() const; + intptr_t GetLibraryIndexOffset() const; + intptr_t GetLibrariesOffset() const; + intptr_t GetClassesOffset() const; intptr_t GetMembersOffset() const; intptr_t GetCodesOffset() const; intptr_t GetSourcePositionsOffset() const; + intptr_t GetSourceFilesOffset() const; + intptr_t GetLineStartsOffset() const; intptr_t GetLocalVariablesOffset() const; intptr_t GetAnnotationsOffset() const; void SetObject(intptr_t index, const Object& obj) const; @@ -251,15 +283,21 @@ class BytecodeComponentData : ValueObject { intptr_t strings_contents_offset, intptr_t objects_contents_offset, intptr_t main_offset, + intptr_t num_libraries, + intptr_t library_index_offset, + intptr_t libraries_offset, + intptr_t classes_offset, intptr_t members_offset, intptr_t codes_offset, intptr_t source_positions_offset, + intptr_t source_files_offset, + intptr_t line_starts_offset, intptr_t local_variables_offset, intptr_t annotations_offset, Heap::Space space); private: - const Array& data_; + Array& data_; }; class BytecodeReader : public AllStatic { @@ -272,6 +310,15 @@ class BytecodeReader : public AllStatic { // Read annotation for the given annotation field. static RawObject* ReadAnnotation(const Field& annotation_field); + // Read declaration of the given library. + static void LoadLibraryDeclaration(const Library& library); + + // Read declaration of the given class. + static void LoadClassDeclaration(const Class& cls); + + // Read members of the given class. + static void FinishClassLoading(const Class& cls); + #if !defined(PRODUCT) // Compute local variable descriptors for [function] with [bytecode]. static RawLocalVarDescriptors* ComputeLocalVarDescriptors( diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc index 0306907541d..8fa57999450 100644 --- a/runtime/vm/compiler/frontend/kernel_to_il.cc +++ b/runtime/vm/compiler/frontend/kernel_to_il.cc @@ -724,9 +724,17 @@ FlowGraph* FlowGraphBuilder::BuildGraph() { info.potential_natives() == GrowableObjectArray::null()); #endif + auto& kernel_data = ExternalTypedData::Handle(Z); + intptr_t kernel_data_program_offset = 0; + if (!function.is_declared_in_bytecode()) { + kernel_data = function.KernelData(); + kernel_data_program_offset = function.KernelDataProgramOffset(); + } + + // TODO(alexmarkov): refactor this - StreamingFlowGraphBuilder should not be + // used for bytecode functions. StreamingFlowGraphBuilder streaming_flow_graph_builder( - this, ExternalTypedData::Handle(Z, function.KernelData()), - function.KernelDataProgramOffset()); + this, kernel_data, kernel_data_program_offset); return streaming_flow_graph_builder.BuildGraph(); } diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc index bd50a0f7db8..35c0178fdd0 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc @@ -2561,47 +2561,8 @@ RawTypedData* KernelReaderHelper::GetLineStartsFor(intptr_t index) { SetOffset(GetOffsetForSourceInfo(index)); SkipBytes(ReadUInt()); // skip uri. SkipBytes(ReadUInt()); // skip source. - const intptr_t line_start_count = ReadUInt(); // read number of line start - // entries. - MallocGrowableArray line_starts_array; - - intptr_t max_delta = 0; - for (intptr_t i = 0; i < line_start_count; ++i) { - int32_t delta = ReadUInt(); - line_starts_array.Add(delta); - if (delta > max_delta) { - max_delta = delta; - } - } - - intptr_t cid; - if (max_delta <= kMaxInt8) { - cid = kTypedDataInt8ArrayCid; - } else if (max_delta <= kMaxInt16) { - cid = kTypedDataInt16ArrayCid; - } else { - cid = kTypedDataInt32ArrayCid; - } - - TypedData& line_starts_data = - TypedData::Handle(Z, TypedData::New(cid, line_start_count, Heap::kOld)); - for (intptr_t j = 0; j < line_start_count; ++j) { - int32_t line_start = line_starts_array[j]; - switch (cid) { - case kTypedDataInt8ArrayCid: - line_starts_data.SetInt8(j, static_cast(line_start)); - break; - case kTypedDataInt16ArrayCid: - line_starts_data.SetInt16(j << 1, static_cast(line_start)); - break; - case kTypedDataInt32ArrayCid: - line_starts_data.SetInt32(j << 2, line_start); - break; - default: - UNREACHABLE(); - } - } - return line_starts_data.raw(); + const intptr_t line_start_count = ReadUInt(); + return reader_.ReadLineStartsData(line_start_count); } String& KernelReaderHelper::SourceTableImportUriFor(intptr_t index, @@ -2787,8 +2748,7 @@ void TypeTranslator::BuildInterfaceType(bool simple) { } else { // Note that the type argument vector is not yet extended. result_ = - Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()), - klass.token_pos()); + Type::New(klass, Object::null_type_arguments(), klass.token_pos()); } return; } diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h index ad4898cd5a1..1dc3f3c406e 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.h +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h @@ -62,6 +62,7 @@ class TranslationHelper { RawGrowableObjectArray* EnsurePotentialPragmaFunctions(); void SetKernelProgramInfo(const KernelProgramInfo& info); + const KernelProgramInfo& GetKernelProgramInfo() const { return info_; } intptr_t StringOffset(StringIndex index) const; intptr_t StringSize(StringIndex index) const; diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index 12d8bd24383..5c422d86459 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -749,7 +749,7 @@ class KernelBytecode { // Maximum bytecode format version supported by VM. // The range of supported versions should include version produced by bytecode // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart). - static const intptr_t kMaxSupportedBytecodeFormatVersion = 9; + static const intptr_t kMaxSupportedBytecodeFormatVersion = 10; enum Opcode { #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name, diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index f40c90b146f..a341cad4793 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -569,10 +569,6 @@ void Exceptions::JumpToFrame(Thread* thread, uword stack_pointer, uword frame_pointer, bool clear_deopt_at_target) { - uword fp_for_clearing = - (clear_deopt_at_target ? frame_pointer + 1 : frame_pointer); - ClearLazyDeopts(thread, fp_for_clearing); - #if !defined(DART_PRECOMPILED_RUNTIME) // TODO(regis): We still possibly need to unwind interpreter frames if they // are callee frames of the C++ frame handling the exception. @@ -585,6 +581,10 @@ void Exceptions::JumpToFrame(Thread* thread, } #endif // !defined(DART_PRECOMPILED_RUNTIME) + const uword fp_for_clearing = + (clear_deopt_at_target ? frame_pointer + 1 : frame_pointer); + ClearLazyDeopts(thread, fp_for_clearing); + #if defined(USING_SIMULATOR) // Unwinding of the C++ frames and destroying of their stack resources is done // by the simulator, because the target stack_pointer is a simulated stack diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc index b16d1b3a190..160e8a97371 100644 --- a/runtime/vm/kernel.cc +++ b/runtime/vm/kernel.cc @@ -352,6 +352,16 @@ void CollectTokenPositionsFor(const Script& interesting_script) { if (klass.script() == interesting_script.raw()) { token_positions.Add(klass.token_pos().value()); } + // If class is declared in bytecode, its members should be loaded + // (via class finalization) before their token positions could be + // collected. + if (klass.is_declared_in_bytecode() && !klass.is_finalized()) { + const Error& error = + Error::Handle(zone, klass.EnsureIsFinalized(thread)); + if (!error.IsNull()) { + Exceptions::PropagateError(error); + } + } if (klass.is_finalized()) { temp_array = klass.fields(); for (intptr_t i = 0; i < temp_array.Length(); ++i) { @@ -403,6 +413,7 @@ void CollectTokenPositionsFor(const Script& interesting_script) { } } else { // Class isn't finalized yet: read the data attached to it. + ASSERT(!klass.is_declared_in_bytecode()); ASSERT(klass.kernel_offset() > 0); data = lib.kernel_data(); ASSERT(!data.IsNull()); diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc index d3f28383ae7..d974b31e456 100644 --- a/runtime/vm/kernel_binary.cc +++ b/runtime/vm/kernel_binary.cc @@ -29,6 +29,50 @@ const char* Reader::TagName(Tag tag) { return "Unknown"; } +RawTypedData* Reader::ReadLineStartsData(intptr_t line_start_count) { + TypedData& line_starts_data = TypedData::Handle( + TypedData::New(kTypedDataInt8ArrayCid, line_start_count, Heap::kOld)); + + const intptr_t start_offset = offset(); + intptr_t i = 0; + for (; i < line_start_count; ++i) { + const intptr_t delta = ReadUInt(); + if (delta > kMaxInt8) { + break; + } + line_starts_data.SetInt8(i, static_cast(delta)); + } + + if (i < line_start_count) { + // Slow path: choose representation between Int16 and Int32 typed data. + set_offset(start_offset); + intptr_t max_delta = 0; + for (intptr_t i = 0; i < line_start_count; ++i) { + const intptr_t delta = ReadUInt(); + if (delta > max_delta) { + max_delta = delta; + } + } + + ASSERT(max_delta > kMaxInt8); + const intptr_t cid = (max_delta <= kMaxInt16) ? kTypedDataInt16ArrayCid + : kTypedDataInt32ArrayCid; + line_starts_data = TypedData::New(cid, line_start_count, Heap::kOld); + + set_offset(start_offset); + for (intptr_t i = 0; i < line_start_count; ++i) { + const intptr_t delta = ReadUInt(); + if (cid == kTypedDataInt16ArrayCid) { + line_starts_data.SetInt16(i << 1, static_cast(delta)); + } else { + line_starts_data.SetInt32(i << 2, delta); + } + } + } + + return line_starts_data.raw(); +} + const char* kKernelInvalidFilesize = "File size is too small to be a valid kernel file"; const char* kKernelInvalidMagicIdentifier = "Invalid magic identifier"; diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index 8b99273fa39..00c119f5a7b 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -366,6 +366,8 @@ class Reader : public ValueObject { return &buffer()[offset]; } + RawTypedData* ReadLineStartsData(intptr_t line_start_count); + private: const uint8_t* buffer() const { if (raw_buffer_ != NULL) { diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc index 4f60e0f71e2..d37c67d2bd7 100644 --- a/runtime/vm/kernel_loader.cc +++ b/runtime/vm/kernel_loader.cc @@ -659,6 +659,7 @@ void KernelLoader::LoadNativeExtensionLibraries( for (intptr_t i = 0; i < length; ++i) { library ^= potential_extension_libraries_.At(i); + ASSERT(!library.is_declared_in_bytecode()); helper_.SetOffset(library.kernel_offset()); LibraryHelper library_helper(&helper_); @@ -729,11 +730,17 @@ RawObject* KernelLoader::LoadProgram(bool process_pending_classes) { LongJumpScope jump; if (setjmp(*jump.Set()) == 0) { - // Note that `problemsAsJson` on Component is implicitly skipped. - const intptr_t length = program_->library_count(); - Object& last_library = Library::Handle(Z); - for (intptr_t i = 0; i < length; i++) { - last_library = LoadLibrary(i); + bool libraries_loaded = false; + if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) { + libraries_loaded = bytecode_metadata_helper_.ReadLibraries(); + } + + if (!libraries_loaded) { + // Note that `problemsAsJson` on Component is implicitly skipped. + const intptr_t length = program_->library_count(); + for (intptr_t i = 0; i < length; i++) { + LoadLibrary(i); + } } if (process_pending_classes) { @@ -797,6 +804,26 @@ RawObject* KernelLoader::LoadProgram(bool process_pending_classes) { return Thread::Current()->StealStickyError(); } +void KernelLoader::LoadLibrary(const Library& library) { + ASSERT(!library.Loaded()); + + if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) { + bytecode_metadata_helper_.ReadLibrary(library); + if (library.Loaded()) { + return; + } + } + const auto& uri = String::Handle(Z, library.url()); + const intptr_t num_libraries = program_->library_count(); + for (intptr_t i = 0; i < num_libraries; ++i) { + const String& library_uri = LibraryUri(i); + if (library_uri.Equals(uri)) { + LoadLibrary(i); + return; + } + } +} + RawObject* KernelLoader::LoadExpressionEvaluationFunction( const String& library_url, const String& klass) { @@ -1067,12 +1094,12 @@ RawLibrary* KernelLoader::LoadLibrary(intptr_t index) { LoadLibraryImportsAndExports(&library, toplevel_class); library_helper.SetJustRead(LibraryHelper::kDependencies); - const GrowableObjectArray& classes = - GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()); - // Everything up til the classes are skipped implicitly, and library_helper // is no longer used. + const GrowableObjectArray& classes = + GrowableObjectArray::Handle(Z, I->object_store()->pending_classes()); + // Load all classes. intptr_t next_class_offset = library_index.ClassOffset(0); Class& klass = Class::Handle(Z); @@ -1092,12 +1119,10 @@ RawLibrary* KernelLoader::LoadLibrary(intptr_t index) { if (FLAG_enable_mirrors && annotation_count > 0) { ASSERT(annotations_kernel_offset > 0); library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource, - annotations_kernel_offset); + annotations_kernel_offset, 0); } if (register_class) { - classes.Add(toplevel_class, Heap::kOld); - if (library_index.HasSourceReferences()) { helper_.SetOffset(library_index.SourceReferencesOffset()); intptr_t count = helper_.ReadUInt(); @@ -1129,6 +1154,9 @@ void KernelLoader::FinishTopLevelClassLoading( ActiveClassScope active_class_scope(&active_class_, &toplevel_class); if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup support for old bytecode format versions"); + ASSERT(!toplevel_class.is_declared_in_bytecode()); if (bytecode_metadata_helper_.ReadMembers(library_kernel_offset_, toplevel_class, false)) { ASSERT(toplevel_class.is_loaded()); @@ -1342,6 +1370,10 @@ void KernelLoader::LoadLibraryImportsAndExports(Library* library, void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper, intptr_t type_parameter_count) { const Class* klass = active_class_.klass; + + // Enable access to type_parameters(). + klass->set_is_declaration_loaded(); + // Note: This assumes that ClassHelper is exactly at the position where // the length of the type parameters have been read, and that the order in // the binary is as follows: [...], kTypeParameters, kSuperClass, kMixinType, @@ -1379,8 +1411,6 @@ void KernelLoader::LoadPreliminaryClass(ClassHelper* class_helper, if (class_helper->is_transformed_mixin_application()) { klass->set_is_transformed_mixin_application(); } - - klass->set_is_declaration_loaded(); } void KernelLoader::LoadClass(const Library& library, @@ -1443,7 +1473,7 @@ void KernelLoader::LoadClass(const Library& library, if ((FLAG_enable_mirrors || has_pragma_annotation) && annotation_count > 0) { library.AddClassMetadata(*out_class, toplevel_class, TokenPosition::kNoSource, - class_offset - correction_offset_); + class_offset - correction_offset_, 0); } // We do not register expression evaluation classes with the VM: @@ -1474,17 +1504,15 @@ void KernelLoader::FinishClassLoading(const Class& klass, ActiveClassScope active_class_scope(&active_class_, &klass); - bool discard_fields = false; - if (library.raw() == Library::InternalLibrary() && - klass.Name() == Symbols::ClassID().raw()) { - // If this is a dart:internal.ClassID class ignore field declarations - // contained in the Kernel file and instead inject our own const - // fields. - klass.InjectCIDFields(); - discard_fields = true; - } + // If this is a dart:internal.ClassID class ignore field declarations + // contained in the Kernel file and instead inject our own const + // fields. + const bool discard_fields = klass.InjectCIDFields(); if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) { + static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 10, + "Cleanup support for old bytecode format versions"); + ASSERT(!klass.is_declared_in_bytecode()); if (bytecode_metadata_helper_.ReadMembers( klass.kernel_offset() + library_kernel_offset_, klass, discard_fields)) { @@ -1681,6 +1709,7 @@ void KernelLoader::FinishClassLoading(const Class& klass, } void KernelLoader::FinishLoading(const Class& klass) { + ASSERT(!klass.is_declared_in_bytecode()); ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0)); Zone* zone = Thread::Current()->zone(); @@ -2257,9 +2286,11 @@ RawFunction* CreateFieldInitializerFunction(Thread* thread, const PatchClass& initializer_owner = PatchClass::Handle(zone, PatchClass::New(field_owner, script)); const Library& lib = Library::Handle(zone, field_owner.library()); - initializer_owner.set_library_kernel_data( - ExternalTypedData::Handle(zone, lib.kernel_data())); - initializer_owner.set_library_kernel_offset(lib.kernel_offset()); + if (!lib.is_declared_in_bytecode()) { + initializer_owner.set_library_kernel_data( + ExternalTypedData::Handle(zone, lib.kernel_data())); + initializer_owner.set_library_kernel_offset(lib.kernel_offset()); + } // Create a static initializer. const Function& initializer_fun = Function::Handle( diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h index 79c58b6ade3..f6d7665ef54 100644 --- a/runtime/vm/kernel_loader.h +++ b/runtime/vm/kernel_loader.h @@ -196,6 +196,9 @@ class KernelLoader : public ValueObject { // was no main procedure, or a failure object if there was an error. RawObject* LoadProgram(bool process_pending_classes = true); + // Load given library. + void LoadLibrary(const Library& library); + // Returns the function which will evaluate the expression, or a failure // object if there was an error. RawObject* LoadExpressionEvaluationFunction(const String& library_url, @@ -219,8 +222,6 @@ class KernelLoader : public ValueObject { intptr_t kernel_buffer_length, const String& url); - RawLibrary* LoadLibrary(intptr_t index); - void FinishTopLevelClassLoading(const Class& toplevel_class, const Library& library, const LibraryIndex& library_index); @@ -258,6 +259,16 @@ class KernelLoader : public ValueObject { return translation_helper_.DartSymbolObfuscate(index); } + private: + KernelLoader(const Script& script, + const ExternalTypedData& kernel_data, + intptr_t data_program_offset); + + void InitializeFields( + DirectChainedHashMap* uri_to_source_table); + + RawLibrary* LoadLibrary(intptr_t index); + const String& LibraryUri(intptr_t library_index) { return translation_helper_.DartSymbolPlain( translation_helper_.CanonicalNameString( @@ -284,15 +295,6 @@ class KernelLoader : public ValueObject { uint8_t CharacterAt(StringIndex string_index, intptr_t index); - private: - friend class BuildingTranslationHelper; - - KernelLoader(const Script& script, - const ExternalTypedData& kernel_data, - intptr_t data_program_offset); - - void InitializeFields( - DirectChainedHashMap* uri_to_source_table); static void index_programs(kernel::Reader* reader, GrowableArray* subprogram_file_starts); void walk_incremental_kernel(BitVector* modified_libs, @@ -459,6 +461,8 @@ class KernelLoader : public ValueObject { GrowableArray functions_; GrowableArray fields_; + friend class BuildingTranslationHelper; + DISALLOW_COPY_AND_ASSIGN(KernelLoader); }; diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index cecbb3e6a76..19ceac86648 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -1931,7 +1931,8 @@ RawError* Object::Init(Isolate* isolate, ASSERT(!lib.IsNull()); cls = lib.LookupClassAllowPrivate(Symbols::ClassID()); ASSERT(!cls.IsNull()); - cls.InjectCIDFields(); + const bool injected = cls.InjectCIDFields(); + ASSERT(injected); isolate->object_store()->InitKnownObjects(); #endif // !defined(DART_PRECOMPILED_RUNTIME) @@ -2311,7 +2312,8 @@ RawClass* Class::New() { // references, but do not recompute size. result.set_is_prefinalized(); } - result.set_kernel_offset(-1); + NOT_IN_PRECOMPILED(result.set_is_declared_in_bytecode(false)); + NOT_IN_PRECOMPILED(result.set_binary_declaration_offset(0)); result.InitEmptyFields(); Isolate::Current()->RegisterClass(result); return result.raw(); @@ -2593,12 +2595,13 @@ void Class::set_library(const Library& value) const { void Class::set_type_parameters(const TypeArguments& value) const { ASSERT((num_type_arguments() == kUnknownNumTypeArguments) || - is_prefinalized()); + is_declared_in_bytecode() || is_prefinalized()); StorePointer(&raw_ptr()->type_parameters_, value.raw()); } intptr_t Class::NumTypeParameters(Thread* thread) const { - if (type_parameters() == TypeArguments::null()) { + if (!is_declaration_loaded()) { + ASSERT(is_prefinalized()); const intptr_t cid = id(); if ((cid == kArrayCid) || (cid == kImmutableArrayCid) || (cid == kGrowableObjectArrayCid)) { @@ -2606,6 +2609,9 @@ intptr_t Class::NumTypeParameters(Thread* thread) const { } return 0; } + if (type_parameters() == TypeArguments::null()) { + return 0; + } REUSABLE_TYPE_ARGUMENTS_HANDLESCOPE(thread); TypeArguments& type_params = thread->TypeArgumentsHandle(); type_params = type_parameters(); @@ -3596,7 +3602,12 @@ void Class::AddFields(const GrowableArray& new_fields) const { SetFields(new_arr); } -void Class::InjectCIDFields() const { +bool Class::InjectCIDFields() const { + if (library() != Library::InternalLibrary() || + Name() != Symbols::ClassID().raw()) { + return false; + } + Thread* thread = Thread::Current(); Zone* zone = thread->zone(); Field& field = Field::Handle(zone); @@ -3631,6 +3642,8 @@ void Class::InjectCIDFields() const { CLASS_LIST_TYPED_DATA(ADD_SET_FIELD) #undef ADD_SET_FIELD #undef CLASS_LIST_WITH_NULL + + return true; } template @@ -3654,6 +3667,8 @@ RawClass* Class::NewCommon(intptr_t index) { result.set_num_type_arguments(kUnknownNumTypeArguments); result.set_num_native_fields(0); result.set_state_bits(0); + NOT_IN_PRECOMPILED(result.set_is_declared_in_bytecode(false)); + NOT_IN_PRECOMPILED(result.set_binary_declaration_offset(0)); result.InitEmptyFields(); return result.raw(); } @@ -3661,7 +3676,6 @@ RawClass* Class::NewCommon(intptr_t index) { template RawClass* Class::New(intptr_t index) { Class& result = Class::Handle(NewCommon(index)); - result.set_kernel_offset(-1); Isolate::Current()->RegisterClass(result); return result.raw(); } @@ -3676,7 +3690,6 @@ RawClass* Class::New(const Library& lib, result.set_name(name); result.set_script(script); result.set_token_pos(token_pos); - result.set_kernel_offset(-1); if (register_class) { Isolate::Current()->RegisterClass(result); } @@ -3707,7 +3720,6 @@ RawClass* Class::NewNativeWrapper(const Library& library, cls.set_is_declaration_loaded(); cls.set_is_type_finalized(); cls.set_is_synthesized_class(); - cls.set_kernel_offset(-1); library.AddClass(cls); return cls.raw(); } else { @@ -3978,6 +3990,11 @@ TokenPosition Class::ComputeEndTokenPos() const { ASSERT(!scr.IsNull()); if (scr.kind() == RawScript::kKernelTag) { + if (is_declared_in_bytecode()) { + // TODO(alexmarkov): keep end_token_pos in Class? + UNIMPLEMENTED(); + return token_pos(); + } ASSERT(kernel_offset() > 0); const Library& lib = Library::Handle(zone, library()); const ExternalTypedData& kernel_data = @@ -7779,6 +7796,10 @@ RawExternalTypedData* Function::KernelData() const { } intptr_t Function::KernelDataProgramOffset() const { + ASSERT(!is_declared_in_bytecode()); + if (IsNoSuchMethodDispatcher() || IsInvokeFieldDispatcher()) { + return 0; + } Object& data = Object::Handle(raw_ptr()->data_); if (data.IsArray()) { Object& script = Object::Handle(Array::Cast(data).At(0)); @@ -7795,6 +7816,7 @@ intptr_t Function::KernelDataProgramOffset() const { const Object& obj = Object::Handle(raw_ptr()->owner_); if (obj.IsClass()) { Library& lib = Library::Handle(Class::Cast(obj).library()); + ASSERT(!lib.is_declared_in_bytecode()); return lib.kernel_offset(); } ASSERT(obj.IsPatchClass()); @@ -8434,6 +8456,7 @@ void Field::InheritBinaryDeclarationFrom(const Field& src) const { } intptr_t Field::KernelDataProgramOffset() const { + ASSERT(!is_declared_in_bytecode()); const Object& obj = Object::Handle(raw_ptr()->owner_); // During background JIT compilation field objects are copied // and copy points to the original field via the owner field. @@ -8441,6 +8464,7 @@ intptr_t Field::KernelDataProgramOffset() const { return Field::Cast(obj).KernelDataProgramOffset(); } else if (obj.IsClass()) { Library& lib = Library::Handle(Class::Cast(obj).library()); + ASSERT(!lib.is_declared_in_bytecode()); return lib.kernel_offset(); } ASSERT(obj.IsPatchClass()); @@ -9995,14 +10019,15 @@ void Library::AddMetadata(const Object& owner, void Library::AddClassMetadata(const Class& cls, const Object& tl_owner, TokenPosition token_pos, - intptr_t kernel_offset) const { + intptr_t kernel_offset, + intptr_t bytecode_offset) const { Thread* thread = Thread::Current(); Zone* zone = thread->zone(); // We use the toplevel class as the owner of a class's metadata field because // a class's metadata is in scope of the library, not the class. AddMetadata(tl_owner, String::Handle(zone, MakeClassMetaName(thread, zone, cls)), - token_pos, kernel_offset, 0); + token_pos, kernel_offset, bytecode_offset); } void Library::AddFieldMetadata(const Field& field, @@ -10039,8 +10064,10 @@ void Library::AddTypeParameterMetadata(const TypeParameter& param, void Library::AddLibraryMetadata(const Object& tl_owner, TokenPosition token_pos, - intptr_t kernel_offset) const { - AddMetadata(tl_owner, Symbols::TopLevel(), token_pos, kernel_offset, 0); + intptr_t kernel_offset, + intptr_t bytecode_offset) const { + AddMetadata(tl_owner, Symbols::TopLevel(), token_pos, kernel_offset, + bytecode_offset); } RawString* Library::MakeMetadataName(const Object& obj) const { @@ -10969,7 +10996,8 @@ RawLibrary* Library::NewLibraryHelper(const String& url, bool import_core_lib) { result.set_debuggable(true); } result.set_is_dart_scheme(dart_scheme); - result.set_kernel_offset(-1); + NOT_IN_PRECOMPILED(result.set_is_declared_in_bytecode(false)); + NOT_IN_PRECOMPILED(result.set_binary_declaration_offset(0)); result.StoreNonPointer(&result.raw_ptr()->load_state_, RawLibrary::kAllocated); result.StoreNonPointer(&result.raw_ptr()->index_, -1); @@ -17684,7 +17712,14 @@ bool Type::IsEquivalent(const Instance& other, TrailPtr trail) const { for (intptr_t i = 0; i < from_index; i++) { type_arg = type_args.TypeAt(i); other_type_arg = other_type_args.TypeAt(i); - ASSERT(type_arg.IsEquivalent(other_type_arg, trail)); + // Type arguments may not match if they are TypeRefs without + // underlying type (which will be set later). + ASSERT( + type_arg.IsEquivalent(other_type_arg, trail) || + (type_arg.IsTypeRef() && + TypeRef::Cast(type_arg).type() == AbstractType::null()) || + (other_type_arg.IsTypeRef() && + TypeRef::Cast(other_type_arg).type() == AbstractType::null())); } } #endif @@ -18127,7 +18162,7 @@ RawTypeRef* TypeRef::InstantiateFrom( } void TypeRef::set_type(const AbstractType& value) const { - ASSERT(value.IsFunctionType() || value.HasTypeClass()); + ASSERT(value.IsNull() || value.IsFunctionType() || value.HasTypeClass()); ASSERT(!value.IsTypeRef()); StorePointer(&raw_ptr()->type_, value.raw()); } @@ -18143,9 +18178,10 @@ RawAbstractType* TypeRef::Canonicalize(TrailPtr trail) const { // TODO(regis): Try to reduce the number of nodes required to represent the // referenced recursive type. AbstractType& ref_type = AbstractType::Handle(type()); - ASSERT(!ref_type.IsNull()); - ref_type = ref_type.Canonicalize(trail); - set_type(ref_type); + if (!ref_type.IsNull()) { + ref_type = ref_type.Canonicalize(trail); + set_type(ref_type); + } return raw(); } @@ -18172,10 +18208,10 @@ void TypeRef::EnumerateURIs(URIs* uris) const { intptr_t TypeRef::Hash() const { // Do not calculate the hash of the referenced type to avoid divergence. - const AbstractType& ref_type = AbstractType::Handle(type()); - ASSERT(!ref_type.IsNull()); - const uint32_t result = Class::Handle(ref_type.type_class()).id(); - return FinalizeHash(result, kHashBits); + // TypeRef can participate in type canonicalization even before referenced + // type is set, so its hash should not rely on referenced type. + const intptr_t kTypeRefHash = 37; + return kTypeRefHash; } RawTypeRef* TypeRef::New() { diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 122a0121271..58eacf74e8d 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -900,6 +900,7 @@ class Class : public Object { // The type parameters (and their bounds) are specified as an array of // TypeParameter. RawTypeArguments* type_parameters() const { + ASSERT(is_declaration_loaded()); return raw_ptr()->type_parameters_; } void set_type_parameters(const TypeArguments& value) const; @@ -965,7 +966,10 @@ class Class : public Object { RawClass* SuperClass(bool original_classes = false) const; // Interfaces is an array of Types. - RawArray* interfaces() const { return raw_ptr()->interfaces_; } + RawArray* interfaces() const { + ASSERT(is_declaration_loaded()); + return raw_ptr()->interfaces_; + } void set_interfaces(const Array& value) const; // Returns the list of classes directly implementing this class. @@ -1050,7 +1054,10 @@ class Class : public Object { void AddField(const Field& field) const; void AddFields(const GrowableArray& fields) const; - void InjectCIDFields() const; + // If this is a dart:internal.ClassID class, then inject our own const + // fields. Returns true if synthetic fields are injected and regular + // field declarations should be ignored. + bool InjectCIDFields() const; // Returns an array of all instance fields of this class and its superclasses // indexed by offset in words. @@ -1192,18 +1199,72 @@ class Class : public Object { RawCode* allocation_stub() const { return raw_ptr()->allocation_stub_; } void set_allocation_stub(const Code& value) const; +#if !defined(DART_PRECOMPILED_RUNTIME) + intptr_t binary_declaration_offset() const { + return RawClass::BinaryDeclarationOffset::decode( + raw_ptr()->binary_declaration_); + } + void set_binary_declaration_offset(intptr_t value) const { + ASSERT(value >= 0); + StoreNonPointer(&raw_ptr()->binary_declaration_, + RawClass::BinaryDeclarationOffset::update( + value, raw_ptr()->binary_declaration_)); + } +#endif // !defined(DART_PRECOMPILED_RUNTIME) + intptr_t kernel_offset() const { #if defined(DART_PRECOMPILED_RUNTIME) - return -1; + return 0; #else - return raw_ptr()->kernel_offset_; + ASSERT(!is_declared_in_bytecode()); + return binary_declaration_offset(); #endif } - void set_kernel_offset(intptr_t offset) const { - NOT_IN_PRECOMPILED(StoreNonPointer(&raw_ptr()->kernel_offset_, offset)); + void set_kernel_offset(intptr_t value) const { +#if defined(DART_PRECOMPILED_RUNTIME) + UNREACHABLE(); +#else + ASSERT(!is_declared_in_bytecode()); + set_binary_declaration_offset(value); +#endif } + intptr_t bytecode_offset() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return 0; +#else + ASSERT(is_declared_in_bytecode()); + return binary_declaration_offset(); +#endif + } + + void set_bytecode_offset(intptr_t value) const { +#if defined(DART_PRECOMPILED_RUNTIME) + UNREACHABLE(); +#else + ASSERT(is_declared_in_bytecode()); + set_binary_declaration_offset(value); +#endif + } + + bool is_declared_in_bytecode() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return false; +#else + return RawClass::IsDeclaredInBytecode::decode( + raw_ptr()->binary_declaration_); +#endif + } + +#if !defined(DART_PRECOMPILED_RUNTIME) + void set_is_declared_in_bytecode(bool value) const { + StoreNonPointer(&raw_ptr()->binary_declaration_, + RawClass::IsDeclaredInBytecode::update( + value, raw_ptr()->binary_declaration_)); + } +#endif // !defined(DART_PRECOMPILED_RUNTIME) + void DisableAllocationStub() const; RawArray* constants() const; @@ -1397,9 +1458,10 @@ class Class : public Object { static const intptr_t kUnknownNumTypeArguments = -1; int16_t num_type_arguments() const { return raw_ptr()->num_type_arguments_; } - void set_num_type_arguments(intptr_t value) const; public: + void set_num_type_arguments(intptr_t value) const; + bool has_pragma() const { return HasPragmaBit::decode(raw_ptr()->state_bits_); } @@ -3955,7 +4017,8 @@ class Library : public Object { void AddClassMetadata(const Class& cls, const Object& tl_owner, TokenPosition token_pos, - intptr_t kernel_offset) const; + intptr_t kernel_offset, + intptr_t bytecode_offset) const; void AddFieldMetadata(const Field& field, TokenPosition token_pos, intptr_t kernel_offset, @@ -3966,7 +4029,8 @@ class Library : public Object { intptr_t bytecode_offset) const; void AddLibraryMetadata(const Object& tl_owner, TokenPosition token_pos, - intptr_t kernel_offset) const; + intptr_t kernel_offset, + intptr_t bytecode_offset) const; void AddTypeParameterMetadata(const TypeParameter& param, TokenPosition token_pos) const; void CloneMetadataFrom(const Library& from_library, @@ -4057,17 +4121,72 @@ class Library : public Object { RawExternalTypedData* kernel_data() const { return raw_ptr()->kernel_data_; } void set_kernel_data(const ExternalTypedData& data) const; - intptr_t kernel_offset() const { #if !defined(DART_PRECOMPILED_RUNTIME) - return raw_ptr()->kernel_offset_; + intptr_t binary_declaration_offset() const { + return RawLibrary::BinaryDeclarationOffset::decode( + raw_ptr()->binary_declaration_); + } + void set_binary_declaration_offset(intptr_t value) const { + ASSERT(value >= 0); + StoreNonPointer(&raw_ptr()->binary_declaration_, + RawLibrary::BinaryDeclarationOffset::update( + value, raw_ptr()->binary_declaration_)); + } +#endif // !defined(DART_PRECOMPILED_RUNTIME) + + intptr_t kernel_offset() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return 0; #else - return -1; + ASSERT(!is_declared_in_bytecode()); + return binary_declaration_offset(); #endif } - void set_kernel_offset(intptr_t offset) const { - NOT_IN_PRECOMPILED(StoreNonPointer(&raw_ptr()->kernel_offset_, offset)); + + void set_kernel_offset(intptr_t value) const { +#if defined(DART_PRECOMPILED_RUNTIME) + UNREACHABLE(); +#else + ASSERT(!is_declared_in_bytecode()); + set_binary_declaration_offset(value); +#endif } + intptr_t bytecode_offset() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return 0; +#else + ASSERT(is_declared_in_bytecode()); + return binary_declaration_offset(); +#endif + } + + void set_bytecode_offset(intptr_t value) const { +#if defined(DART_PRECOMPILED_RUNTIME) + UNREACHABLE(); +#else + ASSERT(is_declared_in_bytecode()); + set_binary_declaration_offset(value); +#endif + } + + bool is_declared_in_bytecode() const { +#if defined(DART_PRECOMPILED_RUNTIME) + return false; +#else + return RawLibrary::IsDeclaredInBytecode::decode( + raw_ptr()->binary_declaration_); +#endif + } + +#if !defined(DART_PRECOMPILED_RUNTIME) + void set_is_declared_in_bytecode(bool value) const { + StoreNonPointer(&raw_ptr()->binary_declaration_, + RawLibrary::IsDeclaredInBytecode::update( + value, raw_ptr()->binary_declaration_)); + } +#endif // !defined(DART_PRECOMPILED_RUNTIME) + static RawLibrary* LookupLibrary(Thread* thread, const String& url); static RawLibrary* GetLibrary(intptr_t index); diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 032fb604c29..0dba671124a 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -422,8 +422,10 @@ void Class::PatchFieldsAndFunctions() const { PatchClass::Handle(PatchClass::New(*this, Script::Handle(script()))); ASSERT(!patch.IsNull()); const Library& lib = Library::Handle(library()); - patch.set_library_kernel_data(ExternalTypedData::Handle(lib.kernel_data())); - patch.set_library_kernel_offset(lib.kernel_offset()); + if (!lib.is_declared_in_bytecode()) { + patch.set_library_kernel_data(ExternalTypedData::Handle(lib.kernel_data())); + patch.set_library_kernel_offset(lib.kernel_offset()); + } const Array& funcs = Array::Handle(functions()); Function& func = Function::Handle(); diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 3ec790b1367..e63d22bb67b 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -807,7 +807,12 @@ class RawClass : public RawObject { int16_t num_type_arguments_; // Number of type arguments in flattened vector. uint16_t num_native_fields_; uint32_t state_bits_; - NOT_IN_PRECOMPILED(intptr_t kernel_offset_); + +#if !defined(DART_PRECOMPILED_RUNTIME) + typedef BitField IsDeclaredInBytecode; + typedef BitField BinaryDeclarationOffset; + uint32_t binary_declaration_; +#endif // !defined(DART_PRECOMPILED_RUNTIME) friend class Instance; friend class Isolate; @@ -1215,9 +1220,12 @@ class RawLibrary : public RawObject { bool is_dart_scheme_; bool debuggable_; // True if debugger can stop in library. bool is_in_fullsnapshot_; // True if library is in a full snapshot. - NOT_IN_PRECOMPILED(intptr_t kernel_offset_); // Offset of this library's - // kernel data in the overall - // kernel program. + +#if !defined(DART_PRECOMPILED_RUNTIME) + typedef BitField IsDeclaredInBytecode; + typedef BitField BinaryDeclarationOffset; + uint32_t binary_declaration_; +#endif // !defined(DART_PRECOMPILED_RUNTIME) friend class Class; friend class Isolate; diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 2944b9952c3..c8866583ade 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -2565,6 +2565,7 @@ void DeoptimizeAt(const Code& optimized_code, StackFrame* frame) { // N.B.: Update the pending deopt table before updating the frame. The // profiler may attempt a stack walk in between. + ASSERT(!frame->is_interpreted()); thread->isolate()->AddPendingDeopt(frame->fp(), deopt_pc); frame->MarkForLazyDeopt(); diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index b17870e7504..fb281f72770 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -85,6 +85,7 @@ class ObjectPointerVisitor; V(DartSchemePrivate, "dart:_") \ V(DartTypedData, "dart:typed_data") \ V(DartVMProduct, "dart.vm.product") \ + V(DartVMServiceIO, "dart:vmservice_io") \ V(DartVMService, "dart:_vmservice") \ V(DebugClassName, "#DebugClass") \ V(DebugProcedureName, ":Eval") \ diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status index 1a54ab1be92..5953301dd5e 100644 --- a/tests/language_2/language_2_kernel.status +++ b/tests/language_2/language_2_kernel.status @@ -1035,10 +1035,12 @@ symbol_conflict_test: Pass, Slow [ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ] least_upper_bound_expansive_test/none: RuntimeError # Please triage. +[ ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp) && ($runtime == dart_precompiled || $runtime == vm) ] +type_alias_equality_test/04: RuntimeError # Issue 32783 + [ ($compiler == app_jitk || $compiler == dartk || $compiler == dartkp) && ($runtime == dart_precompiled || $runtime == vm) ] covariant_subtyping_with_mixin_test: RuntimeError # Issue 34321 type_alias_equality_test/03: RuntimeError # Issue 32783 -type_alias_equality_test/04: RuntimeError # Issue 32783 [ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ] async_star_test/01: Skip # Timeout