| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| #if !defined(DART_PRECOMPILED_RUNTIME) |
| |
| #include "platform/globals.h" |
| #include "vm/flags.h" |
| #include "vm/growable_array.h" |
| #include "vm/kernel.h" |
| #include "vm/kernel_to_il.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) |
| #else |
| #define TRACE_READ_OFFSET() |
| #endif |
| |
| namespace dart { |
| |
| |
| namespace kernel { |
| |
| |
| static const uint32_t kMagicProgramFile = 0x90ABCDEFu; |
| |
| |
| // Keep in sync with package:dynamo/lib/binary/tag.dart |
| enum Tag { |
| kNothing = 0, |
| kSomething = 1, |
| |
| kClass = 2, |
| |
| 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, |
| |
| 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, |
| |
| 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_.Add(current_count_); |
| current_count_ = 0; |
| } |
| |
| void LeaveScope() { |
| variables_.TruncateTo(variables_.length() - current_count_); |
| current_count_ = variable_count_[variable_count_.length() - 1]; |
| variable_count_.RemoveLast(); |
| } |
| |
| T* Lookup(int index) { |
| ASSERT(index < variables_.length()); |
| return variables_[index]; |
| } |
| |
| void Push(T* v) { |
| variables_.Add(v); |
| current_count_++; |
| } |
| |
| void Push(List<T>* decl) { |
| for (intptr_t i = 0; i < decl->length(); i++) { |
| variables_.Add(decl[i]); |
| current_count_++; |
| } |
| } |
| |
| void Pop(T* decl) { |
| variables_.RemoveLast(); |
| current_count_--; |
| } |
| |
| void Pop(List<T>* decl) { |
| variables_.TruncateTo(variables_.length() - decl->length()); |
| current_count_ -= decl->length(); |
| } |
| |
| private: |
| int current_count_; |
| MallocGrowableArray<T*> variables_; |
| MallocGrowableArray<int> variable_count_; |
| }; |
| |
| |
| template <typename T> |
| class BlockMap { |
| public: |
| BlockMap() : current_count_(0), stack_height_(0) {} |
| |
| void EnterScope() { |
| variable_count_.Add(current_count_); |
| current_count_ = 0; |
| } |
| |
| void LeaveScope() { |
| stack_height_ -= current_count_; |
| current_count_ = variable_count_[variable_count_.length() - 1]; |
| variable_count_.RemoveLast(); |
| } |
| |
| int Lookup(T* object) { |
| typename MallocMap<T, int>::Pair* result = variables_.LookupPair(object); |
| ASSERT(result != NULL); |
| if (result == NULL) FATAL("lookup failure"); |
| return RawPointerKeyValueTrait<T, int>::ValueOf(*result); |
| } |
| |
| void Push(T* v) { |
| ASSERT(variables_.LookupPair(v) == NULL); |
| int index = stack_height_++; |
| variables_.Insert(v, index); |
| current_count_++; |
| } |
| |
| void Set(T* v, int index) { |
| typename MallocMap<T, int>::Pair* entry = variables_.LookupPair(v); |
| ASSERT(entry != NULL); |
| entry->value = index; |
| } |
| |
| void Push(List<T>* decl) { |
| for (intptr_t i = 0; i < decl->length(); i++) { |
| Push(decl[i]); |
| } |
| } |
| |
| void Pop(T* v) { |
| current_count_--; |
| stack_height_--; |
| } |
| |
| private: |
| int current_count_; |
| int stack_height_; |
| MallocMap<T, int> variables_; |
| MallocGrowableArray<int> variable_count_; |
| }; |
| |
| |
| template <typename T> |
| class VariableScope { |
| public: |
| explicit VariableScope(T* builder) : builder_(builder) { |
| builder_->variables().EnterScope(); |
| } |
| ~VariableScope() { builder_->variables().LeaveScope(); } |
| |
| private: |
| T* builder_; |
| }; |
| |
| |
| template <typename T> |
| class TypeParameterScope { |
| public: |
| explicit TypeParameterScope(T* builder) : builder_(builder) { |
| builder_->type_parameters().EnterScope(); |
| } |
| ~TypeParameterScope() { builder_->type_parameters().LeaveScope(); } |
| |
| private: |
| T* builder_; |
| }; |
| |
| |
| template <typename T> |
| class SwitchCaseScope { |
| public: |
| explicit SwitchCaseScope(T* builder) : builder_(builder) { |
| builder_->switch_cases().EnterScope(); |
| } |
| ~SwitchCaseScope() { builder_->switch_cases().LeaveScope(); } |
| |
| private: |
| T* builder_; |
| }; |
| |
| |
| // Unlike other scopes, labels from enclosing functions are not visible in |
| // nested functions. The LabelScope class is used to hide outer labels. |
| template <typename Builder, typename Block> |
| class LabelScope { |
| public: |
| explicit LabelScope(Builder* builder) : builder_(builder) { |
| outer_block_ = builder_->labels(); |
| builder_->set_labels(&block_); |
| } |
| ~LabelScope() { builder_->set_labels(outer_block_); } |
| |
| private: |
| Builder* builder_; |
| Block block_; |
| Block* outer_block_; |
| }; |
| |
| class ReaderHelper { |
| public: |
| ReaderHelper() : program_(NULL), labels_(NULL) {} |
| |
| Program* program() { return program_; } |
| void set_program(Program* program) { program_ = program; } |
| |
| BlockStack<VariableDeclaration>& variables() { return scope_; } |
| BlockStack<TypeParameter>& type_parameters() { return type_parameters_; } |
| BlockStack<SwitchCase>& switch_cases() { return switch_cases_; } |
| |
| BlockStack<LabeledStatement>* labels() { return labels_; } |
| void set_labels(BlockStack<LabeledStatement>* labels) { labels_ = labels; } |
| |
| CanonicalName* GetCanonicalName(int index) { return canonical_names_[index]; } |
| void SetCanonicalName(int index, CanonicalName* name) { |
| canonical_names_[index] = name; |
| } |
| void SetCanonicalNameCount(int count) { canonical_names_.SetLength(count); } |
| |
| private: |
| Program* program_; |
| MallocGrowableArray<CanonicalName*> canonical_names_; |
| BlockStack<VariableDeclaration> scope_; |
| BlockStack<TypeParameter> type_parameters_; |
| BlockStack<SwitchCase> switch_cases_; |
| BlockStack<LabeledStatement>* labels_; |
| }; |
| |
| |
| class Reader { |
| public: |
| Reader(const uint8_t* buffer, intptr_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; |
| } |
| } |
| |
| void add_token_position( |
| MallocGrowableArray<MallocGrowableArray<intptr_t>*>* list, |
| TokenPosition position) { |
| intptr_t size = list->length(); |
| while (size <= current_script_id_) { |
| MallocGrowableArray<intptr_t>* tmp = new MallocGrowableArray<intptr_t>(); |
| list->Add(tmp); |
| size = list->length(); |
| } |
| list->At(current_script_id_)->Add(position.value()); |
| } |
| |
| void record_token_position(TokenPosition position) { |
| if (position.IsReal()) { |
| add_token_position(&helper()->program()->valid_token_positions, position); |
| } |
| } |
| |
| void record_yield_token_position(TokenPosition position) { |
| add_token_position(&helper()->program()->yield_token_positions, position); |
| } |
| |
| /** |
| * Read and return a TokenPosition from this reader. |
| * @param record specifies whether or not the read position is saved as a |
| * valid token position in the current script. |
| * If not be sure to record it later by calling record_token_position (after |
| * setting the correct current_script_id). |
| */ |
| TokenPosition ReadPosition(bool record = true) { |
| // Position is saved as unsigned, |
| // but actually ranges from -1 and up (thus the -1) |
| intptr_t value = ReadUInt() - 1; |
| TokenPosition result = TokenPosition(value); |
| max_position_ = Utils::Maximum(max_position_, result); |
| if (min_position_.IsNoSource()) { |
| min_position_ = result; |
| } else if (result.IsReal()) { |
| min_position_ = Utils::Minimum(min_position_, result); |
| } |
| |
| if (record) { |
| record_token_position(result); |
| } |
| return result; |
| } |
| |
| 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: %" Pd ", size: %" Pd ")", |
| offset_, size_); |
| } |
| } |
| |
| void DumpOffset(const char* str) { |
| OS::PrintErr("@%" Pd " %s\n", offset_, str); |
| } |
| |
| // The largest position read yet (since last reset). |
| // This is automatically updated when calling ReadPosition, |
| // but can be overwritten (e.g. via the PositionScope class). |
| TokenPosition max_position() { return max_position_; } |
| // The smallest position read yet (since last reset). |
| // This is automatically updated when calling ReadPosition, |
| // but can be overwritten (e.g. via the PositionScope class). |
| TokenPosition min_position() { return min_position_; } |
| // The current script id for what we are currently processing. |
| // Note though that this is only a convenience helper and has to be set |
| // manually. |
| intptr_t current_script_id() { return current_script_id_; } |
| void set_current_script_id(intptr_t script_id) { |
| current_script_id_ = script_id; |
| } |
| |
| 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_; } |
| |
| CanonicalName* ReadCanonicalNameReference() { |
| int index = ReadUInt(); |
| if (index == 0) return NULL; |
| CanonicalName* name = builder_.GetCanonicalName(index - 1); |
| ASSERT(name != NULL); |
| return name; |
| } |
| |
| intptr_t offset() { return offset_; } |
| |
| private: |
| const uint8_t* buffer_; |
| intptr_t size_; |
| intptr_t offset_; |
| ReaderHelper builder_; |
| TokenPosition max_position_; |
| TokenPosition min_position_; |
| intptr_t current_script_id_; |
| |
| friend class PositionScope; |
| }; |
| |
| |
| // A helper class that resets the readers min and max positions both upon |
| // initialization and upon destruction, i.e. when created the min an max |
| // positions will be reset to "noSource", when destructing the min and max will |
| // be reset to have they value they would have had, if they hadn't been reset in |
| // the first place. |
| class PositionScope { |
| public: |
| explicit PositionScope(Reader* reader) |
| : reader_(reader), |
| min_(reader->min_position_), |
| max_(reader->max_position_) { |
| reader->min_position_ = reader->max_position_ = TokenPosition::kNoSource; |
| } |
| |
| ~PositionScope() { |
| if (reader_->min_position_.IsNoSource()) { |
| reader_->min_position_ = min_; |
| } else if (min_.IsReal()) { |
| reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_); |
| } |
| reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_); |
| } |
| |
| private: |
| Reader* reader_; |
| TokenPosition min_; |
| TokenPosition max_; |
| }; |
| |
| 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 (intptr_t 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 (intptr_t 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 (intptr_t i = 0; i < length_; i++) { |
| ASSERT(array_[i] == NULL); |
| array_[i] = IT::ReadFrom(reader); |
| } |
| } |
| |
| 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 (intptr_t 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 (intptr_t i = 0; i < length; i++) { |
| (*this)[i]->ReadFrom(reader); |
| } |
| } |
| |
| |
| 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 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); |
| } |
| }; |
| |
| |
| class VariableDeclarationImpl { |
| public: |
| static VariableDeclaration* ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return VariableDeclaration::ReadFromImpl(reader, false); |
| } |
| }; |
| |
| |
| 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 StringTable::ReadFrom(Reader* reader) { |
| strings_.ReadFromStatic<StringImpl>(reader); |
| } |
| |
| |
| void SourceTable::ReadFrom(Reader* reader) { |
| size_ = reader->helper()->program()->source_uri_table().strings().length(); |
| source_code_ = new String*[size_]; |
| line_starts_ = new intptr_t*[size_]; |
| line_count_ = new intptr_t[size_]; |
| for (intptr_t i = 0; i < size_; ++i) { |
| source_code_[i] = StringImpl::ReadFrom(reader); |
| intptr_t line_count = reader->ReadUInt(); |
| intptr_t* line_starts = new intptr_t[line_count]; |
| line_count_[i] = line_count; |
| intptr_t previous_line_start = 0; |
| for (intptr_t j = 0; j < line_count; ++j) { |
| intptr_t line_start = reader->ReadUInt() + previous_line_start; |
| line_starts[j] = line_start; |
| previous_line_start = line_start; |
| } |
| line_starts_[i] = line_starts; |
| } |
| } |
| |
| |
| Library* Library::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| int flags = reader->ReadFlags(); |
| ASSERT(flags == 0); // external libraries not supported |
| |
| canonical_name_ = reader->ReadCanonicalNameReference(); |
| name_ = Reference::ReadStringFrom(reader); |
| import_uri_ = canonical_name_->name(); |
| source_uri_index_ = reader->ReadUInt(); |
| reader->set_current_script_id(source_uri_index_); |
| |
| int num_imports = reader->ReadUInt(); |
| if (num_imports != 0) { |
| FATAL("Deferred imports not implemented in VM"); |
| } |
| int num_classes = reader->ReadUInt(); |
| classes().EnsureInitialized(num_classes); |
| for (intptr_t i = 0; i < num_classes; i++) { |
| Tag tag = reader->ReadTag(); |
| ASSERT(tag == kClass); |
| NormalClass* klass = classes().GetOrCreate<NormalClass>(i, this); |
| klass->ReadFrom(reader); |
| } |
| |
| fields().ReadFrom<Field>(reader, this); |
| procedures().ReadFrom<Procedure>(reader, this); |
| return this; |
| } |
| |
| |
| Class* Class::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| |
| canonical_name_ = reader->ReadCanonicalNameReference(); |
| position_ = reader->ReadPosition(false); |
| is_abstract_ = reader->ReadBool(); |
| name_ = Reference::ReadStringFrom(reader); |
| source_uri_index_ = reader->ReadUInt(); |
| reader->set_current_script_id(source_uri_index_); |
| reader->record_token_position(position_); |
| annotations_.ReadFromStatic<Expression>(reader); |
| |
| return this; |
| } |
| |
| |
| 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); |
| reader->ReadOptional<DartType>(); // Mixed-in type is unused. |
| implemented_classes_.ReadFromStatic<DowncastReader<DartType, InterfaceType> >( |
| reader); |
| fields_.ReadFrom<Field>(reader, this); |
| constructors_.ReadFrom<Constructor>(reader, this); |
| procedures_.ReadFrom<Procedure>(reader, this); |
| |
| return this; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| CanonicalName* Reference::ReadMemberFrom(Reader* reader, bool allow_null) { |
| TRACE_READ_OFFSET(); |
| |
| CanonicalName* canonical_name = reader->ReadCanonicalNameReference(); |
| if (canonical_name == NULL && !allow_null) { |
| FATAL("Expected a valid member reference, but got `null`"); |
| } |
| |
| if (canonical_name != NULL) { |
| canonical_name->set_referenced(true); |
| } |
| |
| return canonical_name; |
| } |
| |
| |
| CanonicalName* Reference::ReadClassFrom(Reader* reader, bool allow_null) { |
| TRACE_READ_OFFSET(); |
| |
| CanonicalName* canonical_name = reader->ReadCanonicalNameReference(); |
| if (canonical_name == NULL && !allow_null) { |
| FATAL("Expected a valid class reference, but got `null`"); |
| } |
| |
| if (canonical_name != NULL) { |
| canonical_name->set_referenced(true); |
| } |
| |
| return canonical_name; |
| } |
| |
| |
| String* Reference::ReadStringFrom(Reader* reader) { |
| int index = reader->ReadUInt(); |
| return reader->helper()->program()->string_table().strings()[index]; |
| } |
| |
| |
| Field* Field::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| kernel_offset_ = reader->offset(); // Notice the ReadTag() below. |
| Tag tag = reader->ReadTag(); |
| ASSERT(tag == kField); |
| |
| canonical_name_ = reader->ReadCanonicalNameReference(); |
| position_ = reader->ReadPosition(false); |
| end_position_ = reader->ReadPosition(false); |
| flags_ = reader->ReadFlags(); |
| name_ = Name::ReadFrom(reader); |
| source_uri_index_ = reader->ReadUInt(); |
| reader->set_current_script_id(source_uri_index_); |
| reader->record_token_position(position_); |
| reader->record_token_position(end_position_); |
| annotations_.ReadFromStatic<Expression>(reader); |
| type_ = DartType::ReadFrom(reader); |
| initializer_ = reader->ReadOptional<Expression>(); |
| return this; |
| } |
| |
| |
| Constructor* Constructor::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Tag tag = reader->ReadTag(); |
| ASSERT(tag == kConstructor); |
| |
| canonical_name_ = reader->ReadCanonicalNameReference(); |
| VariableScope<ReaderHelper> parameters(reader->helper()); |
| position_ = reader->ReadPosition(); |
| end_position_ = reader->ReadPosition(); |
| flags_ = reader->ReadFlags(); |
| name_ = Name::ReadFrom(reader); |
| annotations_.ReadFromStatic<Expression>(reader); |
| function_ = FunctionNode::ReadFrom(reader); |
| initializers_.ReadFromStatic<Initializer>(reader); |
| return this; |
| } |
| |
| |
| Procedure* Procedure::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Tag tag = reader->ReadTag(); |
| ASSERT(tag == kProcedure); |
| |
| canonical_name_ = reader->ReadCanonicalNameReference(); |
| VariableScope<ReaderHelper> parameters(reader->helper()); |
| position_ = reader->ReadPosition(false); |
| end_position_ = reader->ReadPosition(false); |
| kind_ = static_cast<ProcedureKind>(reader->ReadByte()); |
| flags_ = reader->ReadFlags(); |
| name_ = Name::ReadFrom(reader); |
| source_uri_index_ = reader->ReadUInt(); |
| reader->set_current_script_id(source_uri_index_); |
| reader->record_token_position(position_); |
| reader->record_token_position(end_position_); |
| annotations_.ReadFromStatic<Expression>(reader); |
| function_ = reader->ReadOptional<FunctionNode>(); |
| return this; |
| } |
| |
| |
| 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(); |
| } |
| |
| |
| FieldInitializer* FieldInitializer::ReadFromImpl(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| FieldInitializer* initializer = new FieldInitializer(); |
| initializer->field_reference_ = Reference::ReadMemberFrom(reader); |
| initializer->value_ = Expression::ReadFrom(reader); |
| return initializer; |
| } |
| |
| |
| SuperInitializer* SuperInitializer::ReadFromImpl(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| SuperInitializer* init = new SuperInitializer(); |
| init->target_reference_ = Reference::ReadMemberFrom(reader); |
| init->arguments_ = Arguments::ReadFrom(reader); |
| return init; |
| } |
| |
| |
| RedirectingInitializer* RedirectingInitializer::ReadFromImpl(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| RedirectingInitializer* init = new RedirectingInitializer(); |
| init->target_reference_ = Reference::ReadMemberFrom(reader); |
| init->arguments_ = Arguments::ReadFrom(reader); |
| return init; |
| } |
| |
| |
| LocalInitializer* LocalInitializer::ReadFromImpl(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| LocalInitializer* init = new LocalInitializer(); |
| init->variable_ = VariableDeclaration::ReadFromImpl(reader, false); |
| return init; |
| } |
| |
| |
| 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 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(); |
| } |
| |
| |
| VariableGet* VariableGet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableGet* get = new VariableGet(); |
| get->position_ = reader->ReadPosition(); |
| 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->position_ = reader->ReadPosition(); |
| get->variable_ = reader->helper()->variables().Lookup(payload); |
| return get; |
| } |
| |
| |
| VariableSet* VariableSet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableSet* set = new VariableSet(); |
| set->position_ = reader->ReadPosition(); |
| 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->position_ = reader->ReadPosition(); |
| set->expression_ = Expression::ReadFrom(reader); |
| return set; |
| } |
| |
| |
| PropertyGet* PropertyGet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| PropertyGet* get = new PropertyGet(); |
| get->position_ = reader->ReadPosition(); |
| get->receiver_ = Expression::ReadFrom(reader); |
| get->name_ = Name::ReadFrom(reader); |
| get->interface_target_reference_ = Reference::ReadMemberFrom(reader, true); |
| return get; |
| } |
| |
| |
| PropertySet* PropertySet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| PropertySet* set = new PropertySet(); |
| set->position_ = reader->ReadPosition(); |
| set->receiver_ = Expression::ReadFrom(reader); |
| set->name_ = Name::ReadFrom(reader); |
| set->value_ = Expression::ReadFrom(reader); |
| set->interface_target_reference_ = Reference::ReadMemberFrom(reader, true); |
| return set; |
| } |
| |
| |
| DirectPropertyGet* DirectPropertyGet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| DirectPropertyGet* get = new DirectPropertyGet(); |
| get->position_ = reader->ReadPosition(); |
| get->receiver_ = Expression::ReadFrom(reader); |
| get->target_reference_ = Reference::ReadMemberFrom(reader); |
| return get; |
| } |
| |
| |
| DirectPropertySet* DirectPropertySet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| DirectPropertySet* set = new DirectPropertySet(); |
| set->position_ = reader->ReadPosition(); |
| set->receiver_ = Expression::ReadFrom(reader); |
| set->target_reference_ = Reference::ReadMemberFrom(reader); |
| set->value_ = Expression::ReadFrom(reader); |
| return set; |
| } |
| |
| |
| StaticGet* StaticGet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| StaticGet* get = new StaticGet(); |
| get->position_ = reader->ReadPosition(); |
| get->target_reference_ = Reference::ReadMemberFrom(reader); |
| return get; |
| } |
| |
| |
| StaticSet* StaticSet::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| StaticSet* set = new StaticSet(); |
| set->position_ = reader->ReadPosition(); |
| set->target_reference_ = Reference::ReadMemberFrom(reader); |
| set->expression_ = Expression::ReadFrom(reader); |
| return set; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| NamedExpression* NamedExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| String* name = Reference::ReadStringFrom(reader); |
| Expression* expression = Expression::ReadFrom(reader); |
| return new NamedExpression(name, expression); |
| } |
| |
| |
| MethodInvocation* MethodInvocation::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| MethodInvocation* invocation = new MethodInvocation(); |
| invocation->position_ = reader->ReadPosition(); |
| invocation->receiver_ = Expression::ReadFrom(reader); |
| invocation->name_ = Name::ReadFrom(reader); |
| invocation->arguments_ = Arguments::ReadFrom(reader); |
| invocation->interface_target_reference_ = |
| Reference::ReadMemberFrom(reader, true); |
| return invocation; |
| } |
| |
| |
| DirectMethodInvocation* DirectMethodInvocation::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| DirectMethodInvocation* invocation = new DirectMethodInvocation(); |
| invocation->receiver_ = Expression::ReadFrom(reader); |
| invocation->target_reference_ = Reference::ReadMemberFrom(reader); |
| invocation->arguments_ = Arguments::ReadFrom(reader); |
| return invocation; |
| } |
| |
| |
| StaticInvocation* StaticInvocation::ReadFrom(Reader* reader, bool is_const) { |
| TRACE_READ_OFFSET(); |
| StaticInvocation* invocation = new StaticInvocation(); |
| invocation->is_const_ = is_const; |
| invocation->position_ = reader->ReadPosition(); |
| invocation->procedure_reference_ = Reference::ReadMemberFrom(reader); |
| invocation->arguments_ = Arguments::ReadFrom(reader); |
| return invocation; |
| } |
| |
| |
| ConstructorInvocation* ConstructorInvocation::ReadFrom(Reader* reader, |
| bool is_const) { |
| TRACE_READ_OFFSET(); |
| ConstructorInvocation* invocation = new ConstructorInvocation(); |
| invocation->is_const_ = is_const; |
| invocation->position_ = reader->ReadPosition(); |
| invocation->target_reference_ = Reference::ReadMemberFrom(reader); |
| invocation->arguments_ = Arguments::ReadFrom(reader); |
| return invocation; |
| } |
| |
| |
| Not* Not::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Not* n = new Not(); |
| n->expression_ = Expression::ReadFrom(reader); |
| return n; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| StringConcatenation* StringConcatenation::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| StringConcatenation* concat = new StringConcatenation(); |
| concat->position_ = reader->ReadPosition(); |
| concat->expressions_.ReadFromStatic<Expression>(reader); |
| return concat; |
| } |
| |
| |
| IsExpression* IsExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| IsExpression* expr = new IsExpression(); |
| expr->position_ = reader->ReadPosition(); |
| expr->operand_ = Expression::ReadFrom(reader); |
| expr->type_ = DartType::ReadFrom(reader); |
| return expr; |
| } |
| |
| |
| AsExpression* AsExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| AsExpression* expr = new AsExpression(); |
| expr->position_ = reader->ReadPosition(); |
| expr->operand_ = Expression::ReadFrom(reader); |
| expr->type_ = DartType::ReadFrom(reader); |
| return expr; |
| } |
| |
| |
| StringLiteral* StringLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new StringLiteral(Reference::ReadStringFrom(reader)); |
| } |
| |
| |
| BigintLiteral* BigintLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new BigintLiteral(Reference::ReadStringFrom(reader)); |
| } |
| |
| |
| 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; |
| } |
| |
| |
| DoubleLiteral* DoubleLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| DoubleLiteral* literal = new DoubleLiteral(); |
| literal->value_ = Reference::ReadStringFrom(reader); |
| return literal; |
| } |
| |
| |
| BoolLiteral* BoolLiteral::ReadFrom(Reader* reader, bool value) { |
| TRACE_READ_OFFSET(); |
| BoolLiteral* lit = new BoolLiteral(); |
| lit->value_ = value; |
| return lit; |
| } |
| |
| |
| NullLiteral* NullLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new NullLiteral(); |
| } |
| |
| |
| SymbolLiteral* SymbolLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| SymbolLiteral* lit = new SymbolLiteral(); |
| lit->value_ = Reference::ReadStringFrom(reader); |
| return lit; |
| } |
| |
| |
| TypeLiteral* TypeLiteral::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| TypeLiteral* literal = new TypeLiteral(); |
| literal->type_ = DartType::ReadFrom(reader); |
| return literal; |
| } |
| |
| |
| ThisExpression* ThisExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new ThisExpression(); |
| } |
| |
| |
| Rethrow* Rethrow::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Rethrow* rethrow = new Rethrow(); |
| rethrow->position_ = reader->ReadPosition(); |
| return rethrow; |
| } |
| |
| |
| Throw* Throw::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Throw* t = new Throw(); |
| t->position_ = reader->ReadPosition(); |
| t->expression_ = Expression::ReadFrom(reader); |
| return t; |
| } |
| |
| |
| ListLiteral* ListLiteral::ReadFrom(Reader* reader, bool is_const) { |
| TRACE_READ_OFFSET(); |
| ListLiteral* literal = new ListLiteral(); |
| literal->is_const_ = is_const; |
| literal->position_ = reader->ReadPosition(); |
| literal->type_ = DartType::ReadFrom(reader); |
| literal->expressions_.ReadFromStatic<Expression>(reader); |
| return literal; |
| } |
| |
| |
| MapLiteral* MapLiteral::ReadFrom(Reader* reader, bool is_const) { |
| TRACE_READ_OFFSET(); |
| MapLiteral* literal = new MapLiteral(); |
| literal->is_const_ = is_const; |
| literal->position_ = reader->ReadPosition(); |
| literal->key_type_ = DartType::ReadFrom(reader); |
| literal->value_type_ = DartType::ReadFrom(reader); |
| literal->entries_.ReadFromStatic<MapEntry>(reader); |
| return literal; |
| } |
| |
| |
| MapEntry* MapEntry::ReadFrom(Reader* reader) { |
| MapEntry* entry = new MapEntry(); |
| entry->key_ = Expression::ReadFrom(reader); |
| entry->value_ = Expression::ReadFrom(reader); |
| return entry; |
| } |
| |
| |
| AwaitExpression* AwaitExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| AwaitExpression* await = new AwaitExpression(); |
| await->operand_ = Expression::ReadFrom(reader); |
| return await; |
| } |
| |
| |
| FunctionExpression* FunctionExpression::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableScope<ReaderHelper> parameters(reader->helper()); |
| FunctionExpression* expr = new FunctionExpression(); |
| expr->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| expr->function_ = FunctionNode::ReadFrom(reader); |
| return expr; |
| } |
| |
| |
| Let* Let::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| PositionScope scope(reader); |
| |
| Let* let = new Let(); |
| let->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| let->variable_ = VariableDeclaration::ReadFromImpl(reader, false); |
| let->body_ = Expression::ReadFrom(reader); |
| let->position_ = reader->min_position(); |
| let->end_position_ = reader->max_position(); |
| |
| return let; |
| } |
| |
| |
| 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, true); |
| case kFunctionDeclaration: |
| return FunctionDeclaration::ReadFrom(reader); |
| default: |
| UNREACHABLE(); |
| } |
| return NULL; |
| } |
| |
| |
| InvalidStatement* InvalidStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new InvalidStatement(); |
| } |
| |
| |
| ExpressionStatement* ExpressionStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new ExpressionStatement(Expression::ReadFrom(reader)); |
| } |
| |
| |
| Block* Block::ReadFromImpl(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| PositionScope scope(reader); |
| |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| Block* block = new Block(); |
| block->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| block->statements().ReadFromStatic<Statement>(reader); |
| block->position_ = reader->min_position(); |
| block->end_position_ = reader->max_position(); |
| |
| return block; |
| } |
| |
| |
| EmptyStatement* EmptyStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new EmptyStatement(); |
| } |
| |
| |
| AssertStatement* AssertStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| AssertStatement* stmt = new AssertStatement(); |
| stmt->condition_ = Expression::ReadFrom(reader); |
| stmt->message_ = reader->ReadOptional<Expression>(); |
| return stmt; |
| } |
| |
| |
| LabeledStatement* LabeledStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| LabeledStatement* stmt = new LabeledStatement(); |
| reader->helper()->labels()->Push(stmt); |
| stmt->body_ = Statement::ReadFrom(reader); |
| reader->helper()->labels()->Pop(stmt); |
| return stmt; |
| } |
| |
| |
| BreakStatement* BreakStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| BreakStatement* stmt = new BreakStatement(); |
| stmt->position_ = reader->ReadPosition(); |
| stmt->target_ = reader->helper()->labels()->Lookup(reader->ReadUInt()); |
| return stmt; |
| } |
| |
| |
| WhileStatement* WhileStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| WhileStatement* stmt = new WhileStatement(); |
| stmt->condition_ = Expression::ReadFrom(reader); |
| stmt->body_ = Statement::ReadFrom(reader); |
| return stmt; |
| } |
| |
| |
| DoStatement* DoStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| DoStatement* dostmt = new DoStatement(); |
| dostmt->body_ = Statement::ReadFrom(reader); |
| dostmt->condition_ = Expression::ReadFrom(reader); |
| return dostmt; |
| } |
| |
| |
| ForStatement* ForStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| PositionScope scope(reader); |
| |
| ForStatement* forstmt = new ForStatement(); |
| forstmt->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| forstmt->variables_.ReadFromStatic<VariableDeclarationImpl>(reader); |
| forstmt->condition_ = reader->ReadOptional<Expression>(); |
| forstmt->updates_.ReadFromStatic<Expression>(reader); |
| forstmt->body_ = Statement::ReadFrom(reader); |
| forstmt->end_position_ = reader->max_position(); |
| forstmt->position_ = reader->min_position(); |
| |
| return forstmt; |
| } |
| |
| |
| ForInStatement* ForInStatement::ReadFrom(Reader* reader, bool is_async) { |
| TRACE_READ_OFFSET(); |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| PositionScope scope(reader); |
| |
| ForInStatement* forinstmt = new ForInStatement(); |
| forinstmt->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| forinstmt->is_async_ = is_async; |
| forinstmt->position_ = reader->ReadPosition(); |
| forinstmt->variable_ = VariableDeclaration::ReadFromImpl(reader, false); |
| forinstmt->iterable_ = Expression::ReadFrom(reader); |
| forinstmt->body_ = Statement::ReadFrom(reader); |
| forinstmt->end_position_ = reader->max_position(); |
| if (!forinstmt->position_.IsReal()) { |
| forinstmt->position_ = reader->min_position(); |
| } |
| forinstmt->variable_->set_end_position(forinstmt->position_); |
| |
| return forinstmt; |
| } |
| |
| |
| 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 (intptr_t i = 0; i < count; i++) { |
| SwitchCase* sc = stmt->cases_.GetOrCreate<SwitchCase>(i); |
| reader->helper()->switch_cases().Push(sc); |
| } |
| for (intptr_t i = 0; i < count; i++) { |
| SwitchCase* sc = stmt->cases_[i]; |
| sc->ReadFrom(reader); |
| } |
| return stmt; |
| } |
| |
| |
| SwitchCase* SwitchCase::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| expressions_.ReadFromStatic<Expression>(reader); |
| for (intptr_t i = 0; i < expressions_.length(); ++i) { |
| expressions_[i]->set_position(reader->ReadPosition()); |
| } |
| is_default_ = reader->ReadBool(); |
| body_ = Statement::ReadFrom(reader); |
| return this; |
| } |
| |
| |
| ContinueSwitchStatement* ContinueSwitchStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| ContinueSwitchStatement* stmt = new ContinueSwitchStatement(); |
| stmt->target_ = reader->helper()->switch_cases().Lookup(reader->ReadUInt()); |
| return stmt; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| ReturnStatement* ReturnStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| ReturnStatement* ret = new ReturnStatement(); |
| ret->position_ = reader->ReadPosition(); |
| ret->expression_ = reader->ReadOptional<Expression>(); |
| return ret; |
| } |
| |
| |
| TryCatch* TryCatch::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| PositionScope scope(reader); |
| |
| TryCatch* tc = new TryCatch(); |
| tc->body_ = Statement::ReadFrom(reader); |
| tc->catches_.ReadFromStatic<Catch>(reader); |
| tc->position_ = reader->min_position(); |
| |
| return tc; |
| } |
| |
| |
| Catch* Catch::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| PositionScope scope(reader); |
| |
| Catch* c = new Catch(); |
| c->kernel_offset_ = reader->offset(); // Catch has no tag. |
| c->guard_ = DartType::ReadFrom(reader); |
| c->exception_ = |
| reader->ReadOptional<VariableDeclaration, VariableDeclarationImpl>(); |
| c->stack_trace_ = |
| reader->ReadOptional<VariableDeclaration, VariableDeclarationImpl>(); |
| c->body_ = Statement::ReadFrom(reader); |
| c->end_position_ = reader->max_position(); |
| c->position_ = reader->min_position(); |
| |
| return c; |
| } |
| |
| |
| TryFinally* TryFinally::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| TryFinally* tf = new TryFinally(); |
| tf->body_ = Statement::ReadFrom(reader); |
| tf->finalizer_ = Statement::ReadFrom(reader); |
| return tf; |
| } |
| |
| |
| YieldStatement* YieldStatement::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| YieldStatement* stmt = new YieldStatement(); |
| stmt->position_ = reader->ReadPosition(); |
| reader->record_yield_token_position(stmt->position_); |
| stmt->flags_ = reader->ReadByte(); |
| stmt->expression_ = Expression::ReadFrom(reader); |
| return stmt; |
| } |
| |
| |
| VariableDeclaration* VariableDeclaration::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| Tag tag = reader->ReadTag(); |
| ASSERT(tag == kVariableDeclaration); |
| return VariableDeclaration::ReadFromImpl(reader, true); |
| } |
| |
| |
| VariableDeclaration* VariableDeclaration::ReadFromImpl(Reader* reader, |
| bool read_tag) { |
| TRACE_READ_OFFSET(); |
| PositionScope scope(reader); |
| |
| VariableDeclaration* decl = new VariableDeclaration(); |
| // -1 or -0 depending on whether there's a tag or not. |
| decl->kernel_offset_ = reader->offset() - (read_tag ? 1 : 0); |
| decl->position_ = reader->ReadPosition(); |
| decl->equals_position_ = reader->ReadPosition(); |
| decl->flags_ = reader->ReadFlags(); |
| decl->name_ = Reference::ReadStringFrom(reader); |
| decl->type_ = DartType::ReadFrom(reader); |
| decl->initializer_ = reader->ReadOptional<Expression>(); |
| |
| // Go to next token position so it ends *after* the last potentially |
| // debuggable position in the initializer. |
| TokenPosition position = reader->max_position(); |
| if (position.IsReal()) position.Next(); |
| decl->end_position_ = position; |
| reader->helper()->variables().Push(decl); |
| |
| return decl; |
| } |
| |
| |
| FunctionDeclaration* FunctionDeclaration::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| FunctionDeclaration* decl = new FunctionDeclaration(); |
| decl->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte. |
| decl->position_ = reader->ReadPosition(); |
| decl->variable_ = VariableDeclaration::ReadFromImpl(reader, false); |
| VariableScope<ReaderHelper> parameters(reader->helper()); |
| decl->function_ = FunctionNode::ReadFrom(reader); |
| return decl; |
| } |
| |
| |
| Name* Name::ReadFrom(Reader* reader) { |
| String* string = Reference::ReadStringFrom(reader); |
| if (string->size() >= 1 && string->buffer()[0] == '_') { |
| CanonicalName* library_reference = reader->ReadCanonicalNameReference(); |
| return new Name(string, library_reference); |
| } else { |
| return new Name(string, NULL); |
| } |
| } |
| |
| |
| 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(); |
| } |
| |
| |
| DynamicType* DynamicType::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new DynamicType(); |
| } |
| |
| |
| VoidType* VoidType::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| return new VoidType(); |
| } |
| |
| |
| InterfaceType* InterfaceType::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| CanonicalName* klass_name = Reference::ReadClassFrom(reader); |
| InterfaceType* type = new InterfaceType(klass_name); |
| type->type_arguments().ReadFromStatic<DartType>(reader); |
| return type; |
| } |
| |
| |
| InterfaceType* InterfaceType::ReadFrom(Reader* reader, |
| bool _without_type_arguments_) { |
| TRACE_READ_OFFSET(); |
| CanonicalName* klass_name = Reference::ReadClassFrom(reader); |
| InterfaceType* type = new InterfaceType(klass_name); |
| ASSERT(_without_type_arguments_); |
| return type; |
| } |
| |
| |
| 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; |
| } |
| |
| |
| TypeParameterType* TypeParameterType::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| TypeParameterType* type = new TypeParameterType(); |
| type->parameter_ = |
| reader->helper()->type_parameters().Lookup(reader->ReadUInt()); |
| return type; |
| } |
| |
| |
| Program* Program::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| uint32_t magic = reader->ReadUInt32(); |
| if (magic != kMagicProgramFile) FATAL("Invalid magic identifier"); |
| |
| Program* program = new Program(); |
| program->canonical_name_root_ = CanonicalName::NewRoot(); |
| reader->helper()->set_program(program); |
| |
| program->string_table_.ReadFrom(reader); |
| program->source_uri_table_.ReadFrom(reader); |
| program->source_table_.ReadFrom(reader); |
| |
| int canonical_names = reader->ReadUInt(); |
| reader->helper()->SetCanonicalNameCount(canonical_names); |
| for (int i = 0; i < canonical_names; ++i) { |
| int biased_parent_index = reader->ReadUInt(); |
| CanonicalName* parent; |
| if (biased_parent_index != 0) { |
| parent = reader->helper()->GetCanonicalName(biased_parent_index - 1); |
| } else { |
| parent = program->canonical_name_root(); |
| } |
| ASSERT(parent != NULL); |
| int name_index = reader->ReadUInt(); |
| String* name = program->string_table().strings()[name_index]; |
| CanonicalName* canonical_name = parent->AddChild(name); |
| reader->helper()->SetCanonicalName(i, canonical_name); |
| } |
| |
| int libraries = reader->ReadUInt(); |
| program->libraries().EnsureInitialized(libraries); |
| for (intptr_t i = 0; i < libraries; i++) { |
| program->libraries().GetOrCreate<Library>(i)->ReadFrom(reader); |
| } |
| |
| program->main_method_reference_ = Reference::ReadMemberFrom(reader); |
| |
| return program; |
| } |
| |
| |
| FunctionNode* FunctionNode::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| TypeParameterScope<ReaderHelper> scope(reader->helper()); |
| |
| FunctionNode* function = new FunctionNode(); |
| function->kernel_offset_ = reader->offset(); // FunctionNode has no tag. |
| function->position_ = reader->ReadPosition(); |
| function->end_position_ = reader->ReadPosition(); |
| function->async_marker_ = |
| static_cast<FunctionNode::AsyncMarker>(reader->ReadByte()); |
| function->dart_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); |
| |
| LabelScope<ReaderHelper, BlockStack<LabeledStatement> > labels( |
| reader->helper()); |
| VariableScope<ReaderHelper> vars(reader->helper()); |
| function->body_ = reader->ReadOptional<Statement>(); |
| return function; |
| } |
| |
| |
| TypeParameter* TypeParameter::ReadFrom(Reader* reader) { |
| TRACE_READ_OFFSET(); |
| name_ = Reference::ReadStringFrom(reader); |
| bound_ = DartType::ReadFrom(reader); |
| return this; |
| } |
| |
| |
| } // namespace kernel |
| |
| |
| kernel::Program* ReadPrecompiledKernelFromBuffer(const uint8_t* buffer, |
| intptr_t buffer_length) { |
| kernel::Reader reader(buffer, buffer_length); |
| return kernel::Program::ReadFrom(&reader); |
| } |
| |
| |
| } // namespace dart |
| #endif // !defined(DART_PRECOMPILED_RUNTIME) |