[dart2js] Migrate constants/values.dart

Change-Id: Ia042b4ba17407bd8a4da404ce832ae83d046cb1a
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243880
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
Reviewed-by: Nate Biggs <natebiggs@google.com>
This commit is contained in:
Stephen Adams 2022-05-06 15:58:15 +00:00 committed by Commit Bot
parent 04bcc30c58
commit e3e9aed1f5
7 changed files with 159 additions and 121 deletions

View file

@ -5,6 +5,8 @@
// @dart = 2.10
import '../common.dart';
import '../constants/common_elements_for_constants.dart'
as common_elements_for_constants;
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../elements/entities.dart';
@ -17,7 +19,11 @@ import '../universe/selector.dart' show Selector;
import 'names.dart' show Identifiers, Uris;
/// The common elements and types in Dart.
abstract class CommonElements implements CommonElementsForDartTypes {
abstract class CommonElements
implements
CommonElementsForDartTypes,
common_elements_for_constants.CommonElements {
@override
final DartTypes dartTypes;
final ElementEnvironment _env;
ClassEntity _objectClass;
@ -329,6 +335,7 @@ abstract class CommonElements implements CommonElementsForDartTypes {
element.name == 'apply' && element.enclosingClass == functionClass;
/// The `dynamic` type.
@override
DynamicType get dynamicType => _env.dynamicType;
/// The `Object` type defined in 'dart:core'.
@ -336,6 +343,7 @@ abstract class CommonElements implements CommonElementsForDartTypes {
InterfaceType get objectType => _getRawType(objectClass);
/// The `bool` type defined in 'dart:core'.
@override
InterfaceType get boolType => _getRawType(boolClass);
/// The `num` type defined in 'dart:core'.
@ -350,6 +358,7 @@ abstract class CommonElements implements CommonElementsForDartTypes {
InterfaceType get doubleType => _getRawType(doubleClass);
/// The `String` type defined in 'dart:core'.
@override
InterfaceType get stringType => _getRawType(stringClass);
/// The `Symbol` type defined in 'dart:core'.

View file

@ -0,0 +1,19 @@
// Copyright (c) 2022, 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.
import '../elements/types.dart';
/// This is a facade interface for the members of CommonElements that are
/// required by 'constants/value.dart'.
// TODO(48820): When CommonElements is migrated, remove this facade.
abstract class CommonElements {
DartType get boolType;
DartType get doubleType;
DartType get dynamicType;
DartType get intType;
DartType get nullType;
DartType get stringType;
DartTypes get dartTypes;
}

View file

@ -2,18 +2,19 @@
// 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.
// @dart = 2.10
library dart2js.constants.values;
import '../common.dart';
import '../common/elements.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../deferred_load/output_unit.dart' show OutputUnit;
import '../deferred_load/output_unit_migrated.dart' show OutputUnit;
import '../js/js.dart' as js;
import '../util/util.dart';
import 'common_elements_for_constants.dart';
// TODO(48820): When CommonElements is migrated, replace this import with
// import '../common/elements.dart' show CommonElements;
enum ConstantValueKind {
FUNCTION,
NULL,
@ -104,9 +105,9 @@ abstract class ConstantValue {
bool get isNegativeInfinity => false;
// TODO(johnniwinther): Replace with a 'type' getter.
DartType /*!*/ getType(CommonElements types);
DartType getType(CommonElements types);
List<ConstantValue /*!*/ > /*!*/ getDependencies();
List<ConstantValue> getDependencies();
accept(ConstantValueVisitor visitor, arg);
@ -118,10 +119,10 @@ abstract class ConstantValue {
/// For the synthetic constants, [DeferredConstantValue],
/// [DeferredGlobalConstantValue], [SyntheticConstantValue],
/// [InterceptorConstantValue] the unparse is descriptive only.
String toDartText(DartTypes dartTypes);
String toDartText(DartTypes? dartTypes);
/// Returns a structured representation of this constant suited for debugging.
String toStructuredText(DartTypes dartTypes);
String toStructuredText(DartTypes? dartTypes);
ConstantValueKind get kind;
@ -135,9 +136,9 @@ abstract class ConstantValue {
}
class FunctionConstantValue extends ConstantValue {
final FunctionEntity /*!*/ element;
final FunctionEntity element;
// TODO(johnniwinther): Should the type be derived from [element].
final FunctionType /*!*/ type;
final FunctionType type;
FunctionConstantValue(this.element, this.type);
@ -166,16 +167,16 @@ class FunctionConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.FUNCTION;
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
if (element.enclosingClass != null) {
return '${element.enclosingClass.name}.${element.name}';
return '${element.enclosingClass!.name}.${element.name}';
} else {
return '${element.name}';
}
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
return 'FunctionConstant(${toDartText(dartTypes)})';
}
}
@ -228,10 +229,10 @@ class NullConstantValue extends PrimitiveConstantValue {
ConstantValueKind get kind => ConstantValueKind.NULL;
@override
String toStructuredText(DartTypes dartTypes) => 'NullConstant';
String toStructuredText(DartTypes? dartTypes) => 'NullConstant';
@override
String toDartText(DartTypes dartTypes) => 'null';
String toDartText(DartTypes? dartTypes) => 'null';
}
abstract class NumConstantValue extends PrimitiveConstantValue {
@ -244,7 +245,7 @@ abstract class NumConstantValue extends PrimitiveConstantValue {
}
class IntConstantValue extends NumConstantValue {
final BigInt /*!*/ intValue;
final BigInt intValue;
// Caching IntConstantValues representing -2 through 10 so that we don't have
// to create new ones every time those values are used.
@ -253,7 +254,7 @@ class IntConstantValue extends NumConstantValue {
@override
double get doubleValue => intValue.toDouble();
factory IntConstantValue(BigInt /*!*/ value) {
factory IntConstantValue(BigInt value) {
var existing = _cachedValues[value];
if (existing != null) return existing;
var intConstantVal = IntConstantValue._internal(value);
@ -302,11 +303,11 @@ class IntConstantValue extends NumConstantValue {
ConstantValueKind get kind => ConstantValueKind.INT;
@override
String toStructuredText(DartTypes dartTypes) =>
String toStructuredText(DartTypes? dartTypes) =>
'IntConstant(${toDartText(dartTypes)})';
@override
String toDartText(DartTypes dartTypes) => intValue.toString();
String toDartText(DartTypes? dartTypes) => intValue.toString();
}
class DoubleConstantValue extends NumConstantValue {
@ -380,11 +381,11 @@ class DoubleConstantValue extends NumConstantValue {
ConstantValueKind get kind => ConstantValueKind.DOUBLE;
@override
String toStructuredText(DartTypes dartTypes) =>
String toStructuredText(DartTypes? dartTypes) =>
'DoubleConstant(${toDartText(dartTypes)})';
@override
String toDartText(DartTypes dartTypes) => doubleValue.toString();
String toDartText(DartTypes? dartTypes) => doubleValue.toString();
}
abstract class BoolConstantValue extends PrimitiveConstantValue {
@ -411,7 +412,7 @@ abstract class BoolConstantValue extends PrimitiveConstantValue {
ConstantValueKind get kind => ConstantValueKind.BOOL;
@override
String toStructuredText(DartTypes dartTypes) =>
String toStructuredText(DartTypes? dartTypes) =>
'BoolConstant(${toDartText(dartTypes)})';
}
@ -438,7 +439,7 @@ class TrueConstantValue extends BoolConstantValue {
int get hashCode => 499;
@override
String toDartText(DartTypes dartTypes) => boolValue.toString();
String toDartText(DartTypes? dartTypes) => boolValue.toString();
}
class FalseConstantValue extends BoolConstantValue {
@ -464,11 +465,11 @@ class FalseConstantValue extends BoolConstantValue {
int get hashCode => 536555975;
@override
String toDartText(DartTypes dartTypes) => boolValue.toString();
String toDartText(DartTypes? dartTypes) => boolValue.toString();
}
class StringConstantValue extends PrimitiveConstantValue {
final String /*!*/ stringValue;
final String stringValue;
@override
final int hashCode;
@ -505,10 +506,10 @@ class StringConstantValue extends PrimitiveConstantValue {
// TODO(johnniwinther): Ensure correct escaping.
@override
String toDartText(DartTypes dartTypes) => '"${stringValue}"';
String toDartText(DartTypes? dartTypes) => '"${stringValue}"';
@override
String toStructuredText(DartTypes dartTypes) =>
String toStructuredText(DartTypes? dartTypes) =>
'StringConstant(${toDartText(dartTypes)})';
}
@ -523,7 +524,7 @@ abstract class ObjectConstantValue extends ConstantValue {
@override
DartType getType(CommonElements types) => type;
void _unparseTypeArguments(DartTypes dartTypes, StringBuffer sb) {
void _unparseTypeArguments(DartTypes? dartTypes, StringBuffer sb) {
if (dartTypes == null || !dartTypes.treatAsRawType(type)) {
sb.write('<');
sb.write(type.typeArguments.join(', '));
@ -560,15 +561,15 @@ class TypeConstantValue extends ObjectConstantValue {
ConstantValueKind get kind => ConstantValueKind.TYPE;
@override
String toDartText(DartTypes dartTypes) => '$representedType';
String toDartText(DartTypes? dartTypes) => '$representedType';
@override
String toStructuredText(DartTypes dartTypes) =>
String toStructuredText(DartTypes? dartTypes) =>
'TypeConstant(${representedType})';
}
class ListConstantValue extends ObjectConstantValue {
final List<ConstantValue /*!*/ > /*!*/ entries;
final List<ConstantValue> entries;
@override
final int hashCode;
@ -606,7 +607,7 @@ class ListConstantValue extends ObjectConstantValue {
ConstantValueKind get kind => ConstantValueKind.LIST;
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
_unparseTypeArguments(dartTypes, sb);
sb.write('[');
@ -619,7 +620,7 @@ class ListConstantValue extends ObjectConstantValue {
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
sb.write('ListConstant(');
_unparseTypeArguments(dartTypes, sb);
@ -669,7 +670,7 @@ abstract class SetConstantValue extends ObjectConstantValue {
accept(ConstantValueVisitor visitor, arg) => visitor.visitSet(this, arg);
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
_unparseTypeArguments(dartTypes, sb);
sb.write('{');
@ -679,7 +680,7 @@ abstract class SetConstantValue extends ObjectConstantValue {
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
sb.write('SetConstant(');
_unparseTypeArguments(dartTypes, sb);
@ -702,7 +703,7 @@ abstract class MapConstantValue extends ObjectConstantValue {
final List<ConstantValue> values;
@override
final int hashCode;
Map<ConstantValue, ConstantValue> _lookupMap;
Map<ConstantValue, ConstantValue>? _lookupMap;
MapConstantValue(
InterfaceType type, List<ConstantValue> keys, List<ConstantValue> values)
@ -742,7 +743,7 @@ abstract class MapConstantValue extends ObjectConstantValue {
int get length => keys.length;
ConstantValue lookup(ConstantValue key) {
ConstantValue? lookup(ConstantValue key) {
var lookupMap = _lookupMap ??= Map.fromIterables(keys, values);
return lookupMap[key];
}
@ -754,7 +755,7 @@ abstract class MapConstantValue extends ObjectConstantValue {
ConstantValueKind get kind => ConstantValueKind.MAP;
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
_unparseTypeArguments(dartTypes, sb);
sb.write('{');
@ -769,7 +770,7 @@ abstract class MapConstantValue extends ObjectConstantValue {
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
sb.write('MapConstant(');
_unparseTypeArguments(dartTypes, sb);
@ -818,12 +819,12 @@ class InterceptorConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.INTERCEPTOR;
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
return 'interceptor($cls)';
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
return 'InterceptorConstant(${cls.name})';
}
}
@ -859,13 +860,13 @@ class JsNameConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.JS_NAME;
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
if (name.isFinalized) 'js_name(${name})';
return 'js_name(name.nonfinalizedDebugText())';
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
if (name.isFinalized) return 'JsNameConstant(${name})';
return 'JsNameConstant(name.nonfinalizedDebugText())';
}
@ -898,10 +899,10 @@ class DummyInterceptorConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.DUMMY_INTERCEPTOR;
@override
String toDartText(DartTypes dartTypes) => 'dummy_interceptor()';
String toDartText(DartTypes? dartTypes) => 'dummy_interceptor()';
@override
String toStructuredText(DartTypes dartTypes) => 'DummyInterceptorConstant()';
String toStructuredText(DartTypes? dartTypes) => 'DummyInterceptorConstant()';
}
/// A constant used to represent the sentinel for uninitialized late fields and
@ -926,10 +927,10 @@ class LateSentinelConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.LATE_SENTINEL;
@override
String toDartText(DartTypes dartTypes) => 'late_sentinel()';
String toDartText(DartTypes? dartTypes) => 'late_sentinel()';
@override
String toStructuredText(DartTypes dartTypes) => 'LateSentinelConstant()';
String toStructuredText(DartTypes? dartTypes) => 'LateSentinelConstant()';
}
// A constant with an empty type used in [HInstruction]s of an expression
@ -957,10 +958,10 @@ class UnreachableConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.UNREACHABLE;
@override
String toDartText(DartTypes dartTypes) => 'unreachable()';
String toDartText(DartTypes? dartTypes) => 'unreachable()';
@override
String toStructuredText(DartTypes dartTypes) => 'UnreachableConstant()';
String toStructuredText(DartTypes? dartTypes) => 'UnreachableConstant()';
}
class ConstructedConstantValue extends ObjectConstantValue {
@ -975,7 +976,7 @@ class ConstructedConstantValue extends ObjectConstantValue {
: this.fields = fields,
hashCode = Hashing.unorderedMapHash(fields, Hashing.objectHash(type)),
super(type) {
assert(type != null);
assert((type as dynamic) != null);
assert(!fields.containsKey(null));
assert(!fields.containsValue(null));
}
@ -1009,18 +1010,18 @@ class ConstructedConstantValue extends ObjectConstantValue {
ConstantValueKind get kind => ConstantValueKind.CONSTRUCTED;
Iterable<FieldEntity> get _fieldsSortedByName {
return fields.keys.toList()..sort((a, b) => a.name.compareTo(b.name));
return fields.keys.toList()..sort((a, b) => a.name!.compareTo(b.name!));
}
@override
String toDartText(DartTypes dartTypes) {
String toDartText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
sb.write(type.element.name);
_unparseTypeArguments(dartTypes, sb);
sb.write('(');
int i = 0;
for (FieldEntity field in _fieldsSortedByName) {
ConstantValue value = fields[field];
ConstantValue value = fields[field]!;
if (i > 0) sb.write(',');
sb.write(field.name);
sb.write('=');
@ -1032,14 +1033,14 @@ class ConstructedConstantValue extends ObjectConstantValue {
}
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
StringBuffer sb = StringBuffer();
sb.write('ConstructedConstant(');
sb.write(type);
sb.write('(');
int i = 0;
for (FieldEntity field in _fieldsSortedByName) {
ConstantValue value = fields[field];
ConstantValue value = fields[field]!;
if (i > 0) sb.write(',');
sb.write(field.name);
sb.write('=');
@ -1087,11 +1088,11 @@ class InstantiationConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.INSTANTIATION;
@override
String toDartText(DartTypes dartTypes) =>
String toDartText(DartTypes? dartTypes) =>
'<${typeArguments.join(', ')}>(${function.toDartText(dartTypes)})';
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
return 'InstantiationConstant($typeArguments,'
'${function.toStructuredText(dartTypes)})';
}
@ -1113,7 +1114,7 @@ class DeferredGlobalConstantValue extends ConstantValue {
DeferredGlobalConstantValue(this.referenced, this.unit);
final ConstantValue referenced;
final OutputUnit unit;
final OutputUnit? unit;
bool get isReference => true;
@ -1141,11 +1142,11 @@ class DeferredGlobalConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.DEFERRED_GLOBAL;
@override
String toDartText(DartTypes dartTypes) =>
String toDartText(DartTypes? dartTypes) =>
'deferred_global(${referenced.toDartText(dartTypes)})';
@override
String toStructuredText(DartTypes dartTypes) {
String toStructuredText(DartTypes? dartTypes) {
return 'DeferredGlobalConstant(${referenced.toStructuredText(dartTypes)})';
}
}
@ -1172,8 +1173,8 @@ class NonConstantValue extends ConstantValue {
ConstantValueKind get kind => ConstantValueKind.NON_CONSTANT;
@override
String toStructuredText(DartTypes dartTypes) => 'NonConstant';
String toStructuredText(DartTypes? dartTypes) => 'NonConstant';
@override
String toDartText(DartTypes dartTypes) => '>>non-constant<<';
String toDartText(DartTypes? dartTypes) => '>>non-constant<<';
}

View file

@ -13,52 +13,9 @@ import '../elements/entities.dart';
import '../serialization/serialization.dart';
import '../options.dart';
/// A "hunk" of the program that will be loaded whenever one of its [imports]
/// are loaded.
///
/// Elements that are only used in one deferred import, is in an OutputUnit with
/// the deferred import as single element in the [imports] set.
///
/// Whenever a deferred Element is shared between several deferred imports it is
/// in an output unit with those imports in the [imports] Set.
///
/// We never create two OutputUnits sharing the same set of [imports].
class OutputUnit implements Comparable<OutputUnit> {
/// `true` if this output unit is for the main output file.
final bool isMainOutput;
/// A unique name representing this [OutputUnit].
final String name;
/// The deferred imports that use the elements in this output unit.
final Set<ImportEntity> imports;
OutputUnit(this.isMainOutput, this.name, this.imports);
@override
int compareTo(OutputUnit other) {
if (identical(this, other)) return 0;
if (isMainOutput && !other.isMainOutput) return -1;
if (!isMainOutput && other.isMainOutput) return 1;
var size = imports.length;
var otherSize = other.imports.length;
if (size != otherSize) return size.compareTo(otherSize);
var thisImports = imports.toList();
var otherImports = other.imports.toList();
for (var i = 0; i < size; i++) {
var cmp = compareImportEntities(thisImports[i], otherImports[i]);
if (cmp != 0) return cmp;
}
// TODO(sigmund): make compare stable. If we hit this point, all imported
// libraries are the same, however [this] and [other] use different deferred
// imports in the program. We can make this stable if we sort based on the
// deferred imports themselves (e.g. their declaration location).
return name.compareTo(other.name);
}
@override
String toString() => "OutputUnit($name, $imports)";
}
// TODO(48820): Move OutputUnit and compareImportEntities back here.
import 'output_unit_migrated.dart';
export 'output_unit_migrated.dart';
/// Interface for updating an [OutputUnitData] object with data for late
/// members, that is, members created on demand during code generation.
@ -397,11 +354,3 @@ String deferredPartFileName(CompilerOptions options, String name,
String extension = addExtension ? ".part.js" : "";
return "${outName}_$name$extension";
}
int compareImportEntities(ImportEntity a, ImportEntity b) {
if (a == b) {
return 0;
} else {
return a.uri.path.compareTo(b.uri.path);
}
}

View file

@ -0,0 +1,60 @@
// Copyright (c) 2021, 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.
import '../elements/entities.dart' show ImportEntity;
/// A "hunk" of the program that will be loaded whenever one of its [imports]
/// are loaded.
///
/// Elements that are only used in one deferred import, is in an OutputUnit with
/// the deferred import as single element in the [imports] set.
///
/// Whenever a deferred Element is shared between several deferred imports it is
/// in an output unit with those imports in the [imports] Set.
///
/// We never create two OutputUnits sharing the same set of [imports].
class OutputUnit implements Comparable<OutputUnit> {
/// `true` if this output unit is for the main output file.
final bool isMainOutput;
/// A unique name representing this [OutputUnit].
final String name;
/// The deferred imports that use the elements in this output unit.
final Set<ImportEntity> imports;
OutputUnit(this.isMainOutput, this.name, this.imports);
@override
int compareTo(OutputUnit other) {
if (identical(this, other)) return 0;
if (isMainOutput && !other.isMainOutput) return -1;
if (!isMainOutput && other.isMainOutput) return 1;
var size = imports.length;
var otherSize = other.imports.length;
if (size != otherSize) return size.compareTo(otherSize);
var thisImports = imports.toList();
var otherImports = other.imports.toList();
for (var i = 0; i < size; i++) {
var cmp = compareImportEntities(thisImports[i], otherImports[i]);
if (cmp != 0) return cmp;
}
// TODO(sigmund): make compare stable. If we hit this point, all imported
// libraries are the same, however [this] and [other] use different deferred
// imports in the program. We can make this stable if we sort based on the
// deferred imports themselves (e.g. their declaration location).
return name.compareTo(other.name);
}
@override
String toString() => "OutputUnit($name, $imports)";
}
int compareImportEntities(ImportEntity a, ImportEntity b) {
if (a == b) {
return 0;
} else {
return a.uri.path.compareTo(b.uri.path);
}
}

View file

@ -916,8 +916,8 @@ class _ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
return InstantiationConstantValue(typeArguments, function);
}
List<ConstantValue> _handleValues(List<ConstantValue> values) {
List<ConstantValue> result;
List<ConstantValue /*!*/ > _handleValues(List<ConstantValue /*!*/ > values) {
List<ConstantValue /*!*/ > result;
for (int i = 0; i < values.length; i++) {
var value = values[i];
var newValue = value.accept(this, null);

View file

@ -1242,7 +1242,7 @@ abstract class HInstruction implements SpannableWithEntity {
domain.isPrimitiveOrNull(instructionType);
/// Type of the instruction.
AbstractValue instructionType;
AbstractValue /*!*/ instructionType;
HInstruction getDartReceiver(JClosedWorld closedWorld) => null;
bool onlyThrowsNSM() => false;
@ -2934,7 +2934,7 @@ class HLoopBranch extends HConditionalBranch {
}
class HConstant extends HInstruction {
final ConstantValue constant;
final ConstantValue /*!*/ constant;
HConstant.internal(this.constant, AbstractValue constantType)
: super([], constantType);