Skip to content

Commit

Permalink
[dartdevc] emit base types (void/dynamic) eagerly
Browse files Browse the repository at this point in the history
This is a somewhat roundabout way to prevent a hot restart from redefining these types.
This fixes the issues arising: #37259.
Should more cleanly separate fields reset on a hot restart from ones preserved.

Change-Id: Id0c45cbeed67b574c3259e1f87a405137ae93575
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111315
Reviewed-by: Mark Zhou <[email protected]>
Commit-Queue: Vijay Menon <[email protected]>
  • Loading branch information
vsmenon authored and [email protected] committed Jul 31, 2019
1 parent 0451f59 commit 2390a25
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
29 changes: 23 additions & 6 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
/// declarations are assumed to be available before we start execution.
/// See [startTopLevel].
void _declareBeforeUse(Class c) {
if (c != null && _emittingClassExtends) _emitClass(c);
if (c != null && _emittingClassExtends) {
_emitClass(c);
}
}

js_ast.Statement _emitClassDeclaration(Class c) {
Expand Down Expand Up @@ -2059,11 +2061,26 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
// TODO(jmesserly): it'd be nice to avoid this special case.
var lazyFields = <Field>[];
var savedUri = _currentUri;

// Helper functions to test if a constructor invocation is internal and
// should be eagerly evaluated.
var isInternalConstructor = (ConstructorInvocation node) {
var type = node.getStaticType(_types) as InterfaceType;
var library = type.classNode.enclosingLibrary;
return isSdkInternalRuntime(library);
};
for (var field in fields) {
var init = field.initializer;
if (init == null ||
init is BasicLiteral ||
init is ConstructorInvocation && isInternalConstructor(init) ||
init is StaticInvocation && isInlineJS(init.target)) {
if (init is ConstructorInvocation) {
// This is an eagerly executed constructor invocation. We need to
// ensure the class is emitted before this statement.
var type = init.getStaticType(_types) as InterfaceType;
_emitClass(type.classNode);
}
_currentUri = field.fileUri;
moduleItems.add(js.statement('# = #;', [
_emitTopLevelName(field),
Expand Down Expand Up @@ -5448,11 +5465,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

@override
js_ast.Expression visitPartialInstantiationConstant(
PartialInstantiationConstant node) =>
runtimeCall('gbind(#, #)', [
visitConstant(node.tearOffConstant),
node.types.map(_emitType).toList()
]);
PartialInstantiationConstant node) =>
runtimeCall('gbind(#, #)', [
visitConstant(node.tearOffConstant),
node.types.map(_emitType).toList()
]);

@override
js_ast.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
Expand Down
8 changes: 8 additions & 0 deletions tests/compiler/dartdevc_native/hot_restart_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ Type typeOf<T>() => T;

Type fooOf<T>() => typeOf<Foo<T>>();

typedef funcType = Function(String);

void func(Object o) {}

void main() {
var f1 = Foo<Bar>();
var t1 = typeOf<Foo<Bar>>();
Expect.equals(f1.type(), t1);
var s1 = fooOf<Bar>();
Expect.equals(t1, s1);

Expect.isTrue(func is funcType);

dart.hotRestart();

var f2 = Foo<Bar>();
Expand All @@ -31,4 +37,6 @@ void main() {
Expect.equals(f2.type(), t2);
var s2 = fooOf<Bar>();
Expect.equals(t2, s2);

Expect.isTrue(func is funcType);
}

0 comments on commit 2390a25

Please sign in to comment.