// 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 'dbc.dart' show constantPoolIndexLimit, BytecodeLimitExceededException;
import 'bytecode_serialization.dart'
    show BufferedWriter, BufferedReader, StringTable;
import 'object_table.dart' show ObjectHandle, ObjectTable;

/*

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;
  PackedString 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;
  Byte flag;
}

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

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

type ConstantICData extends ConstantPoolEntry {
  Byte tag = 7;
  Byte flags(invocationKindBit0, invocationKindBit1, isDynamic);
             // Where invocationKind is index into InvocationKind.
  PackedObject targetName;
  ConstantIndex argDesc;
}

type ConstantStaticICData extends ConstantPoolEntry {
  Byte tag = 8;
  PackedObject target;
  ConstantIndex argDesc;
}

type ConstantStaticField extends ConstantPoolEntry {
  Byte tag = 9;
  PackedObject field;
}

// Occupies 2 entries in the constant pool.
type ConstantInstanceField extends ConstantPoolEntry {
  Byte tag = 10;
  PackedObject field;
}

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

type ConstantTypeArgumentsField extends ConstantPoolEntry {
  Byte tag = 12;
  PackedObject class;
}

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

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

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

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

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

type ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
  Byte tag = 18;
  PackedObject instantiatingClass;
  List<PackedObject> types;
}

type ConstantClosureFunction extends ConstantPoolEntry {
  Byte tag = 19;
  UInt closureIndex;
}

type ConstantEndClosureFunctionScope extends ConstantPoolEntry {
  Byte tag = 20;
}

type ConstantNativeEntry extends ConstantPoolEntry {
  Byte tag = 21;
  PackedString nativeName;
}

type ConstantSubtypeTestCache extends ConstantPoolEntry {
  Byte tag = 22;
}

type ConstantPartialTearOffInstantiation extends ConstantPoolEntry {
  Byte tag = 23;
  ConstantIndex tearOffConstant;
  ConstantIndex typeArguments;
}

type ConstantEmptyTypeArguments extends ConstantPoolEntry {
  Byte tag = 24;
}

type ConstantSymbol extends ConstantPoolEntry {
  Byte tag = 25;
  PackedObject name;
}

*/

enum ConstantTag {
  kInvalid,
  kNull,
  kString,
  kInt,
  kDouble,
  kBool,
  kArgDesc,
  kICData,
  kStaticICData,
  kStaticField,
  kInstanceField,
  kClass,
  kTypeArgumentsField,
  kTearOff,
  kType,
  kTypeArguments,
  kList,
  kInstance,
  kTypeArgumentsForInstanceAllocation,
  kClosureFunction,
  kEndClosureFunctionScope,
  kNativeEntry,
  kSubtypeTestCache,
  kPartialTearOffInstantiation,
  kEmptyTypeArguments,
  kSymbol,
}

abstract class ConstantPoolEntry {
  const ConstantPoolEntry();

  ConstantTag get tag;

  // Returns number of extra reserved constant pool entries
  // following this entry.
  int get numReservedEntries => 0;

  void write(BufferedWriter writer) {
    writer.writeByte(tag.index);
    writeValue(writer);
  }

  void writeValue(BufferedWriter writer);

  factory ConstantPoolEntry.read(BufferedReader reader) {
    ConstantTag tag = ConstantTag.values[reader.readByte()];
    switch (tag) {
      case ConstantTag.kInvalid:
        break;
      case ConstantTag.kNull:
        return new ConstantNull.read(reader);
      case ConstantTag.kString:
        return new ConstantString.read(reader);
      case ConstantTag.kInt:
        return new ConstantInt.read(reader);
      case ConstantTag.kDouble:
        return new ConstantDouble.read(reader);
      case ConstantTag.kBool:
        return new ConstantBool.read(reader);
      case ConstantTag.kICData:
        return new ConstantICData.read(reader);
      case ConstantTag.kStaticICData:
        return new ConstantStaticICData.read(reader);
      case ConstantTag.kArgDesc:
        return new ConstantArgDesc.read(reader);
      case ConstantTag.kStaticField:
        return new ConstantStaticField.read(reader);
      case ConstantTag.kInstanceField:
        return new ConstantInstanceField.read(reader);
      case ConstantTag.kClass:
        return new ConstantClass.read(reader);
      case ConstantTag.kTypeArgumentsField:
        return new ConstantTypeArgumentsField.read(reader);
      case ConstantTag.kTearOff:
        return new ConstantTearOff.read(reader);
      case ConstantTag.kType:
        return new ConstantType.read(reader);
      case ConstantTag.kTypeArguments:
        return new ConstantTypeArguments.read(reader);
      case ConstantTag.kList:
        return new ConstantList.read(reader);
      case ConstantTag.kInstance:
        return new ConstantInstance.read(reader);
      case ConstantTag.kTypeArgumentsForInstanceAllocation:
        return new ConstantTypeArgumentsForInstanceAllocation.read(reader);
      case ConstantTag.kClosureFunction:
        return new ConstantClosureFunction.read(reader);
      case ConstantTag.kEndClosureFunctionScope:
        return new ConstantEndClosureFunctionScope.read(reader);
      case ConstantTag.kNativeEntry:
        return new ConstantNativeEntry.read(reader);
      case ConstantTag.kSubtypeTestCache:
        return new ConstantSubtypeTestCache.read(reader);
      case ConstantTag.kPartialTearOffInstantiation:
        return new ConstantPartialTearOffInstantiation.read(reader);
      case ConstantTag.kEmptyTypeArguments:
        return new ConstantEmptyTypeArguments.read(reader);
      case ConstantTag.kSymbol:
        return new ConstantSymbol.read(reader);
    }
    throw 'Unexpected constant tag $tag';
  }
}

class ConstantNull extends ConstantPoolEntry {
  const ConstantNull();

  @override
  ConstantTag get tag => ConstantTag.kNull;

  @override
  void writeValue(BufferedWriter writer) {}

  ConstantNull.read(BufferedReader reader);

  @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 writeValue(BufferedWriter writer) {
    writer.writePackedStringReference(value);
  }

  ConstantString.read(BufferedReader reader)
      : value = reader.readPackedStringReference();

  @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);

  @override
  ConstantTag get tag => ConstantTag.kInt;

  @override
  void writeValue(BufferedWriter writer) {
    // TODO(alexmarkov): more efficient encoding
    writer.writeUInt32(value & 0xffffffff);
    writer.writeUInt32((value >> 32) & 0xffffffff);
  }

  ConstantInt.read(BufferedReader reader)
      : value = reader.readUInt32() | (reader.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);

  @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 writeValue(BufferedWriter writer) {
    // TODO(alexmarkov): more efficient encoding
    int bits = doubleToIntBits(value);
    writer.writeUInt32(bits & 0xffffffff);
    writer.writeUInt32((bits >> 32) & 0xffffffff);
  }

  ConstantDouble.read(BufferedReader reader)
      : value =
            intBitsToDouble(reader.readUInt32() | (reader.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 writeValue(BufferedWriter writer) {
    writer.writeByte(value ? 1 : 0);
  }

  ConstantBool.read(BufferedReader reader) : value = reader.readByte() != 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, this.argNames);

  ConstantArgDesc.fromArguments(
      Arguments args, bool hasReceiver, bool isFactory)
      : 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),
            isFactory ? 0 : args.types.length,
            new List<String>.from(args.named.map((ne) => ne.name)));

  @override
  ConstantTag get tag => ConstantTag.kArgDesc;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedUInt30(numArguments);
    writer.writePackedUInt30(numTypeArgs);
    writer.writePackedUInt30(argNames.length);
    argNames.forEach(writer.writePackedStringReference);
  }

  ConstantArgDesc.read(BufferedReader reader)
      : numArguments = reader.readPackedUInt30(),
        numTypeArgs = reader.readPackedUInt30(),
        argNames = new List<String>.generate(reader.readPackedUInt30(),
            (_) => reader.readPackedStringReference());

  @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 {
  static const int invocationKindMask = 3;
  static const int flagDynamic = 1 << 2;

  final int _flags;
  final ObjectHandle targetName;
  final int argDescConstantIndex;

  ConstantICData(InvocationKind invocationKind, this.targetName,
      this.argDescConstantIndex, bool isDynamic)
      : assert(invocationKind.index <= invocationKindMask),
        _flags = invocationKind.index | (isDynamic ? flagDynamic : 0);

  InvocationKind get invocationKind =>
      InvocationKind.values[_flags & invocationKindMask];

  bool get isDynamic => (_flags & flagDynamic) != 0;

  @override
  ConstantTag get tag => ConstantTag.kICData;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writeByte(_flags);
    writer.writePackedObject(targetName);
    writer.writePackedUInt30(argDescConstantIndex);
  }

  ConstantICData.read(BufferedReader reader)
      : _flags = reader.readByte(),
        targetName = reader.readPackedObject(),
        argDescConstantIndex = reader.readPackedUInt30();

  @override
  String toString() => 'ICData '
      '${isDynamic ? 'dynamic ' : ''}'
      '${_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 ObjectHandle target;
  final int argDescConstantIndex;

  ConstantStaticICData(this.target, this.argDescConstantIndex);

  @override
  ConstantTag get tag => ConstantTag.kStaticICData;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(target);
    writer.writePackedUInt30(argDescConstantIndex);
  }

  ConstantStaticICData.read(BufferedReader reader)
      : target = reader.readPackedObject(),
        argDescConstantIndex = reader.readPackedUInt30();

  @override
  String toString() => 'StaticICData '
      '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 ConstantStaticField extends ConstantPoolEntry {
  final ObjectHandle field;

  ConstantStaticField(this.field);

  @override
  ConstantTag get tag => ConstantTag.kStaticField;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(field);
  }

  ConstantStaticField.read(BufferedReader reader)
      : field = reader.readPackedObject();

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

  @override
  int get hashCode => field.hashCode;

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

class ConstantInstanceField extends ConstantPoolEntry {
  final ObjectHandle field;

  int get numReservedEntries => 1;

  ConstantInstanceField(this.field);

  @override
  ConstantTag get tag => ConstantTag.kInstanceField;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(field);
  }

  ConstantInstanceField.read(BufferedReader reader)
      : field = reader.readPackedObject();

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

  @override
  int get hashCode => field.hashCode;

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

class ConstantClass extends ConstantPoolEntry {
  final ObjectHandle classHandle;

  ConstantClass(this.classHandle);

  @override
  ConstantTag get tag => ConstantTag.kClass;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(classHandle);
  }

  ConstantClass.read(BufferedReader reader)
      : classHandle = reader.readPackedObject();

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

  @override
  int get hashCode => classHandle.hashCode;

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

class ConstantTypeArgumentsField extends ConstantPoolEntry {
  final ObjectHandle classHandle;

  ConstantTypeArgumentsField(this.classHandle);

  @override
  ConstantTag get tag => ConstantTag.kTypeArgumentsField;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(classHandle);
  }

  ConstantTypeArgumentsField.read(BufferedReader reader)
      : classHandle = reader.readPackedObject();

  @override
  String toString() => 'TypeArgumentsField $classHandle';

  @override
  int get hashCode => classHandle.hashCode;

  @override
  bool operator ==(other) =>
      other is ConstantTypeArgumentsField &&
      this.classHandle == other.classHandle;
}

class ConstantTearOff extends ConstantPoolEntry {
  final ObjectHandle procedure;

  ConstantTearOff(this.procedure);

  @override
  ConstantTag get tag => ConstantTag.kTearOff;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(procedure);
  }

  ConstantTearOff.read(BufferedReader reader)
      : procedure = reader.readPackedObject();

  @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 ObjectHandle type;

  ConstantType(this.type);

  @override
  ConstantTag get tag => ConstantTag.kType;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(type);
  }

  ConstantType.read(BufferedReader reader) : type = reader.readPackedObject();

  @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<ObjectHandle> typeArgs;

  ConstantTypeArguments(this.typeArgs);

  @override
  ConstantTag get tag => ConstantTag.kTypeArguments;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedList(typeArgs);
  }

  ConstantTypeArguments.read(BufferedReader reader)
      : typeArgs = reader.readPackedList();

  @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 ObjectHandle typeArg;
  final List<int> entries;

  ConstantList(this.typeArg, this.entries);

  @override
  ConstantTag get tag => ConstantTag.kList;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(typeArg);
    writer.writePackedUInt30(entries.length);
    entries.forEach(writer.writePackedUInt30);
  }

  ConstantList.read(BufferedReader reader)
      : typeArg = reader.readPackedObject(),
        entries = new List<int>.generate(
            reader.readPackedUInt30(), (_) => reader.readPackedUInt30());

  @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 ObjectHandle classHandle;
  final int _typeArgumentsConstantIndex;
  final Map<ObjectHandle, int> _fieldValues;

  ConstantInstance(
      this.classHandle, this._typeArgumentsConstantIndex, this._fieldValues);

  @override
  ConstantTag get tag => ConstantTag.kInstance;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(classHandle);
    writer.writePackedUInt30(_typeArgumentsConstantIndex);
    writer.writePackedUInt30(_fieldValues.length);
    _fieldValues.forEach((ObjectHandle field, int valueIndex) {
      writer.writePackedObject(field);
      writer.writePackedUInt30(valueIndex);
    });
  }

  ConstantInstance.read(BufferedReader reader)
      : classHandle = reader.readPackedObject(),
        _typeArgumentsConstantIndex = reader.readPackedUInt30(),
        _fieldValues = new Map<ObjectHandle, int>() {
    final fieldValuesLen = reader.readPackedUInt30();
    for (int i = 0; i < fieldValuesLen; i++) {
      final field = reader.readPackedObject();
      final valueIndex = reader.readPackedUInt30();
      _fieldValues[field] = valueIndex;
    }
  }

  @override
  String toString() {
    final values = _fieldValues.map<String, String>(
        (ObjectHandle field, int valueIndex) =>
            new MapEntry(field.toString(), 'CP#$valueIndex'));
    return 'Instance $classHandle type-args CP#$_typeArgumentsConstantIndex $values';
  }

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

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

class ConstantTypeArgumentsForInstanceAllocation extends ConstantPoolEntry {
  final ObjectHandle instantiatingClass;
  final List<ObjectHandle> typeArgs;

  ConstantTypeArgumentsForInstanceAllocation(
      this.instantiatingClass, this.typeArgs);

  @override
  ConstantTag get tag => ConstantTag.kTypeArgumentsForInstanceAllocation;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(instantiatingClass);
    writer.writePackedList(typeArgs);
  }

  ConstantTypeArgumentsForInstanceAllocation.read(BufferedReader reader)
      : instantiatingClass = reader.readPackedObject(),
        typeArgs = reader.readPackedList();

  @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 ConstantClosureFunction extends ConstantPoolEntry {
  final int closureIndex;

  ConstantClosureFunction(this.closureIndex);

  @override
  ConstantTag get tag => ConstantTag.kClosureFunction;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedUInt30(closureIndex);
  }

  ConstantClosureFunction.read(BufferedReader reader)
      : closureIndex = reader.readPackedUInt30();

  @override
  String toString() {
    return 'ClosureFunction $closureIndex';
  }

  @override
  int get hashCode => closureIndex;

  @override
  bool operator ==(other) =>
      other is ConstantClosureFunction &&
      this.closureIndex == other.closureIndex;
}

class ConstantEndClosureFunctionScope extends ConstantPoolEntry {
  ConstantEndClosureFunctionScope();

  @override
  ConstantTag get tag => ConstantTag.kEndClosureFunctionScope;

  @override
  void writeValue(BufferedWriter writer) {}

  ConstantEndClosureFunctionScope.read(BufferedReader reader) {}

  @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 writeValue(BufferedWriter writer) {
    writer.writePackedStringReference(nativeName);
  }

  ConstantNativeEntry.read(BufferedReader reader)
      : nativeName = reader.readPackedStringReference();

  @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 writeValue(BufferedWriter writer) {}

  ConstantSubtypeTestCache.read(BufferedReader reader);

  @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 ConstantPartialTearOffInstantiation extends ConstantPoolEntry {
  final int tearOffConstantIndex;
  final int typeArgumentsConstantIndex;

  ConstantPartialTearOffInstantiation(
      this.tearOffConstantIndex, this.typeArgumentsConstantIndex);

  @override
  ConstantTag get tag => ConstantTag.kPartialTearOffInstantiation;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedUInt30(tearOffConstantIndex);
    writer.writePackedUInt30(typeArgumentsConstantIndex);
  }

  ConstantPartialTearOffInstantiation.read(BufferedReader reader)
      : tearOffConstantIndex = reader.readPackedUInt30(),
        typeArgumentsConstantIndex = reader.readPackedUInt30();

  @override
  String toString() {
    return 'PartialTearOffInstantiation tear-off CP#$tearOffConstantIndex type-args CP#$typeArgumentsConstantIndex';
  }

  @override
  int get hashCode =>
      _combineHashes(tearOffConstantIndex, typeArgumentsConstantIndex);

  @override
  bool operator ==(other) =>
      other is ConstantPartialTearOffInstantiation &&
      this.tearOffConstantIndex == other.tearOffConstantIndex &&
      this.typeArgumentsConstantIndex == other.typeArgumentsConstantIndex;
}

class ConstantEmptyTypeArguments extends ConstantPoolEntry {
  const ConstantEmptyTypeArguments();

  @override
  ConstantTag get tag => ConstantTag.kEmptyTypeArguments;

  @override
  void writeValue(BufferedWriter writer) {}

  ConstantEmptyTypeArguments.read(BufferedReader reader);

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

  @override
  int get hashCode => 997;

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

class ConstantSymbol extends ConstantPoolEntry {
  final ObjectHandle name;

  ConstantSymbol(this.name);

  @override
  ConstantTag get tag => ConstantTag.kSymbol;

  @override
  void writeValue(BufferedWriter writer) {
    writer.writePackedObject(name);
  }

  ConstantSymbol.read(BufferedReader reader) : name = reader.readPackedObject();

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

  @override
  int get hashCode => name.hashCode;

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

/// Reserved constant pool entry.
class _ReservedConstantPoolEntry extends ConstantPoolEntry {
  const _ReservedConstantPoolEntry();

  ConstantTag get tag => throw 'This constant pool entry is reserved';
  void writeValue(BufferedWriter writer) =>
      throw 'This constant pool entry is reserved';

  @override
  String toString() => 'Reserved';
}

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

  ConstantPool(this.stringTable, this.objectTable);

  int addNull() => _add(const ConstantNull());

  int addString(String value) => _add(new ConstantString(_indexString(value)));

  int addInt(int value) => _add(new ConstantInt(value));

  int addDouble(double value) => _add(new ConstantDouble(value));

  int addBool(bool value) => _add(new ConstantBool(value));

  int addArgDesc(int numArguments,
          {int numTypeArgs = 0, List<String> argNames = const <String>[]}) =>
      _add(new ConstantArgDesc(
          numArguments, numTypeArgs, _indexStrings(argNames)));

  int addArgDescByArguments(Arguments args,
          {bool hasReceiver: false, bool isFactory: false}) =>
      _add(new ConstantArgDesc.fromArguments(
          _indexArgNames(args), hasReceiver, isFactory));

  int addICData(
          InvocationKind invocationKind, Name targetName, int argDescCpIndex,
          {bool isDynamic: false}) =>
      _add(new ConstantICData(
          invocationKind,
          objectTable.getSelectorNameHandle(targetName,
              isGetter: invocationKind == InvocationKind.getter,
              isSetter: invocationKind == InvocationKind.setter),
          argDescCpIndex,
          isDynamic));

  int addStaticICData(
          InvocationKind invocationKind, Member target, int argDescCpIndex) =>
      _add(new ConstantStaticICData(
          objectTable.getMemberHandle(target,
              isGetter: invocationKind == InvocationKind.getter,
              isSetter: invocationKind == InvocationKind.setter),
          argDescCpIndex));

  int addStaticField(Field field) =>
      _add(new ConstantStaticField(objectTable.getHandle(field)));

  int addInstanceField(Field field) =>
      _add(new ConstantInstanceField(objectTable.getHandle(field)));

  int addClass(Class node) =>
      _add(new ConstantClass(objectTable.getHandle(node)));

  int addTypeArgumentsField(Class node) =>
      _add(new ConstantTypeArgumentsField(objectTable.getHandle(node)));

  int addTearOff(Procedure node) =>
      _add(new ConstantTearOff(objectTable.getHandle(node)));

  int addType(DartType type) =>
      _add(new ConstantType(objectTable.getHandle(type)));

  int addTypeArguments(List<DartType> typeArgs) =>
      _add(new ConstantTypeArguments(objectTable.getHandles(typeArgs)));

  int addList(DartType typeArgument, List<int> entries) =>
      _add(new ConstantList(objectTable.getHandle(typeArgument), entries));

  int addInstance(
          Class klass, int typeArgumentsCpIndex, Map<Field, int> fieldValues) =>
      _add(new ConstantInstance(
          objectTable.getHandle(klass),
          typeArgumentsCpIndex,
          fieldValues.map<ObjectHandle, int>((Field field, int valueCpIndex) =>
              new MapEntry(objectTable.getHandle(field), valueCpIndex))));

  int addTypeArgumentsForInstanceAllocation(
          Class classNode, List<DartType> typeArgs) =>
      _add(new ConstantTypeArgumentsForInstanceAllocation(
          objectTable.getHandle(classNode), objectTable.getHandles(typeArgs)));

  int addClosureFunction(int closureIndex) =>
      _add(new ConstantClosureFunction(closureIndex));

  int addEndClosureFunctionScope() =>
      _add(new ConstantEndClosureFunctionScope());

  int addNativeEntry(String nativeName) =>
      _add(new ConstantNativeEntry(_indexString(nativeName)));

  int addSubtypeTestCache() => _add(new ConstantSubtypeTestCache());

  int addPartialTearOffInstantiation(
          int tearOffCpIndex, int typeArgumentsCpIndex) =>
      _add(new ConstantPartialTearOffInstantiation(
          tearOffCpIndex, typeArgumentsCpIndex));

  int addEmptyTypeArguments() => _add(const ConstantEmptyTypeArguments());

  int addSymbol(Library library, String name) =>
      _add(new ConstantSymbol(objectTable.getNameHandle(library, name)));

  int _add(ConstantPoolEntry entry) {
    return _canonicalizationCache.putIfAbsent(entry, () {
      int index = entries.length;
      if (index >= constantPoolIndexLimit) {
        throw new ConstantPoolIndexOverflowException();
      }
      _addEntry(entry);
      return index;
    });
  }

  void _addEntry(ConstantPoolEntry entry) {
    entries.add(entry);
    for (int i = 0; i < entry.numReservedEntries; ++i) {
      entries.add(const _ReservedConstantPoolEntry());
    }
  }

  // Currently, string table is written as a part of Component's metadata
  // *before* constant pools are written.
  // So we need to index all strings when filling up constant pools.
  String _indexString(String str) {
    stringTable.put(str);
    return str;
  }

  List<String> _indexStrings(List<String> strings) {
    for (var str in strings) {
      stringTable.put(str);
    }
    return strings;
  }

  Arguments _indexArgNames(Arguments args) {
    for (var arg in args.named) {
      stringTable.put(arg.name);
    }
    return args;
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(entries.length);
    entries.forEach((e) {
      if (e is _ReservedConstantPoolEntry) {
        return;
      }
      e.write(writer);
    });
  }

  ConstantPool.read(BufferedReader reader)
      : stringTable = reader.stringReader,
        objectTable = reader.objectReader {
    int len = reader.readPackedUInt30();
    for (int i = 0; i < len; i++) {
      final e = new ConstantPoolEntry.read(reader);
      _addEntry(e);
      i += e.numReservedEntries;
    }
  }

  @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;

class ConstantPoolIndexOverflowException
    extends BytecodeLimitExceededException {}
