| Index: lib/compiler/implementation/constants.dart
|
| diff --git a/lib/compiler/implementation/constants.dart b/lib/compiler/implementation/constants.dart
|
| index 242c4580f021b1243f251835fe98a9895d2f30d5..cb83dfc35b9dacb4807068f3b786ecb9a385849c 100644
|
| --- a/lib/compiler/implementation/constants.dart
|
| +++ b/lib/compiler/implementation/constants.dart
|
| @@ -2,20 +2,6 @@
|
| // 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.
|
|
|
| -interface ConstantVisitor<R> {
|
| - R visitSentinel(SentinelConstant constant);
|
| - R visitFunction(FunctionConstant constant);
|
| - R visitNull(NullConstant constant);
|
| - R visitInt(IntConstant constant);
|
| - R visitDouble(DoubleConstant constant);
|
| - R visitTrue(TrueConstant constant);
|
| - R visitFalse(FalseConstant constant);
|
| - R visitString(StringConstant constant);
|
| - R visitList(ListConstant constant);
|
| - R visitMap(MapConstant constant);
|
| - R visitConstructed(ConstructedConstant constant);
|
| -}
|
| -
|
| class Constant implements Hashable {
|
| const Constant();
|
|
|
| @@ -40,23 +26,35 @@ class Constant implements Hashable {
|
| bool isNaN() => false;
|
| bool isMinusZero() => false;
|
|
|
| + abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler);
|
| + /**
|
| + * Unless the constant can be emitted multiple times (as for numbers and
|
| + * strings) adds its canonical name to the buffer.
|
| + */
|
| + abstract void _writeCanonicalizedJsCode(CodeBuffer buffer,
|
| + ConstantHandler handler);
|
| abstract List<Constant> getDependencies();
|
| -
|
| - abstract accept(ConstantVisitor);
|
| }
|
|
|
| class SentinelConstant extends Constant {
|
| const SentinelConstant();
|
| static final SENTINEL = const SentinelConstant();
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + handler.compiler.internalError(
|
| + "The parameter sentinel constant does not need specific JS code");
|
| + }
|
| +
|
| + void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add(handler.compiler.namer.CURRENT_ISOLATE);
|
| + }
|
| +
|
| List<Constant> getDependencies() => const <Constant>[];
|
|
|
| - // Just use a random value.
|
| - int hashCode() => 24297418;
|
| + // Just use a randome value.
|
| + int hashCode() => 926429784158;
|
|
|
| bool isSentinel() => true;
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitSentinel(this);
|
| }
|
|
|
| class FunctionConstant extends Constant {
|
| @@ -77,9 +75,16 @@ class FunctionConstant extends Constant {
|
| return new DartString.literal(element.name.slowToString());
|
| }
|
|
|
| - int hashCode() => (17 * element.hashCode()) & 0x7fffffff;
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + handler.compiler.internalError(
|
| + "A constant function does not need specific JS code");
|
| + }
|
|
|
| - accept(ConstantVisitor visitor) => visitor.visitFunction(this);
|
| + void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add(handler.compiler.namer.isolatePropertiesAccess(element));
|
| + }
|
| +
|
| + int hashCode() => (17 * element.hashCode()) & 0x7fffffff;
|
| }
|
|
|
| class PrimitiveConstant extends Constant {
|
| @@ -98,6 +103,10 @@ class PrimitiveConstant extends Constant {
|
| // Primitive constants don't have dependencies.
|
| List<Constant> getDependencies() => const <Constant>[];
|
| abstract DartString toDartString();
|
| +
|
| + void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + _writeJsCode(buffer, handler);
|
| + }
|
| }
|
|
|
| class NullConstant extends PrimitiveConstant {
|
| @@ -116,8 +125,6 @@ class NullConstant extends PrimitiveConstant {
|
| // The magic constant has no meaning. It is just a random value.
|
| int hashCode() => 785965825;
|
| DartString toDartString() => const LiteralDartString("null");
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitNull(this);
|
| }
|
|
|
| class NumConstant extends PrimitiveConstant {
|
| @@ -149,6 +156,10 @@ class IntConstant extends NumConstant {
|
| const IntConstant._internal(this.value);
|
| bool isInt() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add("$value");
|
| + }
|
| +
|
| // We have to override the equality operator so that ints and doubles are
|
| // treated as separate constants.
|
| // The is [:!IntConstant:] check at the beginning of the function makes sure
|
| @@ -161,8 +172,6 @@ class IntConstant extends NumConstant {
|
|
|
| int hashCode() => value.hashCode();
|
| DartString toDartString() => new DartString.literal(value.toString());
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitInt(this);
|
| }
|
|
|
| class DoubleConstant extends NumConstant {
|
| @@ -188,6 +197,18 @@ class DoubleConstant extends NumConstant {
|
| // We need to check for the negative sign since -0.0 == 0.0.
|
| bool isMinusZero() => value == 0.0 && value.isNegative();
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + if (value.isNaN()) {
|
| + buffer.add("(0/0)");
|
| + } else if (value == double.INFINITY) {
|
| + buffer.add("(1/0)");
|
| + } else if (value == -double.INFINITY) {
|
| + buffer.add("(-1/0)");
|
| + } else {
|
| + buffer.add("$value");
|
| + }
|
| + }
|
| +
|
| bool operator ==(var other) {
|
| if (other is !DoubleConstant) return false;
|
| DoubleConstant otherDouble = other;
|
| @@ -203,8 +224,6 @@ class DoubleConstant extends NumConstant {
|
|
|
| int hashCode() => value.hashCode();
|
| DartString toDartString() => new DartString.literal(value.toString());
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitDouble(this);
|
| }
|
|
|
| class BoolConstant extends PrimitiveConstant {
|
| @@ -224,6 +243,10 @@ class TrueConstant extends BoolConstant {
|
| const TrueConstant._internal() : super._internal();
|
| bool isTrue() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add("true");
|
| + }
|
| +
|
| FalseConstant negate() => new FalseConstant();
|
|
|
| bool operator ==(var other) => this === other;
|
| @@ -231,8 +254,6 @@ class TrueConstant extends BoolConstant {
|
| // significance.
|
| int hashCode() => 499;
|
| DartString toDartString() => const LiteralDartString("true");
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitTrue(this);
|
| }
|
|
|
| class FalseConstant extends BoolConstant {
|
| @@ -242,6 +263,10 @@ class FalseConstant extends BoolConstant {
|
| const FalseConstant._internal() : super._internal();
|
| bool isFalse() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add("false");
|
| + }
|
| +
|
| TrueConstant negate() => new TrueConstant();
|
|
|
| bool operator ==(var other) => this === other;
|
| @@ -249,8 +274,6 @@ class FalseConstant extends BoolConstant {
|
| // significance.
|
| int hashCode() => 536555975;
|
| DartString toDartString() => const LiteralDartString("false");
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitFalse(this);
|
| }
|
|
|
| class StringConstant extends PrimitiveConstant {
|
| @@ -266,6 +289,14 @@ class StringConstant extends PrimitiveConstant {
|
| }
|
| bool isString() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add("'");
|
| + ConstantHandler.writeEscapedString(value, buffer, (reason) {
|
| + handler.compiler.reportError(node, reason);
|
| + });
|
| + buffer.add("'");
|
| + }
|
| +
|
| bool operator ==(var other) {
|
| if (other is !StringConstant) return false;
|
| StringConstant otherString = other;
|
| @@ -275,8 +306,6 @@ class StringConstant extends PrimitiveConstant {
|
| int hashCode() => _hashCode;
|
| DartString toDartString() => value;
|
| int get length => value.length;
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitString(this);
|
| }
|
|
|
| class ObjectConstant extends Constant {
|
| @@ -288,6 +317,11 @@ class ObjectConstant extends Constant {
|
| // TODO(1603): The class should be marked as abstract, but the VM doesn't
|
| // currently allow this.
|
| abstract int hashCode();
|
| +
|
| + void _writeCanonicalizedJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + String name = handler.getNameForConstant(this);
|
| + buffer.add(handler.compiler.namer.isolatePropertiesAccessForConstant(name));
|
| + }
|
| }
|
|
|
| class ListConstant extends ObjectConstant {
|
| @@ -302,6 +336,19 @@ class ListConstant extends ObjectConstant {
|
| }
|
| bool isList() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + // TODO(floitsch): we should not need to go through the compiler to make
|
| + // the list constant.
|
| + buffer.add("${handler.compiler.namer.ISOLATE}.makeConstantList");
|
| + buffer.add("([");
|
| + for (int i = 0; i < entries.length; i++) {
|
| + if (i != 0) buffer.add(", ");
|
| + Constant entry = entries[i];
|
| + handler.writeConstant(buffer, entry);
|
| + }
|
| + buffer.add("])");
|
| + }
|
| +
|
| bool operator ==(var other) {
|
| if (other is !ListConstant) return false;
|
| ListConstant otherList = other;
|
| @@ -319,8 +366,6 @@ class ListConstant extends ObjectConstant {
|
| List<Constant> getDependencies() => entries;
|
|
|
| int get length => entries.length;
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitList(this);
|
| }
|
|
|
| class MapConstant extends ObjectConstant {
|
| @@ -328,8 +373,7 @@ class MapConstant extends ObjectConstant {
|
| * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript
|
| * object. It would change the prototype chain.
|
| */
|
| - static const LiteralDartString PROTO_PROPERTY =
|
| - const LiteralDartString("__proto__");
|
| + static const String PROTO_PROPERTY = "__proto__";
|
|
|
| /** The dart class implementing constant map literals. */
|
| static const SourceString DART_CLASS = const SourceString("ConstantMap");
|
| @@ -354,6 +398,66 @@ class MapConstant extends ObjectConstant {
|
| }
|
| bool isMap() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| +
|
| + void writeJsMap() {
|
| + buffer.add("{");
|
| + int valueIndex = 0;
|
| + for (int i = 0; i < keys.entries.length; i++) {
|
| + StringConstant key = keys.entries[i];
|
| + if (key.value == const LiteralDartString(PROTO_PROPERTY)) continue;
|
| +
|
| + if (valueIndex != 0) buffer.add(", ");
|
| +
|
| + key._writeJsCode(buffer, handler);
|
| + buffer.add(": ");
|
| + Constant value = values[valueIndex++];
|
| + handler.writeConstant(buffer, value);
|
| + }
|
| + buffer.add("}");
|
| + if (valueIndex != values.length) {
|
| + handler.compiler.internalError("Bad value count.");
|
| + }
|
| + }
|
| +
|
| + void badFieldCountError() {
|
| + handler.compiler.internalError(
|
| + "Compiler and ConstantMap disagree on number of fields.");
|
| + }
|
| +
|
| + ClassElement classElement = type.element;
|
| + buffer.add("new ");
|
| + buffer.add(handler.getJsConstructor(classElement));
|
| + buffer.add("(");
|
| + // The arguments of the JavaScript constructor for any given Dart class
|
| + // are in the same order as the members of the class element.
|
| + int emittedArgumentCount = 0;
|
| + classElement.forEachInstanceField(
|
| + includeBackendMembers: true,
|
| + includeSuperMembers: true,
|
| + f: (ClassElement enclosing, Element field) {
|
| + if (emittedArgumentCount != 0) buffer.add(", ");
|
| + if (field.name == LENGTH_NAME) {
|
| + buffer.add(keys.entries.length);
|
| + } else if (field.name == JS_OBJECT_NAME) {
|
| + writeJsMap();
|
| + } else if (field.name == KEYS_NAME) {
|
| + handler.writeConstant(buffer, keys);
|
| + } else if (field.name == PROTO_VALUE) {
|
| + assert(protoValue !== null);
|
| + handler.writeConstant(buffer, protoValue);
|
| + } else {
|
| + badFieldCountError();
|
| + }
|
| + emittedArgumentCount++;
|
| + });
|
| + if ((protoValue === null && emittedArgumentCount != 3) ||
|
| + (protoValue !== null && emittedArgumentCount != 4)) {
|
| + badFieldCountError();
|
| + }
|
| + buffer.add(")");
|
| + }
|
| +
|
| bool operator ==(var other) {
|
| if (other is !MapConstant) return false;
|
| MapConstant otherMap = other;
|
| @@ -375,8 +479,6 @@ class MapConstant extends ObjectConstant {
|
| }
|
|
|
| int get length => keys.length;
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitMap(this);
|
| }
|
|
|
| class ConstructedConstant extends ObjectConstant {
|
| @@ -395,6 +497,18 @@ class ConstructedConstant extends ObjectConstant {
|
| }
|
| bool isConstructedObject() => true;
|
|
|
| + void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
|
| + buffer.add("new ");
|
| + buffer.add(handler.getJsConstructor(type.element));
|
| + buffer.add("(");
|
| + for (int i = 0; i < fields.length; i++) {
|
| + if (i != 0) buffer.add(", ");
|
| + Constant field = fields[i];
|
| + handler.writeConstant(buffer, field);
|
| + }
|
| + buffer.add(")");
|
| + }
|
| +
|
| bool operator ==(var otherVar) {
|
| if (otherVar is !ConstructedConstant) return false;
|
| ConstructedConstant other = otherVar;
|
| @@ -410,6 +524,4 @@ class ConstructedConstant extends ObjectConstant {
|
|
|
| int hashCode() => _hashCode;
|
| List<Constant> getDependencies() => fields;
|
| -
|
| - accept(ConstantVisitor visitor) => visitor.visitConstructed(this);
|
| }
|
|
|