// Copyright (c) 2016, 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.
#if !defined(DART_PRECOMPILED_RUNTIME)

#include <map>
#include <vector>

#include "platform/globals.h"
#include "vm/flags.h"
#include "vm/kernel.h"
#include "vm/os.h"

#if defined(DEBUG)
#define TRACE_READ_OFFSET()                                                    \
  do {                                                                         \
    if (FLAG_trace_kernel_binary) reader->DumpOffset(DART_PRETTY_FUNCTION);    \
  } while (0)
#define TRACE_WRITE_OFFSET()                                                   \
  do {                                                                         \
    if (FLAG_trace_kernel_binary) writer->DumpOffset(DART_PRETTY_FUNCTION);    \
  } while (0)
#else
#define TRACE_READ_OFFSET()
#define TRACE_WRITE_OFFSET()
#endif

namespace dart {


ByteWriter::~ByteWriter() {}


namespace kernel {


static const uint32_t kMagicProgramFile = 0x90ABCDEFu;


// Keep in sync with package:dynamo/lib/binary/tag.dart
enum Tag {
  kNothing = 0,
  kSomething = 1,

  kNormalClass = 2,
  kMixinClass = 3,

  kField = 4,
  kConstructor = 5,
  kProcedure = 6,

  kInvalidInitializer = 7,
  kFieldInitializer = 8,
  kSuperInitializer = 9,
  kRedirectingInitializer = 10,
  kLocalInitializer = 11,

  kDirectPropertyGet = 15,
  kDirectPropertySet = 16,
  kDirectMethodInvocation = 17,
  kConstStaticInvocation = 18,
  kInvalidExpression = 19,
  kVariableGet = 20,
  kVariableSet = 21,
  kPropertyGet = 22,
  kPropertySet = 23,
  kSuperPropertyGet = 24,
  kSuperPropertySet = 25,
  kStaticGet = 26,
  kStaticSet = 27,
  kMethodInvocation = 28,
  kSuperMethodInvocation = 29,
  kStaticInvocation = 30,
  kConstructorInvocation = 31,
  kConstConstructorInvocation = 32,
  kNot = 33,
  kLogicalExpression = 34,
  kConditionalExpression = 35,
  kStringConcatenation = 36,
  kIsExpression = 37,
  kAsExpression = 38,
  kStringLiteral = 39,
  kDoubleLiteral = 40,
  kTrueLiteral = 41,
  kFalseLiteral = 42,
  kNullLiteral = 43,
  kSymbolLiteral = 44,
  kTypeLiteral = 45,
  kThisExpression = 46,
  kRethrow = 47,
  kThrow = 48,
  kListLiteral = 49,
  kMapLiteral = 50,
  kAwaitExpression = 51,
  kFunctionExpression = 52,
  kLet = 53,
  kBlockExpression = 54,

  kPositiveIntLiteral = 55,
  kNegativeIntLiteral = 56,
  kBigIntLiteral = 57,
  kConstListLiteral = 58,
  kConstMapLiteral = 59,

  kInvalidStatement = 60,
  kExpressionStatement = 61,
  kBlock = 62,
  kEmptyStatement = 63,
  kAssertStatement = 64,
  kLabeledStatement = 65,
  kBreakStatement = 66,
  kWhileStatement = 67,
  kDoStatement = 68,
  kForStatement = 69,
  kForInStatement = 70,
  kSwitchStatement = 71,
  kContinueSwitchStatement = 72,
  kIfStatement = 73,
  kReturnStatement = 74,
  kTryCatch = 75,
  kTryFinally = 76,
  kYieldStatement = 77,
  kVariableDeclaration = 78,
  kFunctionDeclaration = 79,
  kAsyncForInStatement = 80,

  kInvalidType = 90,
  kDynamicType = 91,
  kVoidType = 92,
  kInterfaceType = 93,
  kFunctionType = 94,
  kTypeParameterType = 95,
  kSimpleInterfaceType = 96,
  kSimpleFunctionType = 97,

  kNullReference = 99,
  kNormalClassReference = 100,
  kMixinClassReference = 101,

  kLibraryFieldReference = 102,
  kClassFieldReference = 103,
  kClassConstructorReference = 104,
  kLibraryProcedureReference = 105,
  kClassProcedureReference = 106,

  kSpecializedTagHighBit = 0x80,  // 10000000
  kSpecializedTagMask = 0xF8,     // 11111000
  kSpecializedPayloadMask = 0x7,  // 00000111

  kSpecializedVariableGet = 128,
  kSpecializedVariableSet = 136,
  kSpecialIntLiteral = 144,
};


static const int SpecializedIntLiteralBias = 3;


template <typename T>
class BlockStack {
 public:
  BlockStack() : current_count_(0) {}

  void EnterScope() {
    variable_count_.push_back(current_count_);
    current_count_ = 0;
  }

  void LeaveScope() {
    variables_.resize(variables_.size() - current_count_);
    current_count_ = variable_count_[variable_count_.size() - 1];
    variable_count_.pop_back();
  }

  T* Lookup(int index) {
    ASSERT(static_cast<unsigned>(index) < variables_.size());
    return variables_[index];
  }

  void Push(T* v) {
    variables_.push_back(v);
    current_count_++;
  }

  void Push(List<T>* decl) {
    for (int i = 0; i < decl->length(); i++) {
      variables_.push_back(decl[i]);
      current_count_++;
    }
  }

  void Pop(T* decl) {
    variables_.resize(variables_.size() - 1);
    current_count_--;
  }

  void Pop(List<T>* decl) {
    variables_.resize(variables_.size() - decl->length());
    current_count_ -= decl->length();
  }

 private:
  int current_count_;
  std::vector<T*> variables_;
  std::vector<int> variable_count_;
};


template <typename T>
class BlockMap {
 public:
  BlockMap() : current_count_(0), stack_height_(0) {}

  void EnterScope() {
    variable_count_.push_back(current_count_);
    current_count_ = 0;
  }

  void LeaveScope() {
    stack_height_ -= current_count_;
    current_count_ = variable_count_[variable_count_.size() - 1];
    variable_count_.pop_back();
  }

  int Lookup(T* object) {
    ASSERT(variables_.find(object) != variables_.end());
    if (variables_.find(object) == variables_.end()) FATAL("lookup failure");
    return variables_[object];
  }

  void Push(T* v) {
    int index = stack_height_++;
    variables_[v] = index;
    current_count_++;
  }

  void Set(T* v, int index) { variables_[v] = index; }

  void Push(List<T>* decl) {
    for (int i = 0; i < decl->length(); i++) {
      Push(decl[i]);
    }
  }

  void Pop(T* v) {
    current_count_--;
    stack_height_--;
  }

 private:
  int current_count_;
  int stack_height_;
  std::map<T*, int> variables_;
  std::vector<int> variable_count_;
};


template <typename T>
class VariableScope {
 public:
  explicit VariableScope(T* builder) : builder_(builder) {
    builder_->variables().EnterScope();
  }
  ~VariableScope() { builder_->variables().LeaveScope(); }

 private:
  T* builder_;
};


template <typename T>
class TypeParameterScope {
 public:
  explicit TypeParameterScope(T* builder) : builder_(builder) {
    builder_->type_parameters().EnterScope();
  }
  ~TypeParameterScope() { builder_->type_parameters().LeaveScope(); }

 private:
  T* builder_;
};


template <typename T>
class SwitchCaseScope {
 public:
  explicit SwitchCaseScope(T* builder) : builder_(builder) {
    builder_->switch_cases().EnterScope();
  }
  ~SwitchCaseScope() { builder_->switch_cases().LeaveScope(); }

 private:
  T* builder_;
};


// Unlike other scopes, labels from enclosing functions are not visible in
// nested functions.  The LabelScope class is used to hide outer labels.
template <typename Builder, typename Block>
class LabelScope {
 public:
  explicit LabelScope(Builder* builder) : builder_(builder) {
    outer_block_ = builder_->labels();
    builder_->set_labels(&block_);
  }
  ~LabelScope() { builder_->set_labels(outer_block_); }

 private:
  Builder* builder_;
  Block block_;
  Block* outer_block_;
};

class ReaderHelper {
 public:
  ReaderHelper() : program_(NULL), labels_(NULL) {}

  Program* program() { return program_; }
  void set_program(Program* program) { program_ = program; }

  BlockStack<VariableDeclaration>& variables() { return scope_; }
  BlockStack<TypeParameter>& type_parameters() { return type_parameters_; }
  BlockStack<SwitchCase>& switch_cases() { return switch_cases_; }

  BlockStack<LabeledStatement>* labels() { return labels_; }
  void set_labels(BlockStack<LabeledStatement>* labels) { labels_ = labels; }

 private:
  Program* program_;
  BlockStack<VariableDeclaration> scope_;
  BlockStack<TypeParameter> type_parameters_;
  BlockStack<SwitchCase> switch_cases_;
  BlockStack<LabeledStatement>* labels_;
};


class Reader {
 public:
  Reader(const uint8_t* buffer, int64_t size)
      : buffer_(buffer), size_(size), offset_(0) {}

  uint32_t ReadUInt32() {
    ASSERT(offset_ + 4 <= size_);

    uint32_t value = (buffer_[offset_ + 0] << 24) |
                     (buffer_[offset_ + 1] << 16) |
                     (buffer_[offset_ + 2] << 8) | (buffer_[offset_ + 3] << 0);
    offset_ += 4;
    return value;
  }

  uint32_t ReadUInt() {
    ASSERT(offset_ + 1 <= size_);
    uint8_t byte0 = buffer_[offset_];
    if ((byte0 & 0x80) == 0) {
      // 0...
      offset_++;
      return byte0;
    } else if ((byte0 & 0xc0) == 0x80) {
      // 10...
      ASSERT(offset_ + 2 <= size_);
      uint32_t value = ((byte0 & ~0x80) << 8) | (buffer_[offset_ + 1]);
      offset_ += 2;
      return value;
    } else {
      // 11...
      ASSERT(offset_ + 4 <= size_);
      uint32_t value = ((byte0 & ~0xc0) << 24) | (buffer_[offset_ + 1] << 16) |
                       (buffer_[offset_ + 2] << 8) |
                       (buffer_[offset_ + 3] << 0);
      offset_ += 4;
      return value;
    }
  }

  TokenPosition ReadPosition() {
    intptr_t value = ReadUInt();
    // Position is saved as unsigned,
    // but actually ranges from -1 and up (thus the -1)
    return TokenPosition(value - 1);
  }

  intptr_t ReadListLength() { return ReadUInt(); }

  uint8_t ReadByte() { return buffer_[offset_++]; }

  bool ReadBool() { return (ReadByte() & 1) == 1; }

  word ReadFlags() { return ReadByte(); }

  Tag ReadTag(uint8_t* payload = NULL) {
    uint8_t byte = ReadByte();
    bool has_payload = (byte & kSpecializedTagHighBit) != 0;
    if (has_payload) {
      if (payload != NULL) {
        *payload = byte & kSpecializedPayloadMask;
      }
      return static_cast<Tag>(byte & kSpecializedTagMask);
    } else {
      return static_cast<Tag>(byte);
    }
  }

  const uint8_t* Consume(int count) {
    ASSERT(offset_ + count <= size_);
    const uint8_t* old = buffer_ + offset_;
    offset_ += count;
    return old;
  }

  void EnsureEnd() {
    if (offset_ != size_) {
      FATAL2(
          "Reading Kernel file: Expected to be at EOF "
          "(offset: %" Pd64 ", size: %" Pd64 ")",
          offset_, size_);
    }
  }

  void DumpOffset(const char* str) {
    OS::PrintErr("@%" Pd64 " %s\n", offset_, str);
  }

  template <typename T, typename RT>
  T* ReadOptional() {
    Tag tag = ReadTag();
    if (tag == kNothing) {
      return NULL;
    }
    ASSERT(tag == kSomething);
    return RT::ReadFrom(this);
  }

  template <typename T>
  T* ReadOptional() {
    return ReadOptional<T, T>();
  }

  ReaderHelper* helper() { return &builder_; }

 private:
  const uint8_t* buffer_;
  int64_t size_;
  int64_t offset_;
  ReaderHelper builder_;
};


class WriterHelper {
 public:
  WriterHelper() : labels_(NULL) {}

  void SetProgram(Program* program) {
    program_ = program;
    for (int i = 0; i < program->libraries().length(); i++) {
      Library* lib = program->libraries()[i];
      libraries_.Set(lib, i);

      for (int j = 0; j < lib->classes().length(); j++) {
        Class* klass = lib->classes()[j];
        classes_.Set(klass, j);

        for (int k = 0; k < klass->fields().length(); k++) {
          Field* field = klass->fields()[k];
          fields_.Set(field, k);
        }
        for (int k = 0; k < klass->constructors().length(); k++) {
          Constructor* constructor = klass->constructors()[k];
          constructors_.Set(constructor, k);
        }
        for (int k = 0; k < klass->procedures().length(); k++) {
          Procedure* procedure = klass->procedures()[k];
          procedures_.Set(procedure, k);
        }
      }

      for (int k = 0; k < lib->fields().length(); k++) {
        Field* field = lib->fields()[k];
        fields_.Set(field, k);
      }

      for (int k = 0; k < lib->procedures().length(); k++) {
        Procedure* procedure = lib->procedures()[k];
        procedures_.Set(procedure, k);
      }
    }
  }

  Program* program() { return program_; }

  BlockMap<String>& strings() { return strings_; }
  BlockMap<Library>& libraries() { return libraries_; }
  BlockMap<Class>& classes() { return classes_; }
  BlockMap<Field>& fields() { return fields_; }
  BlockMap<Procedure>& procedures() { return procedures_; }
  BlockMap<Constructor>& constructors() { return constructors_; }

  BlockMap<VariableDeclaration>& variables() { return scope_; }
  BlockMap<TypeParameter>& type_parameters() { return type_parameters_; }
  BlockMap<SwitchCase>& switch_cases() { return switch_cases_; }

  BlockMap<LabeledStatement>* labels() { return labels_; }
  void set_labels(BlockMap<LabeledStatement>* labels) { labels_ = labels; }

 private:
  Program* program_;

  BlockMap<String> strings_;
  BlockMap<Library> libraries_;
  BlockMap<Class> classes_;
  BlockMap<Field> fields_;
  BlockMap<Procedure> procedures_;
  BlockMap<Constructor> constructors_;

  BlockMap<VariableDeclaration> scope_;
  BlockMap<TypeParameter> type_parameters_;
  BlockMap<SwitchCase> switch_cases_;
  BlockMap<LabeledStatement>* labels_;
};


class Writer {
 public:
  explicit Writer(ByteWriter* writer) : out_(writer), offset_(0) {}

  void WriteUInt32(uint32_t value) {
    uint8_t buffer[4] = {
        static_cast<uint8_t>((value >> 24) & 0xff),
        static_cast<uint8_t>((value >> 16) & 0xff),
        static_cast<uint8_t>((value >> 8) & 0xff),
        static_cast<uint8_t>((value >> 0) & 0xff),
    };
    WriteBytes(buffer, 4);
  }

  void WriteUInt(uint32_t value) {
    if (value < 0x80) {
      // 0...
      WriteByte(static_cast<uint8_t>(value));
    } else if (value < 0x4000) {
      // 10...
      WriteByte(static_cast<uint8_t>(((value >> 8) & 0x3f) | 0x80));
      WriteByte(static_cast<uint8_t>(value & 0xff));
    } else {
      // 11...
      // Ensure the highest 2 bits is not used for anything (we use it to for
      // encoding).
      ASSERT(static_cast<uint8_t>((value >> 24) & 0xc0) == 0);
      uint8_t buffer[4] = {
          static_cast<uint8_t>(((value >> 24) & 0x7f) | 0xc0),
          static_cast<uint8_t>((value >> 16) & 0xff),
          static_cast<uint8_t>((value >> 8) & 0xff),
          static_cast<uint8_t>((value >> 0) & 0xff),
      };
      WriteBytes(buffer, 4);
    }
  }

  void WriteListLength(intptr_t value) { return WriteUInt(value); }

  void WriteByte(uint8_t value) {
    out_->WriteByte(value);
    offset_++;
  }

  void WriteBool(bool value) { WriteByte(value ? 1 : 0); }

  void WriteFlags(uint8_t value) { WriteByte(value); }

  void WriteTag(Tag tag) { WriteByte(static_cast<uint8_t>(tag)); }

  void WriteTag(Tag tag, uint8_t payload) {
    ASSERT((payload & ~kSpecializedPayloadMask) == 0);
    WriteByte(kSpecializedTagHighBit | static_cast<uint8_t>(tag) | payload);
  }

  void WriteBytes(uint8_t* bytes, int length) {
    out_->WriteBytes(bytes, length);
    offset_ += length;
  }

  void WritePosition(TokenPosition position) {
    intptr_t value = position.value() + 1;
    WriteUInt(value);
  }

  template <typename T>
  void WriteOptional(T* object) {
    if (object == NULL) {
      WriteTag(kNothing);
    } else {
      WriteTag(kSomething);
      object->WriteTo(this);
    }
  }

  template <typename T, typename WT>
  void WriteOptionalStatic(T* object) {
    if (object == NULL) {
      WriteTag(kNothing);
    } else {
      WriteTag(kSomething);
      WT::WriteTo(this, object);
    }
  }

  template <typename T>
  void WriteOptionalStatic(T* object) {
    return WriteOptionalStatic<T, T>(object);
  }

  void DumpOffset(const char* str) {
    OS::PrintErr("@%" Pd64 " %s\n", offset_, str);
  }

  WriterHelper* helper() { return &helper_; }

 private:
  ByteWriter* out_;
  WriterHelper helper_;
  int64_t offset_;
};


template <typename T>
template <typename IT>
void List<T>::ReadFrom(Reader* reader, TreeNode* parent) {
  TRACE_READ_OFFSET();
  ASSERT(parent != NULL);
  int length = reader->ReadListLength();
  EnsureInitialized(length);

  for (int i = 0; i < length_; i++) {
    IT* object = GetOrCreate<IT>(i, parent);
    object->ReadFrom(reader);
  }
}


template <typename T>
template <typename IT>
void List<T>::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  int length = reader->ReadListLength();
  EnsureInitialized(length);

  for (int i = 0; i < length_; i++) {
    GetOrCreate<IT>(i)->ReadFrom(reader);
  }
}


template <typename T>
template <typename IT>
void List<T>::ReadFromStatic(Reader* reader) {
  TRACE_READ_OFFSET();
  int length = reader->ReadListLength();
  EnsureInitialized(length);

  for (int i = 0; i < length_; i++) {
    ASSERT(array_[i] == NULL);
    array_[i] = IT::ReadFrom(reader);
  }
}


template <typename T>
void List<T>::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();

  // NOTE: We only support dense lists.
  writer->WriteListLength(length_);
  for (int i = 0; i < length_; i++) {
    T* object = array_[i];
    ASSERT(object != NULL);
    object->WriteTo(writer);
  }
}


template <typename T>
template <typename IT>
void List<T>::WriteToStatic(Writer* writer) {
  TRACE_WRITE_OFFSET();

  // NOTE: We only support dense lists.
  writer->WriteListLength(length_);
  for (int i = 0; i < length_; i++) {
    T* object = array_[i];
    ASSERT(object != NULL);
    IT::WriteTo(writer, object);
  }
}


void TypeParameterList::ReadFrom(Reader* reader) {
  // It is possible for the bound of the first type parameter to refer to
  // the second type parameter. This means we need to create [TypeParameter]
  // objects before reading the bounds.
  int length = reader->ReadListLength();
  EnsureInitialized(length);

  // Make all [TypeParameter]s available in scope.
  for (int i = 0; i < length; i++) {
    TypeParameter* parameter = (*this)[i] = new TypeParameter();
    reader->helper()->type_parameters().Push(parameter);
  }

  // Read all [TypeParameter]s and their bounds.
  for (int i = 0; i < length; i++) {
    (*this)[i]->ReadFrom(reader);
  }
}


void TypeParameterList::WriteTo(Writer* writer) {
  writer->WriteListLength(length());

  // Make all [TypeParameter]s available in scope.
  for (int i = 0; i < length(); i++) {
    TypeParameter* parameter = (*this)[i];
    writer->helper()->type_parameters().Push(parameter);
  }

  // Write all [TypeParameter]s and their bounds.
  for (int i = 0; i < length(); i++) {
    TypeParameter* parameter = (*this)[i];
    parameter->WriteTo(writer);
  }
}


template <typename A, typename B>
Tuple<A, B>* Tuple<A, B>::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  A* first = A::ReadFrom(reader);
  B* second = B::ReadFrom(reader);
  return new Tuple<A, B>(first, second);
}


template <typename A, typename B>
void Tuple<A, B>::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  first_->WriteTo(writer);
  second_->WriteTo(writer);
}


template <typename B, typename S>
class DowncastReader {
 public:
  static S* ReadFrom(Reader* reader) {
    TRACE_READ_OFFSET();
    return S::Cast(B::ReadFrom(reader));
  }
};


class StringImpl {
 public:
  static String* ReadFrom(Reader* reader) {
    TRACE_READ_OFFSET();
    return String::ReadFromImpl(reader);
  }

  static void WriteTo(Writer* writer, String* string) {
    TRACE_WRITE_OFFSET();
    string->WriteToImpl(writer);
  }
};


class VariableDeclarationImpl {
 public:
  static VariableDeclaration* ReadFrom(Reader* reader) {
    TRACE_READ_OFFSET();
    return VariableDeclaration::ReadFromImpl(reader);
  }

  static void WriteTo(Writer* writer, VariableDeclaration* d) {
    TRACE_WRITE_OFFSET();
    d->WriteToImpl(writer);
  }
};


String* String::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return Reference::ReadStringFrom(reader);
}


String* String::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  uint32_t bytes = reader->ReadUInt();
  String* string = new String(reader->Consume(bytes), bytes);
  return string;
}


void String::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  Reference::WriteStringTo(writer, this);
}


void String::WriteToImpl(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteUInt(size_);
  writer->WriteBytes(buffer_, size_);
}


void StringTable::ReadFrom(Reader* reader) {
  strings_.ReadFromStatic<StringImpl>(reader);
}


void StringTable::WriteTo(Writer* writer) {
  strings_.WriteToStatic<StringImpl>(writer);

  // Build up the "String* -> index" table.
  WriterHelper* helper = writer->helper();
  for (int i = 0; i < strings_.length(); i++) {
    helper->strings().Push(strings_[i]);
  }
}


void LineStartingTable::ReadFrom(Reader* reader) {
  size_ = reader->helper()->program()->source_uri_table().strings().length();
  values_ = new intptr_t*[size_];
  for (intptr_t i = 0; i < size_; ++i) {
    intptr_t line_count = reader->ReadUInt();
    intptr_t* line_starts = new intptr_t[line_count + 1];
    line_starts[0] = line_count;
    intptr_t previous_line_start = 0;
    for (intptr_t j = 0; j < line_count; ++j) {
      intptr_t line_start = reader->ReadUInt() + previous_line_start;
      line_starts[j + 1] = line_start;
      previous_line_start = line_start;
    }
    values_[i] = line_starts;
  }
}


void LineStartingTable::WriteTo(Writer* writer) {
  for (intptr_t i = 0; i < size_; ++i) {
    intptr_t* line_starts = values_[i];
    intptr_t line_count = line_starts[0];
    writer->WriteUInt(line_count);

    intptr_t previous_line_start = 0;
    for (intptr_t j = 0; j < line_count; ++j) {
      intptr_t line_start = line_starts[j + 1];
      writer->WriteUInt(line_start - previous_line_start);
      previous_line_start = line_start;
    }
  }
}


Library* Library::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  int flags = reader->ReadFlags();
  ASSERT(flags == 0);  // external libraries not supported
  name_ = Reference::ReadStringFrom(reader);
  import_uri_ = Reference::ReadStringFrom(reader);
  source_uri_index_ = reader->ReadUInt();

  int num_classes = reader->ReadUInt();
  classes().EnsureInitialized(num_classes);
  for (int i = 0; i < num_classes; i++) {
    Tag tag = reader->ReadTag();
    if (tag == kNormalClass) {
      NormalClass* klass = classes().GetOrCreate<NormalClass>(i, this);
      klass->ReadFrom(reader);
    } else {
      ASSERT(tag == kMixinClass);
      MixinClass* klass = classes().GetOrCreate<MixinClass>(i, this);
      klass->ReadFrom(reader);
    }
  }

  fields().ReadFrom<Field>(reader, this);
  procedures().ReadFrom<Procedure>(reader, this);
  return this;
}


void Library::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  name_->WriteTo(writer);
  import_uri_->WriteTo(writer);
  writer->WriteUInt(source_uri_index_);

  writer->WriteUInt(classes_.length());
  for (int i = 0; i < classes_.length(); i++) {
    Class* klass = classes_[i];
    if (klass->IsNormalClass()) {
      writer->WriteTag(kNormalClass);
      NormalClass::Cast(klass)->WriteTo(writer);
    } else {
      writer->WriteTag(kMixinClass);
      MixinClass::Cast(klass)->WriteTo(writer);
    }
  }
  fields().WriteTo(writer);
  procedures().WriteTo(writer);
}


Class* Class::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();

  is_abstract_ = reader->ReadBool();
  name_ = Reference::ReadStringFrom(reader);
  source_uri_index_ = reader->ReadUInt();
  annotations_.ReadFromStatic<Expression>(reader);

  return this;
}


void Class::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteBool(is_abstract_);
  name_->WriteTo(writer);
  writer->WriteUInt(source_uri_index_);
  annotations_.WriteTo(writer);
}


NormalClass* NormalClass::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Class::ReadFrom(reader);
  TypeParameterScope<ReaderHelper> scope(reader->helper());

  type_parameters_.ReadFrom(reader);
  DartType* type = reader->ReadOptional<DartType>();

  super_class_ = InterfaceType::Cast(type);
  implemented_classes_.ReadFromStatic<DowncastReader<DartType, InterfaceType> >(
      reader);
  fields_.ReadFrom<Field>(reader, this);
  constructors_.ReadFrom<Constructor>(reader, this);
  procedures_.ReadFrom<Procedure>(reader, this);

  return this;
}


void NormalClass::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  Class::WriteTo(writer);
  TypeParameterScope<WriterHelper> scope(writer->helper());

  type_parameters().WriteTo(writer);
  writer->WriteOptional<DartType>(super_class_);
  implemented_classes().WriteTo(writer);
  fields_.WriteTo(writer);
  constructors_.WriteTo(writer);
  procedures_.WriteTo(writer);
}


MixinClass* MixinClass::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TypeParameterScope<ReaderHelper> scope(reader->helper());

  Class::ReadFrom(reader);
  type_parameters_.ReadFrom(reader);
  first_ = InterfaceType::Cast(DartType::ReadFrom(reader));
  second_ = InterfaceType::Cast(DartType::ReadFrom(reader));
  implemented_classes_.ReadFromStatic<DowncastReader<DartType, InterfaceType> >(
      reader);
  constructors_.ReadFrom<Constructor>(reader, this);
  return this;
}


void MixinClass::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  TypeParameterScope<WriterHelper> scope(writer->helper());

  Class::WriteTo(writer);
  type_parameters_.WriteTo(writer);
  first_->WriteTo(writer);
  second_->WriteTo(writer);
  implemented_classes_.WriteTo(writer);
  constructors_.WriteTo(writer);
}


Member* Reference::ReadMemberFrom(Reader* reader, bool allow_null) {
  TRACE_READ_OFFSET();

  Program* program = reader->helper()->program();
  Tag tag = reader->ReadTag();
  switch (tag) {
    case kLibraryFieldReference: {
      int library_idx = reader->ReadUInt();
      int field_idx = reader->ReadUInt();
      Library* library = program->libraries().GetOrCreate<Library>(library_idx);
      return library->fields().GetOrCreate<Field>(field_idx, library);
    }
    case kLibraryProcedureReference: {
      int library_idx = reader->ReadUInt();
      int procedure_idx = reader->ReadUInt();
      Library* library = program->libraries().GetOrCreate<Library>(library_idx);
      return library->procedures().GetOrCreate<Procedure>(procedure_idx,
                                                          library);
    }
    case kClassFieldReference:
    case kClassConstructorReference:
    case kClassProcedureReference: {
      Class* klass = Reference::ReadClassFrom(reader);
      if (tag == kClassFieldReference) {
        int field_idx = reader->ReadUInt();
        return klass->fields().GetOrCreate<Field>(field_idx, klass);
      } else if (tag == kClassConstructorReference) {
        int constructor_idx = reader->ReadUInt();
        return klass->constructors().GetOrCreate<Constructor>(constructor_idx,
                                                              klass);
      } else {
        ASSERT(tag == kClassProcedureReference);
        int procedure_idx = reader->ReadUInt();
        return klass->procedures().GetOrCreate<Procedure>(procedure_idx, klass);
      }
    }
    case kNullReference:
      if (allow_null) {
        return NULL;
      } else {
        FATAL("Expected a valid member reference, but got `null`");
      }
    default:
      UNREACHABLE();
      break;
  }

  UNREACHABLE();
  return NULL;
}


void Reference::WriteMemberTo(Writer* writer, Member* member, bool allow_null) {
  TRACE_WRITE_OFFSET();
  if (member == NULL) {
    if (allow_null) {
      writer->WriteTag(kNullReference);
      return;
    } else {
      FATAL("Expected a valid member reference but got `null`");
    }
  }
  TreeNode* node = member->parent();

  WriterHelper* helper = writer->helper();

  if (node->IsLibrary()) {
    Library* library = Library::Cast(node);
    if (member->IsField()) {
      Field* field = Field::Cast(member);
      writer->WriteTag(kLibraryFieldReference);
      writer->WriteUInt(helper->libraries().Lookup(library));
      writer->WriteUInt(helper->fields().Lookup(field));
    } else {
      Procedure* procedure = Procedure::Cast(member);
      writer->WriteTag(kLibraryProcedureReference);
      writer->WriteUInt(helper->libraries().Lookup(library));
      writer->WriteUInt(helper->procedures().Lookup(procedure));
    }
  } else {
    Class* klass = Class::Cast(node);

    if (member->IsField()) {
      Field* field = Field::Cast(member);
      writer->WriteTag(kClassFieldReference);
      Reference::WriteClassTo(writer, klass);
      writer->WriteUInt(helper->fields().Lookup(field));
    } else if (member->IsConstructor()) {
      Constructor* constructor = Constructor::Cast(member);
      writer->WriteTag(kClassConstructorReference);
      Reference::WriteClassTo(writer, klass);
      writer->WriteUInt(helper->constructors().Lookup(constructor));
    } else {
      Procedure* procedure = Procedure::Cast(member);
      writer->WriteTag(kClassProcedureReference);
      Reference::WriteClassTo(writer, klass);
      writer->WriteUInt(helper->procedures().Lookup(procedure));
    }
  }
}


Class* Reference::ReadClassFrom(Reader* reader, bool allow_null) {
  TRACE_READ_OFFSET();
  Program* program = reader->helper()->program();

  Tag klass_member_tag = reader->ReadTag();
  if (klass_member_tag == kNullReference) {
    if (allow_null) {
      return NULL;
    } else {
      FATAL("Expected a valid class reference but got `null`.");
    }
  }
  int library_idx = reader->ReadUInt();
  int class_idx = reader->ReadUInt();

  Library* library = program->libraries().GetOrCreate<Library>(library_idx);
  Class* klass;
  if (klass_member_tag == kNormalClassReference) {
    klass = library->classes().GetOrCreate<NormalClass>(class_idx, library);
  } else {
    ASSERT(klass_member_tag == kMixinClassReference);
    klass = library->classes().GetOrCreate<MixinClass>(class_idx, library);
  }
  return klass;
}


void Reference::WriteClassTo(Writer* writer, Class* klass, bool allow_null) {
  TRACE_WRITE_OFFSET();
  if (klass == NULL) {
    if (allow_null) {
      writer->WriteTag(kNullReference);
      return;
    } else {
      FATAL("Expected a valid class reference but got `null`.");
    }
  }
  if (klass->IsNormalClass()) {
    writer->WriteTag(kNormalClassReference);
  } else {
    ASSERT(klass->IsMixinClass());
    writer->WriteTag(kMixinClassReference);
  }

  writer->WriteUInt(writer->helper()->libraries().Lookup(klass->parent()));
  writer->WriteUInt(writer->helper()->classes().Lookup(klass));
}


String* Reference::ReadStringFrom(Reader* reader) {
  int index = reader->ReadUInt();
  return reader->helper()->program()->string_table().strings()[index];
}


void Reference::WriteStringTo(Writer* writer, String* string) {
  int index = writer->helper()->strings().Lookup(string);
  writer->WriteUInt(index);
}


Field* Field::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  ASSERT(tag == kField);

  position_ = reader->ReadPosition();
  flags_ = reader->ReadFlags();
  name_ = Name::ReadFrom(reader);
  source_uri_index_ = reader->ReadUInt();
  annotations_.ReadFromStatic<Expression>(reader);
  type_ = DartType::ReadFrom(reader);
  inferred_value_ = reader->ReadOptional<InferredValue>();
  initializer_ = reader->ReadOptional<Expression>();
  return this;
}


void Field::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kField);
  writer->WritePosition(position_);
  writer->WriteFlags(flags_);
  name_->WriteTo(writer);
  writer->WriteUInt(source_uri_index_);
  annotations_.WriteTo(writer);
  type_->WriteTo(writer);
  writer->WriteOptional<InferredValue>(inferred_value_);
  writer->WriteOptional<Expression>(initializer_);
}


Constructor* Constructor::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  ASSERT(tag == kConstructor);

  VariableScope<ReaderHelper> parameters(reader->helper());
  flags_ = reader->ReadFlags();
  name_ = Name::ReadFrom(reader);
  annotations_.ReadFromStatic<Expression>(reader);
  function_ = FunctionNode::ReadFrom(reader);
  initializers_.ReadFromStatic<Initializer>(reader);
  return this;
}


void Constructor::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kConstructor);

  VariableScope<WriterHelper> parameters(writer->helper());
  writer->WriteFlags(flags_);
  name_->WriteTo(writer);
  annotations_.WriteTo(writer);
  function_->WriteTo(writer);
  initializers_.WriteTo(writer);
}


Procedure* Procedure::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  ASSERT(tag == kProcedure);

  VariableScope<ReaderHelper> parameters(reader->helper());
  kind_ = static_cast<ProcedureKind>(reader->ReadByte());
  flags_ = reader->ReadFlags();
  name_ = Name::ReadFrom(reader);
  source_uri_index_ = reader->ReadUInt();
  annotations_.ReadFromStatic<Expression>(reader);
  function_ = reader->ReadOptional<FunctionNode>();
  return this;
}


void Procedure::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kProcedure);

  VariableScope<WriterHelper> parameters(writer->helper());
  writer->WriteByte(kind_);
  writer->WriteFlags(flags_);
  name_->WriteTo(writer);
  writer->WriteUInt(source_uri_index_);
  annotations_.WriteTo(writer);
  writer->WriteOptional<FunctionNode>(function_);
}


Initializer* Initializer::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  switch (tag) {
    case kInvalidInitializer:
      return InvalidInitializer::ReadFromImpl(reader);
    case kFieldInitializer:
      return FieldInitializer::ReadFromImpl(reader);
    case kSuperInitializer:
      return SuperInitializer::ReadFromImpl(reader);
    case kRedirectingInitializer:
      return RedirectingInitializer::ReadFromImpl(reader);
    case kLocalInitializer:
      return LocalInitializer::ReadFromImpl(reader);
    default:
      UNREACHABLE();
  }
  return NULL;
}


InvalidInitializer* InvalidInitializer::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  return new InvalidInitializer();
}


void InvalidInitializer::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kInvalidInitializer);
}


FieldInitializer* FieldInitializer::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  FieldInitializer* initializer = new FieldInitializer();
  initializer->field_ = Field::Cast(Reference::ReadMemberFrom(reader));
  initializer->value_ = Expression::ReadFrom(reader);
  return initializer;
}


void FieldInitializer::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kFieldInitializer);
  Reference::WriteMemberTo(writer, field_);
  value_->WriteTo(writer);
}


SuperInitializer* SuperInitializer::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  SuperInitializer* init = new SuperInitializer();
  init->target_ = Constructor::Cast(Reference::ReadMemberFrom(reader));
  init->arguments_ = Arguments::ReadFrom(reader);
  return init;
}


void SuperInitializer::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kSuperInitializer);
  Reference::WriteMemberTo(writer, target_);
  arguments_->WriteTo(writer);
}


RedirectingInitializer* RedirectingInitializer::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  RedirectingInitializer* init = new RedirectingInitializer();
  init->target_ = Constructor::Cast(Reference::ReadMemberFrom(reader));
  init->arguments_ = Arguments::ReadFrom(reader);
  return init;
}


void RedirectingInitializer::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kRedirectingInitializer);
  Reference::WriteMemberTo(writer, target_);
  arguments_->WriteTo(writer);
}


LocalInitializer* LocalInitializer::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  LocalInitializer* init = new LocalInitializer();
  init->variable_ = VariableDeclaration::ReadFromImpl(reader);
  return init;
}


void LocalInitializer::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kLocalInitializer);
  variable_->WriteToImpl(writer);
}


Expression* Expression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  uint8_t payload = 0;
  Tag tag = reader->ReadTag(&payload);
  switch (tag) {
    case kInvalidExpression:
      return InvalidExpression::ReadFrom(reader);
    case kVariableGet:
      return VariableGet::ReadFrom(reader);
    case kSpecializedVariableGet:
      return VariableGet::ReadFrom(reader, payload);
    case kVariableSet:
      return VariableSet::ReadFrom(reader);
    case kSpecializedVariableSet:
      return VariableSet::ReadFrom(reader, payload);
    case kPropertyGet:
      return PropertyGet::ReadFrom(reader);
    case kPropertySet:
      return PropertySet::ReadFrom(reader);
    case kDirectPropertyGet:
      return DirectPropertyGet::ReadFrom(reader);
    case kDirectPropertySet:
      return DirectPropertySet::ReadFrom(reader);
    case kStaticGet:
      return StaticGet::ReadFrom(reader);
    case kStaticSet:
      return StaticSet::ReadFrom(reader);
    case kMethodInvocation:
      return MethodInvocation::ReadFrom(reader);
    case kDirectMethodInvocation:
      return DirectMethodInvocation::ReadFrom(reader);
    case kStaticInvocation:
      return StaticInvocation::ReadFrom(reader, false);
    case kConstStaticInvocation:
      return StaticInvocation::ReadFrom(reader, true);
    case kConstructorInvocation:
      return ConstructorInvocation::ReadFrom(reader, false);
    case kConstConstructorInvocation:
      return ConstructorInvocation::ReadFrom(reader, true);
    case kNot:
      return Not::ReadFrom(reader);
    case kLogicalExpression:
      return LogicalExpression::ReadFrom(reader);
    case kConditionalExpression:
      return ConditionalExpression::ReadFrom(reader);
    case kStringConcatenation:
      return StringConcatenation::ReadFrom(reader);
    case kIsExpression:
      return IsExpression::ReadFrom(reader);
    case kAsExpression:
      return AsExpression::ReadFrom(reader);
    case kSymbolLiteral:
      return SymbolLiteral::ReadFrom(reader);
    case kTypeLiteral:
      return TypeLiteral::ReadFrom(reader);
    case kThisExpression:
      return ThisExpression::ReadFrom(reader);
    case kRethrow:
      return Rethrow::ReadFrom(reader);
    case kThrow:
      return Throw::ReadFrom(reader);
    case kListLiteral:
      return ListLiteral::ReadFrom(reader, false);
    case kConstListLiteral:
      return ListLiteral::ReadFrom(reader, true);
    case kMapLiteral:
      return MapLiteral::ReadFrom(reader, false);
    case kConstMapLiteral:
      return MapLiteral::ReadFrom(reader, true);
    case kAwaitExpression:
      return AwaitExpression::ReadFrom(reader);
    case kFunctionExpression:
      return FunctionExpression::ReadFrom(reader);
    case kLet:
      return Let::ReadFrom(reader);
    case kBlockExpression:
      return BlockExpression::ReadFrom(reader);
    case kBigIntLiteral:
      return BigintLiteral::ReadFrom(reader);
    case kStringLiteral:
      return StringLiteral::ReadFrom(reader);
    case kSpecialIntLiteral:
      return IntLiteral::ReadFrom(reader, payload);
    case kNegativeIntLiteral:
      return IntLiteral::ReadFrom(reader, true);
    case kPositiveIntLiteral:
      return IntLiteral::ReadFrom(reader, false);
    case kDoubleLiteral:
      return DoubleLiteral::ReadFrom(reader);
    case kTrueLiteral:
      return BoolLiteral::ReadFrom(reader, true);
    case kFalseLiteral:
      return BoolLiteral::ReadFrom(reader, false);
    case kNullLiteral:
      return NullLiteral::ReadFrom(reader);
    default:
      UNREACHABLE();
  }
  return NULL;
}


InvalidExpression* InvalidExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new InvalidExpression();
}


void InvalidExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kInvalidExpression);
}


VariableGet* VariableGet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableGet* get = new VariableGet();
  get->variable_ = reader->helper()->variables().Lookup(reader->ReadUInt());
  reader->ReadOptional<DartType>();  // Unused promoted type.
  return get;
}


VariableGet* VariableGet::ReadFrom(Reader* reader, uint8_t payload) {
  TRACE_READ_OFFSET();
  VariableGet* get = new VariableGet();
  get->variable_ = reader->helper()->variables().Lookup(payload);
  return get;
}


void VariableGet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  int index = writer->helper()->variables().Lookup(variable_);
  if ((index & kSpecializedPayloadMask) == index) {
    writer->WriteTag(kSpecializedVariableGet, static_cast<uint8_t>(index));
  } else {
    writer->WriteTag(kVariableGet);
    writer->WriteUInt(index);
    writer->WriteOptional<DartType>(NULL);
  }
}


VariableSet* VariableSet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableSet* set = new VariableSet();
  set->variable_ = reader->helper()->variables().Lookup(reader->ReadUInt());
  set->expression_ = Expression::ReadFrom(reader);
  return set;
}


VariableSet* VariableSet::ReadFrom(Reader* reader, uint8_t payload) {
  TRACE_READ_OFFSET();
  VariableSet* set = new VariableSet();
  set->variable_ = reader->helper()->variables().Lookup(payload);
  set->expression_ = Expression::ReadFrom(reader);
  return set;
}


void VariableSet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  int index = writer->helper()->variables().Lookup(variable_);
  if ((index & kSpecializedPayloadMask) == index) {
    writer->WriteTag(kSpecializedVariableSet, static_cast<uint8_t>(index));
  } else {
    writer->WriteTag(kVariableSet);
    writer->WriteUInt(index);
  }
  expression_->WriteTo(writer);
}


PropertyGet* PropertyGet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  PropertyGet* get = new PropertyGet();
  get->position_ = reader->ReadPosition();
  get->receiver_ = Expression::ReadFrom(reader);
  get->name_ = Name::ReadFrom(reader);
  get->interfaceTarget_ = Reference::ReadMemberFrom(reader, true);
  return get;
}


void PropertyGet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kPropertyGet);
  writer->WritePosition(position_);
  receiver_->WriteTo(writer);
  name_->WriteTo(writer);
  Reference::WriteMemberTo(writer, interfaceTarget_, true);
}


PropertySet* PropertySet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  PropertySet* set = new PropertySet();
  set->position_ = reader->ReadPosition();
  set->receiver_ = Expression::ReadFrom(reader);
  set->name_ = Name::ReadFrom(reader);
  set->value_ = Expression::ReadFrom(reader);
  set->interfaceTarget_ = Reference::ReadMemberFrom(reader, true);
  return set;
}


void PropertySet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kPropertySet);
  writer->WritePosition(position_);
  receiver_->WriteTo(writer);
  name_->WriteTo(writer);
  value_->WriteTo(writer);
  Reference::WriteMemberTo(writer, interfaceTarget_, true);
}


DirectPropertyGet* DirectPropertyGet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  DirectPropertyGet* get = new DirectPropertyGet();
  get->receiver_ = Expression::ReadFrom(reader);
  get->target_ = Reference::ReadMemberFrom(reader);
  return get;
}


void DirectPropertyGet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDirectPropertyGet);
  receiver_->WriteTo(writer);
  Reference::WriteMemberTo(writer, target_);
}


DirectPropertySet* DirectPropertySet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  DirectPropertySet* set = new DirectPropertySet();
  set->receiver_ = Expression::ReadFrom(reader);
  set->target_ = Reference::ReadMemberFrom(reader);
  set->value_ = Expression::ReadFrom(reader);
  return set;
}


void DirectPropertySet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDirectPropertySet);
  receiver_->WriteTo(writer);
  Reference::WriteMemberTo(writer, target_);
  value_->WriteTo(writer);
}


StaticGet* StaticGet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  StaticGet* get = new StaticGet();
  get->position_ = reader->ReadPosition();
  get->target_ = Reference::ReadMemberFrom(reader);
  return get;
}


void StaticGet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kStaticGet);
  writer->WritePosition(position_);
  Reference::WriteMemberTo(writer, target_);
}


StaticSet* StaticSet::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  StaticSet* set = new StaticSet();
  set->target_ = Reference::ReadMemberFrom(reader);
  set->expression_ = Expression::ReadFrom(reader);
  return set;
}


void StaticSet::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kStaticSet);
  Reference::WriteMemberTo(writer, target_);
  expression_->WriteTo(writer);
}


Arguments* Arguments::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Arguments* arguments = new Arguments();
  arguments->types().ReadFromStatic<DartType>(reader);
  arguments->positional().ReadFromStatic<Expression>(reader);
  arguments->named().ReadFromStatic<NamedExpression>(reader);
  return arguments;
}


void Arguments::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  types().WriteTo(writer);
  positional().WriteTo(writer);
  named().WriteTo(writer);
}


NamedExpression* NamedExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  String* name = Reference::ReadStringFrom(reader);
  Expression* expression = Expression::ReadFrom(reader);
  return new NamedExpression(name, expression);
}


void NamedExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  name_->WriteTo(writer);
  expression_->WriteTo(writer);
}


MethodInvocation* MethodInvocation::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  MethodInvocation* invocation = new MethodInvocation();
  invocation->position_ = reader->ReadPosition();
  invocation->receiver_ = Expression::ReadFrom(reader);
  invocation->name_ = Name::ReadFrom(reader);
  invocation->arguments_ = Arguments::ReadFrom(reader);
  invocation->interfaceTarget_ = Reference::ReadMemberFrom(reader, true);
  return invocation;
}


void MethodInvocation::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kMethodInvocation);
  writer->WritePosition(position_);
  receiver_->WriteTo(writer);
  name_->WriteTo(writer);
  arguments_->WriteTo(writer);
  Reference::WriteMemberTo(writer, interfaceTarget_, true);
}


DirectMethodInvocation* DirectMethodInvocation::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  DirectMethodInvocation* invocation = new DirectMethodInvocation();
  invocation->receiver_ = Expression::ReadFrom(reader);
  invocation->target_ = Procedure::Cast(Reference::ReadMemberFrom(reader));
  invocation->arguments_ = Arguments::ReadFrom(reader);
  return invocation;
}


void DirectMethodInvocation::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDirectMethodInvocation);
  receiver_->WriteTo(writer);
  Reference::WriteMemberTo(writer, target_);
  arguments_->WriteTo(writer);
}


StaticInvocation* StaticInvocation::ReadFrom(Reader* reader, bool is_const) {
  TRACE_READ_OFFSET();
  StaticInvocation* invocation = new StaticInvocation();
  invocation->is_const_ = is_const;
  invocation->position_ = reader->ReadPosition();
  invocation->procedure_ = Procedure::Cast(Reference::ReadMemberFrom(reader));
  invocation->arguments_ = Arguments::ReadFrom(reader);
  return invocation;
}


void StaticInvocation::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(is_const_ ? kConstStaticInvocation : kStaticInvocation);
  writer->WritePosition(position_);
  Reference::WriteMemberTo(writer, procedure_);
  arguments_->WriteTo(writer);
}


ConstructorInvocation* ConstructorInvocation::ReadFrom(Reader* reader,
                                                       bool is_const) {
  TRACE_READ_OFFSET();
  ConstructorInvocation* invocation = new ConstructorInvocation();
  invocation->is_const_ = is_const;
  invocation->position_ = reader->ReadPosition();
  invocation->target_ = Constructor::Cast(Reference::ReadMemberFrom(reader));
  invocation->arguments_ = Arguments::ReadFrom(reader);
  return invocation;
}


void ConstructorInvocation::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(is_const_ ? kConstConstructorInvocation
                             : kConstructorInvocation);
  writer->WritePosition(position_);
  Reference::WriteMemberTo(writer, target_);
  arguments_->WriteTo(writer);
}


Not* Not::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Not* n = new Not();
  n->expression_ = Expression::ReadFrom(reader);
  return n;
}


void Not::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kNot);
  expression_->WriteTo(writer);
}


LogicalExpression* LogicalExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  LogicalExpression* expr = new LogicalExpression();
  expr->left_ = Expression::ReadFrom(reader);
  expr->operator_ = static_cast<Operator>(reader->ReadByte());
  expr->right_ = Expression::ReadFrom(reader);
  return expr;
}


void LogicalExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kLogicalExpression);
  left_->WriteTo(writer);
  writer->WriteByte(operator_);
  right_->WriteTo(writer);
}


ConditionalExpression* ConditionalExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  ConditionalExpression* expr = new ConditionalExpression();
  expr->condition_ = Expression::ReadFrom(reader);
  expr->then_ = Expression::ReadFrom(reader);
  expr->otherwise_ = Expression::ReadFrom(reader);
  reader->ReadOptional<DartType>();  // Unused static type.
  return expr;
}


void ConditionalExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kConditionalExpression);
  condition_->WriteTo(writer);
  then_->WriteTo(writer);
  otherwise_->WriteTo(writer);
  writer->WriteOptional<DartType>(NULL);  // Unused static type.
}


StringConcatenation* StringConcatenation::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  StringConcatenation* concat = new StringConcatenation();
  concat->expressions_.ReadFromStatic<Expression>(reader);
  return concat;
}


void StringConcatenation::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kStringConcatenation);
  expressions_.WriteTo(writer);
}


IsExpression* IsExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  IsExpression* expr = new IsExpression();
  expr->operand_ = Expression::ReadFrom(reader);
  expr->type_ = DartType::ReadFrom(reader);
  return expr;
}


void IsExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kIsExpression);
  operand_->WriteTo(writer);
  type_->WriteTo(writer);
}


AsExpression* AsExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  AsExpression* expr = new AsExpression();
  expr->operand_ = Expression::ReadFrom(reader);
  expr->type_ = DartType::ReadFrom(reader);
  return expr;
}


void AsExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kAsExpression);
  operand_->WriteTo(writer);
  type_->WriteTo(writer);
}


StringLiteral* StringLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new StringLiteral(Reference::ReadStringFrom(reader));
}


void StringLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kStringLiteral);
  value_->WriteTo(writer);
}


BigintLiteral* BigintLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new BigintLiteral(Reference::ReadStringFrom(reader));
}


void BigintLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kBigIntLiteral);
  value_->WriteTo(writer);
}


IntLiteral* IntLiteral::ReadFrom(Reader* reader, bool is_negative) {
  TRACE_READ_OFFSET();
  IntLiteral* literal = new IntLiteral();
  literal->value_ = is_negative ? -static_cast<int64_t>(reader->ReadUInt())
                                : reader->ReadUInt();
  return literal;
}


IntLiteral* IntLiteral::ReadFrom(Reader* reader, uint8_t payload) {
  TRACE_READ_OFFSET();
  IntLiteral* literal = new IntLiteral();
  literal->value_ = static_cast<int32_t>(payload) - SpecializedIntLiteralBias;
  return literal;
}


void IntLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  int64_t payload = value_ + SpecializedIntLiteralBias;
  if ((payload & kSpecializedPayloadMask) == payload) {
    writer->WriteTag(kSpecialIntLiteral, static_cast<uint8_t>(payload));
  } else {
    writer->WriteTag(value_ < 0 ? kNegativeIntLiteral : kPositiveIntLiteral);
    writer->WriteUInt(static_cast<uint32_t>(value_ < 0 ? -value_ : value_));
  }
}


DoubleLiteral* DoubleLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  DoubleLiteral* literal = new DoubleLiteral();
  literal->value_ = Reference::ReadStringFrom(reader);
  return literal;
}


void DoubleLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDoubleLiteral);
  value_->WriteTo(writer);
}


BoolLiteral* BoolLiteral::ReadFrom(Reader* reader, bool value) {
  TRACE_READ_OFFSET();
  BoolLiteral* lit = new BoolLiteral();
  lit->value_ = value;
  return lit;
}


void BoolLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(value_ ? kTrueLiteral : kFalseLiteral);
}


NullLiteral* NullLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new NullLiteral();
}


void NullLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kNullLiteral);
}


SymbolLiteral* SymbolLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  SymbolLiteral* lit = new SymbolLiteral();
  lit->value_ = Reference::ReadStringFrom(reader);
  return lit;
}


void SymbolLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kSymbolLiteral);
  value_->WriteTo(writer);
}


TypeLiteral* TypeLiteral::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TypeLiteral* literal = new TypeLiteral();
  literal->type_ = DartType::ReadFrom(reader);
  return literal;
}


void TypeLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kTypeLiteral);
  type_->WriteTo(writer);
}


ThisExpression* ThisExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new ThisExpression();
}


void ThisExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kThisExpression);
}


Rethrow* Rethrow::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new Rethrow();
}


void Rethrow::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kRethrow);
}


Throw* Throw::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Throw* t = new Throw();
  t->position_ = reader->ReadPosition();
  t->expression_ = Expression::ReadFrom(reader);
  return t;
}


void Throw::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kThrow);
  writer->WritePosition(position_);
  expression_->WriteTo(writer);
}


ListLiteral* ListLiteral::ReadFrom(Reader* reader, bool is_const) {
  TRACE_READ_OFFSET();
  ListLiteral* literal = new ListLiteral();
  literal->is_const_ = is_const;
  literal->type_ = DartType::ReadFrom(reader);
  literal->expressions_.ReadFromStatic<Expression>(reader);
  return literal;
}


void ListLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(is_const_ ? kConstListLiteral : kListLiteral);
  type_->WriteTo(writer);
  expressions_.WriteTo(writer);
}


MapLiteral* MapLiteral::ReadFrom(Reader* reader, bool is_const) {
  TRACE_READ_OFFSET();
  MapLiteral* literal = new MapLiteral();
  literal->is_const_ = is_const;
  literal->key_type_ = DartType::ReadFrom(reader);
  literal->value_type_ = DartType::ReadFrom(reader);
  literal->entries_.ReadFromStatic<MapEntry>(reader);
  return literal;
}


void MapLiteral::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(is_const_ ? kConstMapLiteral : kMapLiteral);
  key_type_->WriteTo(writer);
  value_type_->WriteTo(writer);
  entries_.WriteTo(writer);
}


MapEntry* MapEntry::ReadFrom(Reader* reader) {
  MapEntry* entry = new MapEntry();
  entry->key_ = Expression::ReadFrom(reader);
  entry->value_ = Expression::ReadFrom(reader);
  return entry;
}


void MapEntry::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  key_->WriteTo(writer);
  value_->WriteTo(writer);
}


AwaitExpression* AwaitExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  AwaitExpression* await = new AwaitExpression();
  await->operand_ = Expression::ReadFrom(reader);
  return await;
}


void AwaitExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kAwaitExpression);
  operand_->WriteTo(writer);
}


FunctionExpression* FunctionExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> parameters(reader->helper());
  FunctionExpression* expr = new FunctionExpression();
  expr->function_ = FunctionNode::ReadFrom(reader);
  return expr;
}


void FunctionExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  VariableScope<WriterHelper> parameters(writer->helper());
  writer->WriteTag(kFunctionExpression);
  function_->WriteTo(writer);
}


Let* Let::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> vars(reader->helper());
  Let* let = new Let();
  let->variable_ = VariableDeclaration::ReadFromImpl(reader);
  let->body_ = Expression::ReadFrom(reader);
  return let;
}


void Let::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  VariableScope<WriterHelper> vars(writer->helper());
  writer->WriteTag(kLet);
  variable_->WriteToImpl(writer);
  body_->WriteTo(writer);
}


BlockExpression* BlockExpression::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  BlockExpression* be = new BlockExpression();
  be->body_ = Block::ReadFromImpl(reader);
  be->value_ = Expression::ReadFrom(reader);
  return be;
}


void BlockExpression::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kBlockExpression);
  body_->WriteToImpl(writer);
  value_->WriteTo(writer);
}


Statement* Statement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  switch (tag) {
    case kInvalidStatement:
      return InvalidStatement::ReadFrom(reader);
    case kExpressionStatement:
      return ExpressionStatement::ReadFrom(reader);
    case kBlock:
      return Block::ReadFromImpl(reader);
    case kEmptyStatement:
      return EmptyStatement::ReadFrom(reader);
    case kAssertStatement:
      return AssertStatement::ReadFrom(reader);
    case kLabeledStatement:
      return LabeledStatement::ReadFrom(reader);
    case kBreakStatement:
      return BreakStatement::ReadFrom(reader);
    case kWhileStatement:
      return WhileStatement::ReadFrom(reader);
    case kDoStatement:
      return DoStatement::ReadFrom(reader);
    case kForStatement:
      return ForStatement::ReadFrom(reader);
    case kForInStatement:
      return ForInStatement::ReadFrom(reader, false);
    case kAsyncForInStatement:
      return ForInStatement::ReadFrom(reader, true);
    case kSwitchStatement:
      return SwitchStatement::ReadFrom(reader);
    case kContinueSwitchStatement:
      return ContinueSwitchStatement::ReadFrom(reader);
    case kIfStatement:
      return IfStatement::ReadFrom(reader);
    case kReturnStatement:
      return ReturnStatement::ReadFrom(reader);
    case kTryCatch:
      return TryCatch::ReadFrom(reader);
    case kTryFinally:
      return TryFinally::ReadFrom(reader);
    case kYieldStatement:
      return YieldStatement::ReadFrom(reader);
    case kVariableDeclaration:
      return VariableDeclaration::ReadFromImpl(reader);
    case kFunctionDeclaration:
      return FunctionDeclaration::ReadFrom(reader);
    default:
      UNREACHABLE();
  }
  return NULL;
}


InvalidStatement* InvalidStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new InvalidStatement();
}


void InvalidStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kInvalidStatement);
}


ExpressionStatement* ExpressionStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new ExpressionStatement(Expression::ReadFrom(reader));
}


void ExpressionStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kExpressionStatement);
  expression_->WriteTo(writer);
}


Block* Block::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> vars(reader->helper());
  Block* block = new Block();
  block->statements().ReadFromStatic<Statement>(reader);
  return block;
}


void Block::WriteTo(Writer* writer) {
  writer->WriteTag(kBlock);
  WriteToImpl(writer);
}


void Block::WriteToImpl(Writer* writer) {
  TRACE_WRITE_OFFSET();
  VariableScope<WriterHelper> vars(writer->helper());
  statements_.WriteTo(writer);
}


EmptyStatement* EmptyStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new EmptyStatement();
}


void EmptyStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kEmptyStatement);
}


AssertStatement* AssertStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  AssertStatement* stmt = new AssertStatement();
  stmt->condition_ = Expression::ReadFrom(reader);
  stmt->message_ = reader->ReadOptional<Expression>();
  return stmt;
}


void AssertStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kAssertStatement);
  condition_->WriteTo(writer);
  writer->WriteOptional<Expression>(message_);
}


LabeledStatement* LabeledStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  LabeledStatement* stmt = new LabeledStatement();
  reader->helper()->labels()->Push(stmt);
  stmt->body_ = Statement::ReadFrom(reader);
  reader->helper()->labels()->Pop(stmt);
  return stmt;
}


void LabeledStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kLabeledStatement);
  writer->helper()->labels()->Push(this);
  body_->WriteTo(writer);
  writer->helper()->labels()->Pop(this);
}


BreakStatement* BreakStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  BreakStatement* stmt = new BreakStatement();
  stmt->target_ = reader->helper()->labels()->Lookup(reader->ReadUInt());
  return stmt;
}


void BreakStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kBreakStatement);
  writer->WriteUInt(writer->helper()->labels()->Lookup(target_));
}


WhileStatement* WhileStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  WhileStatement* stmt = new WhileStatement();
  stmt->condition_ = Expression::ReadFrom(reader);
  stmt->body_ = Statement::ReadFrom(reader);
  return stmt;
}


void WhileStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kWhileStatement);
  condition_->WriteTo(writer);
  body_->WriteTo(writer);
}


DoStatement* DoStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  DoStatement* dostmt = new DoStatement();
  dostmt->body_ = Statement::ReadFrom(reader);
  dostmt->condition_ = Expression::ReadFrom(reader);
  return dostmt;
}


void DoStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDoStatement);
  body_->WriteTo(writer);
  condition_->WriteTo(writer);
}


ForStatement* ForStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> vars(reader->helper());
  ForStatement* forstmt = new ForStatement();
  forstmt->variables_.ReadFromStatic<VariableDeclarationImpl>(reader);
  forstmt->condition_ = reader->ReadOptional<Expression>();
  forstmt->updates_.ReadFromStatic<Expression>(reader);
  forstmt->body_ = Statement::ReadFrom(reader);
  return forstmt;
}


void ForStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kForStatement);
  VariableScope<WriterHelper> vars(writer->helper());
  variables_.WriteToStatic<VariableDeclarationImpl>(writer);
  writer->WriteOptional<Expression>(condition_);
  updates_.WriteTo(writer);
  body_->WriteTo(writer);
}


ForInStatement* ForInStatement::ReadFrom(Reader* reader, bool is_async) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> vars(reader->helper());
  ForInStatement* forinstmt = new ForInStatement();
  forinstmt->is_async_ = is_async;
  forinstmt->variable_ = VariableDeclaration::ReadFromImpl(reader);
  forinstmt->iterable_ = Expression::ReadFrom(reader);
  forinstmt->body_ = Statement::ReadFrom(reader);
  return forinstmt;
}


void ForInStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(is_async_ ? kAsyncForInStatement : kForInStatement);
  VariableScope<WriterHelper> vars(writer->helper());
  variable_->WriteToImpl(writer);
  iterable_->WriteTo(writer);
  body_->WriteTo(writer);
}


SwitchStatement* SwitchStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  SwitchCaseScope<ReaderHelper> scope(reader->helper());
  SwitchStatement* stmt = new SwitchStatement();
  stmt->condition_ = Expression::ReadFrom(reader);
  // We need to explicitly create empty [SwitchCase]s first in order to add them
  // to the [SwitchCaseScope]. This is necessary since a [Statement] in a switch
  // case can refer to one defined later on.
  int count = reader->ReadUInt();
  for (int i = 0; i < count; i++) {
    SwitchCase* sc = stmt->cases_.GetOrCreate<SwitchCase>(i);
    reader->helper()->switch_cases().Push(sc);
  }
  for (int i = 0; i < count; i++) {
    SwitchCase* sc = stmt->cases_[i];
    sc->ReadFrom(reader);
  }
  return stmt;
}


void SwitchStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  SwitchCaseScope<WriterHelper> scope(writer->helper());
  writer->WriteTag(kSwitchStatement);
  condition_->WriteTo(writer);
  for (int i = 0; i < cases_.length(); i++) {
    writer->helper()->switch_cases().Push(cases_[i]);
  }
  cases_.WriteTo(writer);
}


SwitchCase* SwitchCase::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  expressions_.ReadFromStatic<Expression>(reader);
  is_default_ = reader->ReadBool();
  body_ = Statement::ReadFrom(reader);
  return this;
}


void SwitchCase::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  expressions_.WriteTo(writer);
  writer->WriteBool(is_default_);
  body_->WriteTo(writer);
}


ContinueSwitchStatement* ContinueSwitchStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  ContinueSwitchStatement* stmt = new ContinueSwitchStatement();
  stmt->target_ = reader->helper()->switch_cases().Lookup(reader->ReadUInt());
  return stmt;
}


void ContinueSwitchStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kContinueSwitchStatement);
  writer->WriteUInt(writer->helper()->switch_cases().Lookup(target_));
}


IfStatement* IfStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  IfStatement* ifstmt = new IfStatement();
  ifstmt->condition_ = Expression::ReadFrom(reader);
  ifstmt->then_ = Statement::ReadFrom(reader);
  ifstmt->otherwise_ = Statement::ReadFrom(reader);
  return ifstmt;
}


void IfStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kIfStatement);
  condition_->WriteTo(writer);
  then_->WriteTo(writer);
  otherwise_->WriteTo(writer);
}


ReturnStatement* ReturnStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  ReturnStatement* ret = new ReturnStatement();
  ret->expression_ = reader->ReadOptional<Expression>();
  return ret;
}


void ReturnStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kReturnStatement);
  writer->WriteOptional<Expression>(expression_);
}


TryCatch* TryCatch::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TryCatch* tc = new TryCatch();
  tc->body_ = Statement::ReadFrom(reader);
  tc->catches_.ReadFromStatic<Catch>(reader);
  return tc;
}


void TryCatch::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kTryCatch);
  body_->WriteTo(writer);
  catches_.WriteTo(writer);
}


Catch* Catch::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableScope<ReaderHelper> vars(reader->helper());
  Catch* c = new Catch();
  c->guard_ = DartType::ReadFrom(reader);
  c->exception_ =
      reader->ReadOptional<VariableDeclaration, VariableDeclarationImpl>();
  c->stack_trace_ =
      reader->ReadOptional<VariableDeclaration, VariableDeclarationImpl>();
  c->body_ = Statement::ReadFrom(reader);
  return c;
}


void Catch::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  VariableScope<WriterHelper> vars(writer->helper());
  guard_->WriteTo(writer);
  writer->WriteOptionalStatic<VariableDeclaration, VariableDeclarationImpl>(
      exception_);
  writer->WriteOptionalStatic<VariableDeclaration, VariableDeclarationImpl>(
      stack_trace_);
  body_->WriteTo(writer);
}


TryFinally* TryFinally::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TryFinally* tf = new TryFinally();
  tf->body_ = Statement::ReadFrom(reader);
  tf->finalizer_ = Statement::ReadFrom(reader);
  return tf;
}


void TryFinally::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kTryFinally);
  body_->WriteTo(writer);
  finalizer_->WriteTo(writer);
}


YieldStatement* YieldStatement::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  YieldStatement* stmt = new YieldStatement();
  stmt->flags_ = reader->ReadByte();
  stmt->expression_ = Expression::ReadFrom(reader);
  return stmt;
}


void YieldStatement::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kYieldStatement);
  writer->WriteByte(flags_);
  expression_->WriteTo(writer);
}


VariableDeclaration* VariableDeclaration::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  ASSERT(tag == kVariableDeclaration);
  return VariableDeclaration::ReadFromImpl(reader);
}


VariableDeclaration* VariableDeclaration::ReadFromImpl(Reader* reader) {
  TRACE_READ_OFFSET();
  VariableDeclaration* decl = new VariableDeclaration();
  decl->flags_ = reader->ReadFlags();
  decl->name_ = Reference::ReadStringFrom(reader);
  decl->type_ = DartType::ReadFrom(reader);
  decl->inferred_value_ = reader->ReadOptional<InferredValue>();
  decl->initializer_ = reader->ReadOptional<Expression>();
  reader->helper()->variables().Push(decl);
  return decl;
}


void VariableDeclaration::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kVariableDeclaration);
  WriteToImpl(writer);
}


void VariableDeclaration::WriteToImpl(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteFlags(flags_);
  name_->WriteTo(writer);
  type_->WriteTo(writer);
  writer->WriteOptional<InferredValue>(inferred_value_);
  writer->WriteOptional<Expression>(initializer_);
  writer->helper()->variables().Push(this);
}


FunctionDeclaration* FunctionDeclaration::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  FunctionDeclaration* decl = new FunctionDeclaration();
  decl->variable_ = VariableDeclaration::ReadFromImpl(reader);
  VariableScope<ReaderHelper> parameters(reader->helper());
  decl->function_ = FunctionNode::ReadFrom(reader);
  return decl;
}


void FunctionDeclaration::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kFunctionDeclaration);
  variable_->WriteToImpl(writer);
  VariableScope<WriterHelper> parameters(writer->helper());
  function_->WriteTo(writer);
}


Name* Name::ReadFrom(Reader* reader) {
  String* string = Reference::ReadStringFrom(reader);
  if (string->size() >= 1 && string->buffer()[0] == '_') {
    int lib_index = reader->ReadUInt();
    Library* library =
        reader->helper()->program()->libraries().GetOrCreate<Library>(
            lib_index);
    return new Name(string, library);
  } else {
    return new Name(string, NULL);
  }
}


void Name::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  string_->WriteTo(writer);
  Library* library = library_;
  bool is_private = library != NULL;
  if (is_private) {
    writer->WriteUInt(writer->helper()->libraries().Lookup(library_));
  }
}


InferredValue* InferredValue::ReadFrom(Reader* reader) {
  InferredValue* type = new InferredValue();
  type->klass_ = Reference::ReadClassFrom(reader, true);
  type->kind_ = static_cast<BaseClassKind>(reader->ReadByte());
  type->value_bits_ = reader->ReadByte();
  return type;
}


void InferredValue::WriteTo(Writer* writer) {
  Reference::WriteClassTo(writer, klass_, true);
  writer->WriteByte(static_cast<uint8_t>(kind_));
  writer->WriteByte(value_bits_);
}


DartType* DartType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Tag tag = reader->ReadTag();
  switch (tag) {
    case kInvalidType:
      return InvalidType::ReadFrom(reader);
    case kDynamicType:
      return DynamicType::ReadFrom(reader);
    case kVoidType:
      return VoidType::ReadFrom(reader);
    case kInterfaceType:
      return InterfaceType::ReadFrom(reader);
    case kSimpleInterfaceType:
      return InterfaceType::ReadFrom(reader, true);
    case kFunctionType:
      return FunctionType::ReadFrom(reader);
    case kSimpleFunctionType:
      return FunctionType::ReadFrom(reader, true);
    case kTypeParameterType:
      return TypeParameterType::ReadFrom(reader);
    default:
      UNREACHABLE();
  }
  UNREACHABLE();
  return NULL;
}


InvalidType* InvalidType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new InvalidType();
}


void InvalidType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kInvalidType);
}


DynamicType* DynamicType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new DynamicType();
}


void DynamicType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kDynamicType);
}


VoidType* VoidType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  return new VoidType();
}


void VoidType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kVoidType);
}


InterfaceType* InterfaceType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  Class* klass = Reference::ReadClassFrom(reader);
  InterfaceType* type = new InterfaceType(klass);
  type->type_arguments().ReadFromStatic<DartType>(reader);
  return type;
}


InterfaceType* InterfaceType::ReadFrom(Reader* reader,
                                       bool _without_type_arguments_) {
  TRACE_READ_OFFSET();
  Class* klass = Reference::ReadClassFrom(reader);
  InterfaceType* type = new InterfaceType(klass);
  ASSERT(_without_type_arguments_);
  return type;
}


void InterfaceType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  if (type_arguments_.length() == 0) {
    writer->WriteTag(kSimpleInterfaceType);
    Reference::WriteClassTo(writer, klass_);
  } else {
    writer->WriteTag(kInterfaceType);
    Reference::WriteClassTo(writer, klass_);
    type_arguments_.WriteTo(writer);
  }
}


FunctionType* FunctionType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  FunctionType* type = new FunctionType();
  TypeParameterScope<ReaderHelper> scope(reader->helper());
  type->type_parameters().ReadFrom(reader);
  type->required_parameter_count_ = reader->ReadUInt();
  type->positional_parameters().ReadFromStatic<DartType>(reader);
  type->named_parameters().ReadFromStatic<Tuple<String, DartType> >(reader);
  type->return_type_ = DartType::ReadFrom(reader);
  return type;
}


FunctionType* FunctionType::ReadFrom(Reader* reader, bool _is_simple_) {
  TRACE_READ_OFFSET();
  FunctionType* type = new FunctionType();
  ASSERT(_is_simple_);
  type->positional_parameters().ReadFromStatic<DartType>(reader);
  type->required_parameter_count_ = type->positional_parameters().length();
  type->return_type_ = DartType::ReadFrom(reader);
  return type;
}


void FunctionType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();

  bool is_simple =
      positional_parameters_.length() == required_parameter_count_ &&
      type_parameters_.length() == 0 && named_parameters_.length() == 0;
  if (is_simple) {
    writer->WriteTag(kSimpleFunctionType);
    positional_parameters_.WriteTo(writer);
    return_type_->WriteTo(writer);
  } else {
    TypeParameterScope<WriterHelper> scope(writer->helper());
    writer->WriteTag(kFunctionType);
    type_parameters_.WriteTo(writer);
    writer->WriteUInt(required_parameter_count_);
    positional_parameters_.WriteTo(writer);
    named_parameters_.WriteTo(writer);
    return_type_->WriteTo(writer);
  }
}


TypeParameterType* TypeParameterType::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TypeParameterType* type = new TypeParameterType();
  type->parameter_ =
      reader->helper()->type_parameters().Lookup(reader->ReadUInt());
  return type;
}


void TypeParameterType::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  writer->WriteTag(kTypeParameterType);
  writer->WriteUInt(writer->helper()->type_parameters().Lookup(parameter_));
}


Program* Program::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  uint32_t magic = reader->ReadUInt32();
  if (magic != kMagicProgramFile) FATAL("Invalid magic identifier");

  Program* program = new Program();
  reader->helper()->set_program(program);

  program->string_table_.ReadFrom(reader);
  program->source_uri_table_.ReadFrom(reader);
  program->line_starting_table_.ReadFrom(reader);

  int libraries = reader->ReadUInt();
  program->libraries().EnsureInitialized(libraries);
  for (int i = 0; i < libraries; i++) {
    program->libraries().GetOrCreate<Library>(i)->ReadFrom(reader);
  }

  program->main_method_ = Procedure::Cast(Reference::ReadMemberFrom(reader));

  return program;
}


void Program::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();

  writer->helper()->SetProgram(this);

  writer->WriteUInt32(kMagicProgramFile);

  // NOTE: Currently we don't GC strings and we require that all referenced
  // strings in nodes are present in [string_table_].
  string_table_.WriteTo(writer);
  source_uri_table_.WriteTo(writer);
  line_starting_table_.WriteTo(writer);

  libraries_.WriteTo(writer);
  Reference::WriteMemberTo(writer, main_method_);
}


FunctionNode* FunctionNode::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  TypeParameterScope<ReaderHelper> scope(reader->helper());

  FunctionNode* function = new FunctionNode();
  function->async_marker_ =
      static_cast<FunctionNode::AsyncMarker>(reader->ReadByte());
  function->type_parameters().ReadFrom(reader);
  function->required_parameter_count_ = reader->ReadUInt();
  function->positional_parameters().ReadFromStatic<VariableDeclarationImpl>(
      reader);
  function->named_parameters().ReadFromStatic<VariableDeclarationImpl>(reader);
  function->return_type_ = DartType::ReadFrom(reader);
  function->inferred_return_value_ = reader->ReadOptional<InferredValue>();

  LabelScope<ReaderHelper, BlockStack<LabeledStatement> > labels(
      reader->helper());
  VariableScope<ReaderHelper> vars(reader->helper());
  function->body_ = reader->ReadOptional<Statement>();
  return function;
}


void FunctionNode::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  TypeParameterScope<WriterHelper> scope(writer->helper());

  writer->WriteByte(static_cast<uint8_t>(async_marker_));
  type_parameters().WriteTo(writer);
  writer->WriteUInt(required_parameter_count());
  positional_parameters().WriteToStatic<VariableDeclarationImpl>(writer);
  named_parameters().WriteToStatic<VariableDeclarationImpl>(writer);
  return_type_->WriteTo(writer);
  writer->WriteOptional<InferredValue>(inferred_return_value_);

  LabelScope<WriterHelper, BlockMap<LabeledStatement> > labels(
      writer->helper());
  VariableScope<WriterHelper> vars(writer->helper());
  writer->WriteOptional<Statement>(body_);
}


TypeParameter* TypeParameter::ReadFrom(Reader* reader) {
  TRACE_READ_OFFSET();
  name_ = Reference::ReadStringFrom(reader);
  bound_ = DartType::ReadFrom(reader);
  return this;
}


void TypeParameter::WriteTo(Writer* writer) {
  TRACE_WRITE_OFFSET();
  name_->WriteTo(writer);
  bound_->WriteTo(writer);
}


}  // namespace kernel


kernel::Program* ReadPrecompiledKernelFromBuffer(const uint8_t* buffer,
                                                 intptr_t buffer_length) {
  kernel::Reader reader(buffer, buffer_length);
  return kernel::Program::ReadFrom(&reader);
}


void WritePrecompiledKernel(ByteWriter* byte_writer, kernel::Program* program) {
  ASSERT(byte_writer != NULL);

  kernel::Writer writer(byte_writer);
  program->WriteTo(&writer);
}


}  // namespace dart
#endif  // !defined(DART_PRECOMPILED_RUNTIME)
