Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(761)

Unified Diff: runtime/vm/kernel_binary.h

Issue 2776373002: Initial steps into streaming the kernel flowgraph (Closed)
Patch Set: Rebase + fix lint error Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/kernel.h ('k') | runtime/vm/kernel_binary.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/kernel_binary.h
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
new file mode 100644
index 0000000000000000000000000000000000000000..116ea7d96df4b3ea93736b0c0b0631f17cdac2d1
--- /dev/null
+++ b/runtime/vm/kernel_binary.h
@@ -0,0 +1,544 @@
+// Copyright (c) 2017, 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.
+
+#ifndef RUNTIME_VM_KERNEL_BINARY_H_
+#define RUNTIME_VM_KERNEL_BINARY_H_
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include <map>
+
+#include "vm/kernel.h"
+#include "vm/kernel_to_il.h"
+#include "vm/object.h"
+
+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() && helper()->program() != NULL) {
+ add_token_position(&helper()->program()->valid_token_positions, position);
+ }
+ }
+
+ void record_yield_token_position(TokenPosition position) {
+ if (helper()->program() != NULL) {
+ 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_; }
+ void set_offset(intptr_t offset) { offset_ = offset; }
+ intptr_t size() { return size_; }
+
+ const uint8_t* buffer() { return buffer_; }
+
+ 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_;
+};
+
+} // namespace kernel
+} // namespace dart
+
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+#endif // RUNTIME_VM_KERNEL_BINARY_H_
« no previous file with comments | « runtime/vm/kernel.h ('k') | runtime/vm/kernel_binary.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698