Ensure we're looking at the correct resolved AST when initializing fields in constructors.

Step 30 of bagilliondy.

BUG=https://github.com/dart-lang/sdk/issues/27394
R=sigmund@google.com

Review-Url: https://codereview.chromium.org/2616933003 .
This commit is contained in:
Emily Fortuna
2017-01-05 16:19:57 -08:00
parent 1fc6d58699
commit 0c78abd090
5 changed files with 55 additions and 14 deletions
@@ -115,6 +115,9 @@ class _ResolvedUriTranslator implements ResolvedUriTranslator {
bool allowInternalLibraryAccess = importingLibrary != null &&
(importingLibrary.isPlatformLibrary ||
importingLibrary.isPatch ||
// The memory scheme is specifically for unit tests that use the
// in-memory compiler.
importingLibrary.canonicalUri.scheme == 'memory' ||
importingLibrary.canonicalUri.path
.contains('sdk/tests/compiler/dart2js_native'));
+9 -9
View File
@@ -23,7 +23,6 @@ import '../js/js.dart' as js;
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../kernel/kernel.dart';
import '../native/native.dart' as native;
import '../resolution/tree_elements.dart';
import '../tree/dartstring.dart';
import '../tree/nodes.dart' show Node, BreakStatement;
import '../types/masks.dart';
@@ -115,9 +114,6 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
@override
JavaScriptBackend get backend => compiler.backend;
@override
TreeElements get elements => resolvedAst.elements;
SourceInformationBuilder sourceInformationBuilder;
KernelAstAdapter astAdapter;
LoopHandler<ir.Node> loopHandler;
@@ -298,8 +294,12 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
if (field.initializer == null) {
fieldValues[field] = graph.addConstantNull(closedWorld);
} else {
// Gotta update the resolvedAst when we're looking at field values
// outside the constructor.
astAdapter.pushResolvedAst(field);
field.initializer.accept(this);
fieldValues[field] = pop();
astAdapter.popResolvedAstStack();
}
}
@@ -386,7 +386,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
return builtArguments;
}
/// Inlines the given super [constructor]'s initializers by collecting it's
/// Inlines the given super [constructor]'s initializers by collecting its
/// field values and building its constructor initializers. We visit super
/// constructors all the way up to the [Object] constructor.
void _buildInlinedInitializers(ir.Constructor constructor,
@@ -793,8 +793,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
HLoopInformation loopInfo = current.loopInformation;
HBasicBlock loopEntryBlock = current;
HBasicBlock bodyEntryBlock = current;
JumpTarget target =
elements.getTargetDefinition(astAdapter.getNode(doStatement));
JumpTarget target = astAdapter.elements
.getTargetDefinition(astAdapter.getNode(doStatement));
bool hasContinues = target != null && target.isContinueTarget;
if (hasContinues) {
// Add extra block to hang labels on.
@@ -906,8 +906,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
// Since the body of the loop has a break, we attach a synthesized label
// to the body.
SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
JumpTarget target =
elements.getTargetDefinition(astAdapter.getNode(doStatement));
JumpTarget target = astAdapter.elements
.getTargetDefinition(astAdapter.getNode(doStatement));
LabelDefinition label = target.addLabel(null, 'loop');
label.setBreakTarget();
HLabeledBlockInformation info = new HLabeledBlockInformation(
@@ -11,7 +11,6 @@ import '../elements/resolution_types.dart';
import '../elements/elements.dart';
import '../io/source_information.dart';
import '../js_backend/js_backend.dart';
import '../resolution/tree_elements.dart';
import '../tree/tree.dart' as ast;
import '../types/types.dart';
import '../universe/call_structure.dart' show CallStructure;
@@ -38,9 +37,6 @@ abstract class GraphBuilder {
/// The JavaScript backend we are targeting in this compilation.
JavaScriptBackend get backend;
/// The tree elements for the element being built into an SSA graph.
TreeElements get elements;
CodegenRegistry get registry;
ClosedWorld get closedWorld;
@@ -5,6 +5,8 @@
import 'package:js_runtime/shared/embedded_names.dart';
import 'package:kernel/ast.dart' as ir;
import 'dart:collection' show Queue;
import '../common.dart';
import '../common/names.dart';
import '../compiler.dart';
@@ -36,7 +38,6 @@ import 'types.dart';
class KernelAstAdapter {
final Kernel kernel;
final JavaScriptBackend _backend;
final ResolvedAst _resolvedAst;
final Map<ir.Node, ast.Node> _nodeToAst;
final Map<ir.Node, Element> _nodeToElement;
final Map<ir.VariableDeclaration, SyntheticLocal> _syntheticLocals =
@@ -44,6 +45,12 @@ class KernelAstAdapter {
final Map<ir.LabeledStatement, KernelJumpTarget> _jumpTargets =
<ir.LabeledStatement, KernelJumpTarget>{};
DartTypeConverter _typeConverter;
ResolvedAst _resolvedAst;
/// Sometimes for resolution the resolved AST element needs to change (for
/// example, if we're inlining, or if we're in a constructor, but then also
/// constructing the field values). We keep track of this with a stack.
Queue<ResolvedAst> _resolvedAstStack;
KernelAstAdapter(this.kernel, this._backend, this._resolvedAst,
this._nodeToAst, this._nodeToElement) {
@@ -67,6 +74,20 @@ class KernelAstAdapter {
_nodeToElement[kernel.typeParameters[typeVariable]] = typeVariable;
}
_typeConverter = new DartTypeConverter(this);
_resolvedAstStack = new Queue<ResolvedAst>();
}
/// Push the existing resolved AST on the stack and shift the current resolved
/// AST to the AST that this kernel node points to.
void pushResolvedAst(ir.Node node) {
_resolvedAstStack.addLast(_resolvedAst);
_resolvedAst = getElement(node).resolvedAst;
}
/// Pop the resolved AST stack to reset it to the previous resolved AST node.
void popResolvedAstStack() {
assert(_resolvedAstStack.isNotEmpty);
_resolvedAst = _resolvedAstStack.removeLast();
}
Compiler get _compiler => _backend.compiler;
@@ -46,6 +46,27 @@ main() => new Foo(number: 3);
''';
return check(code, lookup: defaultConstructorFor('Foo'));
});
// TODO(efortuna): Kernel needs to have some additional constructor
// implementaion work before this is legitimately equivalent code to the
// original AST.
/* test('initialized field and constructor', () {
String code = '''
import 'dart:_foreign_helper' show JS, JS_EMBEDDED_GLOBAL;
import 'package:expect/expect.dart';
class Foo {
final value = JS('bool', '#()', JS_EMBEDDED_GLOBAL('', 'foo'));
Foo() {
print('hello world');
}
}
main() => new Foo();
''';
return check(code, lookup: defaultConstructorFor('Foo'));
});*/
}
defaultConstructorFor(String className) => (Compiler compiler) {