// 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 #include #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 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(index) < variables_.size()); return variables_[index]; } void Push(T* v) { variables_.push_back(v); current_count_++; } void Push(List* 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* decl) { variables_.resize(variables_.size() - decl->length()); current_count_ -= decl->length(); } private: int current_count_; std::vector variables_; std::vector variable_count_; }; template 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* 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 variables_; std::vector variable_count_; }; template class VariableScope { public: explicit VariableScope(T* builder) : builder_(builder) { builder_->variables().EnterScope(); } ~VariableScope() { builder_->variables().LeaveScope(); } private: T* builder_; }; template class TypeParameterScope { public: explicit TypeParameterScope(T* builder) : builder_(builder) { builder_->type_parameters().EnterScope(); } ~TypeParameterScope() { builder_->type_parameters().LeaveScope(); } private: T* builder_; }; template 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& variables() { return scope_; } BlockStack& type_parameters() { return type_parameters_; } BlockStack& lables() { return labels_; } BlockStack& switch_cases() { return switch_cases_; } private: Program* program_; BlockStack scope_; BlockStack type_parameters_; BlockStack labels_; BlockStack 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(byte & kSpecializedTagMask); } else { return static_cast(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 T* ReadOptional() { Tag tag = ReadTag(); if (tag == kNothing) { return NULL; } ASSERT(tag == kSomething); return RT::ReadFrom(this); } template T* ReadOptional() { return ReadOptional(); } 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& strings() { return strings_; } BlockMap& libraries() { return libraries_; } BlockMap& classes() { return classes_; } BlockMap& fields() { return fields_; } BlockMap& procedures() { return procedures_; } BlockMap& constructors() { return constructors_; } BlockMap& variables() { return scope_; } BlockMap& type_parameters() { return type_parameters_; } BlockMap& lables() { return labels_; } BlockMap& switch_cases() { return switch_cases_; } private: Program* program_; BlockMap strings_; BlockMap libraries_; BlockMap classes_; BlockMap fields_; BlockMap procedures_; BlockMap constructors_; BlockMap scope_; BlockMap type_parameters_; BlockMap labels_; BlockMap switch_cases_; }; class Writer { public: explicit Writer(ByteWriter* writer) : out_(writer), offset_(0) {} void WriteUInt32(uint32_t value) { uint8_t buffer[4] = { static_cast((value >> 24) & 0xff), static_cast((value >> 16) & 0xff), static_cast((value >> 8) & 0xff), static_cast((value >> 0) & 0xff), }; WriteBytes(buffer, 4); } void WriteUInt(uint32_t value) { if (value < 0x80) { // 0... WriteByte(static_cast(value)); } else if (value < 0x4000) { // 10... WriteByte(static_cast(((value >> 8) & 0x3f) | 0x80)); WriteByte(static_cast(value & 0xff)); } else { // 11... // Ensure the highest 2 bits is not used for anything (we use it to for // encoding). ASSERT(static_cast((value >> 24) & 0xc0) == 0); uint8_t buffer[4] = { static_cast(((value >> 24) & 0x7f) | 0xc0), static_cast((value >> 16) & 0xff), static_cast((value >> 8) & 0xff), static_cast((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(tag)); } void WriteTag(Tag tag, uint8_t payload) { ASSERT((payload & ~kSpecializedPayloadMask) == 0); WriteByte(kSpecializedTagHighBit | static_cast(tag) | payload); } void WriteBytes(uint8_t* bytes, int length) { out_->WriteBytes(bytes, length); offset_ += length; } template void WriteOptional(T* object) { if (object == NULL) { WriteTag(kNothing); } else { WriteTag(kSomething); object->WriteTo(this); } } template void WriteOptionalStatic(T* object) { if (object == NULL) { WriteTag(kNothing); } else { WriteTag(kSomething); WT::WriteTo(this, object); } } template void WriteOptionalStatic(T* object) { return WriteOptionalStatic(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 template void List::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(i, parent); object->ReadFrom(reader); } } template template void List::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); int length = reader->ReadListLength(); EnsureInitialized(length); for (int i = 0; i < length_; i++) { GetOrCreate(i)->ReadFrom(reader); } } template template void List::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 void List::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 template void List::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 Tuple* Tuple::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); A* first = A::ReadFrom(reader); B* second = B::ReadFrom(reader); return new Tuple(first, second); } template void Tuple::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); first_->WriteTo(writer); second_->WriteTo(writer); } template 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(reader); } void StringTable::WriteTo(Writer* writer) { strings_.WriteToStatic(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(i, this); klass->ReadFrom(reader); } else { ASSERT(tag == kMixinClass); MixinClass* klass = classes().GetOrCreate(i, this); klass->ReadFrom(reader); } } fields().ReadFrom(reader, this); procedures().ReadFrom(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(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 scope(reader->helper()); type_parameters_.ReadFrom(reader); DartType* type = reader->ReadOptional(); super_class_ = InterfaceType::Cast(type); implemented_classes_.ReadFromStatic >( reader); fields_.ReadFrom(reader, this); constructors_.ReadFrom(reader, this); procedures_.ReadFrom(reader, this); return this; } void NormalClass::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); Class::WriteTo(writer); TypeParameterScope scope(writer->helper()); type_parameters().WriteTo(writer); writer->WriteOptional(super_class_); implemented_classes().WriteTo(writer); fields_.WriteTo(writer); constructors_.WriteTo(writer); procedures_.WriteTo(writer); } MixinClass* MixinClass::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); TypeParameterScope 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 >( reader); constructors_.ReadFrom(reader, this); return this; } void MixinClass::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); TypeParameterScope 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_idx); return library->fields().GetOrCreate(field_idx, library); } case kLibraryProcedureReference: { int library_idx = reader->ReadUInt(); int procedure_idx = reader->ReadUInt(); Library* library = program->libraries().GetOrCreate(library_idx); return library->procedures().GetOrCreate(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_idx, klass); } else if (tag == kClassConstructorReference) { int constructor_idx = reader->ReadUInt(); return klass->constructors().GetOrCreate(constructor_idx, klass); } else { ASSERT(tag == kClassProcedureReference); int procedure_idx = reader->ReadUInt(); return klass->procedures().GetOrCreate(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_idx); Class* klass; if (klass_member_tag == kNormalClassReference) { klass = library->classes().GetOrCreate(class_idx, library); } else { ASSERT(klass_member_tag == kMixinClassReference); klass = library->classes().GetOrCreate(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(reader); type_ = DartType::ReadFrom(reader); inferred_value_ = reader->ReadOptional(); initializer_ = reader->ReadOptional(); 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(inferred_value_); writer->WriteOptional(initializer_); } Constructor* Constructor::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); Tag tag = reader->ReadTag(); ASSERT(tag == kConstructor); VariableScope parameters(reader->helper()); flags_ = reader->ReadFlags(); name_ = Name::ReadFrom(reader); annotations_.ReadFromStatic(reader); function_ = FunctionNode::ReadFrom(reader); initializers_.ReadFromStatic(reader); return this; } void Constructor::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); writer->WriteTag(kConstructor); VariableScope 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 parameters(reader->helper()); kind_ = static_cast(reader->ReadByte()); flags_ = reader->ReadFlags(); name_ = Name::ReadFrom(reader); reader->ReadUInt(); annotations_.ReadFromStatic(reader); function_ = reader->ReadOptional(); return this; } void Procedure::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); writer->WriteTag(kProcedure); VariableScope parameters(writer->helper()); writer->WriteByte(kind_); writer->WriteFlags(flags_); name_->WriteTo(writer); writer->WriteUInt(0); annotations_.WriteTo(writer); writer->WriteOptional(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(); // 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(index)); } else { writer->WriteTag(kVariableGet); writer->WriteUInt(index); writer->WriteOptional(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(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(reader); arguments->positional().ReadFromStatic(reader); arguments->named().ReadFromStatic(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(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(); // 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(NULL); // Unused static type. } StringConcatenation* StringConcatenation::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); StringConcatenation* concat = new StringConcatenation(); concat->expressions_.ReadFromStatic(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(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(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(payload)); } else { writer->WriteTag(value_ < 0 ? kNegativeIntLiteral : kPositiveIntLiteral); writer->WriteUInt(static_cast(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(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(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 parameters(reader->helper()); FunctionExpression* expr = new FunctionExpression(); expr->function_ = FunctionNode::ReadFrom(reader); return expr; } void FunctionExpression::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); VariableScope parameters(writer->helper()); writer->WriteTag(kFunctionExpression); function_->WriteTo(writer); } Let* Let::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); VariableScope 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 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 vars(reader->helper()); Block* block = new Block(); block->statements().ReadFromStatic(reader); return block; } void Block::WriteTo(Writer* writer) { writer->WriteTag(kBlock); WriteToImpl(writer); } void Block::WriteToImpl(Writer* writer) { TRACE_WRITE_OFFSET(); VariableScope 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(); return stmt; } void AssertStatement::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); writer->WriteTag(kAssertStatement); condition_->WriteTo(writer); writer->WriteOptional(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 vars(reader->helper()); ForStatement* forstmt = new ForStatement(); forstmt->variables_.ReadFromStatic(reader); forstmt->condition_ = reader->ReadOptional(); forstmt->updates_.ReadFromStatic(reader); forstmt->body_ = Statement::ReadFrom(reader); return forstmt; } void ForStatement::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); writer->WriteTag(kForStatement); VariableScope vars(writer->helper()); variables_.WriteToStatic(writer); writer->WriteOptional(condition_); updates_.WriteTo(writer); body_->WriteTo(writer); } ForInStatement* ForInStatement::ReadFrom(Reader* reader, bool is_async) { TRACE_READ_OFFSET(); VariableScope 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 vars(writer->helper()); variable_->WriteToImpl(writer); iterable_->WriteTo(writer); body_->WriteTo(writer); } SwitchStatement* SwitchStatement::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); SwitchCaseScope 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(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 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(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(); return ret; } void ReturnStatement::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); writer->WriteTag(kReturnStatement); writer->WriteOptional(expression_); } TryCatch* TryCatch::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); TryCatch* tc = new TryCatch(); tc->body_ = Statement::ReadFrom(reader); tc->catches_.ReadFromStatic(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 vars(reader->helper()); Catch* c = new Catch(); c->guard_ = DartType::ReadFrom(reader); c->exception_ = reader->ReadOptional(); c->stack_trace_ = reader->ReadOptional(); c->body_ = Statement::ReadFrom(reader); return c; } void Catch::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); VariableScope vars(writer->helper()); guard_->WriteTo(writer); writer->WriteOptionalStatic( exception_); writer->WriteOptionalStatic( 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(); decl->initializer_ = reader->ReadOptional(); 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(inferred_value_); writer->WriteOptional(initializer_); writer->helper()->variables().Push(this); } FunctionDeclaration* FunctionDeclaration::ReadFrom(Reader* reader) { TRACE_READ_OFFSET(); FunctionDeclaration* decl = new FunctionDeclaration(); decl->variable_ = VariableDeclaration::ReadFromImpl(reader); VariableScope 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 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( 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(reader->ReadByte()); type->value_bits_ = reader->ReadByte(); return type; } void InferredValue::WriteTo(Writer* writer) { Reference::WriteClassTo(writer, klass_, true); writer->WriteByte(static_cast(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(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 scope(reader->helper()); type->type_parameters().ReadFrom(reader); type->required_parameter_count_ = reader->ReadUInt(); type->positional_parameters().ReadFromStatic(reader); type->named_parameters().ReadFromStatic >(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(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 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(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 scope(reader->helper()); FunctionNode* function = new FunctionNode(); function->async_marker_ = static_cast(reader->ReadByte()); function->type_parameters().ReadFrom(reader); function->required_parameter_count_ = reader->ReadUInt(); function->positional_parameters().ReadFromStatic( reader); function->named_parameters().ReadFromStatic(reader); function->return_type_ = DartType::ReadFrom(reader); function->inferred_return_value_ = reader->ReadOptional(); VariableScope vars(reader->helper()); function->body_ = reader->ReadOptional(); return function; } void FunctionNode::WriteTo(Writer* writer) { TRACE_WRITE_OFFSET(); TypeParameterScope scope(writer->helper()); writer->WriteByte(static_cast(async_marker_)); type_parameters().WriteTo(writer); writer->WriteUInt(required_parameter_count()); positional_parameters().WriteToStatic(writer); named_parameters().WriteToStatic(writer); return_type_->WriteTo(writer); writer->WriteOptional(inferred_return_value_); VariableScope vars(writer->helper()); writer->WriteOptional(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