Index: sdk/lib/_internal/compiler/implementation/universe/universe.dart |
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart |
deleted file mode 100644 |
index e5e3915d8518b57786f3721788cf218bfb612466..0000000000000000000000000000000000000000 |
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart |
+++ /dev/null |
@@ -1,805 +0,0 @@ |
-// Copyright (c) 2012, 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 universe; |
- |
-import '../elements/elements.dart'; |
-import '../dart2jslib.dart'; |
-import '../dart_types.dart'; |
-import '../types/types.dart'; |
-import '../tree/tree.dart'; |
-import '../util/util.dart'; |
- |
-part 'function_set.dart'; |
-part 'side_effects.dart'; |
- |
-class Universe { |
- /// The set of all directly instantiated classes, that is, classes with a |
- /// generative constructor that has been called directly and not only through |
- /// a super-call. |
- /// |
- /// Invariant: Elements are declaration elements. |
- // TODO(johnniwinther): [_directlyInstantiatedClasses] and |
- // [_instantiatedTypes] sets should be merged. |
- final Set<ClassElement> _directlyInstantiatedClasses = |
- new Set<ClassElement>(); |
- |
- /// The set of all directly instantiated types, that is, the types of the |
- /// directly instantiated classes. |
- /// |
- /// See [_directlyInstantiatedClasses]. |
- final Set<DartType> _instantiatedTypes = new Set<DartType>(); |
- |
- /// The set of all instantiated classes, either directly, as superclasses or |
- /// as supertypes. |
- /// |
- /// Invariant: Elements are declaration elements. |
- final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>(); |
- |
- /** |
- * Documentation wanted -- johnniwinther |
- * |
- * Invariant: Elements are declaration elements. |
- */ |
- final Set<FunctionElement> staticFunctionsNeedingGetter = |
- new Set<FunctionElement>(); |
- final Set<FunctionElement> methodsNeedingSuperGetter = |
- new Set<FunctionElement>(); |
- final Map<String, Set<Selector>> invokedNames = |
- new Map<String, Set<Selector>>(); |
- final Map<String, Set<Selector>> invokedGetters = |
- new Map<String, Set<Selector>>(); |
- final Map<String, Set<Selector>> invokedSetters = |
- new Map<String, Set<Selector>>(); |
- |
- /** |
- * Fields accessed. Currently only the codegen knows this |
- * information. The resolver is too conservative when seeing a |
- * getter and only registers an invoked getter. |
- */ |
- final Set<Element> fieldGetters = new Set<Element>(); |
- |
- /** |
- * Fields set. See comment in [fieldGetters]. |
- */ |
- final Set<Element> fieldSetters = new Set<Element>(); |
- final Set<DartType> isChecks = new Set<DartType>(); |
- |
- /** |
- * Set of (live) [:call:] methods whose signatures reference type variables. |
- * |
- * A live [:call:] method is one whose enclosing class has been instantiated. |
- */ |
- final Set<Element> callMethodsWithFreeTypeVariables = new Set<Element>(); |
- |
- /** |
- * Set of (live) local functions (closures) whose signatures reference type |
- * variables. |
- * |
- * A live function is one whose enclosing member function has been enqueued. |
- */ |
- final Set<Element> closuresWithFreeTypeVariables = new Set<Element>(); |
- |
- /** |
- * Set of all closures in the program. Used by the mirror tracking system |
- * to find all live closure instances. |
- */ |
- final Set<LocalFunctionElement> allClosures = new Set<LocalFunctionElement>(); |
- |
- /** |
- * Set of methods in instantiated classes that are potentially |
- * closurized. |
- */ |
- final Set<Element> closurizedMembers = new Set<Element>(); |
- |
- bool usingFactoryWithTypeArguments = false; |
- |
- /// All directly instantiated classes, that is, classes with a generative |
- /// constructor that has been called directly and not only through a |
- /// super-call. |
- // TODO(johnniwinther): Improve semantic precision. |
- Iterable<ClassElement> get directlyInstantiatedClasses { |
- return _directlyInstantiatedClasses; |
- } |
- |
- /// All instantiated classes, either directly, as superclasses or as |
- /// supertypes. |
- // TODO(johnniwinther): Improve semantic precision. |
- Iterable<ClassElement> get allInstantiatedClasses { |
- return _allInstantiatedClasses; |
- } |
- |
- /// All directly instantiated types, that is, the types of the directly |
- /// instantiated classes. |
- /// |
- /// See [directlyInstantiatedClasses]. |
- // TODO(johnniwinther): Improve semantic precision. |
- Iterable<DartType> get instantiatedTypes => _instantiatedTypes; |
- |
- /// Returns `true` if [cls] is considered to be instantiated, either directly, |
- /// through subclasses or throught subtypes. |
- // TODO(johnniwinther): Improve semantic precision. |
- bool isInstantiated(ClassElement cls) { |
- return _allInstantiatedClasses.contains(cls); |
- } |
- |
- /// Register [type] as (directly) instantiated. |
- /// |
- /// If [byMirrors] is `true`, the instantiation is through mirrors. |
- // TODO(johnniwinther): Fully enforce the separation between exact, through |
- // subclass and through subtype instantiated types/classes. |
- // TODO(johnniwinther): Support unknown type arguments for generic types. |
- void registerTypeInstantiation(InterfaceType type, |
- {bool byMirrors: false}) { |
- _instantiatedTypes.add(type); |
- ClassElement cls = type.element; |
- if (!cls.isAbstract |
- // We can't use the closed-world assumption with native abstract |
- // classes; a native abstract class may have non-abstract subclasses |
- // not declared to the program. Instances of these classes are |
- // indistinguishable from the abstract class. |
- || cls.isNative |
- // Likewise, if this registration comes from the mirror system, |
- // all bets are off. |
- // TODO(herhut): Track classes required by mirrors seperately. |
- || byMirrors) { |
- _directlyInstantiatedClasses.add(cls); |
- } |
- |
- // TODO(johnniwinther): Replace this by separate more specific mappings. |
- if (!_allInstantiatedClasses.add(cls)) return; |
- cls.allSupertypes.forEach((InterfaceType supertype) { |
- _allInstantiatedClasses.add(supertype.element); |
- }); |
- } |
- |
- bool hasMatchingSelector(Set<Selector> selectors, |
- Element member, |
- World world) { |
- if (selectors == null) return false; |
- for (Selector selector in selectors) { |
- if (selector.appliesUnnamed(member, world)) return true; |
- } |
- return false; |
- } |
- |
- bool hasInvocation(Element member, World world) { |
- return hasMatchingSelector(invokedNames[member.name], member, world); |
- } |
- |
- bool hasInvokedGetter(Element member, World world) { |
- return hasMatchingSelector(invokedGetters[member.name], member, world); |
- } |
- |
- bool hasInvokedSetter(Element member, World world) { |
- return hasMatchingSelector(invokedSetters[member.name], member, world); |
- } |
- |
- DartType registerIsCheck(DartType type, Compiler compiler) { |
- type = type.unalias(compiler); |
- // Even in checked mode, type annotations for return type and argument |
- // types do not imply type checks, so there should never be a check |
- // against the type variable of a typedef. |
- isChecks.add(type); |
- return type; |
- } |
- |
- void forgetElement(Element element, Compiler compiler) { |
- allClosures.remove(element); |
- slowDirectlyNestedClosures(element).forEach(compiler.forgetElement); |
- closurizedMembers.remove(element); |
- fieldSetters.remove(element); |
- fieldGetters.remove(element); |
- _directlyInstantiatedClasses.remove(element); |
- _allInstantiatedClasses.remove(element); |
- if (element is ClassElement) { |
- assert(invariant( |
- element, element.thisType.isRaw, |
- message: 'Generic classes not supported (${element.thisType}).')); |
- _instantiatedTypes |
- ..remove(element.rawType) |
- ..remove(element.thisType); |
- } |
- } |
- |
- // TODO(ahe): Replace this method with something that is O(1), for example, |
- // by using a map. |
- List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
- // Return new list to guard against concurrent modifications. |
- return new List<LocalFunctionElement>.from( |
- allClosures.where((LocalFunctionElement closure) { |
- return closure.executableContext == element; |
- })); |
- } |
-} |
- |
-class SelectorKind { |
- final String name; |
- final int hashCode; |
- const SelectorKind(this.name, this.hashCode); |
- |
- static const SelectorKind GETTER = const SelectorKind('getter', 0); |
- static const SelectorKind SETTER = const SelectorKind('setter', 1); |
- static const SelectorKind CALL = const SelectorKind('call', 2); |
- static const SelectorKind OPERATOR = const SelectorKind('operator', 3); |
- static const SelectorKind INDEX = const SelectorKind('index', 4); |
- |
- String toString() => name; |
-} |
- |
-class Selector { |
- final SelectorKind kind; |
- final String name; |
- final LibraryElement library; // Library is null for non-private selectors. |
- |
- // The numbers of arguments of the selector. Includes named arguments. |
- final int argumentCount; |
- final List<String> namedArguments; |
- final List<String> _orderedNamedArguments; |
- final int hashCode; |
- |
- static const String INDEX_NAME ="[]"; |
- static const String INDEX_SET_NAME = "[]="; |
- static const String CALL_NAME = Compiler.CALL_OPERATOR_NAME; |
- |
- Selector.internal(this.kind, |
- this.name, |
- this.library, |
- this.argumentCount, |
- this.namedArguments, |
- this._orderedNamedArguments, |
- this.hashCode) { |
- assert(kind == SelectorKind.INDEX |
- || (name != INDEX_NAME && name != INDEX_SET_NAME)); |
- assert(kind == SelectorKind.OPERATOR |
- || kind == SelectorKind.INDEX |
- || !Elements.isOperatorName(name)); |
- assert(kind == SelectorKind.CALL |
- || kind == SelectorKind.GETTER |
- || kind == SelectorKind.SETTER |
- || Elements.isOperatorName(name)); |
- assert(!isPrivateName(name) || library != null); |
- } |
- |
- static Map<int, List<Selector>> canonicalizedValues = |
- new Map<int, List<Selector>>(); |
- |
- factory Selector(SelectorKind kind, |
- String name, |
- LibraryElement library, |
- int argumentCount, |
- [List<String> namedArguments]) { |
- if (!isPrivateName(name)) library = null; |
- if (namedArguments == null) namedArguments = const <String>[]; |
- int hashCode = computeHashCode( |
- kind, name, library, argumentCount, namedArguments); |
- List<Selector> list = canonicalizedValues.putIfAbsent(hashCode, |
- () => <Selector>[]); |
- for (int i = 0; i < list.length; i++) { |
- Selector existing = list[i]; |
- if (existing.match(kind, name, library, argumentCount, namedArguments)) { |
- assert(existing.hashCode == hashCode); |
- assert(existing.mask == null); |
- return existing; |
- } |
- } |
- List<String> orderedNamedArguments = namedArguments.isEmpty |
- ? const <String>[] |
- : <String>[]; |
- Selector result = new Selector.internal( |
- kind, name, library, argumentCount, |
- namedArguments, orderedNamedArguments, |
- hashCode); |
- list.add(result); |
- return result; |
- } |
- |
- factory Selector.fromElement(Element element) { |
- String name = element.name; |
- if (element.isFunction) { |
- if (name == '[]') { |
- return new Selector.index(); |
- } else if (name == '[]=') { |
- return new Selector.indexSet(); |
- } |
- FunctionSignature signature = |
- element.asFunctionElement().functionSignature; |
- int arity = signature.parameterCount; |
- List<String> namedArguments = null; |
- if (signature.optionalParametersAreNamed) { |
- namedArguments = |
- signature.orderedOptionalParameters.map((e) => e.name).toList(); |
- } |
- if (element.isOperator) { |
- // Operators cannot have named arguments, however, that doesn't prevent |
- // a user from declaring such an operator. |
- return new Selector( |
- SelectorKind.OPERATOR, name, null, arity, namedArguments); |
- } else { |
- return new Selector.call( |
- name, element.library, arity, namedArguments); |
- } |
- } else if (element.isSetter) { |
- return new Selector.setter(name, element.library); |
- } else if (element.isGetter) { |
- return new Selector.getter(name, element.library); |
- } else if (element.isField) { |
- return new Selector.getter(name, element.library); |
- } else { |
- throw new SpannableAssertionFailure( |
- element, "Can't get selector from $element"); |
- } |
- } |
- |
- factory Selector.getter(String name, LibraryElement library) |
- => new Selector(SelectorKind.GETTER, name, library, 0); |
- |
- factory Selector.getterFrom(Selector selector) |
- => new Selector(SelectorKind.GETTER, selector.name, selector.library, 0); |
- |
- factory Selector.setter(String name, LibraryElement library) |
- => new Selector(SelectorKind.SETTER, name, library, 1); |
- |
- factory Selector.unaryOperator(String name) |
- => new Selector(SelectorKind.OPERATOR, |
- Elements.constructOperatorName(name, true), |
- null, 0); |
- |
- factory Selector.binaryOperator(String name) |
- => new Selector(SelectorKind.OPERATOR, |
- Elements.constructOperatorName(name, false), |
- null, 1); |
- |
- factory Selector.index() |
- => new Selector(SelectorKind.INDEX, |
- Elements.constructOperatorName(INDEX_NAME, false), |
- null, 1); |
- |
- factory Selector.indexSet() |
- => new Selector(SelectorKind.INDEX, |
- Elements.constructOperatorName(INDEX_SET_NAME, false), |
- null, 2); |
- |
- factory Selector.call(String name, |
- LibraryElement library, |
- int arity, |
- [List<String> namedArguments]) |
- => new Selector(SelectorKind.CALL, name, library, arity, namedArguments); |
- |
- factory Selector.callClosure(int arity, [List<String> namedArguments]) |
- => new Selector(SelectorKind.CALL, CALL_NAME, null, |
- arity, namedArguments); |
- |
- factory Selector.callClosureFrom(Selector selector) |
- => new Selector(SelectorKind.CALL, CALL_NAME, null, |
- selector.argumentCount, selector.namedArguments); |
- |
- factory Selector.callConstructor(String name, LibraryElement library, |
- [int arity = 0, |
- List<String> namedArguments]) |
- => new Selector(SelectorKind.CALL, name, library, |
- arity, namedArguments); |
- |
- factory Selector.callDefaultConstructor(LibraryElement library) |
- => new Selector(SelectorKind.CALL, "", library, 0); |
- |
- bool get isGetter => identical(kind, SelectorKind.GETTER); |
- bool get isSetter => identical(kind, SelectorKind.SETTER); |
- bool get isCall => identical(kind, SelectorKind.CALL); |
- bool get isClosureCall { |
- String callName = Compiler.CALL_OPERATOR_NAME; |
- return isCall && name == callName; |
- } |
- |
- bool get isIndex => identical(kind, SelectorKind.INDEX) && argumentCount == 1; |
- bool get isIndexSet => identical(kind, SelectorKind.INDEX) && argumentCount == 2; |
- |
- bool get isOperator => identical(kind, SelectorKind.OPERATOR); |
- bool get isUnaryOperator => isOperator && argumentCount == 0; |
- |
- /** Check whether this is a call to 'assert'. */ |
- bool get isAssert => isCall && identical(name, "assert"); |
- |
- int get namedArgumentCount => namedArguments.length; |
- int get positionalArgumentCount => argumentCount - namedArgumentCount; |
- |
- bool get hasExactMask => false; |
- TypeMask get mask => null; |
- Selector get asUntyped => this; |
- |
- /** |
- * The member name for invocation mirrors created from this selector. |
- */ |
- String get invocationMirrorMemberName => |
- isSetter ? '$name=' : name; |
- |
- int get invocationMirrorKind { |
- const int METHOD = 0; |
- const int GETTER = 1; |
- const int SETTER = 2; |
- int kind = METHOD; |
- if (isGetter) { |
- kind = GETTER; |
- } else if (isSetter) { |
- kind = SETTER; |
- } |
- return kind; |
- } |
- |
- bool appliesUnnamed(Element element, World world) { |
- assert(sameNameHack(element, world)); |
- return appliesUntyped(element, world); |
- } |
- |
- bool appliesUntyped(Element element, World world) { |
- assert(sameNameHack(element, world)); |
- if (Elements.isUnresolved(element)) return false; |
- if (isPrivateName(name) && library != element.library) return false; |
- if (world.isForeign(element)) return true; |
- if (element.isSetter) return isSetter; |
- if (element.isGetter) return isGetter || isCall; |
- if (element.isField) { |
- return isSetter |
- ? !element.isFinal && !element.isConst |
- : isGetter || isCall; |
- } |
- if (isGetter) return true; |
- if (isSetter) return false; |
- return signatureApplies(element); |
- } |
- |
- bool signatureApplies(FunctionElement function) { |
- FunctionSignature parameters = function.functionSignature; |
- if (argumentCount > parameters.parameterCount) return false; |
- int requiredParameterCount = parameters.requiredParameterCount; |
- int optionalParameterCount = parameters.optionalParameterCount; |
- if (positionalArgumentCount < requiredParameterCount) return false; |
- |
- if (!parameters.optionalParametersAreNamed) { |
- // We have already checked that the number of arguments are |
- // not greater than the number of parameters. Therefore the |
- // number of positional arguments are not greater than the |
- // number of parameters. |
- assert(positionalArgumentCount <= parameters.parameterCount); |
- return namedArguments.isEmpty; |
- } else { |
- if (positionalArgumentCount > requiredParameterCount) return false; |
- assert(positionalArgumentCount == requiredParameterCount); |
- if (namedArgumentCount > optionalParameterCount) return false; |
- Set<String> nameSet = new Set<String>(); |
- parameters.optionalParameters.forEach((Element element) { |
- nameSet.add(element.name); |
- }); |
- for (String name in namedArguments) { |
- if (!nameSet.contains(name)) return false; |
- // TODO(5213): By removing from the set we are checking |
- // that we are not passing the name twice. We should have this |
- // check in the resolver also. |
- nameSet.remove(name); |
- } |
- return true; |
- } |
- } |
- |
- bool sameNameHack(Element element, World world) { |
- // TODO(ngeoffray): Remove workaround checks. |
- return element.isConstructor || |
- name == element.name || |
- name == 'assert' && world.isAssertMethod(element); |
- } |
- |
- bool applies(Element element, World world) { |
- if (!sameNameHack(element, world)) return false; |
- return appliesUnnamed(element, world); |
- } |
- |
- /** |
- * Fills [list] with the arguments in the normalized order. |
- * |
- * [compileArgument] is a function that returns a compiled version |
- * of an argument located in [arguments]. |
- * |
- * [compileDefaultValue] is a function that returns a compiled constant |
- * of an optional argument that is not in [arguments]. |
- * |
- * Returns [:true:] if the selector and the [element] match; [:false:] |
- * otherwise. |
- * |
- * Invariant: [element] must be the implementation element. |
- */ |
- /*<T>*/ bool addArgumentsToList( |
- Link<Node> arguments, |
- List/*<T>*/ list, |
- FunctionElement element, |
- /*T*/ compileArgument(Node argument), |
- /*T*/ compileDefaultValue(ParameterElement element), |
- World world) { |
- assert(invariant(element, element.isImplementation)); |
- if (!this.applies(element, world)) return false; |
- |
- FunctionSignature parameters = element.functionSignature; |
- parameters.forEachRequiredParameter((ParameterElement element) { |
- list.add(compileArgument(arguments.head)); |
- arguments = arguments.tail; |
- }); |
- |
- if (!parameters.optionalParametersAreNamed) { |
- parameters.forEachOptionalParameter((ParameterElement element) { |
- if (!arguments.isEmpty) { |
- list.add(compileArgument(arguments.head)); |
- arguments = arguments.tail; |
- } else { |
- list.add(compileDefaultValue(element)); |
- } |
- }); |
- } else { |
- // Visit named arguments and add them into a temporary list. |
- List compiledNamedArguments = []; |
- for (; !arguments.isEmpty; arguments = arguments.tail) { |
- NamedArgument namedArgument = arguments.head; |
- compiledNamedArguments.add(compileArgument(namedArgument.expression)); |
- } |
- // Iterate over the optional parameters of the signature, and try to |
- // find them in [compiledNamedArguments]. If found, we use the |
- // value in the temporary list, otherwise the default value. |
- parameters.orderedOptionalParameters.forEach((ParameterElement element) { |
- int foundIndex = namedArguments.indexOf(element.name); |
- if (foundIndex != -1) { |
- list.add(compiledNamedArguments[foundIndex]); |
- } else { |
- list.add(compileDefaultValue(element)); |
- } |
- }); |
- } |
- return true; |
- } |
- |
- /** |
- * Fills [list] with the arguments in the order expected by |
- * [callee], and where [caller] is a synthesized element |
- * |
- * [compileArgument] is a function that returns a compiled version |
- * of a parameter of [callee]. |
- * |
- * [compileConstant] is a function that returns a compiled constant |
- * of an optional argument that is not in the parameters of [callee]. |
- * |
- * Returns [:true:] if the signature of the [caller] matches the |
- * signature of the [callee], [:false:] otherwise. |
- */ |
- static bool addForwardingElementArgumentsToList( |
- FunctionElement caller, |
- List list, |
- FunctionElement callee, |
- compileArgument(Element element), |
- compileConstant(Element element), |
- World world) { |
- |
- FunctionSignature signature = caller.functionSignature; |
- Map mapping = new Map(); |
- |
- // TODO(ngeoffray): This is a hack that fakes up AST nodes, so |
- // that we can call [addArgumentsToList]. |
- Link computeCallNodesFromParameters() { |
- LinkBuilder builder = new LinkBuilder(); |
- signature.forEachRequiredParameter((ParameterElement element) { |
- Node node = element.node; |
- mapping[node] = element; |
- builder.addLast(node); |
- }); |
- if (signature.optionalParametersAreNamed) { |
- signature.forEachOptionalParameter((ParameterElement element) { |
- mapping[element.initializer] = element; |
- builder.addLast(new NamedArgument(null, null, element.initializer)); |
- }); |
- } else { |
- signature.forEachOptionalParameter((ParameterElement element) { |
- Node node = element.node; |
- mapping[node] = element; |
- builder.addLast(node); |
- }); |
- } |
- return builder.toLink(); |
- } |
- |
- internalCompileArgument(Node node) { |
- return compileArgument(mapping[node]); |
- } |
- |
- Link<Node> nodes = computeCallNodesFromParameters(); |
- |
- // Synthesize a selector for the call. |
- // TODO(ngeoffray): Should the resolver do it instead? |
- List<String> namedParameters; |
- if (signature.optionalParametersAreNamed) { |
- namedParameters = |
- signature.optionalParameters.mapToList((e) => e.name); |
- } |
- Selector selector = new Selector.call(callee.name, |
- caller.library, |
- signature.parameterCount, |
- namedParameters); |
- |
- return selector.addArgumentsToList(nodes, |
- list, |
- callee, |
- internalCompileArgument, |
- compileConstant, |
- world); |
- } |
- |
- static bool sameNames(List<String> first, List<String> second) { |
- for (int i = 0; i < first.length; i++) { |
- if (first[i] != second[i]) return false; |
- } |
- return true; |
- } |
- |
- bool match(SelectorKind kind, |
- String name, |
- LibraryElement library, |
- int argumentCount, |
- List<String> namedArguments) { |
- return this.kind == kind |
- && this.name == name |
- && identical(this.library, library) |
- && this.argumentCount == argumentCount |
- && this.namedArguments.length == namedArguments.length |
- && sameNames(this.namedArguments, namedArguments); |
- } |
- |
- static int computeHashCode(SelectorKind kind, |
- String name, |
- LibraryElement library, |
- int argumentCount, |
- List<String> namedArguments) { |
- // Add bits from name and kind. |
- int hash = mixHashCodeBits(name.hashCode, kind.hashCode); |
- // Add bits from the library. |
- if (library != null) hash = mixHashCodeBits(hash, library.hashCode); |
- // Add bits from the unnamed arguments. |
- hash = mixHashCodeBits(hash, argumentCount); |
- // Add bits from the named arguments. |
- int named = namedArguments.length; |
- hash = mixHashCodeBits(hash, named); |
- for (int i = 0; i < named; i++) { |
- hash = mixHashCodeBits(hash, namedArguments[i].hashCode); |
- } |
- return hash; |
- } |
- |
- // TODO(kasperl): Move this out so it becomes useful in other places too? |
- static int mixHashCodeBits(int existing, int value) { |
- // Spread the bits of value. Try to stay in the 30-bit range to |
- // avoid overflowing into a more expensive integer representation. |
- int h = value & 0x1fffffff; |
- h += ((h & 0x3fff) << 15) ^ 0x1fffcd7d; |
- h ^= (h >> 10); |
- h += ((h & 0x3ffffff) << 3); |
- h ^= (h >> 6); |
- h += ((h & 0x7ffffff) << 2) + ((h & 0x7fff) << 14); |
- h ^= (h >> 16); |
- // Combine the two hash values. |
- int high = existing >> 15; |
- int low = existing & 0x7fff; |
- return ((high * 13) ^ (low * 997) ^ h) & SMI_MASK; |
- } |
- |
- List<String> getOrderedNamedArguments() { |
- if (namedArguments.isEmpty) return namedArguments; |
- if (!_orderedNamedArguments.isEmpty) return _orderedNamedArguments; |
- |
- _orderedNamedArguments.addAll(namedArguments); |
- _orderedNamedArguments.sort((String first, String second) { |
- return first.compareTo(second); |
- }); |
- return _orderedNamedArguments; |
- } |
- |
- String namedArgumentsToString() { |
- if (namedArgumentCount > 0) { |
- StringBuffer result = new StringBuffer(); |
- for (int i = 0; i < namedArgumentCount; i++) { |
- if (i != 0) result.write(', '); |
- result.write(namedArguments[i]); |
- } |
- return "[$result]"; |
- } |
- return ''; |
- } |
- |
- String toString() { |
- String named = ''; |
- String type = ''; |
- if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}'; |
- if (mask != null) type = ', mask=$mask'; |
- return 'Selector($kind, $name, ' |
- 'arity=$argumentCount$named$type)'; |
- } |
- |
- Selector extendIfReachesAll(Compiler compiler) { |
- return new TypedSelector( |
- compiler.typesTask.dynamicType, this, compiler.world); |
- } |
- |
- Selector toCallSelector() => new Selector.callClosureFrom(this); |
-} |
- |
-class TypedSelector extends Selector { |
- final Selector asUntyped; |
- final TypeMask mask; |
- |
- TypedSelector.internal(this.mask, Selector selector, int hashCode) |
- : asUntyped = selector, |
- super.internal(selector.kind, |
- selector.name, |
- selector.library, |
- selector.argumentCount, |
- selector.namedArguments, |
- selector._orderedNamedArguments, |
- hashCode) { |
- assert(mask != null); |
- assert(asUntyped.mask == null); |
- } |
- |
- static Map<Selector, Map<TypeMask, TypedSelector>> canonicalizedValues = |
- new Map<Selector, Map<TypeMask, TypedSelector>>(); |
- |
- factory TypedSelector(TypeMask mask, Selector selector, World world) { |
- // TODO(johnniwinther): Allow more TypeSelector kinds during resoluton. |
- assert(world.isClosed || mask.isExact); |
- if (selector.mask == mask) return selector; |
- Selector untyped = selector.asUntyped; |
- Map<TypeMask, TypedSelector> map = canonicalizedValues.putIfAbsent(untyped, |
- () => new Map<TypeMask, TypedSelector>()); |
- TypedSelector result = map[mask]; |
- if (result == null) { |
- int hashCode = Selector.mixHashCodeBits(untyped.hashCode, mask.hashCode); |
- result = map[mask] = new TypedSelector.internal(mask, untyped, hashCode); |
- } |
- return result; |
- } |
- |
- factory TypedSelector.exact( |
- ClassElement base, Selector selector, World world) |
- => new TypedSelector(new TypeMask.exact(base, world), selector, |
- world); |
- |
- factory TypedSelector.subclass( |
- ClassElement base, Selector selector, World world) |
- => new TypedSelector(new TypeMask.subclass(base, world), |
- selector, world); |
- |
- factory TypedSelector.subtype( |
- ClassElement base, Selector selector, World world) |
- => new TypedSelector(new TypeMask.subtype(base, world), |
- selector, world); |
- |
- bool appliesUnnamed(Element element, World world) { |
- assert(sameNameHack(element, world)); |
- // [TypedSelector] are only used after resolution. |
- if (!element.isClassMember) return false; |
- |
- // A closure can be called through any typed selector: |
- // class A { |
- // get foo => () => 42; |
- // bar() => foo(); // The call to 'foo' is a typed selector. |
- // } |
- if (element.enclosingClass.isClosure) { |
- return appliesUntyped(element, world); |
- } |
- |
- if (!mask.canHit(element, this, world)) return false; |
- return appliesUntyped(element, world); |
- } |
- |
- Selector extendIfReachesAll(Compiler compiler) { |
- bool canReachAll = compiler.enabledInvokeOn |
- && mask.needsNoSuchMethodHandling(this, compiler.world); |
- return canReachAll |
- ? new TypedSelector( |
- compiler.typesTask.dynamicType, this, compiler.world) |
- : this; |
- } |
-} |