Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(859)

Unified Diff: runtime/vm/kernel_binary.cc

Issue 2411823003: VM support for running Kernel binaries. (Closed)
Patch Set: Address comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/kernel.cc ('k') | runtime/vm/kernel_reader.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/kernel_binary.cc
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
new file mode 100644
index 0000000000000000000000000000000000000000..407e1a651821001c4bae4670c841a120f5348a8f
--- /dev/null
+++ b/runtime/vm/kernel_binary.cc
@@ -0,0 +1,2902 @@
+// 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.
+
+#include <map>
+#include <vector>
+
+#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(__PRETTY_FUNCTION__); \
+ } while (0)
+#define TRACE_WRITE_OFFSET() do { \
+ if (FLAG_trace_kernel_binary) \
+ writer->DumpOffset(__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_;
+};
+
+
+class ReaderHelper {
+ public:
+ ReaderHelper() : program_(NULL) {}
+ ~ReaderHelper() {}
+
+ Program* program() { return program_; }
+ void set_program(Program* program) { program_ = program; }
+
+ BlockStack<VariableDeclaration>& variables() { return scope_; }
+ BlockStack<TypeParameter>& type_parameters() { return type_parameters_; }
+ BlockStack<LabeledStatement>& lables() { return labels_; }
+ BlockStack<SwitchCase>& switch_cases() { return switch_cases_; }
+
+ private:
+ Program* program_;
+ BlockStack<VariableDeclaration> scope_;
+ BlockStack<TypeParameter> type_parameters_;
+ BlockStack<LabeledStatement> labels_;
+ BlockStack<SwitchCase> switch_cases_;
+};
+
+
+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;
+ }
+ }
+
+ 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:
+ 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<LabeledStatement>& lables() { return labels_; }
+ BlockMap<SwitchCase>& switch_cases() { return switch_cases_; }
+
+ 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<LabeledStatement> labels_;
+ BlockMap<SwitchCase> switch_cases_;
+};
+
+
+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;
+ }
+
+ 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, intptr_t length) {
+ size_ = 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 lineStart = reader->ReadUInt() + previous_line_start;
+ line_starts[j + 1] = lineStart;
+ previous_line_start = lineStart;
+ }
+ 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);
+ 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(0);
+
+ 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);
+ 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(0);
+ 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);
+
+ reader->ReadUInt();
+ flags_ = reader->ReadFlags();
+ name_ = Name::ReadFrom(reader);
+ 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->WriteUInt(0);
+ writer->WriteFlags(flags_);
+ name_->WriteTo(writer);
+ writer->WriteUInt(0);
+ 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);
+ 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(0);
+ 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();
+ reader->ReadUInt();
+ 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->WriteUInt(0);
+ receiver_->WriteTo(writer);
+ name_->WriteTo(writer);
+ Reference::WriteMemberTo(writer, interfaceTarget_, true);
+}
+
+
+PropertySet* PropertySet::ReadFrom(Reader* reader) {
+ TRACE_READ_OFFSET();
+ PropertySet* set = new PropertySet();
+ reader->ReadUInt();
+ 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->WriteUInt(0);
+ 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();
+ reader->ReadUInt();
+ get->target_ = Reference::ReadMemberFrom(reader);
+ return get;
+}
+
+
+void StaticGet::WriteTo(Writer* writer) {
+ TRACE_WRITE_OFFSET();
+ writer->WriteTag(kStaticGet);
+ writer->WriteUInt(0);
+ 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();
+ reader->ReadUInt();
+ 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->WriteUInt(0);
+ 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();
+
+ reader->ReadUInt();
+ Member* member = Reference::ReadMemberFrom(reader);
+ Arguments* args = Arguments::ReadFrom(reader);
+
+ return new StaticInvocation(Procedure::Cast(member), args, is_const);
+}
+
+
+void StaticInvocation::WriteTo(Writer* writer) {
+ TRACE_WRITE_OFFSET();
+ writer->WriteTag(is_const_ ? kConstStaticInvocation : kStaticInvocation);
+ writer->WriteUInt(0);
+ 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;
+ reader->ReadUInt();
+ 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->WriteUInt(0);
+ 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();
+ reader->ReadUInt();
+ t->expression_ = Expression::ReadFrom(reader);
+ return t;
+}
+
+
+void Throw::WriteTo(Writer* writer) {
+ TRACE_WRITE_OFFSET();
+ writer->WriteTag(kThrow);
+ writer->WriteUInt(0);
+ 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()->lables().Push(stmt);
+ stmt->body_ = Statement::ReadFrom(reader);
+ reader->helper()->lables().Pop(stmt);
+ return stmt;
+}
+
+
+void LabeledStatement::WriteTo(Writer* writer) {
+ TRACE_WRITE_OFFSET();
+ writer->WriteTag(kLabeledStatement);
+ writer->helper()->lables().Push(this);
+ body_->WriteTo(writer);
+ writer->helper()->lables().Pop(this);
+}
+
+
+BreakStatement* BreakStatement::ReadFrom(Reader* reader) {
+ TRACE_READ_OFFSET();
+ BreakStatement* stmt = new BreakStatement();
+ stmt->target_ = reader->helper()->lables().Lookup(reader->ReadUInt());
+ return stmt;
+}
+
+
+void BreakStatement::WriteTo(Writer* writer) {
+ TRACE_WRITE_OFFSET();
+ writer->WriteTag(kBreakStatement);
+ writer->WriteUInt(writer->helper()->lables().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);
+ StringTable dummy1;
+ dummy1.ReadFrom(reader);
+ LineStartingTable dummy2;
+ dummy2.ReadFrom(reader, dummy1.strings_.length());
+
+ 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);
+ StringTable dummy1;
+ dummy1.WriteTo(writer);
+ LineStartingTable dummy2;
+ dummy2.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>();
+
+ 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_);
+
+ 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
« no previous file with comments | « runtime/vm/kernel.cc ('k') | runtime/vm/kernel_reader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698