Index: runtime/vm/kernel_binary_flowgraph.h |
diff --git a/runtime/vm/kernel_binary_flowgraph.h b/runtime/vm/kernel_binary_flowgraph.h |
index d52815abb5196cabdf5502f8592318b764e837b4..14dae948fe60bf74c45f759d5cca0dd137811172 100644 |
--- a/runtime/vm/kernel_binary_flowgraph.h |
+++ b/runtime/vm/kernel_binary_flowgraph.h |
@@ -309,7 +309,11 @@ class StreamingFlowGraphBuilder { |
zone_(flow_graph_builder->zone_), |
reader_(new Reader(buffer, buffer_length)), |
constant_evaluator_(this), |
- type_translator_(this, /* finalize= */ true) {} |
+ type_translator_(this, /* finalize= */ true), |
+ current_script_id_(-1), |
+ record_for_script_id_(-1), |
+ record_token_positions_into_(NULL), |
+ record_yield_positions_into_(NULL) {} |
StreamingFlowGraphBuilder(TranslationHelper* translation_helper, |
Zone* zone, |
@@ -320,7 +324,11 @@ class StreamingFlowGraphBuilder { |
zone_(zone), |
reader_(new Reader(buffer, buffer_length)), |
constant_evaluator_(this), |
- type_translator_(this, /* finalize= */ true) {} |
+ type_translator_(this, /* finalize= */ true), |
+ current_script_id_(-1), |
+ record_for_script_id_(-1), |
+ record_token_positions_into_(NULL), |
+ record_yield_positions_into_(NULL) {} |
~StreamingFlowGraphBuilder() { delete reader_; } |
@@ -329,6 +337,14 @@ class StreamingFlowGraphBuilder { |
Fragment BuildStatementAt(intptr_t kernel_offset); |
RawObject* BuildParameterDescriptor(intptr_t kernel_offset); |
RawObject* EvaluateMetadata(intptr_t kernel_offset); |
+ void CollectTokenPositionsFor( |
+ intptr_t script_index, |
+ GrowableArray<intptr_t>* record_token_positions_in, |
+ GrowableArray<intptr_t>* record_yield_positions_in); |
+ intptr_t SourceTableSize(); |
+ String& SourceTableUriFor(intptr_t index); |
+ String& GetSourceFor(intptr_t index); |
+ Array& GetLineStartsFor(intptr_t index); |
private: |
void DiscoverEnclosingElements(Zone* zone, |
@@ -361,9 +377,7 @@ class StreamingFlowGraphBuilder { |
Fragment BuildInitializers(intptr_t constructor_class_parent_offset); |
FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function); |
FlowGraph* BuildGraphOfFunction( |
- bool is_in_builtin_library_toplevel, |
intptr_t constructor_class_parent_offset = -1); |
- Fragment BuildGetMainClosure(); |
Fragment BuildExpression(TokenPosition* position = NULL); |
Fragment BuildStatement(); |
@@ -399,7 +413,12 @@ class StreamingFlowGraphBuilder { |
void SkipName(); |
void SkipArguments(); |
void SkipVariableDeclaration(); |
+ void SkipLibraryCombinator(); |
+ void SkipLibraryDependency(); |
+ void SkipLibraryTypedef(); |
TokenPosition ReadPosition(bool record = true); |
+ void record_token_position(TokenPosition position); |
+ void record_yield_position(TokenPosition position); |
Tag ReadTag(uint8_t* payload = NULL); |
Tag PeekTag(uint8_t* payload = NULL); |
word ReadFlags(); |
@@ -466,13 +485,13 @@ class StreamingFlowGraphBuilder { |
const dart::String& name, |
Token::Kind kind, |
intptr_t argument_count, |
- intptr_t num_args_checked = 1); |
+ intptr_t checked_argument_count = 1); |
Fragment InstanceCall(TokenPosition position, |
const dart::String& name, |
Token::Kind kind, |
intptr_t argument_count, |
const Array& argument_names, |
- intptr_t num_args_checked); |
+ intptr_t checked_argument_count); |
Fragment ThrowException(TokenPosition position); |
Fragment BooleanNegate(); |
Fragment TranslateInstantiatedTypeArguments( |
@@ -607,6 +626,10 @@ class StreamingFlowGraphBuilder { |
Reader* reader_; |
StreamingConstantEvaluator constant_evaluator_; |
StreamingDartTypeTranslator type_translator_; |
+ intptr_t current_script_id_; |
+ intptr_t record_for_script_id_; |
+ GrowableArray<intptr_t>* record_token_positions_into_; |
+ GrowableArray<intptr_t>* record_yield_positions_into_; |
friend class StreamingConstantEvaluator; |
friend class StreamingDartTypeTranslator; |
@@ -616,6 +639,7 @@ class StreamingFlowGraphBuilder { |
friend class FieldHelper; |
friend class ProcedureHelper; |
friend class ClassHelper; |
+ friend class LibraryHelper; |
friend class ConstructorHelper; |
friend class SimpleExpressionConverter; |
friend class KernelReader; |
@@ -856,10 +880,10 @@ class FieldHelper { |
builder_->ReadCanonicalNameReference(); // read canonical_name. |
if (++next_read_ == field) return; |
case kPosition: |
- position_ = builder_->ReadPosition(); // read position. |
+ position_ = builder_->ReadPosition(false); // read position. |
if (++next_read_ == field) return; |
case kEndPosition: |
- end_position_ = builder_->ReadPosition(); // read end position. |
+ end_position_ = builder_->ReadPosition(false); // read end position. |
if (++next_read_ == field) return; |
case kFlags: |
flags_ = builder_->ReadFlags(); // read flags. |
@@ -873,6 +897,9 @@ class FieldHelper { |
if (++next_read_ == field) return; |
case kSourceUriIndex: |
source_uri_index_ = builder_->ReadUInt(); // read source_uri_index. |
+ builder_->current_script_id_ = source_uri_index_; |
+ builder_->record_token_position(position_); |
+ builder_->record_token_position(end_position_); |
if (++next_read_ == field) return; |
case kAnnotations: |
builder_->SkipListOfExpressions(); // read annotations. |
@@ -962,10 +989,10 @@ class ProcedureHelper { |
builder_->ReadCanonicalNameReference(); // read canonical_name. |
if (++next_read_ == field) return; |
case kPosition: |
- position_ = builder_->ReadPosition(); // read position. |
+ position_ = builder_->ReadPosition(false); // read position. |
if (++next_read_ == field) return; |
case kEndPosition: |
- end_position_ = builder_->ReadPosition(); // read end position. |
+ end_position_ = builder_->ReadPosition(false); // read end position. |
if (++next_read_ == field) return; |
case kKind: |
kind_ = static_cast<Procedure::ProcedureKind>( |
@@ -983,6 +1010,9 @@ class ProcedureHelper { |
if (++next_read_ == field) return; |
case kSourceUriIndex: |
source_uri_index_ = builder_->ReadUInt(); // read source_uri_index. |
+ builder_->current_script_id_ = source_uri_index_; |
+ builder_->record_token_position(position_); |
+ builder_->record_token_position(end_position_); |
if (++next_read_ == field) return; |
case kAnnotations: |
builder_->SkipListOfExpressions(); // read annotations. |
@@ -1205,7 +1235,7 @@ class ClassHelper { |
builder_->ReadCanonicalNameReference(); // read canonical_name. |
if (++next_read_ == field) return; |
case kPosition: |
- position_ = builder_->ReadPosition(); // read position. |
+ position_ = builder_->ReadPosition(false); // read position. |
if (++next_read_ == field) return; |
case kIsAbstract: |
is_abstract_ = builder_->ReadBool(); // read is_abstract. |
@@ -1215,6 +1245,8 @@ class ClassHelper { |
if (++next_read_ == field) return; |
case kSourceUriIndex: |
source_uri_index_ = builder_->ReadUInt(); // read source_uri_index. |
+ builder_->current_script_id_ = source_uri_index_; |
+ builder_->record_token_position(position_); |
if (++next_read_ == field) return; |
case kAnnotations: |
builder_->SkipListOfExpressions(); // read annotations. |
@@ -1290,6 +1322,122 @@ class ClassHelper { |
intptr_t next_read_; |
}; |
+// Helper class that reads a kernel Library from binary. |
+// |
+// Use ReadUntilExcluding to read up to but not including a field. |
+// One can then for instance read the field from the call-site (and remember to |
+// call SetAt to inform this helper class), and then use this to read more. |
+// "Dumb" fields are stored (e.g. integers) and can be fetched from this class. |
+// If asked to read a "non-dumb" field (e.g. an expression) it will be skipped. |
+class LibraryHelper { |
+ public: |
+ enum Fields { |
+ kFlags, |
+ kCanonicalName, |
+ kName, |
+ kSourceUriIndex, |
+ kAnnotations, |
+ kDependencies, |
+ kTypedefs, |
+ kClasses, |
+ kToplevelField, |
+ kToplevelProcedures, |
+ kEnd |
+ }; |
+ |
+ explicit LibraryHelper(StreamingFlowGraphBuilder* builder) { |
+ builder_ = builder; |
+ next_read_ = kFlags; |
+ } |
+ |
+ void ReadUntilIncluding(Fields field) { |
+ ReadUntilExcluding(static_cast<Fields>(static_cast<int>(field) + 1)); |
+ } |
+ |
+ void ReadUntilExcluding(Fields field) { |
+ if (field <= next_read_) return; |
+ |
+ // Ordered with fall-through. |
+ switch (next_read_) { |
+ case kFlags: { |
+ word flags = builder_->ReadFlags(); // read flags. |
+ ASSERT(flags == 0); // external libraries not supported |
+ if (++next_read_ == field) return; |
+ } |
+ case kCanonicalName: |
+ canonical_name_ = |
+ builder_->ReadCanonicalNameReference(); // read canonical_name. |
+ if (++next_read_ == field) return; |
+ case kName: |
+ name_index_ = builder_->ReadStringReference(); // read name index. |
+ if (++next_read_ == field) return; |
+ case kSourceUriIndex: |
+ source_uri_index_ = builder_->ReadUInt(); // read source_uri_index. |
+ builder_->current_script_id_ = source_uri_index_; |
+ if (++next_read_ == field) return; |
+ case kAnnotations: |
+ builder_->SkipListOfExpressions(); // read annotations. |
+ if (++next_read_ == field) return; |
+ case kDependencies: { |
+ intptr_t dependency_count = builder_->ReadUInt(); // read list length. |
+ for (intptr_t i = 0; i < dependency_count; ++i) { |
+ builder_->SkipLibraryDependency(); |
+ } |
+ if (++next_read_ == field) return; |
+ } |
+ case kTypedefs: { |
+ intptr_t typedef_count = |
+ builder_->ReadListLength(); // read list length. |
+ for (intptr_t i = 0; i < typedef_count; i++) { |
+ builder_->SkipLibraryTypedef(); |
+ } |
+ if (++next_read_ == field) return; |
+ } |
+ case kClasses: { |
+ int class_count = builder_->ReadListLength(); // read list length. |
+ for (intptr_t i = 0; i < class_count; ++i) { |
+ ClassHelper class_helper(builder_); |
+ class_helper.ReadUntilExcluding(ClassHelper::kEnd); |
+ } |
+ if (++next_read_ == field) return; |
+ } |
+ case kToplevelField: { |
+ intptr_t field_count = builder_->ReadListLength(); // read list length. |
+ for (intptr_t i = 0; i < field_count; ++i) { |
+ FieldHelper field_helper(builder_); |
+ field_helper.ReadUntilExcluding(FieldHelper::kEnd); |
+ } |
+ if (++next_read_ == field) return; |
+ } |
+ case kToplevelProcedures: { |
+ intptr_t procedure_count = |
+ builder_->ReadListLength(); // read list length. |
+ for (intptr_t i = 0; i < procedure_count; ++i) { |
+ ProcedureHelper procedure_helper(builder_); |
+ procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd); |
+ } |
+ if (++next_read_ == field) return; |
+ } |
+ case kEnd: |
+ return; |
+ } |
+ } |
+ |
+ void SetNext(Fields field) { next_read_ = field; } |
+ void SetJustRead(Fields field) { |
+ next_read_ = field; |
+ ++next_read_; |
+ } |
+ |
+ NameIndex canonical_name_; |
+ StringIndex name_index_; |
+ intptr_t source_uri_index_; |
+ |
+ private: |
+ StreamingFlowGraphBuilder* builder_; |
+ intptr_t next_read_; |
+}; |
+ |
// A helper class that saves the current reader position, goes to another reader |
// position, and upon destruction, resets to the original reader position. |
class AlternativeReadingScope { |