f67ce21068
BUG= R=asiva@google.com, fschneider@google.com Review URL: https://codereview.chromium.org/2411823003 .
2903 lines
76 KiB
C++
2903 lines
76 KiB
C++
// 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
|