609d2770be
The canonicalization of symbols needs to take library privacy into account. Since the Symbol class itself only has a [_name] field but does not reference in which library the symbol came from, the [_name] must be mangled. Mangling is done by backends and so we make a new [SymbolConstant] which the backends can desugar by doing appropriate mangling and construction of a [Symbol] instance. Fixes https://github.com/dart-lang/sdk/issues/34396 Change-Id: I2e13288483c35f875d39eefdb73677b2cc03527a Reviewed-on: https://dart-review.googlesource.com/74360 Reviewed-by: Martin Kustermann <kustermann@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
122 lines
4.8 KiB
Dart
122 lines
4.8 KiB
Dart
// Copyright (c) 2017, 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.constants_native_effects;
|
|
|
|
import '../ast.dart';
|
|
import '../transformations/constants.dart';
|
|
import '../core_types.dart';
|
|
|
|
class VmConstantsBackend implements ConstantsBackend {
|
|
final Map<String, String> defines;
|
|
|
|
final Class immutableMapClass;
|
|
final Class internalSymbolClass;
|
|
final Field symbolNameField;
|
|
|
|
VmConstantsBackend._(this.defines, this.immutableMapClass,
|
|
this.internalSymbolClass, this.symbolNameField);
|
|
|
|
/// If [defines] is not `null` it will be used for handling
|
|
/// `const {bool,...}.fromEnvironment()` otherwise the current VM's values
|
|
/// will be used.
|
|
factory VmConstantsBackend(Map<String, String> defines, CoreTypes coreTypes) {
|
|
final Library coreLibrary = coreTypes.coreLibrary;
|
|
final Class immutableMapClass = coreLibrary.classes
|
|
.firstWhere((Class klass) => klass.name == '_ImmutableMap');
|
|
assert(immutableMapClass != null);
|
|
|
|
final Class internalSymbolClass = coreTypes.internalSymbolClass;
|
|
assert(internalSymbolClass != null);
|
|
|
|
final Field symbolNameField =
|
|
internalSymbolClass.fields.where((Field field) {
|
|
return field.isInstanceMember && field.name.name == '_name';
|
|
}).single;
|
|
|
|
return new VmConstantsBackend._(
|
|
defines, immutableMapClass, internalSymbolClass, symbolNameField);
|
|
}
|
|
|
|
Constant buildConstantForNative(
|
|
String nativeName,
|
|
List<DartType> typeArguments,
|
|
List<Constant> positionalArguments,
|
|
Map<String, Constant> namedArguments) {
|
|
switch (nativeName) {
|
|
case 'Bool_fromEnvironment':
|
|
final String name = (positionalArguments[0] as StringConstant).value;
|
|
final Constant constant = namedArguments['defaultValue'];
|
|
final bool defaultValue = constant is BoolConstant
|
|
? constant.value
|
|
: (constant is NullConstant ? null : false);
|
|
bool value;
|
|
if (defines != null) {
|
|
value = defines[name] == 'true'
|
|
? true
|
|
: (defines[name] == 'false' ? false : defaultValue);
|
|
} else {
|
|
value = new bool.fromEnvironment(name, defaultValue: defaultValue);
|
|
}
|
|
return value != null ? new BoolConstant(value) : new NullConstant();
|
|
case 'Integer_fromEnvironment':
|
|
final String name = (positionalArguments[0] as StringConstant).value;
|
|
final Constant constant = namedArguments['defaultValue'];
|
|
final int defaultValue =
|
|
constant is IntConstant ? constant.value : null;
|
|
int value;
|
|
if (defines != null) {
|
|
final String defineValue = defines[name];
|
|
value = defineValue != null
|
|
? (int.tryParse(defineValue) ?? defaultValue)
|
|
: defaultValue;
|
|
} else {
|
|
value = new int.fromEnvironment(name, defaultValue: defaultValue);
|
|
}
|
|
return value != null ? new IntConstant(value) : new NullConstant();
|
|
case 'String_fromEnvironment':
|
|
final String name = (positionalArguments[0] as StringConstant).value;
|
|
final Constant constant = namedArguments['defaultValue'];
|
|
final String defaultValue =
|
|
constant is StringConstant ? constant.value : null;
|
|
String value;
|
|
if (defines != null) {
|
|
value = defines[name] ?? defaultValue;
|
|
} else {
|
|
value = new String.fromEnvironment(name, defaultValue: defaultValue);
|
|
}
|
|
return value == null ? new NullConstant() : new StringConstant(value);
|
|
}
|
|
throw 'No native effect registered for constant evaluation: $nativeName';
|
|
}
|
|
|
|
Constant lowerMapConstant(MapConstant constant) {
|
|
// The _ImmutableMap class is implemented via one field pointing to a list
|
|
// of key/value pairs -- see runtime/lib/immutable_map.dart!
|
|
final List<Constant> kvListPairs =
|
|
new List<Constant>(2 * constant.entries.length);
|
|
for (int i = 0; i < constant.entries.length; i++) {
|
|
final ConstantMapEntry entry = constant.entries[i];
|
|
kvListPairs[2 * i] = entry.key;
|
|
kvListPairs[2 * i + 1] = entry.value;
|
|
}
|
|
// Strong mode is a bit fishy here, since we merge the key and the value
|
|
// type by putting both into the same list!
|
|
final kvListConstant = new ListConstant(const DynamicType(), kvListPairs);
|
|
assert(immutableMapClass.fields.length == 1);
|
|
final Field kvPairListField = immutableMapClass.fields[0];
|
|
return new InstanceConstant(immutableMapClass.reference, <DartType>[
|
|
constant.keyType,
|
|
constant.valueType,
|
|
], <Reference, Constant>{
|
|
kvPairListField.reference: kvListConstant,
|
|
});
|
|
}
|
|
|
|
Constant lowerListConstant(ListConstant constant) {
|
|
// Currently we let vipunen deal with the [ListConstant]s.
|
|
return constant;
|
|
}
|
|
}
|