diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart index b11e45784a4..4fc6d9dde47 100644 --- a/pkg/front_end/tool/_fasta/entry_points.dart +++ b/pkg/front_end/tool/_fasta/entry_points.dart @@ -19,6 +19,7 @@ import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget; import 'package:kernel/type_environment.dart' show SubtypeTester; import 'package:vm/bytecode/gen_bytecode.dart' show generateBytecode; +import 'package:vm/bytecode/options.dart' show BytecodeOptions; import 'package:front_end/src/api_prototype/compiler_options.dart' show CompilerOptions; @@ -329,7 +330,12 @@ Future compilePlatformInternal(CompilerContext c, Uri fullOutput, c.options.ticker.logMs("Wrote outline to ${outlineOutput.toFilePath()}"); if (c.options.bytecode) { - generateBytecode(result.component); + generateBytecode(result.component, + options: new BytecodeOptions( + enableAsserts: true, + emitSourceFiles: true, + emitSourcePositions: true, + environmentDefines: c.options.environmentDefines)); } await writeComponentToFile(result.component, fullOutput, diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart index 37d71ba4d3c..e3d72a2c4ab 100644 --- a/pkg/vm/lib/bytecode/declarations.dart +++ b/pkg/vm/lib/bytecode/declarations.dart @@ -220,22 +220,20 @@ class SourceFile { static const hasLineStartsFlag = 1 << 0; static const hasSourceFlag = 1 << 1; - int flags; final ObjectHandle importUri; - final LineStarts lineStarts; - final String source; + LineStarts lineStarts; + String source; - SourceFile(this.importUri, this.lineStarts, this.source) { - flags = 0; + SourceFile(this.importUri, [this.lineStarts, this.source]); + + void write(BufferedWriter writer) { + int 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) { @@ -261,11 +259,13 @@ class SourceFile { @override String toString() { final StringBuffer sb = new StringBuffer(); - sb.writeln('SourceFile $importUri'); - sb.writeln('------------------------------------------------'); - sb.write(source); - sb.writeln('------------------------------------------------'); - sb.writeln(lineStarts); + sb.write('source: import-uri $importUri'); + if (source != null && source != '') { + sb.write(', ${source.length} text chars'); + } + if (lineStarts != null) { + sb.write(', ${lineStarts.lineStarts.length} line starts'); + } return sb.toString(); } } diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart index 4bc67f72818..4c38ad94c19 100644 --- a/pkg/vm/lib/bytecode/gen_bytecode.dart +++ b/pkg/vm/lib/bytecode/gen_bytecode.dart @@ -211,30 +211,33 @@ class BytecodeGenerator extends RecursiveVisitor { return members; } - ObjectHandle getScript(Uri uri, bool includeSource) { + ObjectHandle getScript(Uri uri, bool includeSourceInfo) { SourceFile source; - if (includeSource && - (options.emitSourceFiles || options.emitSourcePositions)) { - source = bytecodeComponent.uriToSource[uri]; - if (source == null) { - final astSource = astUriToSource[uri]; - if (astSource != null) { + if (options.emitSourceFiles || options.emitSourcePositions) { + final astSource = astUriToSource[uri]; + if (astSource != null) { + source = bytecodeComponent.uriToSource[uri]; + if (source == null) { final importUri = objectTable.getNameHandle(null, astSource.importUri.toString()); - LineStarts lineStarts; - if (options.emitSourcePositions) { - lineStarts = new LineStarts(astSource.lineStarts); - bytecodeComponent.lineStarts.add(lineStarts); - } - String text = ''; - if (options.emitSourceFiles) { - text = astSource.cachedText ?? - utf8.decode(astSource.source, allowMalformed: true); - } - source = new SourceFile(importUri, lineStarts, text); + source = new SourceFile(importUri); bytecodeComponent.sourceFiles.add(source); bytecodeComponent.uriToSource[uri] = source; } + if (options.emitSourcePositions && + includeSourceInfo && + source.lineStarts == null) { + LineStarts lineStarts = new LineStarts(astSource.lineStarts); + bytecodeComponent.lineStarts.add(lineStarts); + source.lineStarts = lineStarts; + } + if (options.emitSourceFiles && + includeSourceInfo && + source.source == null) { + String text = astSource.cachedText ?? + utf8.decode(astSource.source, allowMalformed: true); + source.source = text; + } } } return objectTable.getScriptHandle(uri, source); @@ -777,6 +780,16 @@ class BytecodeGenerator extends RecursiveVisitor { return false; } if (member is Field) { + // TODO(dartbug.com/34277) + // Front-end inserts synthetic static fields "_redirecting#" to record + // information about redirecting constructors in kernel. + // The problem is that initializers of these synthetic static fields + // contain incorrect kernel AST, e.g. StaticGet which takes tear-off + // of a constructor. Do not generate bytecode for them, as they should + // never be used. + if (member.isStatic && member.name.name == "_redirecting#") { + return false; + } return hasInitializerCode(member); } return true; @@ -3083,6 +3096,8 @@ class BytecodeGenerator extends RecursiveVisitor { } else if (target is Procedure) { if (target.isGetter) { _genDirectCall(target, objectTable.getArgDescHandle(0), 0, isGet: true); + } else if (target.isFactory || target.isRedirectingFactoryConstructor) { + throw 'Unexpected target for StaticGet: factory $target'; } else { asm.emitPushConstant(cp.addObjectRef(new TearOffConstant(target))); } diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart index d16c0bdd8b6..688f4370312 100644 --- a/pkg/vm/lib/bytecode/object_table.dart +++ b/pkg/vm/lib/bytecode/object_table.dart @@ -1592,8 +1592,7 @@ class _ScriptHandle extends ObjectHandle { bool operator ==(other) => other is _ScriptHandle && this.uri == other.uri; @override - String toString() => - "$uri${source != null ? '(source ${source.importUri})' : ''}"; + String toString() => "$uri${source != null ? '($source)' : ''}"; } class ObjectTable implements ObjectWriter, ObjectReader { diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc index afcc9f3f600..b6925db0a27 100644 --- a/runtime/vm/class_finalizer.cc +++ b/runtime/vm/class_finalizer.cc @@ -1155,12 +1155,6 @@ void ClassFinalizer::FinalizeClass(const Class& cls) { } // Mark as loaded and finalized. cls.Finalize(); - // Every class should have at least a constructor, unless it is a top level - // class or a typedef class. The Kernel frontend does not create an implicit - // constructor for abstract classes. - // Moreover, Dart 2 precompiler (TFA) can tree shake all members if unused. - ASSERT(FLAG_precompiled_mode || cls.IsTopLevel() || cls.IsTypedefClass() || - cls.is_abstract() || (Array::Handle(cls.functions()).Length() > 0)); FinalizeMemberTypes(cls); // Run additional checks after all types are finalized. if (FLAG_use_cha_deopt) { diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc index 386e3dd1381..ad0e5aef04a 100644 --- a/runtime/vm/object_test.cc +++ b/runtime/vm/object_test.cc @@ -4,6 +4,9 @@ #include "include/dart_api.h" +#include "bin/builtin.h" +#include "bin/vmservice_impl.h" + #include "platform/globals.h" #include "vm/class_finalizer.h" @@ -3974,6 +3977,15 @@ class ObjectAccumulator : public ObjectVisitor { }; ISOLATE_UNIT_TEST_CASE(PrintJSON) { + // Set native resolvers in case we need to read native methods. + { + TransitionVMToNative transition(thread); + bin::Builtin::SetNativeResolver(bin::Builtin::kBuiltinLibrary); + bin::Builtin::SetNativeResolver(bin::Builtin::kIOLibrary); + bin::Builtin::SetNativeResolver(bin::Builtin::kCLILibrary); + bin::VmService::SetNativeResolver(); + } + Heap* heap = Isolate::Current()->heap(); heap->CollectAllGarbage(); GrowableArray objects;