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

Unified Diff: runtime/vm/kernel_binary_flowgraph.cc

Issue 2886873008: [kernel] Streaming ScopeBuilder (Closed)
Patch Set: Addressed (some) comments; rebased. Created 3 years, 6 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_binary_flowgraph.h ('k') | runtime/vm/kernel_reader.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/kernel_binary_flowgraph.cc
diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc
index 9e39c23f5ff2da11bbf27521d69b748cfae5cebc..c88ddce65eb74777894c05761bfd4fd69d1c7b92 100644
--- a/runtime/vm/kernel_binary_flowgraph.cc
+++ b/runtime/vm/kernel_binary_flowgraph.cc
@@ -17,6 +17,1554 @@ namespace kernel {
#define T (type_translator_)
#define I Isolate::Current()
+static bool IsStaticInitializer(const Function& function, Zone* zone) {
+ return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
+ dart::String::Handle(zone, function.name())
+ .StartsWith(Symbols::InitPrefix());
+}
+
+
+StreamingScopeBuilder::StreamingScopeBuilder(ParsedFunction* parsed_function,
+ intptr_t kernel_offset,
+ const uint8_t* buffer,
+ intptr_t buffer_length)
+ : result_(NULL),
+ parsed_function_(parsed_function),
+ kernel_offset_(kernel_offset),
+ translation_helper_(Thread::Current()),
+ zone_(translation_helper_.zone()),
+ current_function_scope_(NULL),
+ scope_(NULL),
+ depth_(0),
+ name_index_(0),
+ needs_expr_temp_(false),
+ builder_(new StreamingFlowGraphBuilder(&translation_helper_,
+ zone_,
+ buffer,
+ buffer_length)),
+ type_translator_(builder_, /*finalize=*/true) {
+ Script& script = Script::Handle(Z, parsed_function->function().script());
+ H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets()));
+ H.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
+ H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names()));
+ type_translator_.active_class_ = &active_class_;
+}
+
+StreamingScopeBuilder::~StreamingScopeBuilder() {
+ delete builder_;
+}
+
+void StreamingScopeBuilder::DiscoverEnclosingElements(
+ Zone* zone,
+ const Function& function,
+ Function* outermost_function,
+ intptr_t* outermost_kernel_offset,
+ intptr_t* parent_class_offset) {
+ // Find out if there is an enclosing kernel class (which will be used to
+ // resolve type parameters).
+ *outermost_function = function.raw();
+ while (outermost_function->parent_function() != Object::null()) {
+ *outermost_function = outermost_function->parent_function();
+ }
+
+ if (outermost_function->kernel_function() != NULL) {
+ *outermost_kernel_offset =
+ static_cast<TreeNode*>(outermost_function->kernel_function())
+ ->kernel_offset();
+ *parent_class_offset = GetParentOffset(*outermost_kernel_offset);
+ }
+}
+
+ScopeBuildingResult* StreamingScopeBuilder::BuildScopes() {
+ if (result_ != NULL) return result_;
+
+ ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0);
+ result_ = new (Z) ScopeBuildingResult();
+
+ ParsedFunction* parsed_function = parsed_function_;
+ const Function& function = parsed_function->function();
+
+ // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
+ // e.g. for type translation.
+ const dart::Class& klass =
+ dart::Class::Handle(zone_, parsed_function_->function().Owner());
+ Function& outermost_function = Function::Handle(Z);
+ intptr_t outermost_kernel_offset = -1;
+ intptr_t parent_class_offset = -1;
+ DiscoverEnclosingElements(Z, function, &outermost_function,
+ &outermost_kernel_offset, &parent_class_offset);
+ // Use [klass]/[kernel_class] as active class. Type parameters will get
+ // resolved via [kernel_class] unless we are nested inside a static factory
+ // in which case we will use [member].
+ intptr_t class_type_parameters = 0;
+ intptr_t class_type_parameters_offset_start = -1;
+ if (parent_class_offset > 0) {
+ GetTypeParameterInfoForClass(parent_class_offset, &class_type_parameters,
+ &class_type_parameters_offset_start);
+ }
+ ActiveClassScope active_class_scope(&active_class_, class_type_parameters,
+ class_type_parameters_offset_start,
+ &klass);
+
+ bool member_is_procedure = false;
+ bool is_factory_procedure = false;
+ intptr_t member_type_parameters = 0;
+ intptr_t member_type_parameters_offset_start = -1;
+ GetTypeParameterInfoForPossibleProcedure(
+ outermost_kernel_offset, &member_is_procedure, &is_factory_procedure,
+ &member_type_parameters, &member_type_parameters_offset_start);
+
+ ActiveMemberScope active_member(&active_class_, member_is_procedure,
+ is_factory_procedure, member_type_parameters,
+ member_type_parameters_offset_start);
+
+ LocalScope* enclosing_scope = NULL;
+ if (function.IsLocalFunction()) {
+ enclosing_scope = LocalScope::RestoreOuterScope(
+ ContextScope::Handle(Z, function.context_scope()));
+ }
+ current_function_scope_ = scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
+ scope_->set_begin_token_pos(function.token_pos());
+ scope_->set_end_token_pos(function.end_token_pos());
+
+ LocalVariable* context_var = parsed_function->current_context_var();
+ context_var->set_is_forced_stack();
+ scope_->AddVariable(context_var);
+
+ parsed_function->SetNodeSequence(
+ new SequenceNode(TokenPosition::kNoSource, scope_));
+
+ intptr_t parent_offset = -1;
+ builder_->SetOffset(kernel_offset_);
+
+ switch (function.kind()) {
+ case RawFunction::kClosureFunction:
+ case RawFunction::kRegularFunction:
+ case RawFunction::kGetterFunction:
+ case RawFunction::kSetterFunction:
+ case RawFunction::kConstructor: {
+ const Tag tag = builder_->PeekTag();
+ if (tag == kProcedure) {
+ Tag has_function_node = ReadProcedureUntilFunctionNode(
+ &unused_word, &unused_intptr); // read first part of procedure.
+ if (has_function_node == kNothing) {
+ // Running a procedure without a function node doesn't make sense.
+ UNREACHABLE();
+ }
+ // Now at start of FunctionNode.
+ } else if (tag == kConstructor) {
+ // read first part of constructor.
+ parent_offset = ReadConstructorUntilFunctionNode();
+ // Now at start of FunctionNode.
+ // Notice that we also have a list of initializers after that!
+ } else if (tag == kFunctionNode) {
+ // Already at start of FunctionNode.
+ } else {
+ UNREACHABLE();
+ }
+ word async_marker_word;
+ ReadFunctionNodeUntilTypeParameters(
+ &async_marker_word,
+ &unused_word); // read first part of function node.
+ current_function_async_marker_ =
+ static_cast<FunctionNode::AsyncMarker>(async_marker_word);
+ // NOTE: FunctionNode is not read entirely yet! It continues below the if.
+
+ intptr_t pos = 0;
+ if (function.IsClosureFunction()) {
+ LocalVariable* variable = MakeVariable(
+ TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::ClosureParameter(), AbstractType::dynamic_type());
+ variable->set_is_forced_stack();
+ scope_->InsertParameterAt(pos++, variable);
+ } else if (!function.is_static()) {
+ // We use [is_static] instead of [IsStaticFunction] because the latter
+ // returns `false` for constructors.
+ dart::Class& klass = dart::Class::Handle(Z, function.Owner());
+ Type& klass_type = H.GetCanonicalType(klass);
+ LocalVariable* variable =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::This(), klass_type);
+ scope_->InsertParameterAt(pos++, variable);
+ result_->this_variable = variable;
+
+ // We visit instance field initializers because they might contain
+ // [Let] expressions and we need to have a mapping.
+ if (tag == kConstructor) {
+ ASSERT(parent_offset >= 0);
+ AlternativeReadingScope alt(builder_->reader_, parent_offset);
+ ReadClassUntilFields(); // read first part of class.
+ intptr_t list_length =
+ builder_->ReadListLength(); // read fields list length.
+ for (intptr_t i = 0; i < list_length; i++) {
+ intptr_t field_offset = builder_->ReaderOffset();
+ TokenPosition position;
+ TokenPosition end_position;
+ word flags;
+ ReadFieldUntilAnnotation(&position, &end_position, &flags,
+ &unused_intptr);
+ bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
+ builder_->SkipListOfExpressions(); // read annotations.
+ builder_->SkipDartType(); // read type.
+ Tag initializer_tag = builder_->ReadTag();
+ if (!is_static && initializer_tag == kSomething) {
+ EnterScope(field_offset);
+ VisitExpression(); // read initializer.
+ ExitScope(position, end_position);
+ } else if (initializer_tag == kSomething) {
+ builder_->SkipExpression(); // read initializer.
+ }
+ }
+ }
+ } else if (function.IsFactory()) {
+ LocalVariable* variable = MakeVariable(
+ TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
+ scope_->InsertParameterAt(pos++, variable);
+ result_->type_arguments_variable = variable;
+ }
+
+ // Continue reading FunctionNode.
+ builder_->SkipTypeParametersList(); // read type_parameters.
+ builder_->ReadUInt(); // read required_parameter_count.
+ AddPositionalAndNamedParameters(
+ pos); // read positional_parameters and named_parameters.
+
+ // We generate a syntethic body for implicit closure functions - which
+ // will forward the call to the real function.
+ // -> see BuildGraphOfImplicitClosureFunction
+ if (!function.IsImplicitClosureFunction()) {
+ builder_->SetOffset(kernel_offset_);
+ first_body_token_position_ = TokenPosition::kNoSource;
+ VisitNode();
+
+ // TODO(jensj): HACK: Push the begin token to after any parameters to
+ // avoid crash when breaking on definition line of async method in
+ // debugger. It seems that another scope needs to be added
+ // in which captures are made, but I can't make that work.
+ // This 'solution' doesn't crash, but I cannot see the parameters at
+ // that particular breakpoint either.
+ // Also push the end token to after the "}" to avoid crashing on
+ // stepping past the last line (to the "}" character).
+ if (first_body_token_position_.IsReal()) {
+ scope_->set_begin_token_pos(first_body_token_position_);
+ }
+ if (scope_->end_token_pos().IsReal()) {
+ scope_->set_end_token_pos(scope_->end_token_pos().Next());
+ }
+ }
+ break;
+ }
+ case RawFunction::kImplicitGetter:
+ case RawFunction::kImplicitStaticFinalGetter:
+ case RawFunction::kImplicitSetter: {
+ ASSERT(builder_->PeekTag() == kField);
+ if (IsStaticInitializer(function, Z)) {
+ VisitNode();
+ break;
+ }
+ bool is_setter = function.IsImplicitSetterFunction();
+ bool is_method = !function.IsStaticFunction();
+ intptr_t pos = 0;
+ if (is_method) {
+ dart::Class& klass = dart::Class::Handle(Z, function.Owner());
+ Type& klass_type = H.GetCanonicalType(klass);
+ LocalVariable* variable =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::This(), klass_type);
+ scope_->InsertParameterAt(pos++, variable);
+ result_->this_variable = variable;
+ }
+ if (is_setter) {
+ result_->setter_value =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::Value(), AbstractType::dynamic_type());
+ scope_->InsertParameterAt(pos++, result_->setter_value);
+ }
+ break;
+ }
+ case RawFunction::kMethodExtractor: {
+ // Add a receiver parameter. Though it is captured, we emit code to
+ // explicitly copy it to a fixed offset in a freshly-allocated context
+ // instead of using the generic code for regular functions.
+ // Therefore, it isn't necessary to mark it as captured here.
+ dart::Class& klass = dart::Class::Handle(Z, function.Owner());
+ Type& klass_type = H.GetCanonicalType(klass);
+ LocalVariable* variable =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::This(), klass_type);
+ scope_->InsertParameterAt(0, variable);
+ result_->this_variable = variable;
+ break;
+ }
+ case RawFunction::kNoSuchMethodDispatcher:
+ case RawFunction::kInvokeFieldDispatcher:
+ for (intptr_t i = 0; i < function.NumParameters(); ++i) {
+ LocalVariable* variable = MakeVariable(
+ TokenPosition::kNoSource, TokenPosition::kNoSource,
+ dart::String::ZoneHandle(Z, function.ParameterNameAt(i)),
+ AbstractType::dynamic_type());
+ scope_->InsertParameterAt(i, variable);
+ }
+ break;
+ case RawFunction::kSignatureFunction:
+ case RawFunction::kIrregexpFunction:
+ UNREACHABLE();
+ }
+ if (needs_expr_temp_) {
+ scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
+ }
+ parsed_function->AllocateVariables();
+
+ return result_;
+}
+
+intptr_t StreamingScopeBuilder::GetParentOffset(intptr_t offset) {
+ AlternativeReadingScope alt(builder_->reader_, offset);
+
+ Tag tag = builder_->PeekTag();
+ intptr_t parent_offset = -1;
+ switch (tag) {
+ case kConstructor:
+ return ReadConstructorUntilFunctionNode();
+ case kProcedure:
+ ReadProcedureUntilFunctionNode(
+ &unused_word, &parent_offset); // read first part of procedure.
+ return parent_offset;
+ case kField:
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &unused_word, &parent_offset);
+ return parent_offset;
+ default:
+ UNIMPLEMENTED();
+ return -1;
+ }
+}
+
+void StreamingScopeBuilder::GetTypeParameterInfoForClass(
+ intptr_t class_offset,
+ intptr_t* type_paremeter_counts,
+ intptr_t* type_paremeter_offset) {
+ AlternativeReadingScope alt(builder_->reader_, class_offset);
+
+ ReadClassUntilTypeParameters();
+ *type_paremeter_counts =
+ builder_->ReadListLength(); // read type_parameters list length.
+ *type_paremeter_offset = builder_->ReaderOffset();
+}
+
+void StreamingScopeBuilder::VisitNode() {
+ Tag tag = builder_->PeekTag();
+ switch (tag) {
+ case kConstructor:
+ VisitConstructor();
+ return;
+ case kProcedure:
+ VisitProcedure();
+ return;
+ case kField:
+ VisitField();
+ return;
+ case kFunctionNode:
+ VisitFunctionNode();
+ return;
+ default:
+ UNIMPLEMENTED();
+ return;
+ }
+}
+
+intptr_t StreamingScopeBuilder::ReadConstructorUntilFunctionNode() {
+ Tag tag = builder_->ReadTag();
+ ASSERT(tag == kConstructor);
+ builder_->SkipCanonicalNameReference(); // read canonical name reference.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ builder_->ReadFlags(); // read flags.
+ intptr_t parent_offset = builder_->ReadUInt(); // parent class binary offset.
+ builder_->SkipName(); // read name.
+ builder_->SkipListOfExpressions(); // read annotations.
+ return parent_offset;
+}
+
+void StreamingScopeBuilder::VisitConstructor() {
+ // Field initializers that come from non-static field declarations are
+ // compiled as if they appear in the constructor initializer list. This is
+ // important for closure-valued field initializers because the VM expects the
+ // corresponding closure functions to appear as if they were nested inside the
+ // constructor.
+ intptr_t parent_offset = ReadConstructorUntilFunctionNode();
+ ASSERT(parent_offset >= 0);
+ {
+ AlternativeReadingScope alt(builder_->reader_, parent_offset);
+ ReadClassUntilFields(); // read first part of class.
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read fields list length.
+ for (intptr_t i = 0; i < list_length; i++) {
+ word flags;
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &flags, &unused_intptr);
+ bool is_static = (flags & Field::kFlagStatic) == Field::kFlagStatic;
+ builder_->SkipListOfExpressions(); // read annotations.
+ builder_->SkipDartType(); // read type.
+ Tag initializer_tag = builder_->ReadTag();
+ if (!is_static && initializer_tag == kSomething) {
+ VisitExpression(); // read initializer.
+ } else if (initializer_tag == kSomething) {
+ builder_->SkipExpression(); // read initializer.
+ }
+ }
+ }
+
+ // Visit children (note that there's no reason to visit the name).
+ VisitFunctionNode();
+ intptr_t list_length =
+ builder_->ReadListLength(); // read initializers list length.
+ for (intptr_t i = 0; i < list_length; i++) {
+ VisitInitializer();
+ }
+}
+
+void StreamingScopeBuilder::VisitProcedure() {
+ Tag function_node = ReadProcedureUntilFunctionNode(
+ &unused_word, &unused_intptr); // read first part of procedure.
+ if (function_node == kSomething) {
+ VisitFunctionNode();
+ }
+}
+
+void StreamingScopeBuilder::ReadFieldUntilAnnotation(
+ TokenPosition* position,
+ TokenPosition* end_position,
+ word* flags,
+ intptr_t* parent_offset) {
+ Tag tag = builder_->ReadTag();
+ ASSERT(tag == kField);
+
+ builder_->SkipCanonicalNameReference(); // read canonical_name.
+ *position = builder_->ReadPosition(); // read position.
+ *end_position = builder_->ReadPosition(); // read end position.
+ *flags = builder_->ReadFlags(); // read flags.
+ *parent_offset = builder_->ReadUInt(); // read parent class binary offset.
+ builder_->SkipName(); // read name.
+ builder_->ReadUInt(); // source_uri_index.
+}
+
+void StreamingScopeBuilder::VisitField() {
+ ReadFieldUntilAnnotation(&unused_tokenposition, &unused_tokenposition,
+ &unused_intptr,
+ &unused_word); // read first part of field.
+ builder_->SkipListOfExpressions(); // read annotations.
+ VisitDartType(); // read type.
+ Tag tag = builder_->ReadTag(); // read initializer (part 1).
+ if (tag == kSomething) {
+ VisitExpression(); // read initializer (part 2).
+ }
+}
+
+Tag StreamingScopeBuilder::ReadProcedureUntilFunctionNode(
+ word* kind,
+ intptr_t* parent_offset) {
+ Tag tag = builder_->ReadTag(); // read tag.
+ ASSERT(tag == kProcedure);
+ builder_->SkipCanonicalNameReference(); // read canonical name reference.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ *kind = builder_->ReadByte(); // read kind.
+ builder_->ReadFlags(); // read flags.
+ *parent_offset = builder_->ReadUInt(); // read parent class binary offset.
+ builder_->SkipName(); // read name,
+ builder_->ReadUInt(); // read source_uri_index.
+ builder_->SkipListOfExpressions(); // read annotations.
+ return builder_->ReadTag(); // read tag for optional function node.
+}
+
+void StreamingScopeBuilder::GetTypeParameterInfoForPossibleProcedure(
+ intptr_t outermost_kernel_offset,
+ bool* member_is_procedure,
+ bool* is_factory_procedure,
+ intptr_t* member_type_parameters,
+ intptr_t* member_type_parameters_offset_start) {
+ if (outermost_kernel_offset >= 0) {
+ AlternativeReadingScope alt(builder_->reader_, outermost_kernel_offset);
+ Tag tag = builder_->PeekTag();
+ if (tag == kProcedure) {
+ *member_is_procedure = true;
+
+ word kind;
+ tag = ReadProcedureUntilFunctionNode(
+ &kind, &unused_intptr); // read first part of procedure.
+ *is_factory_procedure =
+ static_cast<Procedure::ProcedureKind>(kind) == Procedure::kFactory;
+
+ if (tag == kSomething) {
+ ReadFunctionNodeUntilTypeParameters(
+ &unused_word, &unused_word); // read first part of function node.
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read type_parameters list length.
+ if (list_length > 0) {
+ *member_type_parameters = list_length;
+ *member_type_parameters_offset_start = builder_->ReaderOffset();
+ }
+ }
+ }
+ }
+}
+
+void StreamingScopeBuilder::ReadClassUntilTypeParameters() {
+ Tag class_tag = builder_->ReadTag();
+ ASSERT(class_tag == kClass);
+ builder_->SkipCanonicalNameReference(); // read canonical_name.
+ builder_->ReadPosition(); // read position.
+ builder_->ReadBool(); // read is_abstract.
+ builder_->SkipStringReference(); // read name index.
+ builder_->ReadUInt(); // read source_uri_index.
+ builder_->SkipListOfExpressions(); // read annotations.
+}
+
+void StreamingScopeBuilder::ReadClassUntilFields() {
+ ReadClassUntilTypeParameters();
+ builder_->SkipTypeParametersList(); // read type_parameters.
+ Tag type_tag = builder_->ReadTag(); // read type (part 1).
+ if (type_tag == kSomething) {
+ builder_->SkipDartType(); // read type (part 2).
+ }
+ type_tag = builder_->ReadTag(); // read Mixed-in type (part 1).
+ if (type_tag == kSomething) {
+ builder_->SkipDartType(); // read Mixed-in type (part 2).
+ }
+ builder_->SkipListOfDartTypes(); // read implemented_classes.
+}
+
+void StreamingScopeBuilder::ReadFunctionNodeUntilTypeParameters(
+ word* async_marker,
+ word* dart_async_marker) {
+ Tag tag = builder_->ReadTag(); // read tag.
+ ASSERT(tag == kFunctionNode);
+
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read end position.
+ *async_marker = builder_->ReadByte(); // read async marker.
+ *dart_async_marker = builder_->ReadByte(); // read dart async marker.
+}
+
+void StreamingScopeBuilder::VisitFunctionNode() {
+ word async_marker_word;
+ word dart_async_marker_word;
+ ReadFunctionNodeUntilTypeParameters(&async_marker_word,
+ &dart_async_marker_word);
+ FunctionNode::AsyncMarker async_marker =
+ static_cast<FunctionNode::AsyncMarker>(async_marker_word);
+ FunctionNode::AsyncMarker dart_async_marker =
+ static_cast<FunctionNode::AsyncMarker>(dart_async_marker_word);
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read type_parameters list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ builder_->SkipStringReference(); // read ith name index.
+ VisitDartType(); // read ith bound.
+ }
+
+ if (FLAG_causal_async_stacks &&
+ (dart_async_marker == FunctionNode::kAsync ||
+ dart_async_marker == FunctionNode::kAsyncStar)) {
+ LocalVariable* asyncStackTraceVar = MakeVariable(
+ TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::AsyncStackTraceVar(), AbstractType::dynamic_type());
+ scope_->AddVariable(asyncStackTraceVar);
+ }
+
+ if (async_marker == FunctionNode::kSyncYielding) {
+ LocalScope* scope = parsed_function_->node_sequence()->scope();
+ intptr_t offset = parsed_function_->function().num_fixed_parameters();
+ for (intptr_t i = 0;
+ i < parsed_function_->function().NumOptionalPositionalParameters();
+ i++) {
+ scope->VariableAt(offset + i)->set_is_forced_stack();
+ }
+ }
+
+ // Read (but don't visit) the positional and named parameters, because they've
+ // already been added to the scope.
+
+ builder_->ReadUInt(); // read required_parameter_count.
+
+ builder_->SkipListOfVariableDeclarations(); // read list of positionals.
+ builder_->SkipListOfVariableDeclarations(); // read list of named.
+ builder_->SkipDartType(); // read return type.
+
+ if (builder_->ReadTag() == kSomething) {
+ PositionScope scope(builder_->reader_);
+ VisitStatement(); // Read body
+ first_body_token_position_ = builder_->reader_->min_position();
+ }
+
+ // Ensure that :await_jump_var, :await_ctx_var, :async_op and
+ // :async_stack_trace are captured.
+ if (async_marker == FunctionNode::kSyncYielding) {
+ {
+ LocalVariable* temp = NULL;
+ LookupCapturedVariableByName(
+ (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp,
+ Symbols::AwaitJumpVar());
+ }
+ {
+ LocalVariable* temp = NULL;
+ LookupCapturedVariableByName(
+ (depth_.function_ == 0) ? &result_->yield_context_variable : &temp,
+ Symbols::AwaitContextVar());
+ }
+ {
+ LocalVariable* temp =
+ scope_->LookupVariable(Symbols::AsyncOperation(), true);
+ if (temp != NULL) {
+ scope_->CaptureVariable(temp);
+ }
+ }
+ if (FLAG_causal_async_stacks) {
+ LocalVariable* temp =
+ scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true);
+ if (temp != NULL) {
+ scope_->CaptureVariable(temp);
+ }
+ }
+ }
+}
+
+void StreamingScopeBuilder::VisitInitializer() {
+ Tag tag = builder_->ReadTag();
+ switch (tag) {
+ case kInvalidInitializer:
+ return;
+ case kFieldInitializer:
+ builder_->SkipCanonicalNameReference(); // read field_reference.
+ VisitExpression(); // read value.
+ return;
+ case kSuperInitializer:
+ builder_->SkipCanonicalNameReference(); // read field_reference.
+ VisitArguments(); // read arguments.
+ return;
+ case kRedirectingInitializer:
+ builder_->SkipCanonicalNameReference(); // read field_reference.
+ VisitArguments(); // read arguments.
+ return;
+ case kLocalInitializer:
+ VisitVariableDeclaration(); // read variable.
+ return;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void StreamingScopeBuilder::VisitExpression() {
+ uint8_t payload = 0;
+ Tag tag = builder_->ReadTag(&payload);
+ switch (tag) {
+ case kInvalidExpression:
+ return;
+ case kVariableGet: {
+ builder_->ReadPosition(); // read position.
+ intptr_t variable_kernel_offset =
+ builder_->ReadUInt(); // read kernel position.
+ builder_->ReadUInt(); // read relative variable index.
+ builder_->SkipOptionalDartType(); // read promoted type.
+ LookupVariable(variable_kernel_offset);
+ return;
+ }
+ case kSpecializedVariableGet: {
+ builder_->ReadPosition(); // read position.
+ intptr_t variable_kernel_offset =
+ builder_->ReadUInt(); // read kernel position.
+ LookupVariable(variable_kernel_offset);
+ return;
+ }
+ case kVariableSet: {
+ builder_->ReadPosition(); // read position.
+ intptr_t variable_kernel_offset =
+ builder_->ReadUInt(); // read kernel position.
+ builder_->ReadUInt(); // read relative variable index.
+ LookupVariable(variable_kernel_offset);
+ VisitExpression(); // read expression.
+ return;
+ }
+ case kSpecializedVariableSet: {
+ builder_->ReadPosition(); // read position.
+ intptr_t variable_kernel_offset =
+ builder_->ReadUInt(); // read kernel position.
+ LookupVariable(variable_kernel_offset);
+ VisitExpression(); // read expression.
+ return;
+ }
+ case kPropertyGet:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read receiver.
+ builder_->SkipName(); // read name.
+ // Read unused "interface_target_reference".
+ builder_->SkipCanonicalNameReference();
+ return;
+ case kPropertySet:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read receiver.
+ builder_->SkipName(); // read name.
+ VisitExpression(); // read value.
+ // read unused "interface_target_reference".
+ builder_->SkipCanonicalNameReference();
+ return;
+ case kDirectPropertyGet:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read receiver.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ return;
+ case kDirectPropertySet:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read receiver.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ VisitExpression(); // read value·
+ return;
+ case kStaticGet:
+ builder_->ReadPosition(); // read position.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ return;
+ case kStaticSet:
+ builder_->ReadPosition(); // read position.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ VisitExpression(); // read expression.
+ return;
+ case kMethodInvocation:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read receiver.
+ builder_->SkipName(); // read name.
+ VisitArguments(); // read arguments.
+ // read unused "interface_target_reference".
+ builder_->SkipCanonicalNameReference();
+ return;
+ case kDirectMethodInvocation:
+ VisitExpression(); // read receiver.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ VisitArguments(); // read arguments.
+ return;
+ case kStaticInvocation:
+ case kConstStaticInvocation:
+ builder_->ReadPosition(); // read position.
+ builder_->SkipCanonicalNameReference(); // read procedure_reference.
+ VisitArguments(); // read arguments.
+ return;
+ case kConstructorInvocation:
+ case kConstConstructorInvocation:
+ builder_->ReadPosition(); // read position.
+ builder_->SkipCanonicalNameReference(); // read target_reference.
+ VisitArguments(); // read arguments.
+ return;
+ case kNot:
+ VisitExpression(); // read expression.
+ return;
+ case kLogicalExpression:
+ needs_expr_temp_ = true;
+ VisitExpression(); // read left.
+ builder_->SkipBytes(1); // read operator.
+ VisitExpression(); // read right.
+ return;
+ case kConditionalExpression: {
+ needs_expr_temp_ = true;
+ VisitExpression(); // read condition.
+ VisitExpression(); // read then.
+ VisitExpression(); // read otherwise.
+ builder_->SkipOptionalDartType(); // read unused static type.
+ return;
+ }
+ case kStringConcatenation: {
+ builder_->ReadPosition(); // read position.
+ intptr_t list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitExpression(); // read ith expression.
+ }
+ return;
+ }
+ case kIsExpression:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read operand.
+ VisitDartType(); // read type.
+ return;
+ case kAsExpression:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read operand.
+ VisitDartType(); // read type.
+ return;
+ case kSymbolLiteral:
+ builder_->SkipStringReference(); // read index into string table.
+ return;
+ case kTypeLiteral:
+ VisitDartType(); // read type.
+ return;
+ case kThisExpression:
+ HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ return;
+ case kRethrow:
+ builder_->ReadPosition(); // read position.
+ return;
+ case kThrow:
+ builder_->ReadPosition(); // read position.
+ VisitExpression(); // read expression.
+ return;
+ case kListLiteral:
+ case kConstListLiteral: {
+ builder_->ReadPosition(); // read position.
+ VisitDartType(); // read type.
+ intptr_t list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitExpression(); // read ith expression.
+ }
+ return;
+ }
+ case kMapLiteral:
+ case kConstMapLiteral: {
+ builder_->ReadPosition(); // read position.
+ VisitDartType(); // read key type.
+ VisitDartType(); // read value type.
+ intptr_t list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitExpression(); // read ith key.
+ VisitExpression(); // read ith value.
+ }
+ return;
+ }
+ case kFunctionExpression: {
+ intptr_t offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+ HandleLocalFunction(offset);
+ return;
+ }
+ case kLet: {
+ PositionScope scope(builder_->reader_);
+ intptr_t offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+
+ EnterScope(offset);
+
+ VisitVariableDeclaration(); // read variable declaration.
+ VisitExpression(); // read expression.
+
+ ExitScope(builder_->reader_->min_position(),
+ builder_->reader_->max_position());
+ return;
+ }
+ case kBigIntLiteral:
+ builder_->SkipStringReference(); // read string reference.
+ return;
+ case kStringLiteral:
+ builder_->SkipStringReference(); // read string reference.
+ return;
+ case kSpecialIntLiteral:
+ return;
+ case kNegativeIntLiteral:
+ builder_->ReadUInt(); // read value.
+ return;
+ case kPositiveIntLiteral:
+ builder_->ReadUInt(); // read value.
+ return;
+ case kDoubleLiteral:
+ builder_->SkipStringReference(); // read index into string table.
+ return;
+ case kTrueLiteral:
+ return;
+ case kFalseLiteral:
+ return;
+ case kNullLiteral:
+ return;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void StreamingScopeBuilder::VisitStatement() {
+ Tag tag = builder_->ReadTag(); // read tag.
+ switch (tag) {
+ case kInvalidStatement:
+ return;
+ case kExpressionStatement:
+ VisitExpression(); // read expression.
+ return;
+ case kBlock: {
+ PositionScope scope(builder_->reader_);
+ intptr_t offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+
+ EnterScope(offset);
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read number of statements.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitStatement(); // read ith statement.
+ }
+
+ ExitScope(builder_->reader_->min_position(),
+ builder_->reader_->max_position());
+ return;
+ }
+ case kEmptyStatement:
+ return;
+ case kAssertStatement: {
+ if (I->asserts()) {
+ VisitExpression(); // Read condition.
+ Tag tag = builder_->ReadTag(); // read (first part of) message.
+ if (tag == kSomething) {
+ VisitExpression(); // read (rest of) message.
+ }
+ } else {
+ builder_->SkipExpression(); // Read condition.
+ Tag tag = builder_->ReadTag(); // read (first part of) message.
+ if (tag == kSomething) {
+ builder_->SkipExpression(); // read (rest of) message.
+ }
+ }
+ return;
+ }
+ case kLabeledStatement:
+ VisitStatement(); // read body.
+ return;
+ case kBreakStatement:
+ builder_->ReadPosition(); // read position.
+ builder_->ReadUInt(); // read target_index.
+ return;
+ case kWhileStatement:
+ ++depth_.loop_;
+ VisitExpression(); // read condition.
+ VisitStatement(); // read body.
+ --depth_.loop_;
+ return;
+ case kDoStatement:
+ ++depth_.loop_;
+ VisitStatement(); // read body.
+ VisitExpression(); // read condition.
+ --depth_.loop_;
+ return;
+ case kForStatement: {
+ PositionScope scope(builder_->reader_);
+
+ intptr_t offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+
+ EnterScope(offset);
+
+ intptr_t list_length =
+ builder_->ReadListLength(); // read number of variables.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitVariableDeclaration(); // read ith variable.
+ }
+
+ ++depth_.loop_;
+
+ Tag tag = builder_->ReadTag(); // Read first part of condition.
+ if (tag == kSomething) {
+ VisitExpression(); // read rest of condition.
+ }
+ list_length = builder_->ReadListLength(); // read number of updates.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitExpression(); // read ith update.
+ }
+ VisitStatement(); // read body.
+
+ --depth_.loop_;
+
+ ExitScope(builder_->reader_->min_position(),
+ builder_->reader_->max_position());
+ return;
+ }
+ case kForInStatement:
+ case kAsyncForInStatement: {
+ PositionScope scope(builder_->reader_);
+
+ intptr_t start_offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+
+ TokenPosition position = builder_->ReadPosition(); // read position.
+
+ // Notice the ordering: We skip the variable, read the iterable, go back,
+ // re-read the variable, go forward to after having read the iterable.
+ intptr_t offset = builder_->ReaderOffset();
+ builder_->SkipVariableDeclaration(); // read variable.
+ VisitExpression(); // read iterable.
+
+ ++depth_.for_in_;
+ AddIteratorVariable();
+ ++depth_.loop_;
+ EnterScope(start_offset);
+
+ {
+ AlternativeReadingScope alt(builder_->reader_, offset);
+ VisitVariableDeclaration(); // read variable.
+ }
+ VisitStatement(); // read body.
+
+ if (!position.IsReal()) {
+ position = builder_->reader_->min_position();
+ }
+ // TODO(jensj): From kernel_binary.cc
+ // forinstmt->variable_->set_end_position(forinstmt->position_);
+ ExitScope(position, builder_->reader_->max_position());
+ --depth_.loop_;
+ --depth_.for_in_;
+ return;
+ }
+ case kSwitchStatement: {
+ AddSwitchVariable();
+ VisitExpression(); // read condition.
+ int num_cases = builder_->ReadListLength(); // read number of cases.
+ for (intptr_t i = 0; i < num_cases; ++i) {
+ int num_expressions =
+ builder_->ReadListLength(); // read number of expressions.
+ for (intptr_t j = 0; j < num_expressions; ++j) {
+ builder_->ReadPosition(); // read jth position.
+ VisitExpression(); // read jth expression.
+ }
+ builder_->ReadBool(); // read is_default.
+ VisitStatement(); // read body.
+ }
+ return;
+ }
+ case kContinueSwitchStatement:
+ builder_->ReadUInt(); // read target_index.
+ return;
+ case kIfStatement:
+ VisitExpression(); // read condition.
+ VisitStatement(); // read then.
+ VisitStatement(); // read otherwise.
+ return;
+ case kReturnStatement: {
+ if ((depth_.function_ == 0) && (depth_.finally_ > 0) &&
+ (result_->finally_return_variable == NULL)) {
+ const dart::String& name = H.DartSymbol(":try_finally_return_value");
+ LocalVariable* variable =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ name, AbstractType::dynamic_type());
+ current_function_scope_->AddVariable(variable);
+ result_->finally_return_variable = variable;
+ }
+
+ builder_->ReadPosition(); // read position
+ Tag tag = builder_->ReadTag(); // read (first part of) expression.
+ if (tag == kSomething) {
+ VisitExpression(); // read (rest of) expression.
+ }
+ return;
+ }
+ case kTryCatch: {
+ ++depth_.try_;
+ AddTryVariables();
+ VisitStatement(); // read body.
+ --depth_.try_;
+
+ ++depth_.catch_;
+ AddCatchVariables();
+
+ builder_->ReadBool(); // read any_catch_needs_stack_trace.
+ intptr_t num_catches =
+ builder_->ReadListLength(); // read number of catches.
+ for (intptr_t i = 0; i < num_catches; ++i) {
+ PositionScope scope(builder_->reader_);
+ intptr_t offset = builder_->ReaderOffset(); // Catch has no tag.
+
+ EnterScope(offset);
+
+ builder_->SkipDartType(); // read guard.
+ tag = builder_->ReadTag(); // read first part of exception.
+ if (tag == kSomething) {
+ VisitVariableDeclaration(); // read exception.
+ }
+ tag = builder_->ReadTag(); // read first part of stack trace.
+ if (tag == kSomething) {
+ VisitVariableDeclaration(); // read stack trace.
+ }
+ VisitStatement(); // read body.
+
+ ExitScope(builder_->reader_->min_position(),
+ builder_->reader_->max_position());
+ }
+ --depth_.catch_;
+ return;
+ }
+ case kTryFinally: {
+ ++depth_.try_;
+ ++depth_.finally_;
+ AddTryVariables();
+
+ VisitStatement(); // read body.
+
+ --depth_.finally_;
+ --depth_.try_;
+ ++depth_.catch_;
+ AddCatchVariables();
+
+ VisitStatement(); // read finalizer.
+
+ --depth_.catch_;
+ return;
+ }
+ case kYieldStatement: {
+ builder_->ReadPosition(); // read position.
+ word flags = builder_->ReadByte(); // read flags.
+ builder_->SkipExpression(); // read expression.
+
+ ASSERT((flags & YieldStatement::kFlagNative) ==
+ YieldStatement::kFlagNative);
+ if (depth_.function_ == 0) {
+ AddSwitchVariable();
+ // Promote all currently visible local variables into the context.
+ // TODO(27590) CaptureLocalVariables promotes to many variables into
+ // the scope. Mark those variables as stack_local.
+ // TODO(27590) we don't need to promote those variables that are
+ // not used across yields.
+ scope_->CaptureLocalVariables(current_function_scope_);
+ }
+ return;
+ }
+ case kVariableDeclaration:
+ VisitVariableDeclaration(); // read variable declaration.
+ return;
+ case kFunctionDeclaration: {
+ intptr_t offset =
+ builder_->ReaderOffset() - 1; // -1 to include tag byte.
+ builder_->ReadPosition(); // read position.
+ VisitVariableDeclaration(); // read variable declaration.
+ HandleLocalFunction(offset); // read function node.
+ return;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+void StreamingScopeBuilder::VisitArguments() {
+ builder_->ReadUInt(); // read num_arguments.
+
+ // Types
+ intptr_t list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitDartType(); // read ith type.
+ }
+
+ // Positional.
+ list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ VisitExpression(); // read ith positional.
+ }
+
+ // Named.
+ list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ builder_->SkipStringReference(); // read ith name index.
+ VisitExpression(); // read ith expression.
+ }
+}
+
+void StreamingScopeBuilder::VisitVariableDeclaration() {
+ PositionScope scope(builder_->reader_);
+
+ intptr_t kernel_offset_no_tag = builder_->ReaderOffset();
+ TokenPosition position = builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read equals position.
+ word flags = builder_->ReadFlags(); // read flags.
+ bool is_final = (flags & VariableDeclaration::kFlagFinal) ==
+ VariableDeclaration::kFlagFinal;
+ StringIndex name_index = builder_->ReadStringReference(); // read name index.
+ intptr_t offset_for_type = builder_->ReaderOffset();
+ AbstractType& type = T.BuildVariableType(); // read type.
+
+ // In case `declaration->IsConst()` the flow graph building will take care of
+ // evaluating the constant and setting it via
+ // `declaration->SetConstantValue()`.
+ const dart::String& name = (H.StringSize(name_index) == 0)
+ ? GenerateName(":var", name_index_++)
+ : H.DartSymbol(name_index);
+ // We also need to visit the type.
+ builder_->SetOffset(offset_for_type);
+ VisitDartType(); // read type.
+
+ Tag tag = builder_->ReadTag(); // read (first part of) initializer.
+ if (tag == kSomething) {
+ VisitExpression(); // read (actual) initializer.
+ }
+
+ // Go to next token position so it ends *after* the last potentially
+ // debuggable position in the initializer.
+ TokenPosition end_position = builder_->reader_->max_position();
+ if (end_position.IsReal()) {
+ end_position.Next();
+ }
+ LocalVariable* variable = MakeVariable(position, end_position, name, type);
+ if (is_final) {
+ variable->set_is_final();
+ }
+ scope_->AddVariable(variable);
+ result_->locals.Insert(kernel_offset_no_tag, variable);
+}
+
+void StreamingScopeBuilder::VisitDartType() {
+ Tag tag = builder_->ReadTag();
+ switch (tag) {
+ case kInvalidType:
+ case kDynamicType:
+ case kVoidType:
+ case kBottomType:
+ // those contain nothing.
+ return;
+ case kInterfaceType:
+ VisitInterfaceType(false);
+ return;
+ case kSimpleInterfaceType:
+ VisitInterfaceType(true);
+ return;
+ case kFunctionType:
+ VisitFunctionType(false);
+ return;
+ case kSimpleFunctionType:
+ VisitFunctionType(true);
+ return;
+ case kTypeParameterType:
+ VisitTypeParameterType();
+ return;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void StreamingScopeBuilder::VisitInterfaceType(bool simple) {
+ builder_->ReadUInt(); // read klass_name.
+ if (!simple) {
+ intptr_t length = builder_->ReadListLength(); // read number of types.
+ for (intptr_t i = 0; i < length; ++i) {
+ VisitDartType(); // read the ith type.
+ }
+ }
+}
+
+void StreamingScopeBuilder::VisitFunctionType(bool simple) {
+ if (!simple) {
+ intptr_t list_length =
+ builder_->ReadListLength(); // read type_parameters list length.
+ for (int i = 0; i < list_length; ++i) {
+ builder_->SkipStringReference(); // read string index (name).
+ VisitDartType(); // read dart type.
+ }
+ builder_->ReadUInt(); // read required parameter count.
+ builder_->ReadUInt(); // read total parameter count.
+ }
+
+ const intptr_t positional_count =
+ builder_->ReadListLength(); // read positional_parameters list length.
+ for (intptr_t i = 0; i < positional_count; ++i) {
+ VisitDartType(); // read ith positional parameter.
+ }
+
+ if (!simple) {
+ const intptr_t named_count =
+ builder_->ReadListLength(); // read named_parameters list length.
+ for (intptr_t i = 0; i < named_count; ++i) {
+ // read string reference (i.e. named_parameters[i].name).
+ builder_->SkipStringReference();
+ VisitDartType(); // read named_parameters[i].type.
+ }
+ }
+
+ VisitDartType(); // read return type.
+}
+
+void StreamingScopeBuilder::VisitTypeParameterType() {
+ Function& function = Function::Handle(Z, parsed_function_->function().raw());
+ while (function.IsClosureFunction()) {
+ function = function.parent_function();
+ }
+
+ if (function.IsFactory()) {
+ // The type argument vector is passed as the very first argument to the
+ // factory constructor function.
+ HandleSpecialLoad(&result_->type_arguments_variable,
+ Symbols::TypeArgumentsParameter());
+ } else {
+ // The type argument vector is stored on the instance object. We therefore
+ // need to capture `this`.
+ HandleSpecialLoad(&result_->this_variable, Symbols::This());
+ }
+
+ builder_->ReadUInt(); // read index for parameter.
+ builder_->ReadUInt(); // read binary offset.
+ builder_->SkipOptionalDartType(); // read bound bound.
+}
+
+void StreamingScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
+ // "Peek" ahead into the function node
+ intptr_t offset = builder_->ReaderOffset();
+
+ Tag tag = builder_->ReadTag(); // read tag.
+ ASSERT(tag == kFunctionNode);
+ TokenPosition position = builder_->ReadPosition(); // read position.
+ TokenPosition end_position = builder_->ReadPosition(); // read end position.
+ FunctionNode::AsyncMarker async_marker =
+ static_cast<FunctionNode::AsyncMarker>(
+ builder_->ReadByte()); // read async marker.
+ builder_->ReadByte(); // read dart async marker.
+ builder_->SkipTypeParametersList(); // read type_parameters.
+
+ LocalScope* saved_function_scope = current_function_scope_;
+ FunctionNode::AsyncMarker saved_function_async_marker =
+ current_function_async_marker_;
+ StreamingScopeBuilder::DepthState saved_depth_state = depth_;
+ depth_ = DepthState(depth_.function_ + 1);
+ EnterScope(parent_kernel_offset);
+ current_function_scope_ = scope_;
+ current_function_async_marker_ = async_marker;
+ if (depth_.function_ == 1) {
+ FunctionScope function_scope = {offset, scope_};
+ result_->function_scopes.Add(function_scope);
+ }
+
+ builder_->ReadUInt(); // read required_parameter_count.
+ // read positional_parameters and named_parameters.
+ AddPositionalAndNamedParameters();
+
+ // "Peek" is now done.
+ builder_->SetOffset(offset);
+
+ VisitFunctionNode(); // read function node.
+
+ ExitScope(position, end_position);
+ depth_ = saved_depth_state;
+ current_function_scope_ = saved_function_scope;
+ current_function_async_marker_ = saved_function_async_marker;
+}
+
+void StreamingScopeBuilder::EnterScope(intptr_t kernel_offset) {
+ scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
+ ASSERT(kernel_offset >= 0);
+ result_->scopes.Insert(kernel_offset, scope_);
+}
+
+
+void StreamingScopeBuilder::ExitScope(TokenPosition start_position,
+ TokenPosition end_position) {
+ scope_->set_begin_token_pos(start_position);
+ scope_->set_end_token_pos(end_position);
+ scope_ = scope_->parent();
+}
+
+void StreamingScopeBuilder::AddPositionalAndNamedParameters(intptr_t pos) {
+ // List of positional.
+ intptr_t list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ AddVariableDeclarationParameter(pos++); // read ith positional parameter.
+ }
+
+ // List of named.
+ list_length = builder_->ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ AddVariableDeclarationParameter(pos++); // read ith named parameter.
+ }
+}
+
+void StreamingScopeBuilder::AddVariableDeclarationParameter(intptr_t pos) {
+ intptr_t kernel_offset = builder_->ReaderOffset(); // no tag.
+ TokenPosition position = builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read equals position.
+ word flags = builder_->ReadFlags(); // read flags.
+ bool is_final = (flags & VariableDeclaration::kFlagFinal) ==
+ VariableDeclaration::kFlagFinal;
+ String& name = H.DartSymbol(builder_->ReadStringReference()); // read name.
+ AbstractType& type = T.BuildVariableType(); // read type.
+
+ LocalVariable* variable = MakeVariable(position, position, name, type);
+ if (is_final) {
+ variable->set_is_final();
+ }
+ if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
+ variable->set_is_forced_stack();
+ }
+ scope_->InsertParameterAt(pos, variable);
+ result_->locals.Insert(kernel_offset, variable);
+
+ // The default value may contain 'let' bindings for which the constant
+ // evaluator needs scope bindings.
+ Tag tag = builder_->ReadTag();
+ if (tag == kSomething) {
+ VisitExpression(); // read initializer.
+ }
+}
+
+LocalVariable* StreamingScopeBuilder::MakeVariable(
+ TokenPosition declaration_pos,
+ TokenPosition token_pos,
+ const dart::String& name,
+ const AbstractType& type) {
+ return new (Z) LocalVariable(declaration_pos, token_pos, name, type);
+}
+
+void StreamingScopeBuilder::AddExceptionVariable(
+ GrowableArray<LocalVariable*>* variables,
+ const char* prefix,
+ intptr_t nesting_depth) {
+ LocalVariable* v = NULL;
+
+ // If we are inside a function with yield points then Kernel transformer
+ // could have lifted some of the auxiliary exception variables into the
+ // context to preserve them across yield points because they might
+ // be needed for rethrow.
+ // Check if it did and capture such variables instead of introducing
+ // new local ones.
+ // Note: function that wrap kSyncYielding function does not contain
+ // its own try/catches.
+ if (current_function_async_marker_ == FunctionNode::kSyncYielding) {
+ ASSERT(current_function_scope_->parent() != NULL);
+ v = current_function_scope_->parent()->LocalLookupVariable(
+ GenerateName(prefix, nesting_depth - 1));
+ if (v != NULL) {
+ scope_->CaptureVariable(v);
+ }
+ }
+
+ // No need to create variables for try/catch-statements inside
+ // nested functions.
+ if (depth_.function_ > 0) return;
+ if (variables->length() >= nesting_depth) return;
+
+ // If variable was not lifted by the transformer introduce a new
+ // one into the current function scope.
+ if (v == NULL) {
+ v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ GenerateName(prefix, nesting_depth - 1),
+ AbstractType::dynamic_type());
+
+ // If transformer did not lift the variable then there is no need
+ // to lift it into the context when we encouter a YieldStatement.
+ v->set_is_forced_stack();
+ current_function_scope_->AddVariable(v);
+ }
+
+ variables->Add(v);
+}
+
+void StreamingScopeBuilder::AddTryVariables() {
+ AddExceptionVariable(&result_->catch_context_variables,
+ ":saved_try_context_var", depth_.try_);
+}
+
+
+void StreamingScopeBuilder::AddCatchVariables() {
+ AddExceptionVariable(&result_->exception_variables, ":exception",
+ depth_.catch_);
+ AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace",
+ depth_.catch_);
+}
+
+
+void StreamingScopeBuilder::AddIteratorVariable() {
+ if (depth_.function_ > 0) return;
+ if (result_->iterator_variables.length() >= depth_.for_in_) return;
+
+ ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1);
+ LocalVariable* iterator =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ GenerateName(":iterator", depth_.for_in_ - 1),
+ AbstractType::dynamic_type());
+ current_function_scope_->AddVariable(iterator);
+ result_->iterator_variables.Add(iterator);
+}
+
+void StreamingScopeBuilder::AddSwitchVariable() {
+ if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) {
+ LocalVariable* variable =
+ MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::SwitchExpr(), AbstractType::dynamic_type());
+ variable->set_is_forced_stack();
+ current_function_scope_->AddVariable(variable);
+ result_->switch_variable = variable;
+ }
+}
+
+StringIndex StreamingScopeBuilder::GetNameFromVariableDeclaration(
+ intptr_t kernel_offset) {
+ // Temporarily go to the variable declaration, read the name.
+ AlternativeReadingScope alt(builder_->reader_, kernel_offset);
+ builder_->ReadPosition(); // read position.
+ builder_->ReadPosition(); // read equals position.
+ builder_->ReadFlags(); // read flags.
+ return builder_->ReadStringReference(); // read name index.
+}
+
+void StreamingScopeBuilder::LookupVariable(intptr_t declaration_binary_offest) {
+ LocalVariable* variable = result_->locals.Lookup(declaration_binary_offest);
+ if (variable == NULL) {
+ // We have not seen a declaration of the variable, so it must be the
+ // case that we are compiling a nested function and the variable is
+ // declared in an outer scope. In that case, look it up in the scope by
+ // name and add it to the variable map to simplify later lookup.
+ ASSERT(current_function_scope_->parent() != NULL);
+
+ StringIndex var_name =
+ GetNameFromVariableDeclaration(declaration_binary_offest);
+
+ const dart::String& name = H.DartSymbol(var_name);
+ variable = current_function_scope_->parent()->LookupVariable(name, true);
+ ASSERT(variable != NULL);
+ result_->locals.Insert(declaration_binary_offest, variable);
+ }
+
+ if (variable->owner()->function_level() < scope_->function_level()) {
+ // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two
+ // different reasons:
+ // Scenario 1:
+ // We need to know which variables defined in this function
+ // are closed over by nested closures in order to ensure we will
+ // create a [Context] object of appropriate size and store captured
+ // variables there instead of the stack.
+ // Scenario 2:
+ // We need to find out which variables defined in enclosing functions
+ // are closed over by this function/closure or nested closures. This
+ // is necessary in order to build a fat flattened [ContextScope]
+ // object.
+ scope_->CaptureVariable(variable);
+ } else {
+ ASSERT(variable->owner()->function_level() == scope_->function_level());
+ }
+}
+
+const dart::String& StreamingScopeBuilder::GenerateName(const char* prefix,
+ intptr_t suffix) {
+ char name[64];
+ OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
+ return H.DartSymbol(name);
+}
+
+void StreamingScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
+ const dart::String& symbol) {
+ if (current_function_scope_->parent() != NULL) {
+ // We are building the scope tree of a closure function and saw [node]. We
+ // lazily populate the variable using the parent function scope.
+ if (*variable == NULL) {
+ *variable =
+ current_function_scope_->parent()->LookupVariable(symbol, true);
+ ASSERT(*variable != NULL);
+ }
+ }
+
+ if ((current_function_scope_->parent() != NULL) ||
+ (scope_->function_level() > 0)) {
+ // Every scope we use the [variable] from needs to be notified of the usage
+ // in order to ensure that preserving the context scope on that particular
+ // use-site also includes the [variable].
+ scope_->CaptureVariable(*variable);
+ }
+}
+
+void StreamingScopeBuilder::LookupCapturedVariableByName(
+ LocalVariable** variable,
+ const dart::String& name) {
+ if (*variable == NULL) {
+ *variable = scope_->LookupVariable(name, true);
+ ASSERT(*variable != NULL);
+ scope_->CaptureVariable(*variable);
+ }
+}
StreamingDartTypeTranslator::StreamingDartTypeTranslator(
StreamingFlowGraphBuilder* builder,
@@ -38,6 +1586,22 @@ AbstractType& StreamingDartTypeTranslator::BuildType() {
return dart::AbstractType::ZoneHandle(Z, result_.raw());
}
+AbstractType& StreamingDartTypeTranslator::BuildVariableType() {
+ AbstractType& abstract_type = BuildType();
+
+ // We return a new `ZoneHandle` here on purpose: The intermediate language
+ // instructions do not make a copy of the handle, so we do it.
+ AbstractType& type = Type::ZoneHandle(Z);
+
+ if (abstract_type.IsMalformed()) {
+ type = AbstractType::dynamic_type().raw();
+ } else {
+ type = result_.raw();
+ }
+
+ return type;
+}
+
void StreamingDartTypeTranslator::BuildTypeInternal() {
Tag tag = builder_->ReadTag();
switch (tag) {
@@ -105,13 +1669,12 @@ void StreamingDartTypeTranslator::BuildInterfaceType(bool simple) {
void StreamingDartTypeTranslator::BuildFunctionType(bool simple) {
intptr_t list_length = 0;
- intptr_t* type_parameters = NULL;
+ intptr_t first_item_offest = -1;
if (!simple) {
list_length =
builder_->ReadListLength(); // read type_parameters list length
- type_parameters = new intptr_t[list_length];
+ first_item_offest = builder_->ReaderOffset();
for (int i = 0; i < list_length; ++i) {
- type_parameters[i] = builder_->ReaderOffset();
builder_->SkipStringReference(); // read string index (name).
builder_->SkipDartType(); // read dart type.
}
@@ -124,7 +1687,7 @@ void StreamingDartTypeTranslator::BuildFunctionType(bool simple) {
// checker and the runtime unless explicitly specified otherwise.
//
// So we convert malformed return/parameter types to `dynamic`.
- TypeParameterScope scope(this, type_parameters, list_length);
+ TypeParameterScope scope(this, first_item_offest, list_length);
Function& signature_function = Function::ZoneHandle(
Z, Function::NewSignatureFunction(*active_class_->klass,
@@ -205,23 +1768,17 @@ void StreamingDartTypeTranslator::BuildFunctionType(bool simple) {
result_ = signature_type.raw();
}
-static intptr_t FindTypeParameterIndex(intptr_t* parameters,
- intptr_t parameters_count,
- intptr_t look_for) {
+intptr_t StreamingDartTypeTranslator::FindTypeParameterIndex(
+ intptr_t parameters_offset,
+ intptr_t parameters_count,
+ intptr_t look_for) {
+ AlternativeReadingScope alt(builder_->reader_, parameters_offset);
for (intptr_t i = 0; i < parameters_count; ++i) {
- if (look_for == parameters[i]) {
- return i;
- }
- }
- return -1;
-}
-
-static intptr_t FindTypeParameterIndex(List<TypeParameter>* parameters,
- intptr_t look_for) {
- for (intptr_t i = 0; i < parameters->length(); ++i) {
- if (look_for == (*parameters)[i]->kernel_offset()) {
+ if (look_for == builder_->ReaderOffset()) {
return i;
}
+ builder_->SkipStringReference(); // read string index (name).
+ builder_->SkipDartType(); // read dart type.
}
return -1;
}
@@ -240,17 +1797,15 @@ void StreamingDartTypeTranslator::BuildTypeParameterType() {
for (TypeParameterScope* scope = type_parameter_scope_; scope != NULL;
scope = scope->outer()) {
const intptr_t index = FindTypeParameterIndex(
- scope->parameters(), scope->parameters_count(), binary_offset);
+ scope->parameters_offset(), scope->parameters_count(), binary_offset);
if (index >= 0) {
result_ ^= dart::Type::DynamicType();
return;
}
}
- if ((active_class_->member != NULL) && active_class_->member->IsProcedure()) {
- Procedure* procedure = Procedure::Cast(active_class_->member);
- if ((procedure->function() != NULL) &&
- (procedure->function()->type_parameters().length() > 0)) {
+ if (active_class_->member_is_procedure) {
+ if (active_class_->member_type_parameters > 0) {
//
// WARNING: This is a little hackish:
//
@@ -270,9 +1825,10 @@ void StreamingDartTypeTranslator::BuildTypeParameterType() {
// }
//
const intptr_t index = FindTypeParameterIndex(
- &procedure->function()->type_parameters(), binary_offset);
+ active_class_->member_type_parameters_offset_start,
+ active_class_->member_type_parameters, binary_offset);
if (index >= 0) {
- if (procedure->kind() == Procedure::kFactory) {
+ if (active_class_->member_is_factory_procedure) {
// The index of the type parameter in [parameters] is
// the same index into the `klass->type_parameters()` array.
result_ ^= dart::TypeArguments::Handle(
@@ -286,10 +1842,9 @@ void StreamingDartTypeTranslator::BuildTypeParameterType() {
}
}
- ASSERT(active_class_->kernel_class != NULL);
- List<TypeParameter>* parameters =
- &active_class_->kernel_class->type_parameters();
- const intptr_t index = FindTypeParameterIndex(parameters, binary_offset);
+ const intptr_t index = FindTypeParameterIndex(
+ active_class_->class_type_parameters_offset_start,
+ active_class_->class_type_parameters, binary_offset);
if (index >= 0) {
// The index of the type parameter in [parameters] is
// the same index into the `klass->type_parameters()` array.
@@ -323,6 +1878,10 @@ const TypeArguments& StreamingDartTypeTranslator::BuildTypeArguments(
}
if (result_.IsMalformed()) {
type_arguments = TypeArguments::null();
+ // skip rest of arguments.
+ for (++i; i < length; ++i) {
+ builder_->SkipDartType();
+ }
return type_arguments;
}
type_arguments.SetTypeAt(i, result_);
@@ -348,8 +1907,7 @@ StreamingDartTypeTranslator::BuildInstantiatedTypeArguments(
Type& type = Type::Handle(
Z, Type::New(receiver_class, type_arguments, TokenPosition::kNoSource));
if (finalize_) {
- type ^=
- ClassFinalizer::FinalizeType(*builder_->active_class()->klass, type);
+ type ^= ClassFinalizer::FinalizeType(*active_class_->klass, type);
}
const TypeArguments& instantiated_type_arguments =
@@ -387,8 +1945,12 @@ StreamingConstantEvaluator::StreamingConstantEvaluator(
type_translator_(builder_->type_translator_),
script_(Script::Handle(
zone_,
- builder == NULL ? Script::null()
- : builder_->parsed_function()->function().script())),
+ // TODO(jensj): This was added to temporarily be able to let the scope
+ // builder have a StreamingFlowGraphBuilder to get access to
+ // reading functions.
+ (builder == NULL || builder_->flow_graph_builder_ == NULL)
+ ? Script::null()
+ : builder_->parsed_function()->function().script())),
result_(Instance::Handle(zone_)) {}
@@ -1280,7 +2842,7 @@ Fragment StreamingFlowGraphBuilder::BuildStatement() {
case kYieldStatement:
return BuildYieldStatement();
case kVariableDeclaration:
- return BuildVariableDeclaration(true);
+ return BuildVariableDeclaration();
case kFunctionDeclaration:
// TODO(jensj)
UNIMPLEMENTED();
@@ -1316,10 +2878,8 @@ uint32_t StreamingFlowGraphBuilder::ReadUInt() {
}
uint32_t StreamingFlowGraphBuilder::PeekUInt() {
- intptr_t offset = ReaderOffset();
- uint32_t result = reader_->ReadUInt();
- SetOffset(offset);
- return result;
+ AlternativeReadingScope alt(reader_);
+ return reader_->ReadUInt();
}
intptr_t StreamingFlowGraphBuilder::ReadListLength() {
@@ -1427,30 +2987,18 @@ void StreamingFlowGraphBuilder::SkipOptionalDartType() {
void StreamingFlowGraphBuilder::SkipInterfaceType(bool simple) {
ReadUInt(); // read klass_name.
if (!simple) {
- intptr_t length = ReadListLength(); // read number of types.
- for (intptr_t i = 0; i < length; ++i) {
- SkipDartType(); // skip the ith type.
- }
+ SkipListOfDartTypes(); // read list of types.
}
}
void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) {
if (!simple) {
- intptr_t list_length =
- ReadListLength(); // read type_parameters list length.
- for (int i = 0; i < list_length; ++i) {
- SkipStringReference(); // read string index (name).
- SkipDartType(); // read dart type.
- }
+ SkipTypeParametersList(); // read type_parameters.
ReadUInt(); // read required parameter count.
ReadUInt(); // read total parameter count.
}
- const intptr_t positional_count =
- ReadListLength(); // read positional_parameters list length.
- for (intptr_t i = 0; i < positional_count; ++i) {
- SkipDartType(); // read ith positional parameter.
- }
+ SkipListOfDartTypes(); // read positional_parameters types.
if (!simple) {
const intptr_t named_count =
@@ -1465,6 +3013,35 @@ void StreamingFlowGraphBuilder::SkipFunctionType(bool simple) {
SkipDartType(); // read return type.
}
+void StreamingFlowGraphBuilder::SkipListOfExpressions() {
+ intptr_t list_length = ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ SkipExpression(); // read ith expression.
+ }
+}
+
+void StreamingFlowGraphBuilder::SkipListOfDartTypes() {
+ intptr_t list_length = ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ SkipDartType(); // read ith type.
+ }
+}
+
+void StreamingFlowGraphBuilder::SkipListOfVariableDeclarations() {
+ intptr_t list_length = ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ SkipVariableDeclaration(); // read ith variable declaration.
+ }
+}
+
+void StreamingFlowGraphBuilder::SkipTypeParametersList() {
+ intptr_t list_length = ReadListLength(); // read list length.
+ for (intptr_t i = 0; i < list_length; ++i) {
+ SkipStringReference(); // read ith name index.
+ SkipDartType(); // read ith bound.
+ }
+}
+
void StreamingFlowGraphBuilder::SkipExpression() {
uint8_t payload = 0;
Tag tag = ReadTag(&payload);
@@ -1566,14 +3143,10 @@ void StreamingFlowGraphBuilder::SkipExpression() {
SkipExpression(); // read otherwise.
SkipOptionalDartType(); // read unused static type.
return;
- case kStringConcatenation: {
+ case kStringConcatenation:
ReadPosition(); // read position.
- intptr_t list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipExpression(); // read ith expression.
- }
+ SkipListOfExpressions(); // read list of expressions.
return;
- }
case kIsExpression:
ReadPosition(); // read position.
SkipExpression(); // read operand.
@@ -1600,15 +3173,11 @@ void StreamingFlowGraphBuilder::SkipExpression() {
SkipExpression(); // read expression.
return;
case kListLiteral:
- case kConstListLiteral: {
+ case kConstListLiteral:
ReadPosition(); // read position.
SkipDartType(); // read type.
- intptr_t list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipExpression(); // read ith expression.
- }
+ SkipListOfExpressions(); // read list of expressions.
return;
- }
case kMapLiteral:
case kConstMapLiteral: {
ReadPosition(); // read position.
@@ -1622,8 +3191,7 @@ void StreamingFlowGraphBuilder::SkipExpression() {
return;
}
case kFunctionExpression:
- // TODO(jensj)
- UNIMPLEMENTED();
+ SkipFunctionNode(); // read function node.
return;
case kLet:
SkipVariableDeclaration(); // read variable declaration.
@@ -1698,18 +3266,12 @@ void StreamingFlowGraphBuilder::SkipStatement() {
SkipExpression(); // read condition.
return;
case kForStatement: {
- intptr_t list_length = ReadListLength(); // read number of variables.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipVariableDeclaration(); // read ith variable.
- }
+ SkipListOfVariableDeclarations(); // read variables.
Tag tag = ReadTag(); // Read first part of condition.
if (tag == kSomething) {
SkipExpression(); // read rest of condition.
}
- list_length = ReadListLength(); // read number of updates.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipExpression(); // read ith update.
- }
+ SkipListOfExpressions(); // read updates.
SkipStatement(); // read body.
return;
}
@@ -1753,8 +3315,8 @@ void StreamingFlowGraphBuilder::SkipStatement() {
case kTryCatch: {
SkipStatement(); // read body.
ReadBool(); // read any_catch_needs_stack_trace.
- intptr_t num_matches = ReadListLength(); // read number of catches.
- for (intptr_t i = 0; i < num_matches; ++i) {
+ intptr_t num_catches = ReadListLength(); // read number of catches.
+ for (intptr_t i = 0; i < num_catches; ++i) {
SkipDartType(); // read guard.
tag = ReadTag(); // read first part of exception.
if (tag == kSomething) {
@@ -1778,17 +3340,38 @@ void StreamingFlowGraphBuilder::SkipStatement() {
SkipExpression(); // read expression.
return;
case kVariableDeclaration:
- SkipVariableDeclaration();
+ SkipVariableDeclaration(); // read variable declaration.
return;
case kFunctionDeclaration:
- // TODO(jensj)
- UNIMPLEMENTED();
+ ReadPosition(); // read position.
+ SkipVariableDeclaration(); // read variable.
+ SkipFunctionNode(); // read function node.
return;
default:
UNREACHABLE();
}
}
+void StreamingFlowGraphBuilder::SkipFunctionNode() {
+ Tag tag = ReadTag(); // read tag.
+ ASSERT(tag == kFunctionNode);
+
+ ReadPosition(); // read position.
+ ReadPosition(); // read end position.
+ ReadByte(); // read async marker.
+ ReadByte(); // read dart async marker.
+ SkipTypeParametersList(); // read type_parameters.
+ ReadUInt(); // read required_parameter_count.
+
+ SkipListOfVariableDeclarations(); // read list of positionals.
+ SkipListOfVariableDeclarations(); // read list of named.
+ SkipDartType(); // read return type.
+
+ if (ReadTag() == kSomething) {
+ SkipStatement(); // Read body
+ }
+}
+
void StreamingFlowGraphBuilder::SkipName() {
StringIndex name_index = ReadStringReference(); // read name index.
if ((H.StringSize(name_index) >= 1) && H.CharacterAt(name_index, 0) == '_') {
@@ -1799,20 +3382,11 @@ void StreamingFlowGraphBuilder::SkipName() {
void StreamingFlowGraphBuilder::SkipArguments() {
ReadUInt(); // read argument count.
- // List of types.
- intptr_t list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipDartType(); // read ith type.
- }
-
- // List of positional.
- list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipExpression(); // read ith expression.
- }
+ SkipListOfDartTypes(); // read list of types.
+ SkipListOfExpressions(); // read positionals.
// List of named.
- list_length = ReadListLength(); // read list length.
+ intptr_t list_length = ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {
SkipStringReference(); // read ith name index.
SkipExpression(); // read ith expression.
@@ -1942,21 +3516,15 @@ Value* StreamingFlowGraphBuilder::Pop() {
Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() {
// read parts of arguments, then go back to before doing so.
- intptr_t offset = ReaderOffset();
+ AlternativeReadingScope alt(reader_);
ReadUInt(); // read number of arguments.
- // List of types.
- intptr_t list_length = ReadListLength(); // read list length.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipDartType(); // read ith type.
- }
+ SkipListOfDartTypes(); // Read list of types.
// List of positional.
- list_length = ReadListLength(); // read list length.
+ intptr_t list_length = ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {
- Tag tag = ReadTag(); // read first tag.
- SetOffset(offset); // reset offset.
- return tag;
+ return ReadTag(); // read first tag.
}
UNREACHABLE();
@@ -1966,13 +3534,10 @@ Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() {
const TypeArguments& StreamingFlowGraphBuilder::PeekArgumentsInstantiatedType(
const dart::Class& klass) {
// read parts of arguments, then go back to before doing so.
- intptr_t offset = ReaderOffset();
+ AlternativeReadingScope alt(reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
- const TypeArguments& type_arguments =
- T.BuildInstantiatedTypeArguments(klass, list_length); // read types.
- SetOffset(offset);
- return type_arguments;
+ return T.BuildInstantiatedTypeArguments(klass, list_length); // read types.
}
intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() {
@@ -1980,19 +3545,14 @@ intptr_t StreamingFlowGraphBuilder::PeekArgumentsCount() {
}
intptr_t StreamingFlowGraphBuilder::PeekArgumentsTypeCount() {
- intptr_t offset = ReaderOffset();
+ AlternativeReadingScope alt(reader_);
ReadUInt(); // read arguments count.
- intptr_t types_count = ReadListLength(); // read length of types list.
- SetOffset(offset);
- return types_count;
+ return ReadListLength(); // read length of types list.
}
void StreamingFlowGraphBuilder::SkipArgumentsBeforeActualArguments() {
ReadUInt(); // read arguments count.
- intptr_t types_count = ReadListLength();
- for (intptr_t i = 0; i < types_count; ++i) {
- SkipDartType(); // read ith type.
- }
+ SkipListOfDartTypes(); // read list of types.
}
LocalVariable* StreamingFlowGraphBuilder::LookupVariable(
@@ -2182,11 +3742,9 @@ Fragment StreamingFlowGraphBuilder::TranslateFinallyFinalizers(
intptr_t target_context_depth) {
// TranslateFinallyFinalizers can move the readers offset.
// Save the current position and restore it afterwards.
- intptr_t offset = ReaderOffset();
- Fragment result = flow_graph_builder_->TranslateFinallyFinalizers(
- outer_finally, target_context_depth);
- SetOffset(offset);
- return result;
+ AlternativeReadingScope alt(reader_);
+ return flow_graph_builder_->TranslateFinallyFinalizers(outer_finally,
+ target_context_depth);
}
Fragment StreamingFlowGraphBuilder::BranchIfTrue(
@@ -2308,10 +3866,7 @@ Fragment StreamingFlowGraphBuilder::BuildArguments(Array* argument_names,
*argument_count = ReadUInt(); // read arguments count.
// List of types.
- intptr_t list_length = ReadListLength(); // read type count.
- for (intptr_t i = 0; i < list_length; ++i) {
- SkipDartType(); // read ith type.
- }
+ SkipListOfDartTypes(); // read list of types.
return BuildArgumentsFromActualArguments(argument_names, skip_push_arguments,
do_drop);
@@ -3316,7 +4871,7 @@ Fragment StreamingFlowGraphBuilder::BuildMapLiteral(bool is_const,
Fragment StreamingFlowGraphBuilder::BuildLet(TokenPosition* position) {
if (position != NULL) *position = TokenPosition::kNoSource;
- Fragment instructions = BuildVariableDeclaration(false); // read variable.
+ Fragment instructions = BuildVariableDeclaration(); // read variable.
instructions += BuildExpression(); // read body.
return instructions;
}
@@ -3414,9 +4969,8 @@ Fragment StreamingFlowGraphBuilder::BuildEmptyStatement() {
Fragment StreamingFlowGraphBuilder::BuildAssertStatement() {
if (!I->asserts()) {
- intptr_t offset = ReaderOffset() - 1; // Include the tag.
- SetOffset(offset);
- SkipStatement(); // read this statement.
+ SetOffset(ReaderOffset() - 1); // Include the tag.
+ SkipStatement(); // read this statement.
return Fragment();
}
@@ -3602,7 +5156,7 @@ Fragment StreamingFlowGraphBuilder::BuildForStatement() {
intptr_t list_length = ReadListLength(); // read number of variables.
for (intptr_t i = 0; i < list_length; ++i) {
- declarations += BuildVariableDeclaration(false); // read ith variable.
+ declarations += BuildVariableDeclaration(); // read ith variable.
}
loop_depth_inc();
@@ -4017,13 +5571,13 @@ Fragment StreamingFlowGraphBuilder::BuildTryCatch() {
bool needs_stacktrace = ReadBool(); // read any_catch_needs_stack_trace
catch_depth_inc();
- intptr_t num_matches = ReadListLength(); // read number of catches.
+ intptr_t num_catches = ReadListLength(); // read number of catches.
const Array& handler_types =
- Array::ZoneHandle(Z, Array::New(num_matches, Heap::kOld));
+ Array::ZoneHandle(Z, Array::New(num_catches, Heap::kOld));
Fragment catch_body =
CatchBlockEntry(handler_types, try_handler_index, needs_stacktrace);
// Fill in the body of the catch.
- for (intptr_t i = 0; i < num_matches; ++i) {
+ for (intptr_t i = 0; i < num_catches; ++i) {
intptr_t catch_offset = ReaderOffset(); // Catch has no tag.
Tag tag = PeekTag(); // peek guard type.
AbstractType* type_guard = NULL;
@@ -4280,9 +5834,9 @@ Fragment StreamingFlowGraphBuilder::BuildYieldStatement() {
return continuation;
}
-Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration(bool has_tag) {
- intptr_t kernel_position = ReaderOffset() - (has_tag ? 1 : 0);
- LocalVariable* variable = LookupVariable(kernel_position);
+Fragment StreamingFlowGraphBuilder::BuildVariableDeclaration() {
+ intptr_t kernel_position_no_tag = ReaderOffset();
+ LocalVariable* variable = LookupVariable(kernel_position_no_tag);
TokenPosition position = ReadPosition(); // read position.
TokenPosition equals_position = ReadPosition(); // read equals position.
« no previous file with comments | « runtime/vm/kernel_binary_flowgraph.h ('k') | runtime/vm/kernel_reader.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698