| Index: runtime/vm/kernel_binary.cc
|
| diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
|
| index 44980724fba3ac957b4b70827f9e7852f2ab0e22..2c904d0e65fe36c7a450605e5d84fe9bda971d56 100644
|
| --- a/runtime/vm/kernel_binary.cc
|
| +++ b/runtime/vm/kernel_binary.cc
|
| @@ -3,6 +3,7 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
| #if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
| +#include "vm/kernel_binary.h"
|
| #include "platform/globals.h"
|
| #include "vm/flags.h"
|
| #include "vm/growable_array.h"
|
| @@ -25,519 +26,6 @@ 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) {
|
| @@ -645,8 +133,7 @@ String* String::ReadFrom(Reader* reader) {
|
| String* String::ReadFromImpl(Reader* reader) {
|
| TRACE_READ_OFFSET();
|
| uint32_t bytes = reader->ReadUInt();
|
| - String* string = new String(reader->Consume(bytes), bytes);
|
| - return string;
|
| + return new String(reader->Consume(bytes), bytes);
|
| }
|
|
|
| void StringTable::ReadFrom(Reader* reader) {
|
| @@ -679,6 +166,8 @@ Library* Library::ReadFrom(Reader* reader) {
|
| TRACE_READ_OFFSET();
|
| int flags = reader->ReadFlags();
|
| ASSERT(flags == 0); // external libraries not supported
|
| + kernel_data_ = reader->buffer();
|
| + kernel_data_size_ = reader->size();
|
|
|
| canonical_name_ = reader->ReadCanonicalNameReference();
|
| name_ = Reference::ReadStringFrom(reader);
|
| @@ -1324,6 +813,7 @@ ThisExpression* ThisExpression::ReadFrom(Reader* reader) {
|
| Rethrow* Rethrow::ReadFrom(Reader* reader) {
|
| TRACE_READ_OFFSET();
|
| Rethrow* rethrow = new Rethrow();
|
| + rethrow->kernel_offset_ = reader->offset() - 1; // -1 to include tag byte.
|
| rethrow->position_ = reader->ReadPosition();
|
| return rethrow;
|
| }
|
| @@ -1735,12 +1225,12 @@ FunctionDeclaration* FunctionDeclaration::ReadFrom(Reader* reader) {
|
|
|
|
|
| Name* Name::ReadFrom(Reader* reader) {
|
| - String* string = Reference::ReadStringFrom(reader);
|
| - if (string->size() >= 1 && string->buffer()[0] == '_') {
|
| + String* name = Reference::ReadStringFrom(reader);
|
| + if (name->size() >= 1 && name->buffer()[0] == '_') {
|
| CanonicalName* library_reference = reader->ReadCanonicalNameReference();
|
| - return new Name(string, library_reference);
|
| + return new Name(name, library_reference);
|
| } else {
|
| - return new Name(string, NULL);
|
| + return new Name(name, NULL);
|
| }
|
| }
|
|
|
|
|