// 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.constant_pool;

import 'dart:typed_data';

import 'package:kernel/ast.dart' hide MapEntry;
import 'package:kernel/text/ast_to_text.dart' show Printer;

/*

In kernel binary, constant pool is encoded in the following way
(using notation from pkg/kernel/binary.md):

type ConstantPool {
  List<ConstantPoolEntry>
}

type ConstantIndex = UInt;

abstract type ConstantPoolEntry {
  Byte tag;
}

type ConstantNull extends ConstantPoolEntry {
  Byte tag = 1;
}

type ConstantString extends ConstantPoolEntry {
  Byte tag = 2;
  StringReference value;
}

type ConstantInt extends ConstantPoolEntry {
  Byte tag = 3;
  UInt32 low;
  UInt32 high;
}

type ConstantDouble extends ConstantPoolEntry {
  Byte tag = 4;
  UInt32 low;
  UInt32 high;
}

type ConstantBool extends ConstantPoolEntry {
  Byte tag = 5;
  UInt flag;
}

type ConstantArgDesc extends ConstantPoolEntry {
  Byte tag = 6;
  UInt numArguments;
  UInt numTypeArgs;
  List<StringReference> names;
}

enum InvocationKind {
  method, // x.foo(...) or foo(...)
  getter, // x.foo
  setter  // x.foo = ...
}

type ConstantICData extends ConstantPoolEntry {
  Byte tag = 7;
  Byte invocationKind; // Index in InvocationKind enum.
  Name targetName;
  ConstantIndex argDesc;
}

type ConstantStaticICData extends ConstantPoolEntry {
  Byte tag = 8;
  Byte invocationKind; // Index in InvocationKind enum.
  CanonicalNameReference target;
  ConstantIndex argDesc;
}

type ConstantField extends ConstantPoolEntry {
  Byte tag = 9;
  CanonicalNameReference field;
}

type ConstantFieldOffset extends ConstantPoolEntry {
  Byte tag = 10;
  CanonicalNameReference field;
}

type ConstantClass extends ConstantPoolEntry {
  Byte tag = 11;
  CanonicalNameReference class;
}

type ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
  Byte tag = 12;
  CanonicalNameReference class;
}

type ConstantTearOff extends ConstantPoolEntry {
  Byte tag = 13;
  CanonicalNameReference target;
}

type ConstantType extends ConstantPoolEntry {
  Byte tag = 14;
  DartType type;
}

type ConstantTypeArguments extends ConstantPoolEntry {
  Byte tag = 15;
  List<DartType> types;
}

type ConstantList extends ConstantPoolEntry {
  Byte tag = 16;
  DartType typeArg;
  List<ConstantIndex> entries;
}

type ConstantInstance extends ConstantPoolEntry {
  Byte tag = 17;
  CanonicalNameReference class;
  ConstantIndex typeArguments;
  List<Pair<CanonicalNameReference, ConstantIndex>> fieldValues;
}

type ConstantSymbol extends ConstantPoolEntry {
  Byte tag = 18;
  StringReference value;
}

type ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
  Byte tag = 19;
  CanonicalNameReference instantiatingClass;
  List<DartType> types;
}

type ConstantContextOffset extends ConstantPoolEntry {
  Byte tag = 20;
  // 0 = Offset of 'parent' field in Context object.
  // 1 + i = Offset of i-th variable in Context object.
  UInt index;
}

type ConstantClosureFunction extends ConstantPoolEntry {
  Byte tag = 21;
  StringReference name;
  FunctionNode function; // Doesn't have a body.
}

type ConstantEndClosureFunctionScope extends ConstantPoolEntry {
  Byte tag = 22;
}

type ConstantNativeEntry extends ConstantPoolEntry {
  Byte tag = 23;
  StringReference nativeName;
}

type ConstantSubtypeTestCache extends ConstantPoolEntry {
  Byte tag = 24;
}

*/

enum ConstantTag {
  kInvalid,
  kNull,
  kString,
  kInt,
  kDouble,
  kBool,
  kArgDesc,
  kICData,
  kStaticICData,
  kField,
  kFieldOffset,
  kClass,
  kTypeArgumentsFieldOffset,
  kTearOff,
  kType,
  kTypeArguments,
  kList,
  kInstance,
  kSymbol,
  kTypeArgumentsForInstanceAllocation,
  kContextOffset,
  kClosureFunction,
  kEndClosureFunctionScope,
  kNativeEntry,
  kSubtypeTestCache,
}

abstract class ConstantPoolEntry {
  const ConstantPoolEntry();

  ConstantTag get tag;

  void writeToBinary(BinarySink sink) {
    sink.writeUInt30(tag.index);
    writeValueToBinary(sink);
  }

  void writeValueToBinary(BinarySink sink);

  factory ConstantPoolEntry.readFromBinary(BinarySource source) {
    ConstantTag tag = ConstantTag.values[source.readUInt()];
    switch (tag) {
      case ConstantTag.kInvalid:
        break;
      case ConstantTag.kNull:
        return new ConstantNull.readFromBinary(source);
      case ConstantTag.kString:
        return new ConstantString.readFromBinary(source);
      case ConstantTag.kInt:
        return new ConstantInt.readFromBinary(source);
      case ConstantTag.kDouble:
        return new ConstantDouble.readFromBinary(source);
      case ConstantTag.kBool:
        return new ConstantBool.readFromBinary(source);
      case ConstantTag.kICData:
        return new ConstantICData.readFromBinary(source);
      case ConstantTag.kStaticICData:
        return new ConstantStaticICData.readFromBinary(source);
      case ConstantTag.kArgDesc:
        return new ConstantArgDesc.readFromBinary(source);
      case ConstantTag.kField:
        return new ConstantField.readFromBinary(source);
      case ConstantTag.kFieldOffset:
        return new ConstantFieldOffset.readFromBinary(source);
      case ConstantTag.kClass:
        return new ConstantClass.readFromBinary(source);
      case ConstantTag.kTypeArgumentsFieldOffset:
        return new ConstantTypeArgumentsFieldOffset.readFromBinary(source);
      case ConstantTag.kTearOff:
        return new ConstantTearOff.readFromBinary(source);
      case ConstantTag.kType:
        return new ConstantType.readFromBinary(source);
      case ConstantTag.kTypeArguments:
        return new ConstantTypeArguments.readFromBinary(source);
      case ConstantTag.kList:
        return new ConstantList.readFromBinary(source);
      case ConstantTag.kInstance:
        return new ConstantInstance.readFromBinary(source);
      case ConstantTag.kSymbol:
        return new ConstantSymbol.readFromBinary(source);
      case ConstantTag.kTypeArgumentsForInstanceAllocation:
        return new ConstantTypeArgumentsForInstanceAllocation.readFromBinary(
            source);
      case ConstantTag.kContextOffset:
        return new ConstantContextOffset.readFromBinary(source);
      case ConstantTag.kClosureFunction:
        return new ConstantClosureFunction.readFromBinary(source);
      case ConstantTag.kEndClosureFunctionScope:
        return new ConstantEndClosureFunctionScope.readFromBinary(source);
      case ConstantTag.kNativeEntry:
        return new ConstantNativeEntry.readFromBinary(source);
      case ConstantTag.kSubtypeTestCache:
        return new ConstantSubtypeTestCache.readFromBinary(source);
    }
    throw 'Unexpected constant tag $tag';
  }
}

class ConstantNull extends ConstantPoolEntry {
  const ConstantNull();

  @override
  ConstantTag get tag => ConstantTag.kNull;

  @override
  void writeValueToBinary(BinarySink sink) {}

  ConstantNull.readFromBinary(BinarySource source);

  @override
  String toString() => 'Null';

  @override
  int get hashCode => 1961;

  @override
  bool operator ==(other) => other is ConstantNull;
}

class ConstantString extends ConstantPoolEntry {
  final String value;

  ConstantString(this.value);
  ConstantString.fromLiteral(StringLiteral literal) : this(literal.value);

  @override
  ConstantTag get tag => ConstantTag.kString;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeStringReference(value);
  }

  ConstantString.readFromBinary(BinarySource source)
      : value = source.readStringReference();

  @override
  String toString() => 'String \'$value\'';

  @override
  int get hashCode => value.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantString && this.value == other.value;
}

class ConstantInt extends ConstantPoolEntry {
  final int value;

  ConstantInt(this.value);
  ConstantInt.fromLiteral(IntLiteral literal) : this(literal.value);

  @override
  ConstantTag get tag => ConstantTag.kInt;

  @override
  void writeValueToBinary(BinarySink sink) {
    // TODO(alexmarkov): more efficient encoding
    sink.writeUInt32(value & 0xffffffff);
    sink.writeUInt32((value >> 32) & 0xffffffff);
  }

  ConstantInt.readFromBinary(BinarySource source)
      : value = source.readUint32() | (source.readUint32() << 32);

  @override
  String toString() => 'Int $value';

  @override
  int get hashCode => value;

  @override
  bool operator ==(other) => other is ConstantInt && this.value == other.value;
}

class ConstantDouble extends ConstantPoolEntry {
  final double value;

  ConstantDouble(this.value);
  ConstantDouble.fromLiteral(DoubleLiteral literal) : this(literal.value);

  @override
  ConstantTag get tag => ConstantTag.kDouble;

  static int doubleToIntBits(double value) {
    final buf = new ByteData(8);
    buf.setFloat64(0, value, Endian.host);
    return buf.getInt64(0, Endian.host);
  }

  static double intBitsToDouble(int bits) {
    final buf = new ByteData(8);
    buf.setInt64(0, bits, Endian.host);
    return buf.getFloat64(0, Endian.host);
  }

  @override
  void writeValueToBinary(BinarySink sink) {
    // TODO(alexmarkov): more efficient encoding
    int bits = doubleToIntBits(value);
    sink.writeUInt32(bits & 0xffffffff);
    sink.writeUInt32((bits >> 32) & 0xffffffff);
  }

  ConstantDouble.readFromBinary(BinarySource source)
      : value =
            intBitsToDouble(source.readUint32() | (source.readUint32() << 32));

  @override
  String toString() => 'Double $value';

  @override
  int get hashCode => value.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantDouble && value.compareTo(other.value) == 0;
}

class ConstantBool extends ConstantPoolEntry {
  final bool value;

  ConstantBool(this.value);
  ConstantBool.fromLiteral(BoolLiteral literal) : this(literal.value);

  @override
  ConstantTag get tag => ConstantTag.kBool;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeUInt30(value ? 1 : 0);
  }

  ConstantBool.readFromBinary(BinarySource source)
      : value = source.readUInt() != 0;

  @override
  String toString() => 'Bool $value';

  @override
  int get hashCode => value.hashCode;

  @override
  bool operator ==(other) => other is ConstantBool && this.value == other.value;
}

class ConstantArgDesc extends ConstantPoolEntry {
  final int numArguments;
  final int numTypeArgs;
  final List<String> argNames;

  ConstantArgDesc(this.numArguments,
      {this.numTypeArgs = 0, this.argNames = const <String>[]});

  ConstantArgDesc.fromArguments(Arguments args,
      {bool hasReceiver: false, bool isFactory: false})
      : this(
            args.positional.length +
                args.named.length +
                (hasReceiver ? 1 : 0) +
                // VM expects that type arguments vector passed to a factory
                // constructor is counted in numArguments, and not counted in
                // numTypeArgs.
                // TODO(alexmarkov): Clean this up.
                (isFactory ? 1 : 0),
            numTypeArgs: isFactory ? 0 : args.types.length,
            argNames: new List<String>.from(args.named.map((ne) => ne.name)));

  @override
  ConstantTag get tag => ConstantTag.kArgDesc;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeUInt30(numArguments);
    sink.writeUInt30(numTypeArgs);
    sink.writeUInt30(argNames.length);
    argNames.forEach(sink.writeStringReference);
  }

  ConstantArgDesc.readFromBinary(BinarySource source)
      : numArguments = source.readUInt(),
        numTypeArgs = source.readUInt(),
        argNames = new List<String>.generate(
            source.readUInt(), (_) => source.readStringReference());

  @override
  String toString() =>
      'ArgDesc num-args $numArguments, num-type-args $numTypeArgs, names $argNames';

  @override
  int get hashCode => _combineHashes(
      _combineHashes(numArguments, numTypeArgs), listHashCode(argNames));

  @override
  bool operator ==(other) =>
      other is ConstantArgDesc &&
      this.numArguments == other.numArguments &&
      this.numTypeArgs == other.numTypeArgs &&
      listEquals(this.argNames, other.argNames);
}

enum InvocationKind { method, getter, setter }

String _invocationKindToString(InvocationKind kind) {
  switch (kind) {
    case InvocationKind.method:
      return '';
    case InvocationKind.getter:
      return 'get ';
    case InvocationKind.setter:
      return 'set ';
  }
  throw 'Unexpected InvocationKind $kind';
}

class ConstantICData extends ConstantPoolEntry {
  final InvocationKind invocationKind;
  final Name targetName;
  final int argDescConstantIndex;

  ConstantICData(
      this.invocationKind, this.targetName, this.argDescConstantIndex);

  @override
  ConstantTag get tag => ConstantTag.kICData;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeByte(invocationKind.index);
    sink.writeName(targetName);
    sink.writeUInt30(argDescConstantIndex);
  }

  ConstantICData.readFromBinary(BinarySource source)
      : invocationKind = InvocationKind.values[source.readByte()],
        targetName = source.readName(),
        argDescConstantIndex = source.readUInt();

  @override
  String toString() => 'ICData ${_invocationKindToString(invocationKind)}'
      'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';

  // ConstantICData entries are created per call site and should not be merged,
  // so ConstantICData class uses identity [hashCode] and [operator ==].

  @override
  int get hashCode => identityHashCode(this);

  @override
  bool operator ==(other) => identical(this, other);
}

class ConstantStaticICData extends ConstantPoolEntry {
  final InvocationKind invocationKind;
  final Reference _reference;
  final int argDescConstantIndex;

  ConstantStaticICData(
      InvocationKind invocationKind, Member member, int argDescConstantIndex)
      : this.byReference(
            invocationKind, member.reference, argDescConstantIndex);

  ConstantStaticICData.byReference(
      this.invocationKind, this._reference, this.argDescConstantIndex);

  Member get target => _reference.asMember;

  @override
  ConstantTag get tag => ConstantTag.kStaticICData;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeByte(invocationKind.index);
    sink.writeCanonicalNameReference(getCanonicalNameOfMember(target));
    sink.writeUInt30(argDescConstantIndex);
  }

  ConstantStaticICData.readFromBinary(BinarySource source)
      : invocationKind = InvocationKind.values[source.readByte()],
        _reference = source.readCanonicalNameReference().getReference(),
        argDescConstantIndex = source.readUInt();

  @override
  String toString() => 'StaticICData ${_invocationKindToString(invocationKind)}'
      'target \'$target\', arg-desc CP#$argDescConstantIndex';

  // ConstantStaticICData entries are created per call site and should not be
  // merged, so ConstantStaticICData class uses identity [hashCode] and
  // [operator ==].

  @override
  int get hashCode => identityHashCode(this);

  @override
  bool operator ==(other) => identical(this, other);
}

class ConstantField extends ConstantPoolEntry {
  final Reference _reference;

  Field get field => _reference.asField;

  ConstantField(Field field) : this.byReference(field.reference);
  ConstantField.byReference(this._reference);

  @override
  ConstantTag get tag => ConstantTag.kField;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
  }

  ConstantField.readFromBinary(BinarySource source)
      : _reference = source.readCanonicalNameReference().getReference();

  @override
  String toString() => 'Field $field';

  @override
  int get hashCode => field.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantField && this.field == other.field;
}

class ConstantFieldOffset extends ConstantPoolEntry {
  final Reference _reference;

  Field get field => _reference.asField;

  ConstantFieldOffset(Field field) : this.byReference(field.reference);
  ConstantFieldOffset.byReference(this._reference);

  @override
  ConstantTag get tag => ConstantTag.kFieldOffset;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfMember(field));
  }

  ConstantFieldOffset.readFromBinary(BinarySource source)
      : _reference = source.readCanonicalNameReference().getReference();

  @override
  String toString() => 'FieldOffset $field';

  @override
  int get hashCode => field.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantFieldOffset && this.field == other.field;
}

class ConstantClass extends ConstantPoolEntry {
  final Reference _reference;

  Class get classNode => _reference.asClass;

  ConstantClass(Class class_) : this.byReference(class_.reference);
  ConstantClass.byReference(this._reference);

  @override
  ConstantTag get tag => ConstantTag.kClass;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
  }

  ConstantClass.readFromBinary(BinarySource source)
      : _reference = source.readCanonicalNameReference().getReference();

  @override
  String toString() => 'Class $classNode';

  @override
  int get hashCode => classNode.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantClass && this.classNode == other.classNode;
}

class ConstantTypeArgumentsFieldOffset extends ConstantPoolEntry {
  final Reference _reference;

  Class get classNode => _reference.asClass;

  ConstantTypeArgumentsFieldOffset(Class class_)
      : this.byReference(class_.reference);
  ConstantTypeArgumentsFieldOffset.byReference(this._reference);

  @override
  ConstantTag get tag => ConstantTag.kTypeArgumentsFieldOffset;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
  }

  ConstantTypeArgumentsFieldOffset.readFromBinary(BinarySource source)
      : _reference = source.readCanonicalNameReference().getReference();

  @override
  String toString() => 'TypeArgumentsFieldOffset $classNode';

  @override
  int get hashCode => classNode.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantTypeArgumentsFieldOffset &&
      this.classNode == other.classNode;
}

class ConstantTearOff extends ConstantPoolEntry {
  final Reference _reference;

  Procedure get procedure => _reference.asProcedure;

  ConstantTearOff(Procedure procedure) : this.byReference(procedure.reference);
  ConstantTearOff.byReference(this._reference);

  @override
  ConstantTag get tag => ConstantTag.kTearOff;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfMember(procedure));
  }

  ConstantTearOff.readFromBinary(BinarySource source)
      : _reference = source.readCanonicalNameReference().getReference();

  @override
  String toString() => 'TearOff $procedure';

  @override
  int get hashCode => procedure.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantTearOff && this.procedure == other.procedure;
}

class ConstantType extends ConstantPoolEntry {
  final DartType type;

  ConstantType(this.type);

  @override
  ConstantTag get tag => ConstantTag.kType;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeDartType(type);
  }

  ConstantType.readFromBinary(BinarySource source)
      : type = source.readDartType();

  @override
  String toString() => 'Type $type';

  @override
  int get hashCode => type.hashCode;

  @override
  bool operator ==(other) => other is ConstantType && this.type == other.type;
}

class ConstantTypeArguments extends ConstantPoolEntry {
  final List<DartType> typeArgs;

  ConstantTypeArguments(this.typeArgs);

  @override
  ConstantTag get tag => ConstantTag.kTypeArguments;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeUInt30(typeArgs.length);
    typeArgs.forEach(sink.writeDartType);
  }

  ConstantTypeArguments.readFromBinary(BinarySource source)
      : typeArgs = new List<DartType>.generate(
            source.readUInt(), (_) => source.readDartType());

  @override
  String toString() => 'TypeArgs $typeArgs';

  @override
  int get hashCode => listHashCode(typeArgs);

  @override
  bool operator ==(other) =>
      other is ConstantTypeArguments &&
      listEquals(this.typeArgs, other.typeArgs);
}

class ConstantList extends ConstantPoolEntry {
  final DartType typeArg;
  final List<int> entries;

  ConstantList(this.typeArg, this.entries);

  @override
  ConstantTag get tag => ConstantTag.kList;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeDartType(typeArg);
    sink.writeUInt30(entries.length);
    entries.forEach(sink.writeUInt30);
  }

  ConstantList.readFromBinary(BinarySource source)
      : typeArg = source.readDartType(),
        entries =
            new List<int>.generate(source.readUInt(), (_) => source.readUInt());

  @override
  String toString() => 'List type-arg $typeArg, entries CP# $entries';

  @override
  int get hashCode => typeArg.hashCode ^ listHashCode(entries);

  @override
  bool operator ==(other) =>
      other is ConstantList &&
      this.typeArg == other.typeArg &&
      listEquals(this.entries, other.entries);
}

class ConstantInstance extends ConstantPoolEntry {
  final Reference _classReference;
  final int _typeArgumentsConstantIndex;
  final Map<Reference, int> _fieldValues;

  ConstantInstance(Class class_, int typeArgumentsConstantIndex,
      Map<Reference, int> fieldValues)
      : this.byReference(
            class_.reference, typeArgumentsConstantIndex, fieldValues);

  ConstantInstance.byReference(this._classReference,
      this._typeArgumentsConstantIndex, this._fieldValues);

  @override
  ConstantTag get tag => ConstantTag.kInstance;

  Class get classNode => _classReference.asClass;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(getCanonicalNameOfClass(classNode));
    sink.writeUInt30(_typeArgumentsConstantIndex);
    sink.writeUInt30(_fieldValues.length);
    _fieldValues.forEach((Reference fieldRef, int valueIndex) {
      sink.writeCanonicalNameReference(
          getCanonicalNameOfMember(fieldRef.asField));
      sink.writeUInt30(valueIndex);
    });
  }

  ConstantInstance.readFromBinary(BinarySource source)
      : _classReference = source.readCanonicalNameReference().getReference(),
        _typeArgumentsConstantIndex = source.readUInt(),
        _fieldValues = new Map<Reference, int>() {
    final fieldValuesLen = source.readUInt();
    for (int i = 0; i < fieldValuesLen; i++) {
      final fieldRef = source.readCanonicalNameReference().getReference();
      final valueIndex = source.readUInt();
      _fieldValues[fieldRef] = valueIndex;
    }
  }

  @override
  String toString() =>
      'Instance $classNode type-args CP#$_typeArgumentsConstantIndex'
      ' ${_fieldValues.map<String, int>((Reference fieldRef, int valueIndex) =>
              new MapEntry(fieldRef.asField.name.name, valueIndex))}';

  @override
  int get hashCode => _combineHashes(
      _combineHashes(classNode.hashCode, _typeArgumentsConstantIndex),
      mapHashCode(_fieldValues));

  @override
  bool operator ==(other) =>
      other is ConstantInstance &&
      this.classNode == other.classNode &&
      this._typeArgumentsConstantIndex == other._typeArgumentsConstantIndex &&
      mapEquals(this._fieldValues, other._fieldValues);
}

class ConstantSymbol extends ConstantPoolEntry {
  final String value;

  ConstantSymbol(this.value);
  ConstantSymbol.fromLiteral(SymbolLiteral literal) : this(literal.value);

  @override
  ConstantTag get tag => ConstantTag.kSymbol;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeStringReference(value);
  }

  ConstantSymbol.readFromBinary(BinarySource source)
      : value = source.readStringReference();

  @override
  String toString() => 'Symbol \'$value\'';

  @override
  int get hashCode => value.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantSymbol && this.value == other.value;
}

class ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
  final Reference _instantiatingClassRef;
  final List<DartType> typeArgs;

  Class get instantiatingClass => _instantiatingClassRef.asClass;

  ConstantTypeArgumentsForInstanceAllocation(
      Class instantiatingClass, List<DartType> typeArgs)
      : this.byReference(instantiatingClass.reference, typeArgs);
  ConstantTypeArgumentsForInstanceAllocation.byReference(
      this._instantiatingClassRef, this.typeArgs);

  @override
  ConstantTag get tag => ConstantTag.kTypeArgumentsForInstanceAllocation;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeCanonicalNameReference(
        getCanonicalNameOfClass(instantiatingClass));
    sink.writeUInt30(typeArgs.length);
    typeArgs.forEach(sink.writeDartType);
  }

  ConstantTypeArgumentsForInstanceAllocation.readFromBinary(BinarySource source)
      : _instantiatingClassRef =
            source.readCanonicalNameReference().getReference(),
        typeArgs = new List<DartType>.generate(
            source.readUInt(), (_) => source.readDartType());

  @override
  String toString() =>
      'TypeArgumentsForInstanceAllocation $instantiatingClass $typeArgs';

  @override
  int get hashCode =>
      _combineHashes(instantiatingClass.hashCode, listHashCode(typeArgs));

  @override
  bool operator ==(other) =>
      other is ConstantTypeArgumentsForInstanceAllocation &&
      this.instantiatingClass == other.instantiatingClass &&
      listEquals(this.typeArgs, other.typeArgs);
}

class ConstantContextOffset extends ConstantPoolEntry {
  static const int kParent = 0;
  static const int kVariableBase = 1;

  final int _index;

  ConstantContextOffset._(this._index);
  ConstantContextOffset.parent() : this._(kParent);
  ConstantContextOffset.variable(int index) : this._(index + kVariableBase);

  @override
  ConstantTag get tag => ConstantTag.kContextOffset;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeUInt30(_index);
  }

  ConstantContextOffset.readFromBinary(BinarySource source)
      : _index = source.readUInt();

  @override
  String toString() =>
      'ContextOffset ${_index == kParent ? 'parent' : 'var [${_index - kVariableBase}]'}';

  @override
  int get hashCode => _index;

  @override
  bool operator ==(other) =>
      other is ConstantContextOffset && this._index == other._index;
}

class ConstantClosureFunction extends ConstantPoolEntry {
  final String name;
  final FunctionNode function;

  ConstantClosureFunction(this.name, this.function);

  @override
  ConstantTag get tag => ConstantTag.kClosureFunction;

  @override
  void writeValueToBinary(BinarySink sink) {
    assert(function.body == null);
    sink.writeStringReference(name);
    sink.writeNode(function);
  }

  ConstantClosureFunction.readFromBinary(BinarySource source)
      : name = source.readStringReference(),
        function = source.readFunctionNode();

  @override
  String toString() {
    StringBuffer buffer = new StringBuffer();
    new Printer(buffer).writeFunction(function);
    return 'ClosureFunction $name ${buffer.toString().trim()}';
  }

  // ConstantClosureFunction entries are created per closure and should not
  // be merged, so ConstantClosureFunction class uses identity [hashCode] and
  // [operator ==].
}

class ConstantEndClosureFunctionScope extends ConstantPoolEntry {
  ConstantEndClosureFunctionScope();

  @override
  ConstantTag get tag => ConstantTag.kEndClosureFunctionScope;

  @override
  void writeValueToBinary(BinarySink sink) {}

  ConstantEndClosureFunctionScope.readFromBinary(BinarySource source) {}

  @override
  String toString() => 'EndClosureFunctionScope';

  // ConstantEndClosureFunctionScope entries are created per closure and should
  // not be merged, so ConstantEndClosureFunctionScope class uses identity
  // [hashCode] and [operator ==].
}

class ConstantNativeEntry extends ConstantPoolEntry {
  final String nativeName;

  ConstantNativeEntry(this.nativeName);

  @override
  ConstantTag get tag => ConstantTag.kNativeEntry;

  @override
  void writeValueToBinary(BinarySink sink) {
    sink.writeStringReference(nativeName);
  }

  ConstantNativeEntry.readFromBinary(BinarySource source)
      : nativeName = source.readStringReference();

  @override
  String toString() => 'NativeEntry $nativeName';

  @override
  int get hashCode => nativeName.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantNativeEntry && this.nativeName == other.nativeName;
}

class ConstantSubtypeTestCache extends ConstantPoolEntry {
  ConstantSubtypeTestCache();

  @override
  ConstantTag get tag => ConstantTag.kSubtypeTestCache;

  @override
  void writeValueToBinary(BinarySink sink) {}

  ConstantSubtypeTestCache.readFromBinary(BinarySource source);

  @override
  String toString() => 'SubtypeTestCache';

  // ConstantSubtypeTestCache entries are created per subtype test site and
  // should not be merged, so ConstantSubtypeTestCache class uses identity
  // [hashCode] and [operator ==].

  @override
  int get hashCode => identityHashCode(this);

  @override
  bool operator ==(other) => identical(this, other);
}

class ConstantPool {
  final List<ConstantPoolEntry> entries = <ConstantPoolEntry>[];
  final Map<ConstantPoolEntry, int> _canonicalizationCache =
      <ConstantPoolEntry, int>{};

  ConstantPool();

  int add(ConstantPoolEntry entry) {
    return _canonicalizationCache.putIfAbsent(entry, () {
      int index = entries.length;
      entries.add(entry);
      return index;
    });
  }

  void writeToBinary(Node node, BinarySink sink) {
    final function = (node as Member).function;
    sink.enterScope(
        typeParameters: function?.typeParameters, memberScope: true);

    final closureStack = <ConstantClosureFunction>[];

    sink.writeUInt30(entries.length);
    entries.forEach((e) {
      e.writeToBinary(sink);

      if (e is ConstantClosureFunction) {
        sink.enterScope(typeParameters: e.function.typeParameters);
        closureStack.add(e);
      } else if (e is ConstantEndClosureFunctionScope) {
        sink.leaveScope(
            typeParameters: closureStack.removeLast().function.typeParameters);
      }
    });

    assert(closureStack.isEmpty);

    sink.leaveScope(
        typeParameters: function?.typeParameters, memberScope: true);
  }

  ConstantPool.readFromBinary(Node node, BinarySource source) {
    final function = (node as Member).function;
    if (function != null) {
      source.enterScope(typeParameters: function.typeParameters);
    }

    final closureStack = <ConstantClosureFunction>[];

    int len = source.readUInt();
    for (int i = 0; i < len; i++) {
      final e = new ConstantPoolEntry.readFromBinary(source);
      entries.add(e);

      if (e is ConstantClosureFunction) {
        source.enterScope(typeParameters: e.function.typeParameters);
        closureStack.add(e);
      } else if (e is ConstantEndClosureFunctionScope) {
        source.leaveScope(
            typeParameters: closureStack.removeLast().function.typeParameters);
      }
    }

    assert(closureStack.isEmpty);

    if (function != null) {
      source.leaveScope(typeParameters: function.typeParameters);
    }
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.writeln('ConstantPool {');
    for (int i = 0; i < entries.length; i++) {
      sb.writeln('  [$i] = ${entries[i]}');
    }
    sb.writeln('}');
    return sb.toString();
  }
}

int _combineHashes(int hash1, int hash2) =>
    (((hash1 * 31) & 0x3fffffff) + hash2) & 0x3fffffff;
