9cc008e49c
Change-Id: Ib1e8ca3b9bbf62f8282524fc5599eee5cae38389 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99089 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
143 lines
3.6 KiB
Dart
143 lines
3.6 KiB
Dart
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
library vm.bytecode.nullability_detector;
|
|
|
|
import 'package:kernel/ast.dart';
|
|
import 'dbc.dart';
|
|
import 'recognized_methods.dart' show RecognizedMethods;
|
|
|
|
class NullabilityDetector {
|
|
final _IsNullableVisitor _isNullableVisitor;
|
|
|
|
NullabilityDetector(RecognizedMethods recognizedMethods)
|
|
: _isNullableVisitor = new _IsNullableVisitor(recognizedMethods);
|
|
|
|
bool isNullable(Expression expr) => expr.accept(_isNullableVisitor);
|
|
}
|
|
|
|
class _IsNullableVisitor extends ExpressionVisitor<bool> {
|
|
final RecognizedMethods recognizedMethods;
|
|
|
|
_IsNullableVisitor(this.recognizedMethods);
|
|
|
|
@override
|
|
bool defaultExpression(Expression node) => true;
|
|
|
|
@override
|
|
bool visitNullLiteral(NullLiteral node) => true;
|
|
|
|
// All basic literals except NullLiteral are non-nullable.
|
|
@override
|
|
bool defaultBasicLiteral(BasicLiteral node) => false;
|
|
|
|
@override
|
|
bool visitVariableGet(VariableGet node) {
|
|
final v = node.variable;
|
|
if ((v.isConst || v.isFinal) && v.initializer != null) {
|
|
return v.initializer.accept(this);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
bool visitVariableSet(VariableSet node) => node.value.accept(this);
|
|
|
|
@override
|
|
bool visitMethodInvocation(MethodInvocation node) {
|
|
final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
|
|
if (opcode != null) {
|
|
return !_nonNullableBytecodeInstructions.contains(opcode);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
bool visitConstructorInvocation(ConstructorInvocation node) => false;
|
|
|
|
@override
|
|
bool visitNot(Not node) => false;
|
|
|
|
@override
|
|
bool visitLogicalExpression(LogicalExpression node) => false;
|
|
|
|
@override
|
|
bool visitConditionalExpression(ConditionalExpression node) =>
|
|
node.then.accept(this) || node.otherwise.accept(this);
|
|
|
|
@override
|
|
bool visitStringConcatenation(StringConcatenation node) => false;
|
|
|
|
@override
|
|
bool visitIsExpression(IsExpression node) => false;
|
|
|
|
@override
|
|
bool visitAsExpression(AsExpression node) => node.operand.accept(this);
|
|
|
|
@override
|
|
bool visitSymbolLiteral(SymbolLiteral node) => false;
|
|
|
|
@override
|
|
bool visitTypeLiteral(TypeLiteral node) => false;
|
|
|
|
@override
|
|
bool visitThisExpression(ThisExpression node) => false;
|
|
|
|
@override
|
|
bool visitRethrow(Rethrow node) => false;
|
|
|
|
@override
|
|
bool visitThrow(Throw node) => false;
|
|
|
|
@override
|
|
bool visitListLiteral(ListLiteral node) => false;
|
|
|
|
@override
|
|
bool visitMapLiteral(MapLiteral node) => false;
|
|
|
|
@override
|
|
bool visitFunctionExpression(FunctionExpression node) => false;
|
|
|
|
@override
|
|
bool visitConstantExpression(ConstantExpression node) =>
|
|
node.constant is NullConstant;
|
|
|
|
@override
|
|
bool visitLet(Let node) => node.body.accept(this);
|
|
|
|
@override
|
|
bool visitInstantiation(Instantiation node) => false;
|
|
}
|
|
|
|
final _nonNullableBytecodeInstructions = new Set<Opcode>.from([
|
|
Opcode.kBooleanNegateTOS,
|
|
Opcode.kEqualsNull,
|
|
Opcode.kNegateInt,
|
|
Opcode.kAddInt,
|
|
Opcode.kSubInt,
|
|
Opcode.kMulInt,
|
|
Opcode.kTruncDivInt,
|
|
Opcode.kModInt,
|
|
Opcode.kBitAndInt,
|
|
Opcode.kBitOrInt,
|
|
Opcode.kBitXorInt,
|
|
Opcode.kShlInt,
|
|
Opcode.kShrInt,
|
|
Opcode.kCompareIntEq,
|
|
Opcode.kCompareIntGt,
|
|
Opcode.kCompareIntLt,
|
|
Opcode.kCompareIntGe,
|
|
Opcode.kCompareIntLe,
|
|
Opcode.kNegateDouble,
|
|
Opcode.kAddDouble,
|
|
Opcode.kSubDouble,
|
|
Opcode.kMulDouble,
|
|
Opcode.kDivDouble,
|
|
Opcode.kCompareDoubleEq,
|
|
Opcode.kCompareDoubleGt,
|
|
Opcode.kCompareDoubleLt,
|
|
Opcode.kCompareDoubleGe,
|
|
Opcode.kCompareDoubleLe,
|
|
]);
|