blob: 25b88997b7b66707f4b639afc011446e627fdaa7 [file] [log] [blame]
// 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)