mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm/bytecode] Include source info and asserts into platform with bytecode
* Include source positions, source text (if provided by front-end, which is controlled by a separate option) and assertions into platform with bytecode. Also use environment defines if provided. * Omit bytecode for synthetic static fields '_redirecting#' injected by front-end, as they contain invalid AST nodes (taking tear-off of a constructor). This is needed to avoid emitting bytecode which cannot be loaded. * Correctly merge source information such as source text and line numbers in bytecode generator if the script was originally created for an anonymous mixin application without such information. * Always include import URIs into source information, even if other information is excluded (for members in anonymous mixin applications / noSuchMethod forwarders / forwarding stubs). * Set native resolvers for vm/cc/PrintJSON test, as printing all objects to JSON involves collecting token positions, which may read bytecode from platform and need native resolvers to process native method entries. Change-Id: I971e880c25439c0ec69db3a231a0085ccd5d15ad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/113780 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com>
This commit is contained in:
parent
457c4349d0
commit
922c2bfbb0
|
@ -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<void> 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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -211,30 +211,33 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
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<Null> {
|
|||
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<Null> {
|
|||
} 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)));
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<Object*> objects;
|
||||
|
|
Loading…
Reference in a new issue