Version 2.0.0-dev.64.1
Merge commit '3e85df5167fc8b6c8d1b94a7505d157b9494b7ab' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1287ea8..8c27cf3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-## 2.0.0-dev.64.0
+## 2.0.0-dev.64.1
### Language
diff --git a/DEPS b/DEPS
index ae550dd..c1107d7 100644
--- a/DEPS
+++ b/DEPS
@@ -110,7 +110,7 @@
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "1.3.4",
"protobuf_tag": "0.7.1",
- "pub_rev": "8b9526c915bf21627a20cd0104cb6c2be25a879f",
+ "pub_rev": "c84ffa0265fe746824aa6f382cb6c41abc406d42",
"pub_semver_tag": "1.4.1",
"quiver_tag": "5aaa3f58c48608af5b027444d561270b53f15dbf",
"resource_rev":"af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/pkg/analysis_server/test/integration/analysis/package_root_test.dart b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
index 5cca2f0..08c2d8d 100644
--- a/pkg/analysis_server/test/integration/analysis/package_root_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
@@ -83,4 +83,10 @@
class SetAnalysisRootsTest_UseCFE extends SetAnalysisRootsTest {
@override
bool get useCFE => true;
+
+ @override
+ @failingTest
+ test_package_root() {
+ return super.test_package_root();
+ }
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
index ff4bb12..a1845c1 100644
--- a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
@@ -379,7 +379,7 @@
ModifierBuilder builder, Scope memberScope, bool isInstanceMember,
[Scope formalParameterScope,
TypeInferenceListener<int, int, Node, int> listener]) {
- ResolutionStorer<int, int, Node, int> storer;
+ ResolutionStorer storer;
var fileResolutions = _resolutions[builder.fileUri];
if (fileResolutions == null) {
fileResolutions = <CollectedResolution>[];
@@ -387,7 +387,7 @@
}
var resolution = new CollectedResolution();
fileResolutions.add(resolution);
- storer = new ResolutionStorer<int, int, Node, int>(resolution.kernelData);
+ storer = new ResolutionStorer(resolution.kernelData);
return super.createListener(
builder, memberScope, isInstanceMember, formalParameterScope, storer);
}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index b65aa46..eb2e46b 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -417,6 +417,11 @@
ConstantVisitor constantVisitor,
ErrorReporter errorReporter,
{ConstructorInvocation invocation}) {
+ if (!constructor.isConst) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.CONST_WITH_NON_CONST, node);
+ return null;
+ }
if (!getConstructorImpl(constructor).isCycleFree) {
// It's not safe to evaluate this constructor, so bail out.
// TODO(paulberry): ensure that a reasonable error message is produced
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index b34a4c1..54f5982 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2168,7 +2168,6 @@
@override
void beginTypeVariable(Token name) {
debugEvent("beginTypeVariable");
- push(ast.simpleIdentifier(name, isDeclaration: true));
}
@override
diff --git a/pkg/analyzer/lib/src/fasta/resolution_storer.dart b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
index ebdd2cc..3713e55 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_storer.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/fasta/resolution_applier.dart';
+import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
@@ -38,15 +39,22 @@
/// Type inference listener that records inferred types for later use by
/// [ResolutionApplier].
-class ResolutionStorer<Location, Declaration, Reference, PrefixInfo>
- extends TypeInferenceListener<Location, Declaration, Reference,
- PrefixInfo> {
+class ResolutionStorer extends _ResolutionStorer<int, int, Node, int> {
+ ResolutionStorer(Map<int, ResolutionData<DartType, int, Node, int>> data)
+ : super(data);
+}
+
+/// Implementation of [ResolutionStorer], with types parameterized to avoid
+/// accidentally peeking into kernel internals.
+///
+/// TODO(paulberry): when the time is right, fuse this with [ResolutionStorer].
+class _ResolutionStorer<Location, Declaration, Reference, PrefixInfo>
+ implements
+ TypeInferenceListener<Location, Declaration, Reference, PrefixInfo> {
final Map<Location,
ResolutionData<DartType, Declaration, Reference, PrefixInfo>> _data;
- final _stack = <Function>[];
-
- ResolutionStorer(this._data);
+ _ResolutionStorer(this._data);
void _store(Location location,
{List<DartType> argumentTypes,
@@ -85,12 +93,36 @@
}
@override
- void asExpressionExit(Location location, DartType inferredType) {
+ void asExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType) {
_store(location, literalType: inferredType, inferredType: inferredType);
}
@override
- void cascadeExpressionExit(Location location, DartType inferredType) {
+ void assertInitializer(InitializerJudgment judgment, Location location) {}
+
+ @override
+ void assertStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void awaitExpression(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("awaitExpression", location, inferredType);
+
+ @override
+ void block(StatementJudgment judgment, Location location) {}
+
+ @override
+ void boolLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("boolLiteral", location, inferredType);
+
+ @override
+ void breakStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void cascadeExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType) {
// Overridden so that the type of the expression will not be recorded. We
// don't need to record the type because the type is always the same as the
// type of the target, and we don't have the appropriate offset so we can't
@@ -98,7 +130,8 @@
}
@override
- void catchStatementEnter(
+ void catchStatement(
+ Catch judgment,
Location location,
DartType guardType,
Location exceptionLocation,
@@ -117,107 +150,161 @@
}
@override
- void constructorInvocationEnter(Location location, DartType typeContext) {
- _push((Reference expressionTarget, DartType inferredType) {
- // A class reference may have already been stored at this location by
- // storeClassReference. We want to replace it with a constructor
- // reference.
- _unstore(location);
- _store(location, inferredType: inferredType, reference: expressionTarget);
- });
+ void conditionalExpression(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("conditionalExpression", location, inferredType);
+
+ @override
+ void constructorInvocation(ExpressionJudgment judgment, Location location,
+ Reference expressionTarget, DartType inferredType) {
+ // A class reference may have already been stored at this location by
+ // storeClassReference. We want to replace it with a constructor
+ // reference.
+ _unstore(location);
+ _store(location, inferredType: inferredType, reference: expressionTarget);
}
@override
- void constructorInvocationExit(
- Location location, Reference expressionTarget, DartType inferredType) {
- _pop()(expressionTarget, inferredType);
- }
+ void continueSwitchStatement(StatementJudgment judgment, Location location) {}
@override
- void fieldInitializerEnter(Location location, Reference initializerField) {
+ void deferredCheck(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("deferredCheck", location, inferredType);
+
+ @override
+ void doStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void doubleLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("doubleLiteral", location, inferredType);
+
+ @override
+ void expressionStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void fieldInitializer(InitializerJudgment judgment, Location location,
+ Reference initializerField) {
_store(location, reference: initializerField);
}
- void finished() {
- assert(_stack.isEmpty);
- }
-
@override
- void forInStatementEnter(
+ void forInStatement(
+ StatementJudgment judgment,
Location location,
Location variableLocation,
+ DartType variableType,
Location writeLocation,
DartType writeType,
Declaration writeVariable,
Reference writeTarget) {
- _push((DartType variableType) {
- if (variableLocation != null) {
- _store(variableLocation, inferredType: variableType);
+ if (variableLocation != null) {
+ _store(variableLocation, inferredType: variableType);
+ } else {
+ if (writeVariable != null) {
+ _store(writeLocation,
+ declaration: writeVariable, inferredType: writeType);
} else {
- if (writeVariable != null) {
- _store(writeLocation,
- declaration: writeVariable, inferredType: writeType);
- } else {
- _store(writeLocation,
- reference: writeTarget,
- isWriteReference: true,
- writeContext: writeType);
- }
+ _store(writeLocation,
+ reference: writeTarget,
+ isWriteReference: true,
+ writeContext: writeType);
}
- });
+ }
}
@override
- void forInStatementExit(
- Location location, bool variablePresent, DartType variableType) {
- _pop()(variableType);
+ void forStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void functionDeclaration(StatementJudgment judgment, Location location,
+ FunctionType inferredType) {
+ _store(location, inferredType: inferredType);
}
@override
- void genericExpressionEnter(
- String expressionType, Location location, DartType typeContext) {
- super.genericExpressionEnter(expressionType, location, typeContext);
- }
+ void functionExpression(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("functionExpression", location, inferredType);
- @override
- void genericExpressionExit(
+ void genericExpression(
String expressionType, Location location, DartType inferredType) {
_store(location, inferredType: inferredType);
- super.genericExpressionExit(expressionType, location, inferredType);
}
@override
- void functionDeclarationExit(Location location, FunctionType inferredType) {
- _store(location, inferredType: inferredType);
- }
+ void ifNull(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression('ifNull', location, inferredType);
@override
- void nullLiteralExit(
- Location location, bool isSynthetic, DartType inferredType) {
+ void ifStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void intLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("intLiteral", location, inferredType);
+
+ @override
+ void invalidInitializer(InitializerJudgment judgment, Location location) {}
+
+ @override
+ void labeledStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void listLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("listLiteral", location, inferredType);
+
+ @override
+ void logicalExpression(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("logicalExpression", location, inferredType);
+
+ @override
+ void mapLiteral(ExpressionJudgment judgment, Location location,
+ DartType typeContext) =>
+ genericExpression("mapLiteral", location, typeContext);
+
+ @override
+ void namedFunctionExpression(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("namedFunctionExpression", location, inferredType);
+
+ @override
+ void not(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("not", location, inferredType);
+
+ @override
+ void nullLiteral(ExpressionJudgment judgment, Location location,
+ bool isSynthetic, DartType inferredType) {
if (isSynthetic) return null;
- super.nullLiteralExit(location, isSynthetic, inferredType);
+ genericExpression("nullLiteral", location, inferredType);
}
@override
- void indexAssignExit(Location location, Reference writeMember,
- Reference combiner, DartType inferredType) {
+ void indexAssign(ExpressionJudgment judgment, Location location,
+ Reference writeMember, Reference combiner, DartType inferredType) {
_store(location,
reference: writeMember, inferredType: inferredType, combiner: combiner);
}
@override
- void isExpressionExit(
- Location location, DartType testedType, DartType inferredType) {
+ void isExpression(ExpressionJudgment judgment, Location location,
+ DartType testedType, DartType inferredType) {
_store(location, literalType: testedType, inferredType: inferredType);
}
- void isNotExpressionExit(
- Location location, DartType type, DartType inferredType) {
+ void isNotExpression(ExpressionJudgment judgment, Location location,
+ DartType type, DartType inferredType) {
_store(location, literalType: type, inferredType: inferredType);
}
@override
- void methodInvocationExit(
+ void methodInvocation(
+ ExpressionJudgment judgment,
Location resultOffset,
List<DartType> argumentsTypes,
bool isImplicitCall,
@@ -235,12 +322,11 @@
invokeType: invokeType,
isImplicitCall: isImplicitCall,
reference: interfaceMember);
-
- super.genericExpressionExit("methodInvocation", resultOffset, inferredType);
}
@override
- void methodInvocationExitCall(
+ void methodInvocationCall(
+ ExpressionJudgment judgment,
Location resultOffset,
List<DartType> argumentsTypes,
bool isImplicitCall,
@@ -256,13 +342,16 @@
argumentTypes: argumentsTypes,
invokeType: invokeType,
isImplicitCall: isImplicitCall);
-
- super.genericExpressionExit("methodInvocation", resultOffset, inferredType);
}
@override
- void propertyAssignExit(Location location, Reference writeMember,
- DartType writeContext, Reference combiner, DartType inferredType) {
+ void propertyAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ Reference writeMember,
+ DartType writeContext,
+ Reference combiner,
+ DartType inferredType) {
_store(location,
isWriteReference: true,
reference: writeMember,
@@ -272,110 +361,128 @@
}
@override
- void propertyGetExit(
- Location location, Reference member, DartType inferredType) {
+ void propertySet(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("propertySet", location, inferredType);
+
+ @override
+ void propertyGet(ExpressionJudgment judgment, Location location,
+ Reference member, DartType inferredType) {
_store(location, reference: member, inferredType: inferredType);
}
@override
- void propertyGetExitCall(Location location, DartType inferredType) {
+ void propertyGetCall(
+ ExpressionJudgment judgment, Location location, DartType inferredType) {
_store(location, isExplicitCall: true);
}
@override
- void redirectingInitializerEnter(
- Location location, Reference initializerTarget) {
+ void redirectingInitializer(InitializerJudgment judgment, Location location,
+ Reference initializerTarget) {
_store(location, reference: initializerTarget);
}
@override
- void staticAssignEnter(Location location, DartType typeContext) {
- _push((Reference writeMember, DartType writeContext, Reference combiner,
- DartType inferredType) {
- _store(location,
- reference: writeMember,
- isWriteReference: true,
- writeContext: writeContext,
- combiner: combiner,
- inferredType: inferredType);
- });
+ void rethrow_(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression('rethrow', location, inferredType);
+
+ @override
+ void returnStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void staticAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ Reference writeMember,
+ DartType writeContext,
+ Reference combiner,
+ DartType inferredType) {
+ _store(location,
+ reference: writeMember,
+ isWriteReference: true,
+ writeContext: writeContext,
+ combiner: combiner,
+ inferredType: inferredType);
}
@override
- void staticAssignExit(Location location, Reference writeMember,
- DartType writeContext, Reference combiner, DartType inferredType) {
- _pop()(writeMember, writeContext, combiner, inferredType);
+ void staticGet(ExpressionJudgment judgment, Location location,
+ Reference expressionTarget, DartType inferredType) {
+ _store(location, reference: expressionTarget, inferredType: inferredType);
}
@override
- void staticGetEnter(Location location, DartType typeContext) {
- _push(
- (Location location, Reference expressionTarget, DartType inferredType) {
- _store(location, reference: expressionTarget, inferredType: inferredType);
- });
- }
-
- @override
- void staticGetExit(
- Location location, Reference expressionTarget, DartType inferredType) {
- _pop()(location, expressionTarget, inferredType);
- }
-
- @override
- void staticInvocationEnter(Location location,
- Location expressionArgumentsLocation, DartType typeContext) {
- _push((Reference expressionTarget,
- List<DartType> expressionArgumentsTypes,
- FunctionType calleeType,
- Substitution substitution,
- DartType inferredType) {
- FunctionType invokeType = substitution == null
- ? calleeType
- : substitution.substituteType(calleeType.withoutTypeParameters);
- _store(expressionArgumentsLocation,
- invokeType: invokeType,
- argumentTypes: expressionArgumentsTypes,
- reference: expressionTarget,
- inferredType: inferredType);
- });
- }
-
- @override
- void staticInvocationExit(
+ void staticInvocation(
+ ExpressionJudgment judgment,
Location location,
Reference expressionTarget,
List<DartType> expressionArgumentsTypes,
FunctionType calleeType,
Substitution substitution,
DartType inferredType) {
- _pop()(expressionTarget, expressionArgumentsTypes, calleeType, substitution,
- inferredType);
+ FunctionType invokeType = substitution == null
+ ? calleeType
+ : substitution.substituteType(calleeType.withoutTypeParameters);
+ _store(location,
+ invokeType: invokeType,
+ argumentTypes: expressionArgumentsTypes,
+ reference: expressionTarget,
+ inferredType: inferredType);
}
@override
- void stringConcatenationExit(Location location, DartType inferredType) {
+ void stringConcatenation(
+ ExpressionJudgment judgment, Location location, DartType inferredType) {
// We don't need the type - we already know that it is String.
// Moreover, the file offset for StringConcatenation is `-1`.
}
@override
- void thisExpressionExit(Location location, DartType inferredType) {}
+ void stringLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("StringLiteral", location, inferredType);
@override
- void typeLiteralEnter(Location location, DartType typeContext) {
- _push((Reference expressionType, DartType inferredType) {
- _store(location, reference: expressionType, inferredType: inferredType);
- });
- }
+ void superInitializer(InitializerJudgment judgment, Location location) {}
- void typeLiteralExit(
- Location location, Reference expressionType, DartType inferredType) {
- _pop()(expressionType, inferredType);
+ @override
+ void switchStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void symbolLiteral(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("symbolLiteral", location, inferredType);
+
+ @override
+ void thisExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType) {}
+
+ @override
+ void throw_(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression('throw', location, inferredType);
+
+ @override
+ void tryCatch(StatementJudgment judgment, Location location) {}
+
+ @override
+ void tryFinally(StatementJudgment judgment, Location location) {}
+
+ void typeLiteral(ExpressionJudgment judgment, Location location,
+ Reference expressionType, DartType inferredType) {
+ _store(location, reference: expressionType, inferredType: inferredType);
}
@override
- void variableAssignExit(Location location, DartType writeContext,
- Declaration writeVariable, Reference combiner, DartType inferredType) {
+ void variableAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ DartType writeContext,
+ Declaration writeVariable,
+ Reference combiner,
+ DartType inferredType) {
_store(location,
declaration: writeVariable,
isWriteReference: true,
@@ -385,14 +492,14 @@
}
@override
- void variableDeclarationExit(
- Location location, DartType statementType, DartType inferredType) {
+ void variableDeclaration(StatementJudgment judgment, Location location,
+ DartType statementType, DartType inferredType) {
_store(location, literalType: statementType, inferredType: inferredType);
}
@override
- void variableGetExit(Location location, bool isInCascade,
- Declaration expressionVariable, DartType inferredType) {
+ void variableGet(ExpressionJudgment judgment, Location location,
+ bool isInCascade, Declaration expressionVariable, DartType inferredType) {
if (isInCascade) {
return;
}
@@ -400,13 +507,16 @@
declaration: expressionVariable, inferredType: inferredType);
}
- void _push(Function f) {
- _stack.add(f);
- }
+ @override
+ void variableSet(ExpressionJudgment judgment, Location location,
+ DartType inferredType) =>
+ genericExpression("variableSet", location, inferredType);
- Function _pop() {
- return _stack.removeLast();
- }
+ @override
+ void whileStatement(StatementJudgment judgment, Location location) {}
+
+ @override
+ void yieldStatement(StatementJudgment judgment, Location location) {}
@override
void storePrefixInfo(Location location, PrefixInfo prefixInfo) {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index 765ee32..4d9b603 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -533,6 +533,13 @@
@override
@failingTest
+ test_constWithNonConst_in_const_context() async {
+ // Bad state: No data for () at 58
+ await super.test_constWithNonConst_in_const_context();
+ }
+
+ @override
+ @failingTest
test_constWithNonConstantArgument_annotation() async {
// Expected 1 errors of type CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT, found 0
await super.test_constWithNonConstantArgument_annotation();
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 5423d74..6923bc6 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -1630,7 +1630,33 @@
}
''');
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.CONST_WITH_NON_CONST]);
+ // TODO(a14n): the error CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE is
+ // redundant and ought to be suppressed.
+ assertErrors(source, [
+ CompileTimeErrorCode.CONST_WITH_NON_CONST,
+ CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+ ]);
+ verify([source]);
+ }
+
+ test_constWithNonConst_in_const_context() async {
+ Source source = addSource(r'''
+class A {
+ const A(x);
+}
+class B {
+}
+main() {
+ const A(B());
+}
+''');
+ await computeAnalysisResult(source);
+ // TODO(a14n): the error CONST_WITH_NON_CONSTANT_ARGUMENT is redundant and
+ // ought to be suppressed.
+ assertErrors(source, [
+ CompileTimeErrorCode.CONST_WITH_NON_CONST,
+ CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT
+ ]);
verify([source]);
}
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index f94b026..8c5dadf 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -188,13 +188,21 @@
void test_constructorInvocation_noArgs() {
EvaluationResult result =
- _getExpressionValue("const C()", context: 'class C {}');
+ _getExpressionValue("const C()", context: 'class C {const C();}');
expect(result.isValid, isTrue);
DartObject value = result.value;
expect(value, isNotNull);
expect(value.type.name, 'C');
}
+ void test_constructorInvocation_noConstConstructor() {
+ EvaluationResult result =
+ _getExpressionValue("const C()", context: 'class C {}');
+ expect(result.isValid, isFalse);
+ DartObject value = result.value;
+ expect(value, isNull);
+ }
+
void test_constructorInvocation_simpleArgs() {
EvaluationResult result = _getExpressionValue("const C(1)", context: '''
class C {
diff --git a/pkg/analyzer/test/generated/package_build_test.dart b/pkg/analyzer/test/generated/package_build_test.dart
index 47980a8..1cc46a6 100644
--- a/pkg/analyzer/test/generated/package_build_test.dart
+++ b/pkg/analyzer/test/generated/package_build_test.dart
@@ -477,7 +477,8 @@
String root, List<String> packageNames) {
final contextBuilder = new MockContextBuilder();
final packages = new MockPackages();
- final packageMap = new Map.fromIterable(packageNames, value: ((_) => []));
+ final packageMap = new Map<String, List<Folder>>.fromIterable(packageNames,
+ value: ((_) => []));
contextBuilder.packagesMapMap[_p(root)] = packages;
contextBuilder.packagesToMapMap[packages] = packageMap;
return PackageBuildWorkspace.find(provider, _p(root), contextBuilder);
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index a8164c0..8b424b6 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -119,15 +119,12 @@
int decision = _cachedDecisions[element];
if (decision == null) {
- // These synthetic elements are not yet present when we initially compute
- // this cache from metadata annotations, so look for their parent.
- if (element is ConstructorBodyEntity) {
- ConstructorBodyEntity body = element;
- decision = _cachedDecisions[body.constructor];
- }
- if (decision == null) {
- decision = _unknown;
- }
+ // TODO(sra): Have annotations for mustInline / noInline for constructor
+ // bodies. (There used to be some logic here to have constructor bodies,
+ // inherit the settings from annotations on the generative
+ // constructor. This was conflated with the heuristic decisions, leading
+ // to lack of inlining where it was beneficial.)
+ decision = _unknown;
}
if (insideLoop) {
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index fb04063..be3be29 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -5361,6 +5361,10 @@
nativeData,
interceptorData);
localsHandler.scopeInfo = closureDataLookup.getScopeInfo(function);
+
+ CapturedScope scopeData = closureDataLookup.getCapturedScope(function);
+ bool forGenerativeConstructorBody = function is ConstructorBodyEntity;
+
_returnLocal = new SyntheticLocal("result", function, function);
localsHandler.updateLocal(_returnLocal, graph.addConstantNull(closedWorld));
@@ -5372,12 +5376,29 @@
compiledArguments[argumentIndex++]);
}
+ bool hasBox = false;
forEachOrderedParameter(_globalLocalsMap, _elementMap, function,
(Local parameter) {
+ if (forGenerativeConstructorBody && scopeData.isBoxed(parameter)) {
+ // The parameter will be a field in the box passed as the last
+ // parameter. So no need to have it.
+ hasBox = true;
+ return;
+ }
HInstruction argument = compiledArguments[argumentIndex++];
localsHandler.updateLocal(parameter, argument);
});
+ if (hasBox) {
+ HInstruction box = compiledArguments[argumentIndex++];
+ assert(box is HCreateBox);
+ // TODO(sra): Make inlining of closures work. We should always call
+ // enterScope, and pass in the inlined 'this' as well as the 'box'.
+ localsHandler.enterScope(scopeData, null,
+ inlinedBox: box,
+ forGenerativeConstructorBody: forGenerativeConstructorBody);
+ }
+
ClassEntity enclosing = function.enclosingClass;
if ((function.isConstructor || function is ConstructorBodyEntity) &&
rtiNeed.classNeedsTypeArguments(enclosing)) {
@@ -5540,7 +5561,17 @@
bool _isFunctionCalledOnce(FunctionEntity element) {
// ConstructorBodyElements are not in the type inference graph.
- if (element is ConstructorBodyEntity) return false;
+ if (element is ConstructorBodyEntity) {
+ // If there are no subclasses with constructors that have this constructor
+ // as a superconstructor, it is called once by the generative
+ // constructor's factory. A simplified version is to check this is a
+ // constructor body for a leaf class.
+ ClassEntity class_ = element.enclosingClass;
+ if (closedWorld.isDirectlyInstantiated(class_)) {
+ return !closedWorld.isIndirectlyInstantiated(class_);
+ }
+ return false;
+ }
return globalInferenceResults.resultOfMember(element).isCalledOnce;
}
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index f0a914c..57f2d1d 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -128,17 +128,17 @@
/// method creates a box and sets up the redirections.
void enterScope(
CapturedScope closureInfo, SourceInformation sourceInformation,
- {bool forGenerativeConstructorBody: false}) {
+ {bool forGenerativeConstructorBody: false, HInstruction inlinedBox}) {
// See if any variable in the top-scope of the function is captured. If yes
// we need to create a box-object.
if (!closureInfo.requiresContextBox) return;
HInstruction box;
// The scope has captured variables.
if (forGenerativeConstructorBody) {
- // The box is passed as a parameter to a generative
- // constructor body.
- box = builder.addParameter(
- closureInfo.context, _abstractValueDomain.nonNullType);
+ // The box is passed as a parameter to a generative constructor body.
+ box = inlinedBox ??
+ builder.addParameter(
+ closureInfo.context, _abstractValueDomain.nonNullType);
} else {
box = createBox(sourceInformation);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index f4a9d05..1a6e1f0 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3517,8 +3517,8 @@
for (Expression expression in expressions) {
expressionOffsets.add(forest.readOffset(expression));
}
- push(new SwitchCase(toKernelExpressionList(expressions), expressionOffsets,
- toKernelStatement(block),
+ push(new SwitchCaseJudgment(toKernelExpressionList(expressions),
+ expressionOffsets, toKernelStatement(block),
isDefault: defaultKeyword != null)
..fileOffset = firstToken.charOffset);
push(labels);
@@ -3534,7 +3534,7 @@
exitLocalScope();
Expression expression = popForValue();
kernel.Statement result =
- new ShadowSwitchStatement(toKernelExpression(expression), cases)
+ new SwitchStatementJudgment(toKernelExpression(expression), cases)
..fileOffset = switchKeyword.charOffset;
if (target.hasUsers) {
result = new LabeledStatementJudgment(result);
@@ -3715,7 +3715,6 @@
@override
void beginTypeVariable(Token name) {
debugEvent("beginTypeVariable");
- push(new Identifier(name));
}
@override
@@ -3911,14 +3910,14 @@
kernel.Statement deprecated_buildCompileTimeErrorStatement(error,
[int charOffset = -1]) {
- return new ShadowExpressionStatement(toKernelExpression(
+ return new ExpressionStatementJudgment(toKernelExpression(
deprecated_buildCompileTimeError(error, charOffset)));
}
kernel.Statement buildCompileTimeErrorStatement(
Message message, int charOffset,
{List<LocatedMessage> context}) {
- return new ShadowExpressionStatement(toKernelExpression(
+ return new ExpressionStatementJudgment(toKernelExpression(
buildCompileTimeError(message, charOffset, noLength,
context: context)));
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/factory.dart b/pkg/front_end/lib/src/fasta/kernel/factory.dart
index 0300a2a..ebae116 100644
--- a/pkg/front_end/lib/src/fasta/kernel/factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/factory.dart
@@ -117,7 +117,14 @@
Expression expression, Token semicolon);
Initializer fieldInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerField);
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token fieldName,
+ Token equals,
+ Expression expression,
+ Node initializerField);
Statement forInStatement(
StatementJudgment judgment,
@@ -245,7 +252,13 @@
ExpressionJudgment judgment, int fileOffset, DartType inferredType);
Initializer redirectingInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerTarget);
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token constructorName,
+ covariant Object argumentList,
+ Node initializerTarget);
Expression rethrow_(ExpressionJudgment judgment, int fileOffset,
Token rethrowKeyword, DartType inferredType);
@@ -279,7 +292,13 @@
Expression stringLiteral(ExpressionJudgment judgment, int fileOffset,
Token literal, String value, DartType inferredType);
- Initializer superInitializer(InitializerJudgment judgment, int fileOffset);
+ Initializer superInitializer(
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token superKeyword,
+ Token period,
+ Token constructorName,
+ covariant Object argumentList);
Statement switchStatement(StatementJudgment judgment, int fileOffset);
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index ee066cd..0c4014e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -74,6 +74,7 @@
BlockJudgment,
BoolJudgment,
BreakJudgment,
+ CatchJudgment,
CheckLibraryIsLoadedJudgment,
ConditionalJudgment,
ContinueJudgment,
@@ -86,7 +87,7 @@
LabeledStatementJudgment,
LoadLibraryJudgment,
NullJudgment,
- ShadowExpressionStatement,
+ ExpressionStatementJudgment,
ShadowForStatement,
IfJudgment,
ShadowListLiteral,
@@ -99,9 +100,9 @@
ShadowStringLiteral,
ShadowSymbolLiteral,
ShadowSyntheticExpression,
- ShadowTryCatch,
+ TryCatchJudgment,
ShadowTryFinally,
- ShadowWhileStatement,
+ WhileJudgment,
YieldJudgment,
ThisJudgment,
ThrowJudgment,
@@ -353,7 +354,7 @@
DartType stackTraceType,
Statement body) {
exceptionType ??= const DynamicType();
- return new Catch(exceptionParameter, body,
+ return new CatchJudgment(exceptionParameter, body,
guard: exceptionType, stackTrace: stackTraceParameter)
..fileOffset = offsetForToken(onKeyword ?? catchKeyword);
}
@@ -378,7 +379,7 @@
}
Statement expressionStatement(Expression expression, Token semicolon) {
- return new ShadowExpressionStatement(expression);
+ return new ExpressionStatementJudgment(expression);
}
@override
@@ -450,7 +451,7 @@
@override
Statement rethrowStatement(Token rethrowKeyword, Token semicolon) {
- return new ShadowExpressionStatement(
+ return new ExpressionStatementJudgment(
new ShadowRethrow()..fileOffset = offsetForToken(rethrowKeyword));
}
@@ -489,7 +490,7 @@
List<Catch> catchClauses, Token finallyKeyword, Statement finallyBlock) {
Statement tryStatement = body;
if (catchClauses != null) {
- tryStatement = new ShadowTryCatch(tryStatement, catchClauses);
+ tryStatement = new TryCatchJudgment(tryStatement, catchClauses);
}
if (finallyBlock != null) {
tryStatement = new ShadowTryFinally(tryStatement, finallyBlock);
@@ -525,7 +526,7 @@
@override
Statement whileStatement(
Token whileKeyword, Expression condition, Statement body) {
- return new ShadowWhileStatement(condition, body)
+ return new WhileJudgment(condition, body)
..fileOffset = whileKeyword.charOffset;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index c331eb7..35a714d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -72,7 +72,7 @@
ShadowConstructorInvocation,
ContinueSwitchJudgment,
ShadowDeferredCheck,
- ShadowExpressionStatement,
+ ExpressionStatementJudgment,
ShadowFactoryConstructorInvocation,
ShadowFieldInitializer,
ShadowForInStatement,
@@ -100,7 +100,8 @@
ShadowSuperInitializer,
ShadowSuperMethodInvocation,
SuperPropertyGetJudgment,
- ShadowSwitchStatement,
+ SwitchCaseJudgment,
+ SwitchStatementJudgment,
ShadowSyntheticExpression,
VariableAssignmentJudgment,
VariableDeclarationJudgment,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
index 46e49f1..96f72a9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_factory.dart
@@ -179,7 +179,14 @@
@override
Initializer fieldInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerField) {
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token fieldName,
+ Token equals,
+ Expression expression,
+ Node initializerField) {
return judgment;
}
@@ -382,7 +389,13 @@
@override
Initializer redirectingInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerTarget) {
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token constructorName,
+ Object argumentList,
+ Node initializerTarget) {
return judgment;
}
@@ -446,7 +459,13 @@
}
@override
- Initializer superInitializer(InitializerJudgment judgment, int fileOffset) {
+ Initializer superInitializer(
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token superKeyword,
+ Token period,
+ Token constructorName,
+ Object argumentList) {
return judgment;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 519886d..642fa62 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -5,7 +5,7 @@
library fasta.kernel_field_builder;
import 'package:kernel/ast.dart'
- show DartType, Expression, Field, Name, Node, NullLiteral;
+ show DartType, Expression, Field, Name, NullLiteral;
import '../../base/instrumentation.dart'
show Instrumentation, InstrumentationValueForType;
@@ -17,7 +17,7 @@
import '../problems.dart' show internalProblem;
import '../type_inference/type_inference_listener.dart'
- show TypeInferenceListener;
+ show KernelTypeInferenceListener;
import 'kernel_body_builder.dart' show KernelBodyBuilder;
@@ -90,7 +90,7 @@
@override
void prepareTopLevelInference() {
if (!isEligibleForInference) return;
- var listener = new TypeInferenceListener<int, int, Node, int>();
+ var listener = new KernelTypeInferenceListener();
var typeInferrer = library.loader.typeInferenceEngine
.createTopLevelTypeInferrer(
listener, field.enclosingClass?.thisType, field);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 73dee2a..a9b13d6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -168,10 +168,9 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.asExpressionEnter(fileOffset, typeContext);
inferrer.inferExpression(factory, judgment, const UnknownType(), false);
inferredType = type;
- inferrer.listener.asExpressionExit(fileOffset, inferredType);
+ inferrer.listener.asExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -187,9 +186,8 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.assertInitializerEnter(fileOffset);
inferrer.inferStatement(factory, judgment);
- inferrer.listener.assertInitializerExit(fileOffset);
+ inferrer.listener.assertInitializer(this, fileOffset);
}
}
@@ -211,7 +209,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.assertStatementEnter(fileOffset);
var conditionJudgment = this.conditionJudgment;
var messageJudgment = this.messageJudgment;
var expectedType = inferrer.coreTypes.boolClass.rawType;
@@ -223,7 +220,7 @@
inferrer.inferExpression(
factory, messageJudgment, const UnknownType(), false);
}
- inferrer.listener.assertStatementExit(fileOffset);
+ inferrer.listener.assertStatement(this, fileOffset);
}
}
@@ -240,7 +237,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.awaitExpressionEnter(fileOffset, typeContext);
if (!inferrer.typeSchemaEnvironment.isEmptyContext(typeContext)) {
typeContext = inferrer.wrapFutureOrType(typeContext);
}
@@ -248,7 +244,7 @@
inferrer.inferExpression(factory, judgment, typeContext, true);
inferredType =
inferrer.typeSchemaEnvironment.unfutureType(judgment.inferredType);
- inferrer.listener.awaitExpressionExit(fileOffset, inferredType);
+ inferrer.listener.awaitExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -263,11 +259,10 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.blockEnter(fileOffset);
for (var judgment in judgments) {
inferrer.inferStatement(factory, judgment);
}
- inferrer.listener.blockExit(fileOffset);
+ inferrer.listener.block(this, fileOffset);
}
}
@@ -282,9 +277,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.boolLiteralEnter(fileOffset, typeContext);
inferredType = inferrer.coreTypes.boolClass.rawType;
- inferrer.listener.boolLiteralExit(fileOffset, inferredType);
+ inferrer.listener.boolLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -309,9 +303,8 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.breakStatementEnter(fileOffset);
// No inference needs to be done.
- inferrer.listener.breakStatementExit(fileOffset);
+ inferrer.listener.breakStatement(this, fileOffset);
}
}
@@ -375,7 +368,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.cascadeExpressionEnter(fileOffset, typeContext);
var lhsType = inferrer.inferExpression(
factory, variable.initializer, typeContext, true);
if (inferrer.strongMode) {
@@ -388,7 +380,7 @@
if (section.body is! Let) break;
section = section.body;
}
- inferrer.listener.cascadeExpressionExit(fileOffset, lhsType);
+ inferrer.listener.cascadeExpression(this, fileOffset, lhsType);
return lhsType;
}
}
@@ -666,7 +658,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.conditionalExpressionEnter(fileOffset, typeContext);
var conditionJudgment = this.conditionJudgment;
var thenJudgment = this.thenJudgment;
var otherwiseJudgment = this.otherwiseJudgment;
@@ -685,7 +676,7 @@
if (inferrer.strongMode) {
staticType = inferredType;
}
- inferrer.listener.conditionalExpressionExit(fileOffset, inferredType);
+ inferrer.listener.conditionalExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -723,7 +714,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.constructorInvocationEnter(fileOffset, typeContext);
var library = inferrer.engine.beingInferred[target];
if (library != null) {
// There is a cyclic dependency where inferring the types of the
@@ -772,7 +762,7 @@
noLength);
}
inferrer.listener
- .constructorInvocationExit(fileOffset, target, inferredType);
+ .constructorInvocation(this, fileOffset, target, inferredType);
if (isRedirected(this)) {
InterfaceType returnType = inferredType;
@@ -821,9 +811,8 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.continueSwitchStatementEnter(fileOffset);
// No inference needs to be done.
- inferrer.listener.continueSwitchStatementExit(fileOffset);
+ inferrer.listener.continueSwitchStatement(this, fileOffset);
}
}
@@ -839,12 +828,11 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.deferredCheckEnter(fileOffset, typeContext);
// Since the variable is not used in the body we don't need to type infer
// it. We can just type infer the body.
var inferredType =
inferrer.inferExpression(factory, body, typeContext, true);
- inferrer.listener.deferredCheckExit(fileOffset, inferredType);
+ inferrer.listener.deferredCheck(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -861,7 +849,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.doStatementEnter(fileOffset);
var conditionJudgment = this.conditionJudgment;
inferrer.inferStatement(factory, bodyJudgment);
var boolType = inferrer.coreTypes.boolClass.rawType;
@@ -869,7 +856,7 @@
factory, conditionJudgment, boolType, !inferrer.isTopLevel);
inferrer.ensureAssignable(boolType, conditionJudgment.inferredType,
condition, condition.fileOffset);
- inferrer.listener.doStatementExit(fileOffset);
+ inferrer.listener.doStatement(this, fileOffset);
}
}
@@ -884,9 +871,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.doubleLiteralEnter(fileOffset, typeContext);
inferredType = inferrer.coreTypes.doubleClass.rawType;
- inferrer.listener.doubleLiteralExit(fileOffset, inferredType);
+ inferrer.listener.doubleLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -916,17 +902,18 @@
}
/// Concrete shadow object representing an expression statement in kernel form.
-class ShadowExpressionStatement extends ExpressionStatement
+class ExpressionStatementJudgment extends ExpressionStatement
implements StatementJudgment {
- ShadowExpressionStatement(Expression expression) : super(expression);
+ ExpressionStatementJudgment(Expression expression) : super(expression);
+
+ Expression get judgment => expression;
@override
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.expressionStatementEnter(fileOffset);
- inferrer.inferExpression(factory, expression, const UnknownType(), false);
- inferrer.listener.expressionStatementExit(fileOffset);
+ inferrer.inferExpression(factory, judgment, const UnknownType(), false);
+ inferrer.listener.expressionStatement(this, fileOffset);
}
}
@@ -964,7 +951,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.constructorInvocationEnter(fileOffset, typeContext);
var inferredType = inferrer.inferInvocation(
factory,
typeContext,
@@ -973,7 +959,7 @@
computeConstructorReturnType(_initialTarget),
arguments);
inferrer.listener
- .constructorInvocationExit(fileOffset, target, inferredType);
+ .constructorInvocation(this, fileOffset, target, inferredType);
if (isRedirected(this)) {
InterfaceType returnType = inferredType;
@@ -1050,11 +1036,10 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.fieldInitializerEnter(fileOffset, field);
var initializerType =
inferrer.inferExpression(factory, value, field.type, true);
inferrer.ensureAssignable(field.type, initializerType, value, fileOffset);
- inferrer.listener.fieldInitializerExit(fileOffset);
+ inferrer.listener.fieldInitializer(this, fileOffset, field);
}
}
@@ -1099,38 +1084,6 @@
context = const UnknownType();
}
context = inferrer.wrapType(context, iterableClass);
- if (syntheticWrite is VariableSet) {
- inferrer.listener.forInStatementEnter(
- fileOffset,
- variable?.fileOffset,
- syntheticWrite.fileOffset,
- syntheticWrite.variable.type,
- syntheticWrite.variable.fileOffset,
- null);
- } else if (syntheticWrite is PropertySet) {
- inferrer.listener.forInStatementEnter(
- fileOffset,
- variable?.fileOffset,
- syntheticWrite.fileOffset,
- syntheticWrite.interfaceTarget?.setterType,
- null,
- syntheticWrite.interfaceTarget);
- } else if (syntheticWrite is StaticSet) {
- inferrer.listener.forInStatementEnter(
- fileOffset,
- variable?.fileOffset,
- syntheticWrite.fileOffset,
- syntheticWrite.target.setterType,
- null,
- syntheticWrite.target);
- } else if (syntheticWrite == null ||
- syntheticWrite is ShadowSyntheticExpression) {
- inferrer.listener.forInStatementEnter(
- fileOffset, variable?.fileOffset, null, null, null, null);
- } else {
- throw new UnimplementedError(
- '(${syntheticWrite.runtimeType}) $syntheticWrite');
- }
var inferredExpressionType = inferrer.resolveTypeParameter(
inferrer.inferExpression(
factory, iterable, context, typeNeeded || typeChecksNeeded));
@@ -1186,8 +1139,44 @@
}
syntheticAssignment._replaceWithDesugared();
}
- inferrer.listener
- .forInStatementExit(fileOffset, variable != null, variable?.type);
+ if (syntheticWrite is VariableSet) {
+ inferrer.listener.forInStatement(
+ this,
+ fileOffset,
+ variable?.fileOffset,
+ variable?.type,
+ syntheticWrite.fileOffset,
+ syntheticWrite.variable.type,
+ syntheticWrite.variable.fileOffset,
+ null);
+ } else if (syntheticWrite is PropertySet) {
+ inferrer.listener.forInStatement(
+ this,
+ fileOffset,
+ variable?.fileOffset,
+ variable?.type,
+ syntheticWrite.fileOffset,
+ syntheticWrite.interfaceTarget?.setterType,
+ null,
+ syntheticWrite.interfaceTarget);
+ } else if (syntheticWrite is StaticSet) {
+ inferrer.listener.forInStatement(
+ this,
+ fileOffset,
+ variable?.fileOffset,
+ variable?.type,
+ syntheticWrite.fileOffset,
+ syntheticWrite.target.setterType,
+ null,
+ syntheticWrite.target);
+ } else if (syntheticWrite == null ||
+ syntheticWrite is ShadowSyntheticExpression) {
+ inferrer.listener.forInStatement(this, fileOffset, variable?.fileOffset,
+ variable?.type, null, null, null, null);
+ } else {
+ throw new UnimplementedError(
+ '(${syntheticWrite.runtimeType}) $syntheticWrite');
+ }
}
}
@@ -1201,7 +1190,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.forStatementEnter(fileOffset);
for (var variable in variables) {
inferrer.inferStatement(factory, variable);
}
@@ -1216,7 +1204,7 @@
inferrer.inferExpression(factory, update, const UnknownType(), false);
}
inferrer.inferStatement(factory, body);
- inferrer.listener.forStatementExit(fileOffset);
+ inferrer.listener.forStatement(this, fileOffset);
}
}
@@ -1233,7 +1221,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.functionDeclarationEnter(fileOffset);
inferrer.inferMetadataKeepingHelper(factory, variable.annotations);
inferrer.inferLocalFunction(
factory,
@@ -1244,7 +1231,7 @@
? (inferrer.strongMode ? null : const DynamicType())
: function.returnType);
var inferredType = variable.type = function.functionType;
- inferrer.listener.functionDeclarationExit(fileOffset, inferredType);
+ inferrer.listener.functionDeclaration(this, fileOffset, inferredType);
}
static void setHasImplicitReturnType(
@@ -1265,10 +1252,9 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.functionExpressionEnter(fileOffset, typeContext);
var inferredType = inferrer.inferLocalFunction(
factory, function, typeContext, fileOffset, null);
- inferrer.listener.functionExpressionExit(fileOffset, inferredType);
+ inferrer.listener.functionExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1299,14 +1285,12 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.ifNullEnter(fileOffset, typeContext);
// To infer `e0 ?? e1` in context K:
// - Infer e0 in context K to get T0
var lhsType = inferrer.inferExpression(factory, _lhs, typeContext, true);
if (inferrer.strongMode) {
variable.type = lhsType;
}
- inferrer.listener.ifNullBeforeRhs(fileOffset);
// - Let J = T0 if K is `?` else K.
// - Infer e1 in context J to get T1
bool useLub = _forceLub || typeContext is UnknownType;
@@ -1322,7 +1306,7 @@
if (inferrer.strongMode) {
body.staticType = inferredType;
}
- inferrer.listener.ifNullExit(fileOffset, inferredType);
+ inferrer.listener.ifNull(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1342,7 +1326,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.ifStatementEnter(fileOffset);
var conditionJudgment = this.conditionJudgment;
var expectedType = inferrer.coreTypes.boolClass.rawType;
inferrer.inferExpression(
@@ -1353,7 +1336,7 @@
if (otherwiseJudgment != null) {
inferrer.inferStatement(factory, otherwiseJudgment);
}
- inferrer.listener.ifStatementExit(fileOffset);
+ inferrer.listener.ifStatement(this, fileOffset);
}
}
@@ -1414,9 +1397,7 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.indexAssignEnter(desugared.fileOffset, typeContext);
var receiverType = _inferReceiver(inferrer, factory);
- inferrer.listener.indexAssignAfterReceiver(write.fileOffset, typeContext);
var writeMember = inferrer.findMethodInvocationMember(receiverType, write);
// To replicate analyzer behavior, we base type inference on the write
// member. TODO(paulberry): would it be better to use the read member
@@ -1470,7 +1451,7 @@
_storeLetType(inferrer, replacedRead, readType);
}
var inferredResult = _inferRhs(inferrer, factory, readType, writeContext);
- inferrer.listener.indexAssignExit(write.fileOffset, writeMember,
+ inferrer.listener.indexAssign(this, write.fileOffset, writeMember,
inferredResult.combiner, inferredResult.type);
_replaceWithDesugared();
return inferredResult.type;
@@ -1498,9 +1479,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.intLiteralEnter(fileOffset, typeContext);
inferredType = inferrer.coreTypes.intClass.rawType;
- inferrer.listener.intLiteralExit(fileOffset, inferredType);
+ inferrer.listener.intLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1514,10 +1494,9 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.invalidInitializerEnter(fileOffset);
inferrer.inferExpression(
factory, variable.initializer, const UnknownType(), false);
- inferrer.listener.invalidInitializerExit(fileOffset);
+ inferrer.listener.invalidInitializer(this, fileOffset);
}
}
@@ -1534,10 +1513,9 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.isExpressionEnter(fileOffset, typeContext);
inferrer.inferExpression(factory, judgment, const UnknownType(), false);
inferredType = inferrer.coreTypes.boolClass.rawType;
- inferrer.listener.isExpressionExit(fileOffset, type, inferredType);
+ inferrer.listener.isExpression(this, fileOffset, type, inferredType);
return inferredType;
}
}
@@ -1561,11 +1539,10 @@
DartType typeContext) {
IsExpression isExpression = this.operand;
- inferrer.listener.isNotExpressionEnter(fileOffset, typeContext);
inferrer.inferExpression(factory, judgment, const UnknownType(), false);
inferredType = inferrer.coreTypes.boolClass.rawType;
inferrer.listener
- .isNotExpressionExit(fileOffset, isExpression.type, inferredType);
+ .isNotExpression(this, fileOffset, isExpression.type, inferredType);
return inferredType;
}
}
@@ -1581,9 +1558,8 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.labeledStatementEnter(fileOffset);
inferrer.inferStatement(factory, judgment);
- inferrer.listener.labeledStatementExit(fileOffset);
+ inferrer.listener.labeledStatement(this, fileOffset);
}
}
@@ -1605,7 +1581,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.listLiteralEnter(fileOffset, typeContext);
var listClass = inferrer.coreTypes.listClass;
var listType = listClass.thisType;
List<DartType> inferredTypes;
@@ -1657,7 +1632,7 @@
}
}
var inferredType = new InterfaceType(listClass, [inferredTypeArgument]);
- inferrer.listener.listLiteralExit(fileOffset, inferredType);
+ inferrer.listener.listLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1675,17 +1650,15 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.logicalExpressionEnter(fileOffset, typeContext);
var boolType = inferrer.coreTypes.boolClass.rawType;
var leftType =
inferrer.inferExpression(factory, left, boolType, !inferrer.isTopLevel);
- inferrer.listener.logicalExpressionBeforeRhs(fileOffset);
var rightType = inferrer.inferExpression(
factory, right, boolType, !inferrer.isTopLevel);
inferrer.ensureAssignable(boolType, leftType, left, left.fileOffset);
inferrer.ensureAssignable(boolType, rightType, right, right.fileOffset);
var inferredType = boolType;
- inferrer.listener.logicalExpressionExit(fileOffset, inferredType);
+ inferrer.listener.logicalExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1726,7 +1699,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.mapLiteralEnter(fileOffset, typeContext);
var mapClass = inferrer.coreTypes.mapClass;
var mapType = mapClass.thisType;
List<DartType> inferredTypes;
@@ -1797,7 +1769,7 @@
}
var inferredType =
new InterfaceType(mapClass, [inferredKeyType, inferredValueType]);
- inferrer.listener.mapLiteralExit(fileOffset, inferredType);
+ inferrer.listener.mapLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1868,11 +1840,10 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.namedFunctionExpressionEnter(fileOffset, typeContext);
var inferredType = inferrer.inferExpression(
factory, variable.initializer, typeContext, true);
if (inferrer.strongMode) variable.type = inferredType;
- inferrer.listener.namedFunctionExpressionExit(fileOffset, inferredType);
+ inferrer.listener.namedFunctionExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1888,14 +1859,13 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.notEnter(fileOffset, typeContext);
// First infer the receiver so we can look up the method that was invoked.
var boolType = inferrer.coreTypes.boolClass.rawType;
var actualType = inferrer.inferExpression(
factory, operand, boolType, !inferrer.isTopLevel);
inferrer.ensureAssignable(boolType, actualType, operand, fileOffset);
DartType inferredType = boolType;
- inferrer.listener.notExit(fileOffset, inferredType);
+ inferrer.listener.not(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -1977,10 +1947,9 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.nullLiteralEnter(fileOffset, typeContext);
inferredType = inferrer.coreTypes.nullClass.rawType;
inferrer.listener
- .nullLiteralExit(fileOffset, fileOffset == -1, inferredType);
+ .nullLiteral(this, fileOffset, fileOffset == -1, inferredType);
return inferredType;
}
}
@@ -2053,7 +2022,6 @@
DartType typeContext) {
var receiverType = _inferReceiver(inferrer, factory);
- inferrer.listener.propertyAssignEnter(write.fileOffset, typeContext);
DartType readType;
if (read != null) {
var readMember =
@@ -2073,7 +2041,8 @@
var writeContext = inferrer.getSetterType(writeMember, receiverType);
var inferredResult = _inferRhs(inferrer, factory, readType, writeContext);
if (inferrer.strongMode) nullAwareGuard?.staticType = inferredResult.type;
- inferrer.listener.propertyAssignExit(
+ inferrer.listener.propertyAssign(
+ this,
write.fileOffset,
inferrer.getRealTarget(writeMember),
writeContext,
@@ -2119,7 +2088,6 @@
@override
infer<Expression, Statement, Initializer, Type>(ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.redirectingInitializerEnter(fileOffset, target);
List<TypeParameter> classTypeParameters =
target.enclosingClass.typeParameters;
List<DartType> typeArguments =
@@ -2132,7 +2100,7 @@
target.function.functionType, target.enclosingClass.thisType, arguments,
skipTypeArgumentInference: true);
ArgumentsJudgment.removeNonInferrableArgumentTypes(arguments);
- inferrer.listener.redirectingInitializerExit(fileOffset);
+ inferrer.listener.redirectingInitializer(this, fileOffset, target);
}
}
@@ -2145,9 +2113,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.rethrowEnter(fileOffset, typeContext);
var inferredType = const BottomType();
- inferrer.listener.rethrowExit(fileOffset, inferredType);
+ inferrer.listener.rethrow_(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -2162,7 +2129,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.returnStatementEnter(fileOffset);
var judgment = this.judgment;
var closureContext = inferrer.closureContext;
var typeContext = !closureContext.isGenerator
@@ -2182,7 +2148,7 @@
closureContext.handleReturn(
inferrer, inferredType, expression, fileOffset);
}
- inferrer.listener.returnStatementExit(fileOffset);
+ inferrer.listener.returnStatement(this, fileOffset);
}
}
@@ -2211,7 +2177,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.staticAssignEnter(this.write?.fileOffset, typeContext);
DartType readType = const DynamicType(); // Only used in error recovery
var read = this.read;
if (read is StaticGet) {
@@ -2230,7 +2195,7 @@
}
}
var inferredResult = _inferRhs(inferrer, factory, readType, writeContext);
- inferrer.listener.staticAssignExit(write?.fileOffset, writeMember,
+ inferrer.listener.staticAssign(this, write?.fileOffset, writeMember,
writeContext, inferredResult.combiner, inferredResult.type);
_replaceWithDesugared();
return inferredResult.type;
@@ -2249,7 +2214,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.staticGetEnter(fileOffset, typeContext);
var target = this.target;
if (target is ShadowField && target.inferenceNode != null) {
target.inferenceNode.resolve();
@@ -2260,7 +2224,7 @@
type = inferrer.instantiateTearOff(type, typeContext, this);
}
inferredType = type;
- inferrer.listener.staticGetExit(fileOffset, target, inferredType);
+ inferrer.listener.staticGet(this, fileOffset, target, inferredType);
return inferredType;
}
}
@@ -2279,13 +2243,12 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.staticInvocationEnter(
- this.fileOffset, arguments.fileOffset, typeContext);
var calleeType = target.function.functionType;
var inferredType = inferrer.inferInvocation(factory, typeContext,
fileOffset, calleeType, calleeType.returnType, arguments);
- inferrer.listener.staticInvocationExit(
- fileOffset,
+ inferrer.listener.staticInvocation(
+ this,
+ arguments.fileOffset,
target,
arguments.types,
inferrer.lastCalleeType,
@@ -2307,7 +2270,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.stringConcatenationEnter(fileOffset, typeContext);
if (!inferrer.isTopLevel) {
for (kernel.Expression expression in expressions) {
inferrer.inferExpression(
@@ -2315,7 +2277,7 @@
}
}
var inferredType = inferrer.coreTypes.stringClass.rawType;
- inferrer.listener.stringConcatenationExit(fileOffset, inferredType);
+ inferrer.listener.stringConcatenation(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -2331,9 +2293,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.stringLiteralEnter(fileOffset, typeContext);
var inferredType = inferrer.coreTypes.stringClass.rawType;
- inferrer.listener.stringLiteralExit(fileOffset, inferredType);
+ inferrer.listener.stringLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -2348,7 +2309,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.superInitializerEnter(fileOffset);
var substitution = Substitution.fromSupertype(inferrer.classHierarchy
.getClassAsInstanceOf(
inferrer.thisType.classNode, target.enclosingClass));
@@ -2361,7 +2321,7 @@
inferrer.thisType,
arguments,
skipTypeArgumentInference: true);
- inferrer.listener.superInitializerExit(fileOffset);
+ inferrer.listener.superInitializer(this, fileOffset);
}
}
@@ -2414,27 +2374,48 @@
}
}
+/// Concrete shadow object representing a switch case.
+class SwitchCaseJudgment extends SwitchCase {
+ SwitchCaseJudgment(
+ List<Expression> expressions, List<int> expressionOffsets, Statement body,
+ {bool isDefault: false})
+ : super(expressions, expressionOffsets, body, isDefault: isDefault);
+
+ SwitchCaseJudgment.defaultCase(Statement body) : super.defaultCase(body);
+
+ SwitchCaseJudgment.empty() : super.empty();
+
+ List<ExpressionJudgment> get expressionJudgments => expressions.cast();
+
+ StatementJudgment get bodyJudgment => body;
+}
+
/// Concrete shadow object representing a switch statement in kernel form.
-class ShadowSwitchStatement extends SwitchStatement
+class SwitchStatementJudgment extends SwitchStatement
implements StatementJudgment {
- ShadowSwitchStatement(Expression expression, List<SwitchCase> cases)
+ SwitchStatementJudgment(Expression expression, List<SwitchCase> cases)
: super(expression, cases);
+ ExpressionJudgment get expressionJudgment => expression;
+
+ List<SwitchCaseJudgment> get caseJudgments => cases.cast();
+
@override
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.switchStatementEnter(fileOffset);
- var expressionType = inferrer.inferExpression(
- factory, expression, const UnknownType(), true);
- for (var switchCase in cases) {
- for (var caseExpression in switchCase.expressions) {
+ var expressionJudgment = this.expressionJudgment;
+ inferrer.inferExpression(
+ factory, expressionJudgment, const UnknownType(), true);
+ var expressionType = expressionJudgment.inferredType;
+ for (var switchCase in caseJudgments) {
+ for (var caseExpression in switchCase.expressionJudgments) {
inferrer.inferExpression(
factory, caseExpression, expressionType, false);
}
- inferrer.inferStatement(factory, switchCase.body);
+ inferrer.inferStatement(factory, switchCase.bodyJudgment);
}
- inferrer.listener.switchStatementExit(fileOffset);
+ inferrer.listener.switchStatement(this, fileOffset);
}
}
@@ -2449,9 +2430,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.symbolLiteralEnter(fileOffset, typeContext);
var inferredType = inferrer.coreTypes.symbolClass.rawType;
- inferrer.listener.symbolLiteralExit(fileOffset, inferredType);
+ inferrer.listener.symbolLiteral(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -2532,9 +2512,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.thisExpressionEnter(fileOffset, typeContext);
inferredType = inferrer.thisType ?? const DynamicType();
- inferrer.listener.thisExpressionExit(fileOffset, inferredType);
+ inferrer.listener.thisExpression(this, fileOffset, inferredType);
return inferredType;
}
}
@@ -2551,36 +2530,51 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.throwEnter(fileOffset, typeContext);
inferrer.inferExpression(factory, judgment, const UnknownType(), false);
inferredType = const BottomType();
- inferrer.listener.throwExit(fileOffset, inferredType);
+ inferrer.listener.throw_(this, fileOffset, inferredType);
return inferredType;
}
}
+/// Concrete shadow object representing a catch clause.
+class CatchJudgment extends Catch {
+ CatchJudgment(VariableDeclaration exception, Statement body,
+ {DartType guard: const DynamicType(), VariableDeclaration stackTrace})
+ : super(exception, body, guard: guard, stackTrace: stackTrace);
+
+ VariableDeclarationJudgment get exceptionJudgment => exception;
+
+ VariableDeclarationJudgment get stackTraceJudgment => stackTrace;
+
+ StatementJudgment get bodyJudgment => body;
+}
+
/// Concrete shadow object representing a try-catch block in kernel form.
-class ShadowTryCatch extends TryCatch implements StatementJudgment {
- ShadowTryCatch(Statement body, List<Catch> catches) : super(body, catches);
+class TryCatchJudgment extends TryCatch implements StatementJudgment {
+ TryCatchJudgment(Statement body, List<Catch> catches) : super(body, catches);
+
+ StatementJudgment get bodyJudgment => body;
+
+ List<CatchJudgment> get catchJudgments => catches.cast();
@override
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.tryCatchEnter(fileOffset);
- inferrer.inferStatement(factory, body);
- for (var catch_ in catches) {
- inferrer.listener.catchStatementEnter(
+ inferrer.inferStatement(factory, bodyJudgment);
+ for (var catch_ in catchJudgments) {
+ inferrer.inferStatement(factory, catch_.bodyJudgment);
+ inferrer.listener.catchStatement(
+ catch_,
catch_.fileOffset,
catch_.guard,
- catch_.exception?.fileOffset,
- catch_.exception?.type,
- catch_.stackTrace?.fileOffset,
- catch_.stackTrace?.type);
- inferrer.inferStatement(factory, catch_.body);
- inferrer.listener.catchStatementExit(catch_.fileOffset);
+ catch_.exceptionJudgment?.fileOffset,
+ catch_.exceptionJudgment?.type,
+ catch_.stackTraceJudgment?.fileOffset,
+ catch_.stackTraceJudgment?.type);
}
- inferrer.listener.tryCatchExit(fileOffset);
+ inferrer.listener.tryCatch(this, fileOffset);
}
}
@@ -2593,10 +2587,9 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.tryFinallyEnter(fileOffset);
inferrer.inferStatement(factory, body);
inferrer.inferStatement(factory, finalizer);
- inferrer.listener.tryFinallyExit(fileOffset);
+ inferrer.listener.tryFinally(this, fileOffset);
}
}
@@ -2758,9 +2751,8 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.typeLiteralEnter(fileOffset, typeContext);
inferredType = inferrer.coreTypes.typeClass.rawType;
- inferrer.listener.typeLiteralExit(fileOffset, type, inferredType);
+ inferrer.listener.typeLiteral(this, fileOffset, type, inferredType);
return inferredType;
}
}
@@ -2848,7 +2840,6 @@
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory,
DartType typeContext) {
- inferrer.listener.variableAssignEnter(this.write.fileOffset, typeContext);
DartType readType;
var read = this.read;
if (read is VariableGet) {
@@ -2863,7 +2854,8 @@
}
}
var inferredResult = _inferRhs(inferrer, factory, readType, writeContext);
- inferrer.listener.variableAssignExit(
+ inferrer.listener.variableAssign(
+ this,
write.fileOffset,
writeContext,
write is VariableSet ? write.variable.fileOffset : null,
@@ -2925,7 +2917,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.variableDeclarationEnter(fileOffset);
if (annotationJudgments.isNotEmpty) {
inferrer.inferMetadataKeepingHelper(factory, annotationJudgments);
@@ -2972,8 +2963,8 @@
initializer = replacedInitializer;
}
}
- inferrer.listener.variableDeclarationExit(
- fileOffset, type, _implicitlyTyped ? inferredType : type);
+ inferrer.listener.variableDeclaration(
+ this, fileOffset, type, _implicitlyTyped ? inferredType : type);
}
/// Determine whether the given [VariableDeclarationJudgment] had an implicit
@@ -3026,7 +3017,6 @@
bool mutatedInClosure = variable._mutatedInClosure;
DartType declaredOrInferredType = variable.type;
- inferrer.listener.variableGetEnter(fileOffset, typeContext);
DartType promotedType = inferrer.typePromoter
.computePromotedType(_fact, _scope, mutatedInClosure);
if (promotedType != null) {
@@ -3039,29 +3029,32 @@
type = inferrer.instantiateTearOff(type, typeContext, this);
}
inferredType = type;
- inferrer.listener.variableGetExit(
- fileOffset, _isInCascade(), variable.fileOffset, inferredType);
+ inferrer.listener.variableGet(
+ this, fileOffset, _isInCascade(), variable.fileOffset, inferredType);
return inferredType;
}
}
/// Concrete shadow object representing a while loop in kernel form.
-class ShadowWhileStatement extends WhileStatement implements StatementJudgment {
- ShadowWhileStatement(Expression condition, Statement body)
- : super(condition, body);
+class WhileJudgment extends WhileStatement implements StatementJudgment {
+ WhileJudgment(Expression condition, Statement body) : super(condition, body);
+
+ ExpressionJudgment get conditionJudgment => condition;
+
+ StatementJudgment get bodyJudgment => body;
@override
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.whileStatementEnter(fileOffset);
+ var conditionJudgment = this.conditionJudgment;
var expectedType = inferrer.coreTypes.boolClass.rawType;
- var actualType = inferrer.inferExpression(
- factory, condition, expectedType, !inferrer.isTopLevel);
- inferrer.ensureAssignable(
- expectedType, actualType, condition, condition.fileOffset);
- inferrer.inferStatement(factory, body);
- inferrer.listener.whileStatementExit(fileOffset);
+ inferrer.inferExpression(
+ factory, conditionJudgment, expectedType, !inferrer.isTopLevel);
+ inferrer.ensureAssignable(expectedType, conditionJudgment.inferredType,
+ condition, condition.fileOffset);
+ inferrer.inferStatement(factory, bodyJudgment);
+ inferrer.listener.whileStatement(this, fileOffset);
}
}
@@ -3076,7 +3069,6 @@
void infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer,
Factory<Expression, Statement, Initializer, Type> factory) {
- inferrer.listener.yieldStatementEnter(fileOffset);
var judgment = this.judgment;
var closureContext = inferrer.closureContext;
if (closureContext.isGenerator) {
@@ -3094,7 +3086,7 @@
}
closureContext.handleYield(
inferrer, isYieldStar, judgment.inferredType, expression, fileOffset);
- inferrer.listener.yieldStatementExit(fileOffset);
+ inferrer.listener.yieldStatement(this, fileOffset);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart b/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
index 54bc2a2..e3aac90 100644
--- a/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/toplevel_inference_factory.dart
@@ -141,7 +141,14 @@
@override
void fieldInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerField) {}
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token fieldName,
+ Token equals,
+ void expression,
+ Node initializerField) {}
@override
void forInStatement(
@@ -289,7 +296,13 @@
@override
void redirectingInitializer(
- InitializerJudgment judgment, int fileOffset, Node initializerTarget) {}
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token thisKeyword,
+ Token period,
+ Token constructorName,
+ Object argumentList,
+ Node initializerTarget) {}
@override
void rethrow_(ExpressionJudgment judgment, int fileOffset,
@@ -337,7 +350,13 @@
String value, DartType inferredType) {}
@override
- void superInitializer(InitializerJudgment judgment, int fileOffset) {}
+ void superInitializer(
+ InitializerJudgment judgment,
+ int fileOffset,
+ Token superKeyword,
+ Token period,
+ Token constructorName,
+ Object argumentList) {}
@override
void switchStatement(StatementJudgment judgment, int fileOffset) {}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index dba1f6c..b75076e 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -903,6 +903,7 @@
/// Handle the begin of a type formal parameter (e.g. "X extends Y").
/// Substructures:
/// - Metadata
+ /// - Name (identifier)
void beginTypeVariable(Token name) {}
/// Handle the end of a type formal parameter (e.g. "X extends Y").
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index f70d408..4921416 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1947,10 +1947,7 @@
/// ```
Token parseTypeVariable(Token token) {
token = parseMetadataStar(token);
- token = token.next.kind == IDENTIFIER_TOKEN
- ? token.next
- : IdentifierContext.typeVariableDeclaration
- .ensureIdentifier(token, this);
+ token = ensureIdentifier(token, IdentifierContext.typeVariableDeclaration);
listener.beginTypeVariable(token);
Token extendsOrSuper = null;
Token next = token.next;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 2b8f311..1370d5a 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -511,6 +511,7 @@
token = token.next;
listener.beginMetadataStar(token);
listener.endMetadataStar(0);
+ listener.handleIdentifier(token, IdentifierContext.typeVariableDeclaration);
listener.beginTypeVariable(token);
listener.handleNoType(token);
token = processEndGroup(token, start, parser);
@@ -658,10 +659,8 @@
int count = 0;
while (true) {
token = parser.parseMetadataStar(next);
- token = token.next.kind == IDENTIFIER_TOKEN
- ? token.next
- : IdentifierContext.typeVariableDeclaration
- .ensureIdentifier(token, parser);
+ token = parser.ensureIdentifier(
+ token, IdentifierContext.typeVariableDeclaration);
parser.listener.beginTypeVariable(token);
Token extendsOrSuper = null;
next = token.next;
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 516a6b6..961ebe3 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -42,7 +42,7 @@
import '../type_inference/type_inference_engine.dart' show TypeInferenceEngine;
import '../type_inference/type_inference_listener.dart'
- show TypeInferenceListener;
+ show KernelTypeInferenceListener, TypeInferenceListener;
import 'source_library_builder.dart' show SourceLibraryBuilder;
@@ -449,7 +449,7 @@
@override
void endTypeVariable(Token token, Token extendsOrSuper) {
debugEvent("TypeVariable");
- discard(1); // Metadata.
+ discard(2); // Name and metadata.
}
@override
@@ -534,7 +534,7 @@
ModifierBuilder builder, Scope memberScope, bool isInstanceMember,
[Scope formalParameterScope,
TypeInferenceListener<int, int, Node, int> listener]) {
- listener ??= new TypeInferenceListener<int, int, Node, int>();
+ listener ??= new KernelTypeInferenceListener();
// Note: we set thisType regardless of whether we are building a static
// member, since that provides better error recovery.
InterfaceType thisType = currentClass?.target?.thisType;
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index f0e69b9..3a98d19 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1109,8 +1109,6 @@
@override
void beginTypeVariable(Token token) {
debugEvent("beginTypeVariable");
- push(token.lexeme);
- push(token.charOffset);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
index 28ea849..fcf385f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
@@ -2,29 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE.md file.
-import 'package:kernel/ast.dart' show DartType, FunctionType;
+import 'package:kernel/ast.dart' show Catch, DartType, FunctionType, Node;
import 'package:kernel/type_algebra.dart' show Substitution;
-/// Base class for [TypeInferenceListener] that defines the API for debugging.
-///
-/// By default no debug info is printed. To enable debug printing, mix in
-/// [TypeInferenceDebugging].
-class TypeInferenceBase<Location> {
- void genericExpressionEnter(
- String expressionType, Location location, DartType typeContext) {}
-
- void genericExpressionExit(
- String expressionType, Location location, DartType inferredType) {}
-
- void genericInitializerEnter(String initializerType, Location location) {}
-
- void genericInitializerExit(String initializerType, Location location) {}
-
- void genericStatementEnter(String statementType, Location location) {}
-
- void genericStatementExit(String statementType, Location location) {}
-}
+import '../kernel/kernel_shadow_ast.dart'
+ show ExpressionJudgment, InitializerJudgment, StatementJudgment;
/// Callback interface used by [TypeInferrer] to report the results of type
/// inference to a client.
@@ -38,444 +21,502 @@
/// The default implementation (in this base class) does nothing, however it can
/// be used to debug type inference by uncommenting the
/// "with TypeInferenceDebugging" clause below.
-class TypeInferenceListener<Location, Declaration, Reference, PrefixInfo>
- extends TypeInferenceBase<Location> {
- void asExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("asExpression", location, typeContext);
+abstract class TypeInferenceListener<Location, Declaration, Reference,
+ PrefixInfo> {
+ void asExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void asExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("asExpression", location, inferredType);
+ void assertInitializer(InitializerJudgment judgment, Location location);
- void assertInitializerEnter(Location location) =>
- genericInitializerEnter("assertInitializer", location);
+ void assertStatement(StatementJudgment judgment, Location location);
- void assertInitializerExit(Location location) =>
- genericInitializerExit("assertInitializer", location);
+ void awaitExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void assertStatementEnter(Location location) =>
- genericStatementEnter('assertStatement', location);
+ void block(StatementJudgment judgment, Location location);
- void assertStatementExit(Location location) =>
- genericStatementExit('assertStatement', location);
+ void boolLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void awaitExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("awaitExpression", location, typeContext);
+ void breakStatement(StatementJudgment judgment, Location location);
- void awaitExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("awaitExpression", location, inferredType);
+ void cascadeExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void blockEnter(Location location) =>
- genericStatementEnter('block', location);
-
- void blockExit(Location location) => genericStatementExit('block', location);
-
- void boolLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("boolLiteral", location, typeContext);
-
- void boolLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("boolLiteral", location, inferredType);
-
- void breakStatementEnter(Location location) =>
- genericStatementEnter('breakStatement', location);
-
- void breakStatementExit(Location location) =>
- genericStatementExit('breakStatement', location);
-
- void cascadeExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("cascade", location, typeContext);
-
- void cascadeExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("cascade", location, inferredType);
-
- void catchStatementEnter(
+ void catchStatement(
+ Catch judgment,
Location location,
DartType guardType,
Location exceptionLocation,
DartType exceptionType,
Location stackTraceLocation,
- DartType stackTraceType) {}
+ DartType stackTraceType);
- void catchStatementExit(Location location) {}
+ void conditionalExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void conditionalExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("conditionalExpression", location, typeContext);
+ void constructorInvocation(ExpressionJudgment judgment, Location location,
+ Reference expressionTarget, DartType inferredType);
- void conditionalExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("conditionalExpression", location, inferredType);
+ void continueSwitchStatement(StatementJudgment judgment, Location location);
- void constructorInvocationEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("constructorInvocation", location, typeContext);
+ void deferredCheck(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void constructorInvocationExit(Location location, Reference expressionTarget,
- DartType inferredType) =>
- genericExpressionExit("constructorInvocation", location, inferredType);
+ void doStatement(StatementJudgment judgment, Location location);
- void continueSwitchStatementEnter(Location location) =>
- genericStatementEnter('continueSwitchStatement', location);
+ void doubleLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void continueSwitchStatementExit(Location location) =>
- genericStatementExit('continueSwitchStatement', location);
+ void expressionStatement(StatementJudgment judgment, Location location);
- void deferredCheckEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("deferredCheck", location, typeContext);
+ void fieldInitializer(InitializerJudgment judgment, Location location,
+ Reference initializerField);
- void deferredCheckExit(Location location, DartType inferredType) =>
- genericExpressionExit("deferredCheck", location, inferredType);
+ void forInStatement(
+ StatementJudgment judgment,
+ Location location,
+ Location variableLocation,
+ DartType variableType,
+ Location writeLocation,
+ DartType writeVariableType,
+ Declaration writeVariable,
+ Reference writeTarget);
- void doStatementEnter(Location location) =>
- genericStatementEnter("doStatement", location);
+ void forStatement(StatementJudgment judgment, Location location);
- void doStatementExit(Location location) =>
- genericStatementExit("doStatement", location);
+ void functionDeclaration(
+ StatementJudgment judgment, Location location, FunctionType inferredType);
- void doubleLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("doubleLiteral", location, typeContext);
+ void functionExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void doubleLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("doubleLiteral", location, inferredType);
+ void ifNull(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void dryRunEnter(Location location) =>
- genericExpressionEnter("dryRun", location, null);
+ void ifStatement(StatementJudgment judgment, Location location);
- void dryRunExit(Location location) =>
- genericExpressionExit("dryRun", location, null);
+ void indexAssign(ExpressionJudgment judgment, Location location,
+ Reference writeMember, Reference combiner, DartType inferredType);
- void expressionStatementEnter(Location location) =>
- genericStatementEnter('expressionStatement', location);
+ void intLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void expressionStatementExit(Location location) =>
- genericStatementExit('expressionStatement', location);
+ void invalidInitializer(InitializerJudgment judgment, Location location);
- void fieldInitializerEnter(Location location, Reference initializerField) =>
- genericInitializerEnter("fieldInitializer", location);
+ void isExpression(ExpressionJudgment judgment, Location location,
+ DartType testedType, DartType inferredType);
- void fieldInitializerExit(Location location) =>
- genericInitializerExit("fieldInitializer", location);
+ void isNotExpression(ExpressionJudgment judgment, Location location,
+ DartType type, DartType inferredType);
- void forInStatementEnter(
- Location location,
- Location variableLocation,
- Location writeLocation,
- DartType writeVariableType,
- Declaration writeVariable,
- Reference writeTarget) =>
- genericStatementEnter('forInStatement', location);
+ void labeledStatement(StatementJudgment judgment, Location location);
- void forInStatementExit(
- Location location, bool variablePresent, DartType variableType) =>
- genericStatementExit('forInStatement', location);
+ void listLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void forStatementEnter(Location location) =>
- genericStatementEnter('forStatement', location);
+ void logicalExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void forStatementExit(Location location) =>
- genericStatementExit('forStatement', location);
+ void mapLiteral(
+ ExpressionJudgment judgment, Location location, DartType typeContext);
- void functionDeclarationEnter(Location location) =>
- genericStatementEnter('functionDeclaration', location);
+ void methodInvocation(
+ ExpressionJudgment judgment,
+ Location resultOffset,
+ List<DartType> argumentsTypes,
+ bool isImplicitCall,
+ Reference interfaceMember,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType);
- void functionDeclarationExit(Location location, FunctionType inferredType) =>
- genericStatementExit('functionDeclaration', location);
+ void methodInvocationCall(
+ ExpressionJudgment judgment,
+ Location resultOffset,
+ List<DartType> argumentsTypes,
+ bool isImplicitCall,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType);
- void functionExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("functionExpression", location, typeContext);
+ void namedFunctionExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void functionExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("functionExpression", location, inferredType);
+ void not(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void ifNullBeforeRhs(Location location) {}
+ void nullLiteral(ExpressionJudgment judgment, Location location,
+ bool isSynthetic, DartType inferredType);
- void ifNullEnter(Location location, DartType typeContext) =>
- genericExpressionEnter('ifNull', location, typeContext);
+ void propertyAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ Reference writeMember,
+ DartType writeContext,
+ Reference combiner,
+ DartType inferredType);
- void ifNullExit(Location location, DartType inferredType) =>
- genericExpressionExit('ifNull', location, inferredType);
+ void propertyGet(ExpressionJudgment judgment, Location location,
+ Reference member, DartType inferredType);
- void ifStatementEnter(Location location) =>
- genericStatementEnter('ifStatement', location);
+ void propertyGetCall(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void ifStatementExit(Location location) =>
- genericStatementExit('ifStatement', location);
+ void propertySet(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void indexAssignAfterReceiver(Location location, DartType typeContext) {}
+ void redirectingInitializer(InitializerJudgment judgment, Location location,
+ Reference initializerTarget);
- void indexAssignEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("indexAssign", location, typeContext);
+ void rethrow_(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void indexAssignExit(Location location, Reference writeMember,
- Reference combiner, DartType inferredType) =>
- genericExpressionExit("indexAssign", location, inferredType);
+ void returnStatement(StatementJudgment judgment, Location location);
- void intLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("intLiteral", location, typeContext);
+ void staticAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ Reference writeMember,
+ DartType writeContext,
+ Reference combiner,
+ DartType inferredType);
- void intLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("intLiteral", location, inferredType);
+ void staticGet(ExpressionJudgment judgment, Location location,
+ Reference expressionTarget, DartType inferredType);
- void invalidInitializerEnter(Location location) =>
- genericInitializerEnter("invalidInitializer", location);
+ void staticInvocation(
+ ExpressionJudgment judgment,
+ Location location,
+ Reference expressionTarget,
+ List<DartType> expressionArgumentsTypes,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType);
- void invalidInitializerExit(Location location) =>
- genericInitializerExit("invalidInitializer", location);
+ void stringConcatenation(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void isExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("isExpression", location, typeContext);
+ void stringLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void isExpressionExit(
- Location location, DartType testedType, DartType inferredType) =>
- genericExpressionExit("isExpression", location, inferredType);
+ void superInitializer(InitializerJudgment judgment, Location location);
- void isNotExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("isNotExpression", location, typeContext);
+ void switchStatement(StatementJudgment judgment, Location location);
- void isNotExpressionExit(
- Location location, DartType type, DartType inferredType) =>
- genericExpressionExit("isNotExpression", location, inferredType);
+ void symbolLiteral(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void labeledStatementEnter(Location location) =>
- genericStatementEnter('labeledStatement', location);
+ void thisExpression(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void labeledStatementExit(Location location) =>
- genericStatementExit('labeledStatement', location);
+ void throw_(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void listLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("listLiteral", location, typeContext);
+ void tryCatch(StatementJudgment judgment, Location location);
- void listLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("listLiteral", location, inferredType);
+ void tryFinally(StatementJudgment judgment, Location location);
- void logicalExpressionBeforeRhs(Location location) {}
+ void typeLiteral(ExpressionJudgment judgment, Location location,
+ Reference expressionType, DartType inferredType);
- void logicalExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("logicalExpression", location, typeContext);
-
- void logicalExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("logicalExpression", location, inferredType);
-
- void mapLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("mapLiteral", location, typeContext);
-
- void mapLiteralExit(Location location, DartType typeContext) =>
- genericExpressionExit("mapLiteral", location, typeContext);
-
- void methodInvocationBeforeArgs(Location location, bool isImplicitCall) {}
-
- void methodInvocationEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("methodInvocation", location, typeContext);
-
- void methodInvocationExit(
- Location resultOffset,
- List<DartType> argumentsTypes,
- bool isImplicitCall,
- Reference interfaceMember,
- FunctionType calleeType,
- Substitution substitution,
- DartType inferredType) =>
- genericExpressionExit("methodInvocation", resultOffset, inferredType);
-
- void methodInvocationExitCall(
- Location resultOffset,
- List<DartType> argumentsTypes,
- bool isImplicitCall,
- FunctionType calleeType,
- Substitution substitution,
- DartType inferredType) =>
- genericExpressionExit("methodInvocation", resultOffset, inferredType);
-
- void namedFunctionExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("namedFunctionExpression", location, typeContext);
-
- void namedFunctionExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("namedFunctionExpression", location, inferredType);
-
- void notEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("not", location, typeContext);
-
- void notExit(Location location, DartType inferredType) =>
- genericExpressionExit("not", location, inferredType);
-
- void nullLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("nullLiteral", location, typeContext);
-
- void nullLiteralExit(
- Location location, bool isSynthetic, DartType inferredType) =>
- genericExpressionExit("nullLiteral", location, inferredType);
-
- void propertyAssignEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("propertyAssign", location, typeContext);
-
- void propertyAssignExit(Location location, Reference writeMember,
- DartType writeContext, Reference combiner, DartType inferredType) =>
- genericExpressionExit("propertyAssign", location, inferredType);
-
- void propertyGetEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("propertyGet", location, typeContext);
-
- void propertyGetExit(
- Location location, Reference member, DartType inferredType) =>
- genericExpressionExit("propertyGet", location, inferredType);
-
- void propertyGetExitCall(Location location, DartType inferredType) =>
- genericExpressionExit("propertyGet", location, inferredType);
-
- void propertySetEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("propertySet", location, typeContext);
-
- void propertySetExit(Location location, DartType inferredType) =>
- genericExpressionExit("propertySet", location, inferredType);
-
- void redirectingInitializerEnter(
- Location location, Reference initializerTarget) =>
- genericInitializerEnter("redirectingInitializer", location);
-
- void redirectingInitializerExit(Location location) =>
- genericInitializerExit("redirectingInitializer", location);
-
- void rethrowEnter(Location location, DartType typeContext) =>
- genericExpressionEnter('rethrow', location, typeContext);
-
- void rethrowExit(Location location, DartType inferredType) =>
- genericExpressionExit('rethrow', location, inferredType);
-
- void returnStatementEnter(Location location) =>
- genericStatementEnter('returnStatement', location);
-
- void returnStatementExit(Location location) =>
- genericStatementExit('returnStatement', location);
-
- void staticAssignEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("staticAssign", location, typeContext);
-
- void staticAssignExit(Location location, Reference writeMember,
- DartType writeContext, Reference combiner, DartType inferredType) =>
- genericExpressionExit("staticAssign", location, inferredType);
-
- void staticGetEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("staticGet", location, typeContext);
-
- void staticGetExit(Location location, Reference expressionTarget,
- DartType inferredType) =>
- genericExpressionExit("staticGet", location, inferredType);
-
- void staticInvocationEnter(Location location,
- Location expressionArgumentsLocation, DartType typeContext) =>
- genericExpressionEnter("staticInvocation", location, typeContext);
-
- void staticInvocationExit(
- Location location,
- Reference expressionTarget,
- List<DartType> expressionArgumentsTypes,
- FunctionType calleeType,
- Substitution substitution,
- DartType inferredType) =>
- genericExpressionExit("staticInvocation", location, inferredType);
-
- void stringConcatenationEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("stringConcatenation", location, typeContext);
-
- void stringConcatenationExit(Location location, DartType inferredType) =>
- genericExpressionExit("stringConcatenation", location, inferredType);
-
- void stringLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("StringLiteral", location, typeContext);
-
- void stringLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("StringLiteral", location, inferredType);
-
- void superInitializerEnter(Location location) =>
- genericInitializerEnter("superInitializer", location);
-
- void superInitializerExit(Location location) =>
- genericInitializerExit("superInitializer", location);
-
- void switchStatementEnter(Location location) =>
- genericStatementEnter('switchStatement', location);
-
- void switchStatementExit(Location location) =>
- genericStatementExit('switchStatement', location);
-
- void symbolLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("symbolLiteral", location, typeContext);
-
- void symbolLiteralExit(Location location, DartType inferredType) =>
- genericExpressionExit("symbolLiteral", location, inferredType);
-
- void thisExpressionEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("thisExpression", location, typeContext);
-
- void thisExpressionExit(Location location, DartType inferredType) =>
- genericExpressionExit("thisExpression", location, inferredType);
-
- void throwEnter(Location location, DartType typeContext) =>
- genericExpressionEnter('throw', location, typeContext);
-
- void throwExit(Location location, DartType inferredType) =>
- genericExpressionExit('throw', location, inferredType);
-
- void tryCatchEnter(Location location) =>
- genericStatementEnter('tryCatch', location);
-
- void tryCatchExit(Location location) =>
- genericStatementExit('tryCatch', location);
-
- void tryFinallyEnter(Location location) =>
- genericStatementEnter('tryFinally', location);
-
- void tryFinallyExit(Location location) =>
- genericStatementExit('tryFinally', location);
-
- void typeLiteralEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("typeLiteral", location, typeContext);
-
- void typeLiteralExit(
- Location location, Reference expressionType, DartType inferredType) =>
- genericExpressionExit("typeLiteral", location, inferredType);
-
- void variableAssignEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("variableAssign", location, typeContext);
-
- void variableAssignExit(
- Location location,
- DartType writeContext,
- Declaration writeVariable,
- Reference combiner,
- DartType inferredType) =>
- genericExpressionExit("variableAssign", location, inferredType);
-
- void variableDeclarationEnter(Location location) =>
- genericStatementEnter('variableDeclaration', location);
-
- void variableDeclarationExit(
- Location location, DartType statementType, DartType inferredType) =>
- genericStatementExit('variableDeclaration', location);
-
- void variableGetEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("variableGet", location, typeContext);
-
- void variableGetExit(Location location, bool isInCascade,
- Declaration expressionVariable, DartType inferredType) =>
- genericExpressionExit("variableGet", location, inferredType);
-
- void variableSetEnter(Location location, DartType typeContext) =>
- genericExpressionEnter("variableSet", location, typeContext);
+ void variableAssign(
+ ExpressionJudgment judgment,
+ Location location,
+ DartType writeContext,
+ Declaration writeVariable,
+ Reference combiner,
+ DartType inferredType);
- void variableSetExit(Location location, DartType inferredType) =>
- genericExpressionExit("variableSet", location, inferredType);
+ void variableDeclaration(StatementJudgment judgment, Location location,
+ DartType statementType, DartType inferredType);
- void whileStatementEnter(Location location) =>
- genericStatementEnter("whileStatement", location);
+ void variableGet(ExpressionJudgment judgment, Location location,
+ bool isInCascade, Declaration expressionVariable, DartType inferredType);
- void whileStatementExit(Location location) =>
- genericStatementExit("whileStatement", location);
+ void variableSet(
+ ExpressionJudgment judgment, Location location, DartType inferredType);
- void yieldStatementEnter(Location location) =>
- genericStatementEnter('yieldStatement', location);
+ void whileStatement(StatementJudgment judgment, Location location);
- void yieldStatementExit(Location location) =>
- genericStatementExit('yieldStatement', location);
+ void yieldStatement(StatementJudgment judgment, Location location);
- void storePrefixInfo(Location location, PrefixInfo prefixInfo) {}
+ void storePrefixInfo(Location location, PrefixInfo prefixInfo);
void storeClassReference(
- Location location, Reference reference, DartType rawType) {}
+ Location location, Reference reference, DartType rawType);
+}
+
+/// Kernel implementation of TypeInferenceListener; does nothing.
+///
+/// TODO(paulberry): fuse this with KernelFactory.
+class KernelTypeInferenceListener
+ implements TypeInferenceListener<int, int, Node, int> {
+ @override
+ void asExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void assertInitializer(InitializerJudgment judgment, location) {}
+
+ @override
+ void assertStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void awaitExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void block(StatementJudgment judgment, location) {}
+
+ @override
+ void boolLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void breakStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void cascadeExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void catchStatement(
+ Catch judgment,
+ location,
+ DartType guardType,
+ exceptionLocation,
+ DartType exceptionType,
+ stackTraceLocation,
+ DartType stackTraceType) {}
+
+ @override
+ void conditionalExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void constructorInvocation(ExpressionJudgment judgment, location,
+ expressionTarget, DartType inferredType) {}
+
+ @override
+ void continueSwitchStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void deferredCheck(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void doStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void doubleLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void expressionStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void fieldInitializer(
+ InitializerJudgment judgment, location, initializerField) {}
+
+ @override
+ void forInStatement(
+ StatementJudgment judgment,
+ location,
+ variableLocation,
+ DartType variableType,
+ writeLocation,
+ DartType writeVariableType,
+ writeVariable,
+ writeTarget) {}
+
+ @override
+ void forStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void functionDeclaration(
+ StatementJudgment judgment, location, FunctionType inferredType) {}
+
+ @override
+ void functionExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void ifNull(ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void ifStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void indexAssign(ExpressionJudgment judgment, location, writeMember, combiner,
+ DartType inferredType) {}
+
+ @override
+ void intLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void invalidInitializer(InitializerJudgment judgment, location) {}
+
+ @override
+ void isExpression(ExpressionJudgment judgment, location, DartType testedType,
+ DartType inferredType) {}
+
+ @override
+ void isNotExpression(ExpressionJudgment judgment, location, DartType type,
+ DartType inferredType) {}
+
+ @override
+ void labeledStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void listLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void logicalExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void mapLiteral(
+ ExpressionJudgment judgment, location, DartType typeContext) {}
+
+ @override
+ void methodInvocation(
+ ExpressionJudgment judgment,
+ resultOffset,
+ List<DartType> argumentsTypes,
+ bool isImplicitCall,
+ interfaceMember,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType) {}
+
+ @override
+ void methodInvocationCall(
+ ExpressionJudgment judgment,
+ resultOffset,
+ List<DartType> argumentsTypes,
+ bool isImplicitCall,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType) {}
+
+ @override
+ void namedFunctionExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void not(ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void nullLiteral(ExpressionJudgment judgment, location, bool isSynthetic,
+ DartType inferredType) {}
+
+ @override
+ void propertyAssign(ExpressionJudgment judgment, location, writeMember,
+ DartType writeContext, combiner, DartType inferredType) {}
+
+ @override
+ void propertyGet(
+ ExpressionJudgment judgment, location, member, DartType inferredType) {}
+
+ @override
+ void propertyGetCall(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void propertySet(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void redirectingInitializer(
+ InitializerJudgment judgment, location, initializerTarget) {}
+
+ @override
+ void rethrow_(ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void returnStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void staticAssign(ExpressionJudgment judgment, location, writeMember,
+ DartType writeContext, combiner, DartType inferredType) {}
+
+ @override
+ void staticGet(ExpressionJudgment judgment, location, expressionTarget,
+ DartType inferredType) {}
+
+ @override
+ void staticInvocation(
+ ExpressionJudgment judgment,
+ location,
+ expressionTarget,
+ List<DartType> expressionArgumentsTypes,
+ FunctionType calleeType,
+ Substitution substitution,
+ DartType inferredType) {}
+
+ @override
+ void storeClassReference(location, reference, DartType rawType) {}
+
+ @override
+ void storePrefixInfo(location, prefixInfo) {}
+
+ @override
+ void stringConcatenation(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void stringLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void superInitializer(InitializerJudgment judgment, location) {}
+
+ @override
+ void switchStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void symbolLiteral(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void thisExpression(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void throw_(ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void tryCatch(StatementJudgment judgment, location) {}
+
+ @override
+ void tryFinally(StatementJudgment judgment, location) {}
+
+ @override
+ void typeLiteral(ExpressionJudgment judgment, location, expressionType,
+ DartType inferredType) {}
+
+ @override
+ void variableAssign(ExpressionJudgment judgment, location,
+ DartType writeContext, writeVariable, combiner, DartType inferredType) {}
+
+ @override
+ void variableDeclaration(StatementJudgment judgment, location,
+ DartType statementType, DartType inferredType) {}
+
+ @override
+ void variableGet(ExpressionJudgment judgment, location, bool isInCascade,
+ expressionVariable, DartType inferredType) {}
+
+ @override
+ void variableSet(
+ ExpressionJudgment judgment, location, DartType inferredType) {}
+
+ @override
+ void whileStatement(StatementJudgment judgment, location) {}
+
+ @override
+ void yieldStatement(StatementJudgment judgment, location) {}
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 95e550b..521c12f 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -1425,12 +1425,10 @@
Object interfaceMember,
Name methodName,
Arguments arguments}) {
- listener.methodInvocationEnter(expression.fileOffset, typeContext);
// First infer the receiver so we can look up the method that was invoked.
var receiverType = receiver == null
? thisType
: inferExpression(factory, receiver, const UnknownType(), true);
- listener.methodInvocationBeforeArgs(expression.fileOffset, isImplicitCall);
if (strongMode) {
receiverVariable?.type = receiverType;
}
@@ -1462,7 +1460,8 @@
? arguments.fileOffset
: expression.fileOffset;
if (identical(interfaceMember, 'call')) {
- listener.methodInvocationExitCall(
+ listener.methodInvocationCall(
+ expression,
resultOffset,
arguments.types,
isImplicitCall,
@@ -1482,7 +1481,8 @@
templateImplicitCallOfNonMethod.withArguments(receiverType));
parent?.replaceChild(expression, errorNode);
}
- listener.methodInvocationExit(
+ listener.methodInvocation(
+ expression,
resultOffset,
arguments.types,
isImplicitCall,
@@ -1521,7 +1521,6 @@
PropertyGet desugaredGet,
Object interfaceMember,
Name propertyName}) {
- listener.propertyGetEnter(expression.fileOffset, typeContext);
// First infer the receiver so we can look up the getter that was invoked.
DartType receiverType;
if (receiver == null) {
@@ -1557,10 +1556,10 @@
instantiateTearOff(inferredType, typeContext, replacedExpression);
}
if (identical(interfaceMember, 'call')) {
- listener.propertyGetExitCall(expression.fileOffset, inferredType);
+ listener.propertyGetCall(expression, expression.fileOffset, inferredType);
} else {
- listener.propertyGetExit(
- expression.fileOffset, interfaceMember, inferredType);
+ listener.propertyGet(
+ expression, expression.fileOffset, interfaceMember, inferredType);
}
expression.inferredType = inferredType;
}
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 1299b8d..9889ccd 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -284,6 +284,7 @@
'beginTypeVariables <',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -316,6 +317,7 @@
'beginTypeVariables <',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -684,6 +686,7 @@
'beginTypeVariables <',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -692,6 +695,7 @@
'beginTypeVariables <',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -861,6 +865,7 @@
'beginTypeVariables <',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -1038,11 +1043,13 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -1052,6 +1059,7 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleIdentifier T typeReference',
'handleNoTypeArguments >',
@@ -1063,6 +1071,7 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleIdentifier T typeReference',
'handleNoTypeArguments >',
@@ -1074,6 +1083,7 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleIdentifier List typeReference',
'beginTypeArguments <',
@@ -1089,11 +1099,13 @@
'beginTypeVariables <',
'beginMetadataStar R',
'endMetadataStar 0',
+ 'handleIdentifier R typeVariableDeclaration',
'beginTypeVariable R',
'handleNoType R',
'endTypeVariable , null',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoTypeVariables (',
'beginFunctionType void',
@@ -1113,11 +1125,13 @@
'handleNoArguments S',
'endMetadata @ null S',
'endMetadataStar 1',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -1133,11 +1147,13 @@
'endArguments 0 ( )',
'endMetadata @ null S',
'endMetadataStar 1',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -1158,11 +1174,13 @@
'handleNoArguments S',
'endMetadata @ null S',
'endMetadataStar 2',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
'beginMetadataStar T',
'endMetadataStar 0',
+ 'handleIdentifier T typeVariableDeclaration',
'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
@@ -1177,6 +1195,7 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable Function null',
@@ -1189,6 +1208,7 @@
'beginTypeVariables <',
'beginMetadataStar void',
'endMetadataStar 0',
+ 'handleIdentifier typeVariableDeclaration',
'beginTypeVariable ',
'handleNoType ',
'endTypeVariable void null',
@@ -1200,6 +1220,7 @@
'beginTypeVariables <',
'beginMetadataStar S',
'endMetadataStar 0',
+ 'handleIdentifier S typeVariableDeclaration',
'beginTypeVariable S',
'handleNoType S',
'endTypeVariable < null',
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 7a258a5..cc1fb23 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -96,6 +96,7 @@
kernel/test/*: RuntimeError, OK # Issue 26103. Timers are not supported.
[ $runtime == vm ]
+analysis_server/test/benchmarks_test: Pass, Slow
analysis_server/test/completion_test: Pass, Slow
analysis_server/test/integration/analysis/error_test: Pass, Slow
analysis_server/test/integration/analysis/lint_test: Pass, Slow
@@ -255,7 +256,6 @@
front_end/tool/perf_test: Slow, Pass
[ $runtime == vm && $checked ]
-analysis_server/test/benchmarks_test: Pass, Slow
analysis_server/test/completion_test: Pass, Slow
analysis_server/test/integration/edit/sort_members_test: Pass, Slow
analysis_server/test/services/correction/fix_test: Pass, Slow
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index c0c07ff..753bb61 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -133,7 +133,7 @@
type ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
Byte tag = 19;
CanonicalNameReference instantiatingClass;
- ConstantIndex typeArguments;
+ List<DartType> types;
}
type ConstantContextOffset extends ConstantPoolEntry {
@@ -896,16 +896,15 @@
class ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
final Reference _instantiatingClassRef;
- final int _typeArgumentsConstantIndex;
+ final List<DartType> typeArgs;
Class get instantiatingClass => _instantiatingClassRef.asClass;
ConstantTypeArgumentsForInstanceAllocation(
- Class instantiatingClass, int typeArgumentsConstantIndex)
- : this.byReference(
- instantiatingClass.reference, typeArgumentsConstantIndex);
+ Class instantiatingClass, List<DartType> typeArgs)
+ : this.byReference(instantiatingClass.reference, typeArgs);
ConstantTypeArgumentsForInstanceAllocation.byReference(
- this._instantiatingClassRef, this._typeArgumentsConstantIndex);
+ this._instantiatingClassRef, this.typeArgs);
@override
ConstantTag get tag => ConstantTag.kTypeArgumentsForInstanceAllocation;
@@ -914,27 +913,29 @@
void writeValueToBinary(BinarySink sink) {
sink.writeCanonicalNameReference(
getCanonicalNameOfClass(instantiatingClass));
- sink.writeUInt30(_typeArgumentsConstantIndex);
+ sink.writeUInt30(typeArgs.length);
+ typeArgs.forEach(sink.writeDartType);
}
ConstantTypeArgumentsForInstanceAllocation.readFromBinary(BinarySource source)
: _instantiatingClassRef =
source.readCanonicalNameReference().getReference(),
- _typeArgumentsConstantIndex = source.readUInt();
+ typeArgs = new List<DartType>.generate(
+ source.readUInt(), (_) => source.readDartType());
@override
String toString() =>
- 'TypeArgumentsForInstanceAllocation $instantiatingClass type-args CP#$_typeArgumentsConstantIndex';
+ 'TypeArgumentsForInstanceAllocation $instantiatingClass $typeArgs';
@override
int get hashCode =>
- _combineHashes(instantiatingClass.hashCode, _typeArgumentsConstantIndex);
+ _combineHashes(instantiatingClass.hashCode, listHashCode(typeArgs));
@override
bool operator ==(other) =>
other is ConstantTypeArgumentsForInstanceAllocation &&
this.instantiatingClass == other.instantiatingClass &&
- this._typeArgumentsConstantIndex == other._typeArgumentsConstantIndex;
+ listEquals(this.typeArgs, other.typeArgs);
}
class ConstantContextOffset extends ConstantPoolEntry {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 953ae1c..599d4c1 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -150,13 +150,10 @@
final function = enclosingMember.function;
assert(function != null);
- if (locals.hasTypeArgsVar) {
- asm.emitPush(locals.typeArgsVarIndexInFrame);
- } else if (enclosingMember is Procedure &&
- (enclosingMember as Procedure).isFactory) {
- // Null type arguments are passed to factory constructors even if class
- // is not generic. TODO(alexmarkov): Clean this up.
- _genPushNull();
+ if (locals.hasFactoryTypeArgsVar) {
+ asm.emitPush(locals.getVarIndexInFrame(locals.factoryTypeArgsVar));
+ } else if (locals.hasFunctionTypeArgsVar) {
+ asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
}
if (locals.hasReceiver) {
asm.emitPush(locals.getVarIndexInFrame(locals.receiverVar));
@@ -326,12 +323,12 @@
void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
int typeArgsCPIndex() {
- int cpIndex = cp.add(new ConstantTypeArguments(typeArgs));
if (instantiatingClass != null) {
- cpIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
- instantiatingClass, cpIndex));
+ return cp.add(new ConstantTypeArgumentsForInstanceAllocation(
+ instantiatingClass, typeArgs));
+ } else {
+ return cp.add(new ConstantTypeArguments(typeArgs));
}
- return cpIndex;
}
if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
@@ -341,7 +338,14 @@
_genPushInstantiatorTypeArguments();
} else {
_genPushInstantiatorAndFunctionTypeArguments(typeArgs);
- asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex());
+ // TODO(alexmarkov): Optimize type arguments instantiation
+ // by passing rA = 1 in InstantiateTypeArgumentsTOS.
+ // For this purpose, we need to detect if type arguments
+ // would be all-dynamic in case of all-dynamic instantiator and
+ // function type arguments.
+ // Corresponding check is implemented in VM in
+ // TypeArguments::IsRawWhenInstantiatedFromRaw.
+ asm.emitInstantiateTypeArgumentsTOS(0, typeArgsCPIndex());
}
}
}
@@ -364,10 +368,16 @@
void _genPushInstantiatorTypeArguments() {
if (instantiatorTypeArguments != null) {
- _genPushReceiver();
- final int cpIndex =
- cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
- asm.emitLoadFieldTOS(cpIndex);
+ if (locals.hasFactoryTypeArgsVar) {
+ assert(enclosingMember is Procedure &&
+ (enclosingMember as Procedure).isFactory);
+ _genLoadVar(locals.factoryTypeArgsVar);
+ } else {
+ _genPushReceiver();
+ final int cpIndex =
+ cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
+ asm.emitLoadFieldTOS(cpIndex);
+ }
} else {
_genPushNull();
}
@@ -416,8 +426,8 @@
}
void _genPushFunctionTypeArguments() {
- if (locals.hasTypeArgsVar) {
- asm.emitPush(locals.typeArgsVarIndexInFrame);
+ if (locals.hasFunctionTypeArgsVar) {
+ asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
} else {
_genPushNull();
}
@@ -536,10 +546,17 @@
void start(Member node) {
enclosingClass = node.enclosingClass;
enclosingMember = node;
- if (enclosingMember.isInstanceMember || enclosingMember is Constructor) {
+ if (node.isInstanceMember ||
+ node is Constructor ||
+ (node is Procedure && node.isFactory)) {
if (enclosingClass.typeParameters.isNotEmpty) {
classTypeParameters =
new Set<TypeParameter>.from(enclosingClass.typeParameters);
+ // Treat type arguments of factory constructors as class
+ // type parameters.
+ if (node is Procedure && node.isFactory) {
+ classTypeParameters.addAll(node.function.typeParameters);
+ }
}
if (hasInstantiatorTypeArguments(enclosingClass)) {
final typeParameters = enclosingClass.typeParameters
@@ -670,22 +687,22 @@
asm.emitPopLocal(locals.contextVarIndexInFrame);
}
- if (locals.hasTypeArgsVar && isClosure) {
+ if (locals.hasFunctionTypeArgsVar && isClosure) {
if (function.typeParameters.isNotEmpty) {
final int numParentTypeArgs = locals.numParentTypeArguments;
- asm.emitPush(locals.typeArgsVarIndexInFrame);
+ asm.emitPush(locals.functionTypeArgsVarIndexInFrame);
asm.emitPush(locals.closureVarIndexInFrame);
asm.emitLoadFieldTOS(
cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
_genPushInt(numParentTypeArgs);
_genPushInt(numParentTypeArgs + function.typeParameters.length);
_genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
- asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+ asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
} else {
asm.emitPush(locals.closureVarIndexInFrame);
asm.emitLoadFieldTOS(
cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
- asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+ asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
}
}
@@ -699,6 +716,9 @@
if (locals.hasCapturedParameters) {
// Copy captured parameters to their respective locations in the context.
+ if (locals.hasFactoryTypeArgsVar) {
+ _copyParamIfCaptured(locals.factoryTypeArgsVar);
+ }
if (locals.hasReceiver) {
_copyParamIfCaptured(locals.receiverVar);
}
@@ -1234,7 +1254,11 @@
}
}
- _genStaticCall(mapFromLiteral, new ConstantArgDesc(1, numTypeArgs: 1), 2);
+ // Map._fromLiteral is a factory constructor.
+ // Type arguments passed to a factory constructor are counted as a normal
+ // argument and not counted in number of type arguments.
+ assert(mapFromLiteral.isFactory);
+ _genStaticCall(mapFromLiteral, new ConstantArgDesc(2, numTypeArgs: 0), 2);
}
@override
@@ -1246,9 +1270,12 @@
cp.add(new ConstantArgDesc.fromArguments(args, hasReceiver: true));
final icdataIndex = cp.add(
new ConstantICData(InvocationKind.method, node.name, argDescIndex));
+ final totalArgCount = args.positional.length +
+ args.named.length +
+ 1 /* receiver */ +
+ (args.types.isNotEmpty ? 1 : 0) /* type arguments */;
// TODO(alexmarkov): figure out when generate InstanceCall2 (2 checked arguments).
- asm.emitInstanceCall1(
- args.positional.length + args.named.length + 1, icdataIndex);
+ asm.emitInstanceCall1(totalArgCount, icdataIndex);
}
@override
@@ -1285,7 +1312,7 @@
'Unsupported SuperMethodInvocation without target');
}
if (target is Procedure && !target.isGetter) {
- _genStaticCallWithArgs(target, args);
+ _genStaticCallWithArgs(target, args, hasReceiver: true);
} else {
throw new UnsupportedOperationError(
'Unsupported SuperMethodInvocation with target ${target.runtimeType} $target');
@@ -1378,11 +1405,20 @@
@override
visitStaticInvocation(StaticInvocation node) {
- final args = node.arguments;
- if (node.target.isFactory && args.types.isEmpty) {
- // VM needs type arguments for every invocation of a factory constructor.
- // TODO(alexmarkov): Clean this up.
- _genPushNull();
+ Arguments args = node.arguments;
+ if (node.target.isFactory) {
+ final constructedClass = node.target.enclosingClass;
+ if (hasInstantiatorTypeArguments(constructedClass)) {
+ _genTypeArguments(args.types,
+ instantiatingClass: node.target.enclosingClass);
+ } else {
+ assert(args.types.isEmpty);
+ // VM needs type arguments for every invocation of a factory
+ // constructor. TODO(alexmarkov): Clean this up.
+ _genPushNull();
+ }
+ args =
+ new Arguments(node.arguments.positional, named: node.arguments.named);
}
_genArguments(null, args);
_genStaticCallWithArgs(node.target, args, isFactory: node.target.isFactory);
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index d779939..5bea5f6 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -88,11 +88,17 @@
.scratchVar ??
(throw 'Scratch variable is not declared in ${_currentFrame.function}'));
- int get typeArgsVarIndexInFrame => getVarIndexInFrame(_currentFrame
- .typeArgsVar ??
- (throw 'TypeArgs variable is not declared in ${_currentFrame.function}'));
+ int get functionTypeArgsVarIndexInFrame => getVarIndexInFrame(_currentFrame
+ .functionTypeArgsVar ??
+ (throw 'FunctionTypeArgs variable is not declared in ${_currentFrame.function}'));
- bool get hasTypeArgsVar => _currentFrame.typeArgsVar != null;
+ bool get hasFunctionTypeArgsVar => _currentFrame.functionTypeArgsVar != null;
+
+ VariableDeclaration get factoryTypeArgsVar =>
+ _currentFrame.factoryTypeArgsVar ??
+ (throw 'FactoryTypeArgs variable is not declared in ${_currentFrame.function}');
+
+ bool get hasFactoryTypeArgsVar => _currentFrame.factoryTypeArgsVar != null;
VariableDeclaration get receiverVar =>
_currentFrame.receiverVar ??
@@ -204,7 +210,8 @@
bool isDartSync = true;
bool isSyncYielding = false;
VariableDeclaration receiverVar;
- VariableDeclaration typeArgsVar;
+ VariableDeclaration functionTypeArgsVar;
+ VariableDeclaration factoryTypeArgsVar;
VariableDeclaration closureVar;
VariableDeclaration contextVar;
VariableDeclaration scratchVar;
@@ -275,15 +282,29 @@
_currentFrame.isSyncYielding =
function.asyncMarker == AsyncMarker.SyncYielding;
- _currentFrame.numTypeArguments =
- (_currentFrame.parent?.numTypeArguments ?? 0) +
- function.typeParameters.length;
+ if (node is Procedure && node.isFactory) {
+ assert(_currentFrame.parent == null);
+ _currentFrame.numTypeArguments = 0;
+ _currentFrame.factoryTypeArgsVar =
+ new VariableDeclaration(':type_arguments');
+ _declareVariable(_currentFrame.factoryTypeArgsVar);
+ } else {
+ _currentFrame.numTypeArguments =
+ (_currentFrame.parent?.numTypeArguments ?? 0) +
+ function.typeParameters.length;
- if (_currentFrame.numTypeArguments > 0) {
- _currentFrame.typeArgsVar =
- new VariableDeclaration(':function_type_arguments_var');
- _declareVariable(_currentFrame.typeArgsVar);
+ if (_currentFrame.numTypeArguments > 0) {
+ _currentFrame.functionTypeArgsVar =
+ new VariableDeclaration(':function_type_arguments_var');
+ _declareVariable(_currentFrame.functionTypeArgsVar);
+ }
+
+ if (_currentFrame.parent?.factoryTypeArgsVar != null) {
+ _currentFrame.factoryTypeArgsVar =
+ _currentFrame.parent.factoryTypeArgsVar;
+ }
}
+
if (node is Constructor || (node is Procedure && !node.isStatic)) {
_currentFrame.receiverVar = new VariableDeclaration('this');
_declareVariable(_currentFrame.receiverVar);
@@ -383,7 +404,7 @@
final transient = new Set<VariableDeclaration>();
transient
..addAll([
- _currentFrame.typeArgsVar,
+ _currentFrame.functionTypeArgsVar,
_currentFrame.closureVar,
_currentFrame.contextVar,
_currentFrame.scratchVar,
@@ -501,8 +522,15 @@
@override
visitTypeParameterType(TypeParameterType node) {
- if (node.parameter.parent is Class) {
+ var parent = node.parameter.parent;
+ if (parent is Class) {
_useThis();
+ } else if (parent is FunctionNode) {
+ parent = parent.parent;
+ if (parent is Procedure && parent.isFactory) {
+ assert(_currentFrame.factoryTypeArgsVar != null);
+ _useVariable(_currentFrame.factoryTypeArgsVar);
+ }
}
node.visitChildren(this);
}
@@ -746,13 +774,11 @@
function.namedParameters.any(locals.isCaptured);
int count = 0;
- if (hasTypeArgs) {
- assert(!locals.isCaptured(_currentFrame.typeArgsVar));
- _allocateParameter(_currentFrame.typeArgsVar, count++);
- } else if (isFactory) {
- // Null type arguments are passed to factory constructors even if class
- // is not generic. TODO(alexmarkov): Clean this up.
- count++;
+ if (isFactory) {
+ _allocateParameter(_currentFrame.factoryTypeArgsVar, count++);
+ } else if (hasTypeArgs) {
+ assert(!locals.isCaptured(_currentFrame.functionTypeArgsVar));
+ _allocateParameter(_currentFrame.functionTypeArgsVar, count++);
}
if (hasReceiver) {
_allocateParameter(_currentFrame.receiverVar, count++);
@@ -776,7 +802,7 @@
}
void _allocateSpecialVariables() {
- _ensureVariableAllocated(_currentFrame.typeArgsVar);
+ _ensureVariableAllocated(_currentFrame.functionTypeArgsVar);
_ensureVariableAllocated(_currentFrame.contextVar);
_ensureVariableAllocated(_currentFrame.scratchVar);
}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index f9bc6de..60a3f58 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -80,7 +80,7 @@
}
ConstantPool {
[0] = ContextOffset parent
- [1] = TypeArgs [dart.core::int]
+ [1] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
[2] = ArgDesc num-args 1, num-type-args 0, names []
[3] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#2
[4] = ContextOffset var [3]
@@ -105,7 +105,7 @@
[23] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#2
[24] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#2
[25] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#2
- [26] = TypeArgs [dynamic]
+ [26] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
[27] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#13
[28] = ICData get target-name 'future', arg-desc CP#2
}
@@ -306,7 +306,7 @@
[0] = ContextOffset parent
[1] = ContextOffset var [0]
[2] = ContextOffset var [1]
- [3] = TypeArgs [dart.core::int]
+ [3] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
[4] = ArgDesc num-args 1, num-type-args 0, names []
[5] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#4
[6] = ContextOffset var [8]
@@ -339,7 +339,7 @@
[33] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#4
[34] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#4
[35] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#4
- [36] = TypeArgs [dynamic]
+ [36] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
[37] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#22
[38] = ICData get target-name 'future', arg-desc CP#4
}
@@ -619,7 +619,7 @@
ConstantPool {
[0] = ContextOffset parent
[1] = ContextOffset var [0]
- [2] = TypeArgs [dart.core::int]
+ [2] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
[3] = ArgDesc num-args 1, num-type-args 0, names []
[4] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#3
[5] = ContextOffset var [9]
@@ -666,7 +666,7 @@
[46] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#3
[47] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#3
[48] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#3
- [49] = TypeArgs [dynamic]
+ [49] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
[50] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#18
[51] = ICData get target-name 'future', arg-desc CP#3
}
@@ -1127,7 +1127,7 @@
[1] = ContextOffset var [0]
[2] = ContextOffset var [1]
[3] = ContextOffset var [2]
- [4] = TypeArgs [dart.core::int]
+ [4] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
[5] = ArgDesc num-args 1, num-type-args 0, names []
[6] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#5
[7] = ContextOffset var [12]
@@ -1181,7 +1181,7 @@
[55] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#5
[56] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#5
[57] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#5
- [58] = TypeArgs [dynamic]
+ [58] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
[59] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#24
[60] = ICData get target-name 'future', arg-desc CP#5
}
@@ -1810,7 +1810,7 @@
[2] = Int 3
[3] = ClosureFunction nested () → dart.async::Future<dart.core::int> /* originally async */ ;
[4] = FieldOffset dart.core::_Closure::_context
- [5] = TypeArgs [dart.core::int]
+ [5] = TypeArgumentsForInstanceAllocation dart.async::Completer [dart.core::int]
[6] = ArgDesc num-args 1, num-type-args 0, names []
[7] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#6
[8] = ContextOffset var [8]
@@ -1847,7 +1847,7 @@
[39] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#6
[40] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#6
[41] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#6
- [42] = TypeArgs [dynamic]
+ [42] = TypeArgumentsForInstanceAllocation dart.async::Future [dynamic]
[43] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#24
[44] = ICData get target-name 'future', arg-desc CP#6
[45] = EndClosureFunctionScope
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index cd54d28..2080a18 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -222,11 +222,11 @@
PopLocal r2
PushConstant CP#49
Push r2
- InstanceCall1 1, CP#50
+ InstanceCall1 2, CP#50
Drop1
PushConstant CP#51
Push r2
- InstanceCall1 1, CP#52
+ InstanceCall1 2, CP#52
Drop1
PushConstant CP#18
ReturnTOS
@@ -362,7 +362,7 @@
LoadFieldTOS CP#1
LoadFieldTOS CP#17
Push r0
- InstantiateTypeArgumentsTOS 1, CP#34
+ InstantiateTypeArgumentsTOS 0, CP#34
PushConstant CP#36
IndirectStaticCall 1, CP#35
Drop1
@@ -443,11 +443,11 @@
PopLocal r2
PushConstant CP#43
Push r2
- InstanceCall1 1, CP#45
+ InstanceCall1 2, CP#45
Drop1
PushConstant CP#46
Push r2
- InstanceCall1 1, CP#47
+ InstanceCall1 2, CP#47
Drop1
PushConstant CP#18
ReturnTOS
@@ -1351,58 +1351,56 @@
Entry 1
CheckStack
PushConstant CP#0
- PushConstant CP#3
+ PushConstant CP#2
PushConstant CP#1
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#5
- IndirectStaticCall 1, CP#4
+ PushConstant CP#4
+ IndirectStaticCall 1, CP#3
Drop1
- InstanceCall1 1, CP#7
+ InstanceCall1 2, CP#6
Drop1
+ PushConstant CP#7
+ PushConstant CP#2
+ PushConstant CP#1
+ AllocateT
+ StoreLocal r0
+ Push r0
PushConstant CP#8
- PushConstant CP#3
+ IndirectStaticCall 1, CP#3
+ Drop1
+ InstanceCall1 2, CP#9
+ Drop1
+ PushConstant CP#7
+ PushConstant CP#10
PushConstant CP#1
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#9
- IndirectStaticCall 1, CP#4
+ PushConstant CP#11
+ IndirectStaticCall 1, CP#3
Drop1
- InstanceCall1 1, CP#10
+ InstanceCall1 2, CP#12
Drop1
- PushConstant CP#8
- PushConstant CP#12
- PushConstant CP#1
- AllocateT
- StoreLocal r0
- Push r0
PushConstant CP#13
- IndirectStaticCall 1, CP#4
- Drop1
- InstanceCall1 1, CP#14
- Drop1
- PushConstant CP#15
ReturnTOS
}
ConstantPool {
[0] = TypeArgs [#lib::C3, #lib::C4]
[1] = Class #lib::A
- [2] = TypeArgs [#lib::C1, #lib::C2]
- [3] = TypeArgumentsForInstanceAllocation #lib::A type-args CP#2
- [4] = ArgDesc num-args 1, num-type-args 0, names []
- [5] = StaticICData target '#lib::A::', arg-desc CP#4
- [6] = ArgDesc num-args 1, num-type-args 2, names []
- [7] = ICData target-name 'foo', arg-desc CP#6
- [8] = TypeArgs [dart.core::List<#lib::C3>, dart.core::List<#lib::C4>]
- [9] = StaticICData target '#lib::A::', arg-desc CP#4
- [10] = ICData target-name 'foo', arg-desc CP#6
- [11] = TypeArgs [dart.core::List<#lib::C1>, dart.core::List<#lib::C2>]
- [12] = TypeArgumentsForInstanceAllocation #lib::A type-args CP#11
- [13] = StaticICData target '#lib::A::', arg-desc CP#4
- [14] = ICData target-name 'foo', arg-desc CP#6
- [15] = Null
+ [2] = TypeArgumentsForInstanceAllocation #lib::A [#lib::C1, #lib::C2]
+ [3] = ArgDesc num-args 1, num-type-args 0, names []
+ [4] = StaticICData target '#lib::A::', arg-desc CP#3
+ [5] = ArgDesc num-args 1, num-type-args 2, names []
+ [6] = ICData target-name 'foo', arg-desc CP#5
+ [7] = TypeArgs [dart.core::List<#lib::C3>, dart.core::List<#lib::C4>]
+ [8] = StaticICData target '#lib::A::', arg-desc CP#3
+ [9] = ICData target-name 'foo', arg-desc CP#5
+ [10] = TypeArgumentsForInstanceAllocation #lib::A [dart.core::List<#lib::C1>, dart.core::List<#lib::C2>]
+ [11] = StaticICData target '#lib::A::', arg-desc CP#3
+ [12] = ICData target-name 'foo', arg-desc CP#5
+ [13] = Null
}
]static method callA() → void {
new self::A::•<self::C1, self::C2>().{self::A::foo}<self::C3, self::C4>();
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index be92aa5..2ba4d37 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -292,15 +292,15 @@
Bytecode {
Entry 1
CheckStack
- PushConstant CP#1
Push FP[-5]
- InstantiateTypeArgumentsTOS 1, CP#3
+ PushConstant CP#1
+ InstantiateTypeArgumentsTOS 0, CP#2
PushConstant CP#0
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#5
- IndirectStaticCall 1, CP#4
+ PushConstant CP#4
+ IndirectStaticCall 1, CP#3
Drop1
ReturnTOS
PushConstant CP#1
@@ -309,10 +309,9 @@
ConstantPool {
[0] = Class #lib::H
[1] = Null
- [2] = TypeArgs [dart.core::String, #lib::G::test_factory::K, #lib::G::test_factory::V]
- [3] = TypeArgumentsForInstanceAllocation #lib::H type-args CP#2
- [4] = ArgDesc num-args 1, num-type-args 0, names []
- [5] = StaticICData target '#lib::H::', arg-desc CP#4
+ [2] = TypeArgumentsForInstanceAllocation #lib::H [dart.core::String, #lib::G::test_factory::K, #lib::G::test_factory::V]
+ [3] = ArgDesc num-args 1, num-type-args 0, names []
+ [4] = StaticICData target '#lib::H::', arg-desc CP#3
}
] static factory test_factory<K extends core::Object = dynamic, V extends core::Object = dynamic>() → self::G<self::G::test_factory::K, self::G::test_factory::V>
return new self::H::•<core::String, self::G::test_factory::K, self::G::test_factory::V>();
@@ -391,13 +390,12 @@
Bytecode {
Entry 0
CheckStack
- PushConstant CP#0
- NativeCall CP#1
+ Push FP[-5]
+ NativeCall CP#0
ReturnTOS
}
ConstantPool {
- [0] = Null
- [1] = NativeEntry agent_J
+ [0] = NativeEntry agent_J
}
] @_in::ExternalName::•("agent_J")
external static factory •() → self::J;
@@ -430,41 +428,39 @@
Bytecode {
Entry 1
CheckStack
- PushConstant CP#2
+ PushConstant CP#1
PushConstant CP#0
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#3
- PushConstant CP#5
- IndirectStaticCall 2, CP#4
+ PushConstant CP#2
+ PushConstant CP#4
+ IndirectStaticCall 2, CP#3
Drop1
Drop1
- PushConstant CP#8
PushConstant CP#6
+ PushConstant CP#5
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#10
- IndirectStaticCall 1, CP#9
+ PushConstant CP#8
+ IndirectStaticCall 1, CP#7
Drop1
Drop1
- PushConstant CP#11
+ PushConstant CP#9
ReturnTOS
}
ConstantPool {
[0] = Class #lib::A
- [1] = TypeArgs []
- [2] = TypeArgumentsForInstanceAllocation #lib::A type-args CP#1
- [3] = String 'hi'
- [4] = ArgDesc num-args 2, num-type-args 0, names []
- [5] = StaticICData target '#lib::A::', arg-desc CP#4
- [6] = Class #lib::B
- [7] = TypeArgs [dart.core::int]
- [8] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#7
- [9] = ArgDesc num-args 1, num-type-args 0, names []
- [10] = StaticICData target '#lib::B::', arg-desc CP#9
- [11] = Null
+ [1] = TypeArgumentsForInstanceAllocation #lib::A []
+ [2] = String 'hi'
+ [3] = ArgDesc num-args 2, num-type-args 0, names []
+ [4] = StaticICData target '#lib::A::', arg-desc CP#3
+ [5] = Class #lib::B
+ [6] = TypeArgumentsForInstanceAllocation #lib::B [dart.core::int]
+ [7] = ArgDesc num-args 1, num-type-args 0, names []
+ [8] = StaticICData target '#lib::B::', arg-desc CP#7
+ [9] = Null
}
]static method foo2() → void {
new self::A::•("hi");
@@ -476,13 +472,13 @@
CheckStack
PushConstant CP#1
Push FP[-5]
- InstantiateTypeArgumentsTOS 1, CP#3
+ InstantiateTypeArgumentsTOS 0, CP#2
PushConstant CP#0
AllocateT
StoreLocal r0
Push r0
- PushConstant CP#5
- IndirectStaticCall 1, CP#4
+ PushConstant CP#4
+ IndirectStaticCall 1, CP#3
Drop1
Drop1
PushConstant CP#1
@@ -491,10 +487,9 @@
ConstantPool {
[0] = Class #lib::B
[1] = Null
- [2] = TypeArgs [dart.core::List<#lib::foo3::T>]
- [3] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#2
- [4] = ArgDesc num-args 1, num-type-args 0, names []
- [5] = StaticICData target '#lib::B::', arg-desc CP#4
+ [2] = TypeArgumentsForInstanceAllocation #lib::B [dart.core::List<#lib::foo3::T>]
+ [3] = ArgDesc num-args 1, num-type-args 0, names []
+ [4] = StaticICData target '#lib::B::', arg-desc CP#3
}
]static method foo3<T extends core::Object = dynamic>() → void {
new self::B::•<core::List<self::foo3::T>>();
@@ -511,7 +506,7 @@
ReturnTOS
}
ConstantPool {
- [0] = TypeArgs [dart.core::int, dart.core::List<dart.core::String>]
+ [0] = TypeArgumentsForInstanceAllocation #lib::G [dart.core::int, dart.core::List<dart.core::String>]
[1] = ArgDesc num-args 1, num-type-args 0, names []
[2] = StaticICData target '#lib::G::test_factory', arg-desc CP#1
[3] = Null
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index c248ce0..a3c9ec2 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -553,7 +553,7 @@
Drop1
PushConstant CP#16
Push FP[-8]
- InstantiateTypeArgumentsTOS 1, CP#17
+ InstantiateTypeArgumentsTOS 0, CP#17
PushConstant CP#18
PushConstant CP#19
IndirectStaticCall 2, CP#7
@@ -562,7 +562,7 @@
Drop1
PushConstant CP#16
Push FP[-8]
- InstantiateTypeArgumentsTOS 1, CP#21
+ InstantiateTypeArgumentsTOS 0, CP#21
PushConstant CP#1
PushConstant CP#5
CreateArrayTOS
@@ -591,7 +591,7 @@
[4] = Int 1
[5] = Int 2
[6] = Int 3
- [7] = ArgDesc num-args 1, num-type-args 1, names []
+ [7] = ArgDesc num-args 2, num-type-args 0, names []
[8] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
[9] = ArgDesc num-args 1, num-type-args 0, names []
[10] = StaticICData target 'dart.core::print', arg-desc CP#9
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index eb5a775..cf66e57 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -253,7 +253,7 @@
Push FP[-6]
LoadFieldTOS CP#0
PushConstant CP#1
- InstantiateTypeArgumentsTOS 1, CP#2
+ InstantiateTypeArgumentsTOS 0, CP#2
StoreLocal r1
Push r1
PushConstant CP#3
diff --git a/pkg/vm/tool/test_bytecode b/pkg/vm/tool/test_bytecode
index 7b05997..3c1d0e1 100755
--- a/pkg/vm/tool/test_bytecode
+++ b/pkg/vm/tool/test_bytecode
@@ -68,7 +68,7 @@
# $BUILD_DIR/test_bytecode.dill $BUILD_DIR/test_bytecode.txt
# Required flags.
-DART_VM_FLAGS="--preview-dart-2 --optimization-counter-threshold=-1 $DART_VM_FLAGS"
+DART_VM_FLAGS="--optimization-counter-threshold=-1 $DART_VM_FLAGS"
# Optional flags examples. Uncomment as needed.
# DART_VM_FLAGS="--force-log-flush --isolate-log-filter=\"\" $DART_VM_FLAGS"
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index d7734c1..4d54a54 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1509,6 +1509,14 @@
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance);
/**
+ * Returns the name for the provided class type.
+ *
+ * \return A valid string handle if no error occurs during the
+ * operation.
+ */
+DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type);
+
+/**
* Returns the name for the provided function or method.
*
* \return A valid string handle if no error occurs during the
@@ -1553,6 +1561,15 @@
*/
DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure);
+/**
+ * Returns a handle to the library which contains class.
+ *
+ * \return A valid handle to the library with owns class, null if the class
+ * has no library or an error handle if the argument is not a valid handle
+ * to a class type.
+ */
+DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type);
+
/*
* =============================
* Numbers, Integers and Doubles
@@ -1686,6 +1703,20 @@
DART_EXPORT Dart_Handle Dart_GetClosure(Dart_Handle library,
Dart_Handle function_name);
+/**
+ * Returns a closure of static function 'function_name' in the class 'class_name'
+ * in the exported namespace of specified 'library'.
+ *
+ * \param library Library object
+ * \param cls_type Type object representing a Class
+ * \param function_name Name of the static function in the class
+ *
+ * \return A valid Dart instance if no error occurs during the operation.
+ */
+DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
+ Dart_Handle cls_type,
+ Dart_Handle function_name);
+
/*
* ========
* Booleans
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 4a468e5..37836e0 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -30,6 +30,10 @@
// Atomically decrement the value at p by 'value'.
static void DecrementBy(intptr_t* p, intptr_t value);
+ // Atomically perform { tmp = *ptr; *ptr = (tmp OP value); return tmp; }.
+ static uint32_t FetchOrRelaxedUint32(uint32_t* ptr, uint32_t value);
+ static uint32_t FetchAndRelaxedUint32(uint32_t* ptr, uint32_t value);
+
// Atomically compare *ptr to old_value, and if equal, store new_value.
// Returns the original value at ptr.
static uword CompareAndSwapWord(uword* ptr, uword old_value, uword new_value);
diff --git a/runtime/platform/atomic_android.h b/runtime/platform/atomic_android.h
index 42dda56..f95ba02 100644
--- a/runtime/platform/atomic_android.h
+++ b/runtime/platform/atomic_android.h
@@ -46,6 +46,16 @@
__sync_fetch_and_sub(p, value);
}
+inline uint32_t AtomicOperations::FetchOrRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_or(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline uint32_t AtomicOperations::FetchAndRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_and(ptr, value, __ATOMIC_RELAXED);
+}
+
inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
uword old_value,
uword new_value) {
diff --git a/runtime/platform/atomic_fuchsia.h b/runtime/platform/atomic_fuchsia.h
index 5434fb7..2883e1e 100644
--- a/runtime/platform/atomic_fuchsia.h
+++ b/runtime/platform/atomic_fuchsia.h
@@ -43,6 +43,16 @@
__sync_fetch_and_sub(p, value);
}
+inline uint32_t AtomicOperations::FetchOrRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_or(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline uint32_t AtomicOperations::FetchAndRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_and(ptr, value, __ATOMIC_RELAXED);
+}
+
inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
uword old_value,
uword new_value) {
diff --git a/runtime/platform/atomic_linux.h b/runtime/platform/atomic_linux.h
index 3db8d73..fd1773f 100644
--- a/runtime/platform/atomic_linux.h
+++ b/runtime/platform/atomic_linux.h
@@ -46,6 +46,16 @@
__sync_fetch_and_sub(p, value);
}
+inline uint32_t AtomicOperations::FetchOrRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_or(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline uint32_t AtomicOperations::FetchAndRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_and(ptr, value, __ATOMIC_RELAXED);
+}
+
inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
uword old_value,
uword new_value) {
diff --git a/runtime/platform/atomic_macos.h b/runtime/platform/atomic_macos.h
index b08ba4f..b0bd31f 100644
--- a/runtime/platform/atomic_macos.h
+++ b/runtime/platform/atomic_macos.h
@@ -46,6 +46,16 @@
__sync_fetch_and_sub(p, value);
}
+inline uint32_t AtomicOperations::FetchOrRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_or(ptr, value, __ATOMIC_RELAXED);
+}
+
+inline uint32_t AtomicOperations::FetchAndRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return __atomic_fetch_and(ptr, value, __ATOMIC_RELAXED);
+}
+
inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
uword old_value,
uword new_value) {
diff --git a/runtime/platform/atomic_win.h b/runtime/platform/atomic_win.h
index f7fc322..5e6db1b 100644
--- a/runtime/platform/atomic_win.h
+++ b/runtime/platform/atomic_win.h
@@ -102,6 +102,18 @@
#endif
}
+inline uint32_t AtomicOperations::FetchOrRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return static_cast<uint32_t>(InterlockedOrNoFence(
+ reinterpret_cast<LONG*>(ptr), static_cast<LONG>(value)));
+}
+
+inline uint32_t AtomicOperations::FetchAndRelaxedUint32(uint32_t* ptr,
+ uint32_t value) {
+ return static_cast<uint32_t>(InterlockedAndNoFence(
+ reinterpret_cast<LONG*>(ptr), static_cast<LONG>(value)));
+}
+
inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
uword old_value,
uword new_value) {
diff --git a/runtime/vm/atomic_test.cc b/runtime/vm/atomic_test.cc
index c9afc97..5f1d565 100644
--- a/runtime/vm/atomic_test.cc
+++ b/runtime/vm/atomic_test.cc
@@ -50,6 +50,20 @@
EXPECT_EQ(static_cast<intptr_t>(1), v);
}
+VM_UNIT_TEST_CASE(FetchOrRelaxed) {
+ uint32_t v = 42;
+ uint32_t previous = AtomicOperations::FetchOrRelaxedUint32(&v, 3);
+ EXPECT_EQ(static_cast<uint32_t>(42), previous);
+ EXPECT_EQ(static_cast<uint32_t>(43), v);
+}
+
+VM_UNIT_TEST_CASE(FetchAndRelaxed) {
+ uint32_t v = 42;
+ uint32_t previous = AtomicOperations::FetchAndRelaxedUint32(&v, 3);
+ EXPECT_EQ(static_cast<uint32_t>(42), previous);
+ EXPECT_EQ(static_cast<uint32_t>(2), v);
+}
+
VM_UNIT_TEST_CASE(LoadRelaxed) {
uword v = 42;
EXPECT_EQ(static_cast<uword>(42), AtomicOperations::LoadRelaxed(&v));
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index c418f4f..49bded1 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1581,7 +1581,7 @@
Label done;
StoreIntoObjectFilter(object, value, &done, can_be_smi, kJumpToNoUpdate);
// A store buffer update is required.
- RegList regs = (1 << CODE_REG) | (1 << LR);
+ RegList regs = (1 << LR);
if (value != R0) {
regs |= (1 << R0); // Preserve R0.
}
@@ -1590,7 +1590,6 @@
mov(R0, Operand(object));
}
ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset()));
- ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
blx(LR);
PopList(regs);
Bind(&done);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 305b3a9..dee219c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -953,7 +953,6 @@
mov(R0, object);
}
ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
- ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
blr(TMP);
Pop(LR);
if (value != R0) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 76f051f..4f06cd8 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1258,12 +1258,8 @@
if (object != RDX) {
movq(RDX, object);
}
- pushq(CODE_REG);
- movq(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
- movq(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
- call(TMP);
+ call(Address(THR, Thread::update_store_buffer_entry_point_offset()));
- popq(CODE_REG);
if (value != RDX) popq(RDX);
Bind(&done);
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 6a91d21..c62e0dd 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -1193,9 +1193,15 @@
__ movq(destination.reg(), source.reg());
} else {
ASSERT(destination.IsStackSlot());
+ ASSERT((destination.base_reg() != FPREG) ||
+ ((-VariableIndexForFrameSlot(destination.stack_index())) <
+ compiler_->StackSize()));
__ movq(destination.ToStackSlotAddress(), source.reg());
}
} else if (source.IsStackSlot()) {
+ ASSERT((source.base_reg() != FPREG) ||
+ ((-VariableIndexForFrameSlot(source.stack_index())) <
+ compiler_->StackSize()));
if (destination.IsRegister()) {
__ movq(destination.reg(), source.ToStackSlotAddress());
} else {
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 4b6a94d..6ddddb9 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -2977,7 +2977,19 @@
last_used_register_ = -1;
#endif
- cpu_spill_slot_count_ = spill_slots_.length();
+#if defined(TARGET_ARCH_DBC)
+ // Spilling is unsupported on DBC.
+ ASSERT(spill_slots_.length() == 0);
+ cpu_spill_slot_count_ = 0;
+#else
+ // GraphEntryInstr::fixed_slot_count() stack slots are reserved for catch
+ // entries. When allocating a spill slot, AllocateSpillSlotFor() accounts for
+ // these reserved slots and allocates spill slots on top of them.
+ // However, if there are no spill slots allocated, we still need to reserve
+ // slots for catch entries in the spill area.
+ cpu_spill_slot_count_ = Utils::Maximum(
+ spill_slots_.length(), flow_graph_.graph_entry()->fixed_slot_count());
+#endif
spill_slots_.Clear();
quad_spill_slots_.Clear();
untagged_spill_slots_.Clear();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index c440292..19a77d3 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1203,15 +1203,14 @@
obj = H.DartSymbolPlain(builder_->ReadStringReference()).raw();
ASSERT(String::Cast(obj).IsSymbol());
break;
- case kTypeArgumentsForInstanceAllocation: {
+ case ConstantPoolTag::kTypeArgumentsForInstanceAllocation: {
cls =
H.LookupClassByKernelClass(builder_->ReadCanonicalNameReference());
- intptr_t type_args_index = builder_->ReadUInt();
- ASSERT(type_args_index < i);
- type_args ^= pool.ObjectAt(type_args_index);
- elem = Type::New(cls, type_args, TokenPosition::kNoSource);
- elem = ClassFinalizer::FinalizeType(cls, Type::Cast(elem));
- obj = Type::Cast(elem).arguments();
+ obj =
+ builder_->type_translator_
+ .BuildInstantiatedTypeArguments(cls, builder_->ReadListLength())
+ .raw();
+ ASSERT(obj.IsNull() || obj.IsTypeArguments());
} break;
case ConstantPoolTag::kContextOffset: {
intptr_t index = builder_->ReadUInt();
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index ebee057..761e198 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2066,6 +2066,20 @@
return Api::NewHandle(T, func.UserVisibleName());
}
+DART_EXPORT Dart_Handle Dart_ClassName(Dart_Handle cls_type) {
+ DARTSCOPE(Thread::Current());
+ const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
+ if (type_obj.IsNull()) {
+ RETURN_TYPE_ERROR(Z, cls_type, Type);
+ }
+ const Class& klass = Class::Handle(Z, type_obj.type_class());
+ if (klass.IsNull()) {
+ return Api::NewError(
+ "cls_type must be a Type object which represents a Class.");
+ }
+ return Api::NewHandle(T, klass.UserVisibleName());
+}
+
DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
DARTSCOPE(Thread::Current());
const Function& func = Api::UnwrapFunctionHandle(Z, function);
@@ -2120,6 +2134,21 @@
return Api::NewHandle(T, rf);
}
+DART_EXPORT Dart_Handle Dart_ClassLibrary(Dart_Handle cls_type) {
+ DARTSCOPE(Thread::Current());
+ const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
+ const Class& klass = Class::Handle(Z, type_obj.type_class());
+ if (klass.IsNull()) {
+ return Api::NewError(
+ "cls_type must be a Type object which represents a Class.");
+ }
+ const Library& library = Library::Handle(klass.library());
+ if (library.IsNull()) {
+ return Dart_Null();
+ }
+ return Api::NewHandle(Thread::Current(), library.raw());
+}
+
// --- Numbers, Integers and Doubles ----
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
@@ -2300,6 +2329,53 @@
return Api::NewHandle(T, lib.GetFunctionClosure(name));
}
+DART_EXPORT Dart_Handle Dart_GetStaticMethodClosure(Dart_Handle library,
+ Dart_Handle cls_type,
+ Dart_Handle function_name) {
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(Z, library);
+ if (lib.IsNull()) {
+ RETURN_TYPE_ERROR(Z, library, Library);
+ }
+
+ const Type& type_obj = Api::UnwrapTypeHandle(Z, cls_type);
+ if (type_obj.IsNull()) {
+ RETURN_TYPE_ERROR(Z, cls_type, Type);
+ }
+
+ const Class& klass = Class::Handle(Z, type_obj.type_class());
+ if (klass.IsNull()) {
+ return Api::NewError(
+ "cls_type must be a Type object which represents a Class");
+ }
+
+ const String& func_name = Api::UnwrapStringHandle(Z, function_name);
+ if (func_name.IsNull()) {
+ RETURN_TYPE_ERROR(Z, function_name, String);
+ }
+
+ Function& func =
+ Function::Handle(Z, klass.LookupStaticFunctionAllowPrivate(func_name));
+ if (func.IsNull()) {
+ return Dart_Null();
+ }
+
+ if (!func.is_static()) {
+ return Api::NewError("function_name must refer to a static method.");
+ }
+
+ if (func.kind() != RawFunction::kRegularFunction) {
+ return Api::NewError(
+ "function_name must be the name of a regular function.");
+ }
+ func ^= func.ImplicitClosureFunction();
+ if (func.IsNull()) {
+ return Dart_Null();
+ }
+
+ return Api::NewHandle(T, func.ImplicitStaticClosure());
+}
+
// --- Booleans ----
DART_EXPORT Dart_Handle Dart_True() {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index b88dd39..8b7fe6b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -898,6 +898,77 @@
EXPECT(strstr(result, "getInt"));
}
+TEST_CASE(DartAPI_GetStaticMethodClosure) {
+ const char* kScriptChars =
+ "class Foo {\n"
+ " static int getInt() {\n"
+ " return 1;\n"
+ " }\n"
+ " double getDouble() {\n"
+ " return 1.0;\n"
+ " }\n"
+ "}\n";
+ // Create a test library and Load up a test script in it.
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ EXPECT_VALID(lib);
+ Dart_Handle foo_cls = Dart_GetClass(lib, NewString("Foo"));
+ EXPECT_VALID(foo_cls);
+
+ Dart_Handle closure =
+ Dart_GetStaticMethodClosure(lib, foo_cls, NewString("getInt"));
+ EXPECT_VALID(closure);
+ EXPECT(Dart_IsClosure(closure));
+ Dart_Handle closure_str = Dart_ToString(closure);
+ const char* result = "";
+ Dart_StringToCString(closure_str, &result);
+ EXPECT_SUBSTRING("getInt", result);
+
+ Dart_Handle function = Dart_ClosureFunction(closure);
+ EXPECT_VALID(function);
+ EXPECT(Dart_IsFunction(function));
+ Dart_Handle func_str = Dart_ToString(function);
+ Dart_StringToCString(func_str, &result);
+ EXPECT_SUBSTRING("getInt", result);
+
+ Dart_Handle cls = Dart_FunctionOwner(function);
+ EXPECT_VALID(cls);
+ EXPECT(Dart_IsInstance(cls));
+ Dart_Handle cls_str = Dart_ClassName(cls);
+ Dart_StringToCString(cls_str, &result);
+ EXPECT_SUBSTRING("Foo", result);
+
+ EXPECT_ERROR(Dart_ClassName(Dart_Null()),
+ "Dart_ClassName expects argument 'cls_type' to be non-null.");
+ EXPECT_ERROR(
+ Dart_GetStaticMethodClosure(Dart_Null(), foo_cls, NewString("getInt")),
+ "Dart_GetStaticMethodClosure expects argument 'library' to be non-null.");
+ EXPECT_ERROR(
+ Dart_GetStaticMethodClosure(lib, Dart_Null(), NewString("getInt")),
+ "Dart_GetStaticMethodClosure expects argument 'cls_type' to be "
+ "non-null.");
+ EXPECT_ERROR(Dart_GetStaticMethodClosure(lib, foo_cls, Dart_Null()),
+ "Dart_GetStaticMethodClosure expects argument 'function_name' "
+ "to be non-null.");
+}
+
+TEST_CASE(DartAPI_ClassLibrary) {
+ Dart_Handle lib = Dart_LookupLibrary(NewString("dart:core"));
+ EXPECT_VALID(lib);
+ Dart_Handle type = Dart_GetType(lib, NewString("int"), 0, NULL);
+ EXPECT_VALID(type);
+ Dart_Handle result = Dart_ClassLibrary(type);
+ EXPECT_VALID(result);
+ Dart_Handle lib_url = Dart_LibraryUrl(result);
+ const char* str = NULL;
+ Dart_StringToCString(lib_url, &str);
+ EXPECT_STREQ("dart:core", str);
+
+ // Case with no library.
+ type = Dart_GetType(lib, NewString("dynamic"), 0, NULL);
+ EXPECT_VALID(type);
+ EXPECT(Dart_IsNull(Dart_ClassLibrary(type)));
+}
+
TEST_CASE(DartAPI_BooleanValues) {
Dart_Handle str = NewString("test");
EXPECT(!Dart_IsBoolean(str));
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 5dbbdd5..2d4305b 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -911,7 +911,13 @@
RawCode* code = function->ptr()->code_;
ASSERT(code != StubCode::LazyCompile_entry()->code());
// TODO(regis): Once we share the same stack, try to invoke directly.
-
+#if defined(DEBUG)
+ if (IsTracingExecution()) {
+ THR_Print("%" Pu64 " ", icount_);
+ THR_Print("invoking compiled %s\n",
+ Function::Handle(function).ToCString());
+ }
+#endif
// On success, returns a RawInstance. On failure, a RawError.
typedef RawObject* (*invokestub)(RawCode * code, RawArray * argdesc,
RawObject * *arg0, Thread * thread);
@@ -953,6 +959,12 @@
ASSERT(Function::HasBytecode(function));
// Bytecode was loaded in the above compilation step.
// Stay in interpreter.
+#if defined(DEBUG)
+ if (IsTracingExecution()) {
+ THR_Print("%" Pu64 " ", icount_);
+ THR_Print("invoking %s\n", Function::Handle(function).ToCString());
+ }
+#endif
RawCode* bytecode = function->ptr()->bytecode_;
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
callee_fp[kKBCPcMarkerSlotFromFp] = bytecode;
@@ -978,17 +990,17 @@
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
RawFunction* function = FrameFunction(callee_fp);
+ if (Function::HasCode(function) || !Function::HasBytecode(function)) {
+ // TODO(regis): If the function is a dispatcher, execute the dispatch here.
+ return InvokeCompiled(thread, function, argdesc_, call_base, call_top, pc,
+ FP, SP);
+ }
#if defined(DEBUG)
if (IsTracingExecution()) {
THR_Print("%" Pu64 " ", icount_);
THR_Print("invoking %s\n", Function::Handle(function).ToCString());
}
#endif
- if (Function::HasCode(function) || !Function::HasBytecode(function)) {
- // TODO(regis): If the function is a dispatcher, execute the dispatch here.
- return InvokeCompiled(thread, function, argdesc_, call_base, call_top, pc,
- FP, SP);
- }
RawCode* bytecode = function->ptr()->bytecode_;
callee_fp[kKBCPcMarkerSlotFromFp] = bytecode;
callee_fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index d8b7048..bf7d68f 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -623,28 +623,20 @@
template <class TagBitField>
void UpdateTagBit(bool value) {
- uint32_t tags = ptr()->tags_;
- uint32_t old_tags;
- do {
- old_tags = tags;
- uint32_t new_tags = TagBitField::update(value, old_tags);
- tags = AtomicOperations::CompareAndSwapUint32(&ptr()->tags_, old_tags,
- new_tags);
- } while (tags != old_tags);
+ if (value) {
+ AtomicOperations::FetchOrRelaxedUint32(&ptr()->tags_,
+ TagBitField::encode(true));
+ } else {
+ AtomicOperations::FetchAndRelaxedUint32(&ptr()->tags_,
+ ~TagBitField::encode(true));
+ }
}
template <class TagBitField>
bool TryAcquireTagBit() {
- uint32_t tags = ptr()->tags_;
- uint32_t old_tags;
- do {
- old_tags = tags;
- if (TagBitField::decode(tags)) return false;
- uint32_t new_tags = TagBitField::update(true, old_tags);
- tags = AtomicOperations::CompareAndSwapUint32(&ptr()->tags_, old_tags,
- new_tags);
- } while (tags != old_tags);
- return true;
+ uint32_t old_tags = AtomicOperations::FetchOrRelaxedUint32(
+ &ptr()->tags_, TagBitField::encode(true));
+ return !TagBitField::decode(old_tags);
}
// All writes to heap objects should ultimately pass through one of the
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 4069e998..2cbab48 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -90,9 +90,9 @@
#if !defined(TARGET_ARCH_DBC)
ASSERT(HasBeenInitialized());
#if defined(DART_USE_INTERPRETER)
- // Recognize special marker set up by interpreter in entry frame.
- if (is_interpreted_frame && (pc & 2) != 0) {
- return true;
+ if (is_interpreted_frame) {
+ // Recognize special marker set up by interpreter in entry frame.
+ return (pc & 2) != 0;
}
{
uword entry = StubCode::InvokeDartCodeFromBytecode_entry()->EntryPoint();
@@ -106,7 +106,7 @@
uword size = StubCode::InvokeDartCodeSize();
return (pc >= entry) && (pc < (entry + size));
#elif defined(DART_USE_INTERPRETER)
-#error "Simultaneous usage of simulator and interpreter not yet supported."
+#error "Simultaneous usage of DBC simulator and interpreter not yet supported."
#else
// On DBC we use a special marker PC to signify entry frame because there is
// no such thing as invocation stub.
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 37aa4b6..493329f 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1030,21 +1030,21 @@
// Input parameters:
// R0: address (i.e. object) being stored into.
void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
- // Save values being destroyed.
- __ PushList((1 << R1) | (1 << R2) | (1 << R3));
-
Label add_to_buffer;
// Check whether this object has already been remembered. Skip adding to the
// store buffer if the object is in the store buffer already.
// Spilled: R1, R2, R3
// R0: Address being stored
- __ ldr(R2, FieldAddress(R0, Object::tags_offset()));
- __ tst(R2, Operand(1 << RawObject::kRememberedBit));
+ __ ldr(TMP, FieldAddress(R0, Object::tags_offset()));
+ __ tst(TMP, Operand(1 << RawObject::kRememberedBit));
__ b(&add_to_buffer, EQ);
- __ PopList((1 << R1) | (1 << R2) | (1 << R3));
__ Ret();
__ Bind(&add_to_buffer);
+
+ // Save values being destroyed.
+ __ PushList((1 << R1) | (1 << R2) | (1 << R3));
+
// R2: Header word.
if (TargetCPUFeatures::arm_version() == ARMv5TE) {
// TODO(21263): Implement 'swp' and use it below.
@@ -1077,24 +1077,27 @@
// Increment top_ and check for overflow.
// R2: top_.
// R1: StoreBufferBlock.
- Label L;
+ Label overflow;
__ add(R2, R2, Operand(1));
__ str(R2, Address(R1, StoreBufferBlock::top_offset()));
__ CompareImmediate(R2, StoreBufferBlock::kSize);
// Restore values.
__ PopList((1 << R1) | (1 << R2) | (1 << R3));
- __ b(&L, EQ);
+ __ b(&overflow, EQ);
__ Ret();
// Handle overflow: Call the runtime leaf function.
- __ Bind(&L);
+ __ Bind(&overflow);
// Setup frame, push callee-saved registers.
+ __ Push(CODE_REG);
+ __ ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
__ EnterCallRuntimeFrame(0 * kWordSize);
__ mov(R0, Operand(THR));
__ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
// Restore callee-saved registers, tear down frame.
__ LeaveCallRuntimeFrame();
+ __ Pop(CODE_REG);
__ Ret();
}
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 647ae0b..c38de9a 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -958,8 +958,138 @@
__ ret();
}
+// Called when invoking compiled Dart code from interpreted Dart code.
+// Input parameters:
+// LR : points to return address.
+// R0 : raw code object of the Dart function to call.
+// R1 : arguments raw descriptor array.
+// R2 : address of first argument.
+// R3 : current thread.
void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
- __ Unimplemented("Interpreter not yet supported");
+#if defined(DART_USE_INTERPRETER)
+ // Copy the C stack pointer (R31) into the stack pointer we'll actually use
+ // to access the stack.
+ __ SetupDartSP();
+ __ EnterFrame(0);
+
+ // Push code object to PC marker slot.
+ __ ldr(TMP,
+ Address(R3, Thread::invoke_dart_code_from_bytecode_stub_offset()));
+ __ Push(TMP);
+
+ // Save the callee-saved registers.
+ for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
+ const Register r = static_cast<Register>(i);
+ // We use str instead of the Push macro because we will be pushing the PP
+ // register when it is not holding a pool-pointer since we are coming from
+ // C++ code.
+ __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
+ }
+
+ // Save the bottom 64-bits of callee-saved V registers.
+ for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
+ const VRegister r = static_cast<VRegister>(i);
+ __ PushDouble(r);
+ }
+
+ // Set up THR, which caches the current thread in Dart code.
+ if (THR != R3) {
+ __ mov(THR, R3);
+ }
+
+ // Save the current VMTag on the stack.
+ __ LoadFromOffset(R4, THR, Thread::vm_tag_offset());
+ __ Push(R4);
+
+ // Mark that the thread is executing Dart code.
+ __ LoadImmediate(R6, VMTag::kDartTagId);
+ __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
+
+ // Save top resource and top exit frame info. Use R6 as a temporary register.
+ // StackFrameIterator reads the top exit frame info saved in this frame.
+ __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
+ __ StoreToOffset(ZR, THR, Thread::top_resource_offset());
+ __ Push(R6);
+ __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset());
+ __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+ // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
+ ASSERT(kExitLinkSlotFromEntryFp == -22);
+ __ Push(R6);
+
+ // Load arguments descriptor array into R4, which is passed to Dart code.
+ __ mov(R4, R1);
+
+ // Load number of arguments into R5 and adjust count for type arguments.
+ __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset());
+ __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+ __ AddImmediate(TMP, R5, 1); // Include the type arguments.
+ __ cmp(R3, Operand(0));
+ __ csinc(R5, R5, TMP, EQ); // R5 <- (R3 == 0) ? R5 : TMP + 1 (R5 : R5 + 2).
+ __ SmiUntag(R5);
+
+ // R2 points to first argument.
+ // Set up arguments for the Dart call.
+ Label push_arguments;
+ Label done_push_arguments;
+ __ cmp(R5, Operand(0));
+ __ b(&done_push_arguments, EQ); // check if there are arguments.
+ __ LoadImmediate(R1, 0);
+ __ Bind(&push_arguments);
+ __ ldr(R3, Address(R2));
+ __ Push(R3);
+ __ add(R1, R1, Operand(1));
+ __ add(R2, R2, Operand(kWordSize));
+ __ cmp(R1, Operand(R5));
+ __ b(&push_arguments, LT);
+ __ Bind(&done_push_arguments);
+
+ // We now load the pool pointer(PP) with a GC safe value as we are about to
+ // invoke dart code. We don't need a real object pool here.
+ // Smi zero does not work because ARM64 assumes PP to be untagged.
+ __ LoadObject(PP, Object::null_object());
+
+ // Call the Dart code entrypoint.
+ __ mov(CODE_REG, R0);
+ __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ __ blr(R0); // R4 is the arguments descriptor array.
+
+ // Get rid of arguments pushed on the stack.
+ __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
+
+ // Restore the saved top exit frame info and top resource back into the
+ // Isolate structure. Uses R6 as a temporary register for this.
+ __ Pop(R6);
+ __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset());
+ __ Pop(R6);
+ __ StoreToOffset(R6, THR, Thread::top_resource_offset());
+
+ // Restore the current VMTag from the stack.
+ __ Pop(R4);
+ __ StoreToOffset(R4, THR, Thread::vm_tag_offset());
+
+ // Restore the bottom 64-bits of callee-saved V registers.
+ for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
+ const VRegister r = static_cast<VRegister>(i);
+ __ PopDouble(r);
+ }
+
+ // Restore C++ ABI callee-saved registers.
+ for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
+ Register r = static_cast<Register>(i);
+ // We use ldr instead of the Pop macro because we will be popping the PP
+ // register when it is not holding a pool-pointer since we are returning to
+ // C++ code. We also skip the dart stack pointer SP, since we are still
+ // using it as the stack pointer.
+ __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
+ }
+
+ // Restore the frame pointer and C stack pointer and return.
+ __ LeaveFrame();
+ __ RestoreCSP();
+ __ ret();
+#else
+ __ Stop("Not using interpreter");
+#endif // defined(DART_USE_INTERPRETER)
}
// Called for inline allocation of contexts.
@@ -1081,8 +1211,7 @@
// Check whether this object has already been remembered. Skip adding to the
// store buffer if the object is in the store buffer already.
__ LoadFieldFromOffset(TMP, R0, Object::tags_offset(), kWord);
- __ tsti(TMP, Immediate(1 << RawObject::kRememberedBit));
- __ b(&add_to_buffer, EQ);
+ __ tbz(&add_to_buffer, TMP, RawObject::kRememberedBit);
__ ret();
__ Bind(&add_to_buffer);
@@ -1102,8 +1231,7 @@
__ ldxr(R2, R3, kWord);
__ orri(R2, R2, Immediate(1 << RawObject::kRememberedBit));
__ stxr(R1, R2, R3, kWord);
- __ cmp(R1, Operand(1));
- __ b(&retry, EQ);
+ __ cbnz(&retry, R1);
// Load the StoreBuffer block out of the thread. Then load top_ out of the
// StoreBufferBlock and add the address to the pointers_.
@@ -1115,7 +1243,7 @@
// Increment top_ and check for overflow.
// R2: top_.
// R1: StoreBufferBlock.
- Label L;
+ Label overflow;
__ add(R2, R2, Operand(1));
__ StoreToOffset(R2, R1, StoreBufferBlock::top_offset(), kUnsignedWord);
__ CompareImmediate(R2, StoreBufferBlock::kSize);
@@ -1123,18 +1251,21 @@
__ Pop(R3);
__ Pop(R2);
__ Pop(R1);
- __ b(&L, EQ);
+ __ b(&overflow, EQ);
__ ret();
// Handle overflow: Call the runtime leaf function.
- __ Bind(&L);
+ __ Bind(&overflow);
// Setup frame, push callee-saved registers.
+ __ Push(CODE_REG);
+ __ ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
__ EnterCallRuntimeFrame(0 * kWordSize);
__ mov(R0, THR);
__ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
// Restore callee-saved registers, tear down frame.
__ LeaveCallRuntimeFrame();
+ __ Pop(CODE_REG);
__ ret();
}
@@ -1746,8 +1877,115 @@
__ br(R2);
}
+// Stub for interpreting a function call.
+// R5: IC-Data (for methods).
+// R4: Arguments descriptor.
+// R0: Function.
void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
- __ Unimplemented("Interpreter not yet supported");
+#if defined(DART_USE_INTERPRETER)
+ const intptr_t thread_offset = NativeArguments::thread_offset();
+ const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
+ const intptr_t argv_offset = NativeArguments::argv_offset();
+ const intptr_t retval_offset = NativeArguments::retval_offset();
+
+ __ SetPrologueOffset();
+ __ EnterStubFrame();
+
+ // Save exit frame information to enable stack walking as we are about
+ // to transition to Dart VM C++ code.
+ __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+
+#if defined(DEBUG)
+ {
+ Label ok;
+ // Check that we are always entering from Dart code.
+ __ LoadFromOffset(R8, THR, Thread::vm_tag_offset());
+ __ CompareImmediate(R8, VMTag::kDartTagId);
+ __ b(&ok, EQ);
+ __ Stop("Not coming from Dart code.");
+ __ Bind(&ok);
+ }
+#endif
+
+ // Mark that the thread is executing VM code.
+ __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+
+ // Setup space on stack for result of the interpreted function call.
+ __ Push(ZR);
+
+ // Set callee-saved R23 to point to return value slot.
+ __ mov(R23, SP);
+
+ // Push first 3 arguments of the interpreted function call.
+ __ Push(R0); // Function.
+ __ Push(R5); // ICData/MegamorphicCache.
+ __ Push(R4); // Arguments descriptor array.
+
+ // Adjust arguments count.
+ __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+ __ AddImmediate(TMP, R2, 1); // Include the type arguments.
+ __ cmp(R3, Operand(0));
+ __ csinc(R2, R2, TMP, EQ); // R2 <- (R3 == 0) ? R2 : TMP + 1 (R2 : R2 + 2).
+
+ // Push 4th Dart argument of the interpreted function call.
+ // R2: Smi-tagged arguments array length.
+ PushArrayOfArguments(assembler);
+ const intptr_t kNumArgs = 4;
+
+ // Reserve space for arguments and align frame before entering C++ world.
+ // NativeArguments are passed in registers.
+ ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
+ __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+
+ // Pass NativeArguments structure by value and call runtime.
+ // Registers R0, R1, R2, and R3 are used.
+
+ ASSERT(thread_offset == 0 * kWordSize);
+ __ mov(R0, THR); // Set thread in NativeArgs.
+
+ ASSERT(argc_tag_offset == 1 * kWordSize);
+ __ LoadImmediate(R1, kNumArgs); // Set argc in NativeArguments.
+
+ ASSERT(argv_offset == 2 * kWordSize);
+ __ AddImmediate(R2, R23, -kWordSize); // Set argv in NativeArguments.
+
+ ASSERT(retval_offset == 3 * kWordSize);
+ __ mov(R3, R23); // Set retval in NativeArguments.
+
+ __ StoreToOffset(R0, SP, thread_offset);
+ __ StoreToOffset(R1, SP, argc_tag_offset);
+ __ StoreToOffset(R2, SP, argv_offset);
+ __ StoreToOffset(R3, SP, retval_offset);
+ __ mov(R0, SP); // Pass the pointer to the NativeArguments.
+
+ // We are entering runtime code, so the C stack pointer must be restored from
+ // the stack limit to the top of the stack. We cache the stack limit address
+ // in a callee-saved register.
+ __ mov(R25, CSP);
+ __ mov(CSP, SP);
+
+ __ LoadImmediate(R5, kInterpretCallRuntimeEntry.GetEntryPoint());
+ __ blr(R5);
+
+ // Restore SP and CSP.
+ __ mov(SP, CSP);
+ __ mov(CSP, R25);
+
+ // Mark that the thread is executing Dart code.
+ __ LoadImmediate(R2, VMTag::kDartTagId);
+ __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+
+ // Reset exit frame information in Isolate structure.
+ __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+
+ // Load result of interpreted function call into R0.
+ __ LoadFromOffset(R0, R23, 0);
+
+ __ LeaveStubFrame();
+ __ ret();
+#else
+ __ Stop("Not using interpreter");
+#endif // defined(DART_USE_INTERPRETER)
}
// R5: Contains an ICData.
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index bdc494b..60a107b 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -961,8 +961,6 @@
// store buffer if the object is in the store buffer already.
// Spilled: EAX, ECX
// EDX: Address being stored
- Label reload;
- __ Bind(&reload);
__ movl(EAX, FieldAddress(EDX, Object::tags_offset()));
__ testl(EAX, Immediate(1 << RawObject::kRememberedBit));
__ j(EQUAL, &add_to_buffer, Assembler::kNearJump);
@@ -974,11 +972,10 @@
// EDX: Address being stored
// EAX: Current tag value
__ Bind(&add_to_buffer);
- __ movl(ECX, EAX);
- __ orl(ECX, Immediate(1 << RawObject::kRememberedBit));
- // Compare the tag word with EAX, update to ECX if unchanged.
- __ LockCmpxchgl(FieldAddress(EDX, Object::tags_offset()), ECX);
- __ j(NOT_EQUAL, &reload);
+ // lock+orl is an atomic read-modify-write.
+ __ lock();
+ __ orl(FieldAddress(EDX, Object::tags_offset()),
+ Immediate(1 << RawObject::kRememberedBit));
// Load the StoreBuffer block out of the thread. Then load top_ out of the
// StoreBufferBlock and add the address to the pointers_.
@@ -992,7 +989,7 @@
// Spilled: EAX, ECX
// ECX: top_
// EAX: StoreBufferBlock
- Label L;
+ Label overflow;
__ incl(ECX);
__ movl(Address(EAX, StoreBufferBlock::top_offset()), ECX);
__ cmpl(ECX, Immediate(StoreBufferBlock::kSize));
@@ -1000,11 +997,11 @@
// Spilled: EAX, ECX
__ popl(ECX);
__ popl(EAX);
- __ j(EQUAL, &L, Assembler::kNearJump);
+ __ j(EQUAL, &overflow, Assembler::kNearJump);
__ ret();
// Handle overflow: Call the runtime leaf function.
- __ Bind(&L);
+ __ Bind(&overflow);
// Setup frame, push callee-saved registers.
__ EnterCallRuntimeFrame(1 * kWordSize);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 111357c..22da3fe 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -980,6 +980,7 @@
__ movq(Address(THR, Thread::top_resource_offset()), Immediate(0));
__ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset()));
__ pushq(RAX);
+ __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
// The constant kExitLinkSlotFromEntryFp must be kept in sync with the
// code below.
@@ -994,8 +995,6 @@
}
#endif
- __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
-
// Load arguments descriptor array into R10, which is passed to Dart code.
__ movq(R10, kArgDescReg);
@@ -1015,7 +1014,9 @@
__ SmiUntag(RBX);
// Compute address of first argument into RDX.
- ASSERT(kArg0Reg == RDX);
+ if (kArg0Reg != RDX) { // Different registers on WIN64.
+ __ movq(RDX, kArg0Reg);
+ }
// Set up arguments for the Dart call.
Label push_arguments;
@@ -1060,7 +1061,7 @@
__ ret();
#else
__ Stop("Not using interpreter");
-#endif
+#endif // defined(DART_USE_INTERPRETER)
}
// Called for inline allocation of contexts.
@@ -1193,22 +1194,13 @@
// Input parameters:
// RDX: Address being stored
void StubCode::GenerateUpdateStoreBufferStub(Assembler* assembler) {
- // Save registers being destroyed.
- __ pushq(RAX);
- __ pushq(RCX);
-
Label add_to_buffer;
// Check whether this object has already been remembered. Skip adding to the
// store buffer if the object is in the store buffer already.
- // Spilled: RAX, RCX
// RDX: Address being stored
- Label reload;
- __ Bind(&reload);
- __ movl(RAX, FieldAddress(RDX, Object::tags_offset()));
- __ testl(RAX, Immediate(1 << RawObject::kRememberedBit));
+ __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
+ __ testl(TMP, Immediate(1 << RawObject::kRememberedBit));
__ j(EQUAL, &add_to_buffer, Assembler::kNearJump);
- __ popq(RCX);
- __ popq(RAX);
__ ret();
// Update the tags that this object has been remembered.
@@ -1217,11 +1209,14 @@
// RDX: Address being stored
// RAX: Current tag value
__ Bind(&add_to_buffer);
- __ movl(RCX, RAX);
- __ orl(RCX, Immediate(1 << RawObject::kRememberedBit));
- // Compare the tag word with RAX, update to RCX if unchanged.
- __ LockCmpxchgl(FieldAddress(RDX, Object::tags_offset()), RCX);
- __ j(NOT_EQUAL, &reload);
+ // lock+orl is an atomic read-modify-write.
+ __ lock();
+ __ orl(FieldAddress(RDX, Object::tags_offset()),
+ Immediate(1 << RawObject::kRememberedBit));
+
+ // Save registers being destroyed.
+ __ pushq(RAX);
+ __ pushq(RCX);
// Load the StoreBuffer block out of the thread. Then load top_ out of the
// StoreBufferBlock and add the address to the pointers_.
@@ -1233,23 +1228,26 @@
// Increment top_ and check for overflow.
// RCX: top_
// RAX: StoreBufferBlock
- Label L;
+ Label overflow;
__ incq(RCX);
__ movl(Address(RAX, StoreBufferBlock::top_offset()), RCX);
__ cmpl(RCX, Immediate(StoreBufferBlock::kSize));
// Restore values.
__ popq(RCX);
__ popq(RAX);
- __ j(EQUAL, &L, Assembler::kNearJump);
+ __ j(EQUAL, &overflow, Assembler::kNearJump);
__ ret();
// Handle overflow: Call the runtime leaf function.
- __ Bind(&L);
+ __ Bind(&overflow);
// Setup frame, push callee-saved registers.
+ __ pushq(CODE_REG);
+ __ movq(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
__ EnterCallRuntimeFrame(0);
__ movq(CallingConventions::kArg1Reg, THR);
__ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
__ LeaveCallRuntimeFrame();
+ __ popq(CODE_REG);
__ ret();
}
@@ -1950,7 +1948,7 @@
__ ret();
#else
__ Stop("Not using interpreter");
-#endif
+#endif // defined(DART_USE_INTERPRETER)
}
// RBX: Contains an ICData.
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 4ef37d1..5e7b6dd 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -152,7 +152,11 @@
return completer.future
.then((String s) => jsonDecode(s))
.then((dynamic json) {
- return json['result']['result']['kernelBytes'];
+ Map<String, dynamic> jsonMap = json;
+ if (jsonMap.containsKey('error')) {
+ throw jsonMap['error'];
+ }
+ return jsonMap['result']['result']['kernelBytes'];
});
} else {
// fallback to compile using kernel service
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/sync_throw_in_constructor_from_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/sync_throw_in_constructor_from_async.dart
index 5889055..610895a 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/sync_throw_in_constructor_from_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/sync_throw_in_constructor_from_async.dart
@@ -17,7 +17,7 @@
class Class {
@NoInline()
- /*5:Class*/ Class() {
+ Class() {
/*6:Class*/ throw '>ExceptionMarker<';
}
}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor.dart
index 2b7780a..6d7a7f2 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor.dart
@@ -11,7 +11,7 @@
class Class {
@NoInline()
- /*2:Class*/ Class() {
+ Class() {
/*3:Class*/ throw '>ExceptionMarker<';
}
}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
index 0120aa3..7d78c18 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/throw_in_constructor_from_async.dart
@@ -17,7 +17,7 @@
class Class {
@NoInline()
- /*2:Class*/ Class() {
- /*3:Class*/ throw '>ExceptionMarker<';
+ Class() {
+ /*2:Class*/ throw '>ExceptionMarker<';
}
}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
index d9ad5e6..d28f3a2 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -94,6 +94,7 @@
/// methods.
const List<LineException> beforeExceptions = const [
const LineException('wrapException', 'js_helper.dart'),
+ const LineException('throwExpression', 'js_helper.dart'),
];
/// Lines allowed after the intended stack trace. Typically from the event
diff --git a/tools/VERSION b/tools/VERSION
index cb38d48..c3f1dcf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 0
PATCH 0
PRERELEASE 64
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1