Flutter Engine
The Flutter Engine
scope_builder.cc
Go to the documentation of this file.
1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
7#include "vm/compiler/backend/il.h" // For CompileType.
10
11namespace dart {
12namespace kernel {
13
14#define Z (zone_)
15#define H (translation_helper_)
16#define T (type_translator_)
17#define I Isolate::Current()
18#define IG IsolateGroup::Current()
19
21 : result_(nullptr),
22 parsed_function_(parsed_function),
23 translation_helper_(Thread::Current()),
24 zone_(translation_helper_.zone()),
25 current_function_scope_(nullptr),
26 scope_(nullptr),
27 depth_(0),
28 name_index_(0),
29 needs_expr_temp_(false),
30 helper_(
31 zone_,
32 &translation_helper_,
33 TypedDataView::Handle(Z, parsed_function->function().KernelLibrary()),
34 parsed_function->function().KernelLibraryOffset()),
35 constant_reader_(&helper_, &active_class_),
36 inferred_type_metadata_helper_(&helper_, &constant_reader_),
37 inferred_arg_type_metadata_helper_(
38 &helper_,
39 &constant_reader_,
41 procedure_attributes_metadata_helper_(&helper_),
42 type_translator_(&helper_,
43 &constant_reader_,
44 &active_class_,
45 /*finalize=*/true) {
46 const auto& kernel_program_info = KernelProgramInfo::Handle(
47 Z, parsed_function->function().KernelProgramInfo());
48 H.InitFromKernelProgramInfo(kernel_program_info);
49 ASSERT(type_translator_.active_class_ == &active_class_);
50}
51
53 if (result_ != nullptr) return result_;
54
55 ASSERT(scope_ == nullptr && depth_.loop_ == 0 && depth_.function_ == 0);
56 result_ = new (Z) ScopeBuildingResult();
57
58 const Function& function = parsed_function_->function();
59
60 // Setup an [ActiveClassScope] and an [ActiveMemberScope] which will be used
61 // e.g. for type translation.
62 const Class& klass = Class::Handle(Z, function.Owner());
63
64 Function& outermost_function =
65 Function::Handle(Z, function.GetOutermostFunction());
66
67 ActiveClassScope active_class_scope(&active_class_, &klass);
68 ActiveMemberScope active_member(&active_class_, &outermost_function);
69 FunctionType& signature = FunctionType::Handle(Z, function.signature());
70 ActiveTypeParametersScope active_type_params(&active_class_, function,
71 &signature, Z);
72
73 LocalScope* enclosing_scope = nullptr;
74 if (function.IsImplicitClosureFunction() && !function.is_static()) {
75 // Create artificial enclosing scope for the tear-off that contains
76 // captured receiver value. This ensure that AssertAssignable will correctly
77 // load instantiator type arguments if they are needed.
78 Class& klass = Class::Handle(Z, function.Owner());
79 Type& klass_type = H.GetDeclarationType(klass);
80 LocalVariable* receiver_variable =
81 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
82 Symbols::This(), klass_type);
83 parsed_function_->set_receiver_var(receiver_variable);
84 receiver_variable->set_is_captured();
85 enclosing_scope = new (Z) LocalScope(nullptr, 0, 0);
86 enclosing_scope->set_context_level(0);
87 enclosing_scope->AddVariable(receiver_variable);
88 enclosing_scope->AddContextVariable(receiver_variable);
89 } else if (function.HasParent()) {
90 enclosing_scope = LocalScope::RestoreOuterScope(
91 ContextScope::Handle(Z, function.context_scope()));
92 }
93 current_function_scope_ = scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
94 scope_->set_begin_token_pos(function.token_pos());
95 scope_->set_end_token_pos(function.end_token_pos());
96
97 if (function.IsSuspendableFunction()) {
98 LocalVariable* suspend_state_var =
99 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
100 Symbols::SuspendStateVar(), AbstractType::dynamic_type());
101 suspend_state_var->set_is_forced_stack();
102 suspend_state_var->set_invisible(true);
103 scope_->AddVariable(suspend_state_var);
104 parsed_function_->set_suspend_state_var(suspend_state_var);
105 }
106
107 // Add function type arguments variable before current context variable.
108 if (function.IsGeneric() || function.HasGenericParent()) {
109 LocalVariable* type_args_var = MakeVariable(
110 TokenPosition::kNoSource, TokenPosition::kNoSource,
111 Symbols::FunctionTypeArgumentsVar(), AbstractType::dynamic_type());
112 scope_->AddVariable(type_args_var);
113 parsed_function_->set_function_type_arguments(type_args_var);
114 }
115
116 if (parsed_function_->has_arg_desc_var()) {
117 scope_->AddVariable(parsed_function_->arg_desc_var());
118 }
119
120 LocalVariable* context_var = parsed_function_->current_context_var();
121 context_var->set_is_forced_stack();
122 scope_->AddVariable(context_var);
123
124 parsed_function_->set_scope(scope_);
125
126 helper_.SetOffset(function.kernel_offset());
127
128 FunctionNodeHelper function_node_helper(&helper_);
129 const ProcedureAttributesMetadata attrs =
130 procedure_attributes_metadata_helper_.GetProcedureAttributes(
131 function.kernel_offset());
132
133 switch (function.kind()) {
134 case UntaggedFunction::kImplicitClosureFunction: {
135 const auto& parent = Function::Handle(Z, function.parent_function());
136 const auto& target =
137 Function::Handle(Z, function.ImplicitClosureTarget(Z));
138
139 // For BuildGraphOfNoSuchMethodForwarder, since closures no longer
140 // require arg_desc_var in all cases.
141 if (target.IsNull() ||
142 (parent.num_fixed_parameters() != target.num_fixed_parameters())) {
143 needs_expr_temp_ = true;
144 }
145 }
147 case UntaggedFunction::kClosureFunction:
148 case UntaggedFunction::kRegularFunction:
149 case UntaggedFunction::kGetterFunction:
150 case UntaggedFunction::kSetterFunction:
151 case UntaggedFunction::kConstructor: {
152 const Tag tag = helper_.PeekTag();
153 helper_.ReadUntilFunctionNode();
154 function_node_helper.ReadUntilExcluding(
156 // NOTE: FunctionNode is read further below the if.
157
158 if (function.is_ffi_native() || function.IsFfiCallClosure()) {
159 needs_expr_temp_ = true;
160 // Calls with handles need try/catch variables.
161 if (function.FfiCSignatureContainsHandles()) {
162 ++depth_.try_;
163 AddTryVariables();
164 --depth_.try_;
165 ++depth_.catch_;
166 AddCatchVariables();
167 FinalizeCatchVariables();
168 --depth_.catch_;
169 }
170 }
173 function)) {
174 needs_expr_temp_ = true;
175 }
176 intptr_t pos = 0;
177 if (function.IsClosureFunction()) {
178 LocalVariable* closure_parameter = MakeVariable(
179 TokenPosition::kNoSource, TokenPosition::kNoSource,
180 Symbols::ClosureParameter(), AbstractType::dynamic_type());
181 closure_parameter->set_is_forced_stack();
182 scope_->InsertParameterAt(pos++, closure_parameter);
183 } else if (!function.is_static()) {
184 // We use [is_static] instead of [IsStaticFunction] because the latter
185 // returns `false` for constructors.
186 Class& klass = Class::Handle(Z, function.Owner());
187 Type& klass_type = H.GetDeclarationType(klass);
188 LocalVariable* variable =
189 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
190 Symbols::This(), klass_type);
191 scope_->InsertParameterAt(pos++, variable);
192 parsed_function_->set_receiver_var(variable);
193
194 // We visit instance field initializers because they might contain
195 // [Let] expressions and we need to have a mapping.
196 if (tag == kConstructor) {
197 Class& parent_class = Class::Handle(Z, function.Owner());
198 Array& class_fields = Array::Handle(Z, parent_class.fields());
199 Field& class_field = Field::Handle(Z);
200 for (intptr_t i = 0; i < class_fields.Length(); ++i) {
201 class_field ^= class_fields.At(i);
202 if (!class_field.is_static()) {
203 const auto& kernel_data =
204 TypedDataView::Handle(Z, class_field.KernelLibrary());
205 ASSERT(!kernel_data.IsNull());
206 intptr_t field_offset = class_field.kernel_offset();
208 &helper_.reader_, &kernel_data, field_offset);
209 FieldHelper field_helper(&helper_);
211 Tag initializer_tag =
212 helper_.ReadTag(); // read first part of initializer.
213 if (initializer_tag == kSomething) {
214 EnterScope(field_offset);
215 VisitExpression(); // read initializer.
216 ExitScope(field_helper.position_, field_helper.end_position_);
217 }
218 }
219 }
220 }
221 } else if (function.IsFactory()) {
222 LocalVariable* variable = MakeVariable(
223 TokenPosition::kNoSource, TokenPosition::kNoSource,
224 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
225 scope_->InsertParameterAt(pos++, variable);
226 result_->type_arguments_variable = variable;
227 }
228
229 ParameterTypeCheckMode type_check_mode =
230 kTypeCheckForNonDynamicallyInvokedMethod;
231 if (function.is_static()) {
232 // In static functions we don't check anything.
233 type_check_mode = kTypeCheckForStaticFunction;
234 } else if (function.IsImplicitClosureFunction()) {
235 // All non-covariant checks are either performed by the type system,
236 // or by a dynamic closure call dispatcher/mirror if dynamically
237 // invoked. For covariant checks, static targets never have covariant
238 // arguments and dynamic targets do their own covariant checking.
239 // Thus, implicit closure functions perform no checking internally.
240 type_check_mode = kTypeCheckForImplicitClosureFunction;
241 }
242
243 // Continue reading FunctionNode:
244 // read positional_parameters and named_parameters.
245 AddPositionalAndNamedParameters(pos, type_check_mode, attrs);
246
247 if (function.IsSuspendableFunction()) {
248 // Read return type which is used to create a result of
249 // async/async*/sync* function. It may reference receiver or type
250 // arguments of the enclosing function which need to be captured.
251 VisitDartType();
252
253 // Visit optional future value type.
254 if (helper_.ReadTag() == kSomething) {
255 VisitDartType();
256 }
257 }
258
259 // We generate a synthetic body for implicit closure functions - which
260 // will forward the call to the real function.
261 // -> see BuildGraphOfImplicitClosureFunction
262 if (!function.IsImplicitClosureFunction()) {
263 helper_.SetOffset(function.kernel_offset());
264 first_body_token_position_ = TokenPosition::kNoSource;
265 VisitNode();
266
267 // TODO(jensj): HACK: Push the begin token to after any parameters to
268 // avoid crash when breaking on definition line of async method in
269 // debugger. It seems that another scope needs to be added
270 // in which captures are made, but I can't make that work.
271 // This 'solution' doesn't crash, but I cannot see the parameters at
272 // that particular breakpoint either.
273 // Also push the end token to after the "}" to avoid crashing on
274 // stepping past the last line (to the "}" character).
275 if (first_body_token_position_.IsReal()) {
276 scope_->set_begin_token_pos(first_body_token_position_);
277 }
278 if (scope_->end_token_pos().IsReal()) {
279 scope_->set_end_token_pos(scope_->end_token_pos().Next());
280 }
281 }
282 break;
283 }
284 case UntaggedFunction::kImplicitGetter:
285 case UntaggedFunction::kImplicitSetter: {
286 ASSERT(helper_.PeekTag() == kField);
287 const bool is_setter = function.IsImplicitSetterFunction();
288 const bool is_method = !function.IsStaticFunction();
289 const auto& field = Field::Handle(Z, function.accessor_field());
290 intptr_t pos = 0;
291 if (is_method) {
292 Class& klass = Class::Handle(Z, function.Owner());
293 Type& klass_type = H.GetDeclarationType(klass);
294 LocalVariable* variable =
295 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
296 Symbols::This(), klass_type);
297 scope_->InsertParameterAt(pos++, variable);
298 parsed_function_->set_receiver_var(variable);
299 }
300 if (is_setter) {
301 if (CompilerState::Current().is_aot()) {
302 const intptr_t kernel_offset = field.kernel_offset();
303 const InferredTypeMetadata parameter_type =
304 inferred_type_metadata_helper_.GetInferredType(kernel_offset);
305 result_->setter_value = MakeVariable(
306 TokenPosition::kNoSource, TokenPosition::kNoSource,
307 Symbols::Value(),
308 AbstractType::ZoneHandle(Z, function.ParameterTypeAt(pos)),
309 LocalVariable::kNoKernelOffset, /*is_late=*/false,
310 /*inferred_type=*/nullptr,
311 /*inferred_arg_type=*/&parameter_type);
312 } else {
313 result_->setter_value = MakeVariable(
314 TokenPosition::kNoSource, TokenPosition::kNoSource,
315 Symbols::Value(),
316 AbstractType::ZoneHandle(Z, function.ParameterTypeAt(pos)));
317 }
318 scope_->InsertParameterAt(pos++, result_->setter_value);
319
320 if (is_method) {
321 if (field.is_covariant()) {
323 } else if (!field.is_generic_covariant_impl() ||
324 (!attrs.has_non_this_uses && !attrs.has_tearoff_uses)) {
327 }
328 }
329 }
330 break;
331 }
332 case UntaggedFunction::kImplicitStaticGetter: {
333 ASSERT(helper_.PeekTag() == kField);
334 ASSERT(function.IsStaticFunction());
335 // In addition to static field initializers, scopes/local variables
336 // are needed for implicit getters of static const fields, in order to
337 // be able to evaluate their initializers in constant evaluator.
338 if (Field::Handle(Z, function.accessor_field()).is_const()) {
339 VisitNode();
340 }
341 break;
342 }
343 case UntaggedFunction::kFieldInitializer: {
344 ASSERT(helper_.PeekTag() == kField);
345 if (!function.is_static()) {
346 Class& klass = Class::Handle(Z, function.Owner());
347 Type& klass_type = H.GetDeclarationType(klass);
348 LocalVariable* variable =
349 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
350 Symbols::This(), klass_type);
351 scope_->InsertParameterAt(0, variable);
352 parsed_function_->set_receiver_var(variable);
353 }
354 VisitNode();
355 break;
356 }
357 case UntaggedFunction::kDynamicInvocationForwarder: {
358 const String& name = String::Handle(Z, function.name());
360
361 const auto& target = Function::ZoneHandle(Z, function.ForwardingTarget());
362 ASSERT(!target.IsNull());
363
366 function)) {
367 needs_expr_temp_ = true;
368 }
369
370 if (helper_.PeekTag() == kField) {
371 // Create [this] variable.
372 const Class& klass = Class::Handle(Z, function.Owner());
373 parsed_function_->set_receiver_var(
374 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
375 Symbols::This(), H.GetDeclarationType(klass)));
376 scope_->InsertParameterAt(0, parsed_function_->receiver_var());
377
378 // Create setter value variable.
379 if (target.IsImplicitSetterFunction()) {
380 result_->setter_value = MakeVariable(
381 TokenPosition::kNoSource, TokenPosition::kNoSource,
382 Symbols::Value(),
383 AbstractType::ZoneHandle(Z, function.ParameterTypeAt(1)));
384 scope_->InsertParameterAt(1, result_->setter_value);
385 }
386 break;
387 }
388
389 // We do not create dyn:* forwarders for method extractors, since those
390 // can never return unboxed values (they return a closure).
391 ASSERT(!target.IsMethodExtractor());
392
393 helper_.ReadUntilFunctionNode();
394 function_node_helper.ReadUntilExcluding(
396
397 // Create [this] variable.
398 intptr_t pos = 0;
399 Class& klass = Class::Handle(Z, function.Owner());
400 parsed_function_->set_receiver_var(
401 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
402 Symbols::This(), H.GetDeclarationType(klass)));
403 scope_->InsertParameterAt(pos++, parsed_function_->receiver_var());
404
405 // Create all positional and named parameters.
406 AddPositionalAndNamedParameters(
407 pos, kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod,
408 attrs);
409 break;
410 }
411 case UntaggedFunction::kMethodExtractor: {
412 // Add a receiver parameter. Though it is captured, we emit code to
413 // explicitly copy it to a freshly-allocated closure.
414 // Therefore, it isn't necessary to mark it as captured here.
415 Class& klass = Class::Handle(Z, function.Owner());
416 Type& klass_type = H.GetDeclarationType(klass);
417 LocalVariable* variable =
418 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
419 Symbols::This(), klass_type);
420 scope_->InsertParameterAt(0, variable);
421 parsed_function_->set_receiver_var(variable);
422 break;
423 }
424 case UntaggedFunction::kFfiTrampoline: {
425 needs_expr_temp_ = true;
426 // Callbacks need try/catch variables.
427 ++depth_.try_;
428 AddTryVariables();
429 --depth_.try_;
430 ++depth_.catch_;
431 AddCatchVariables();
432 FinalizeCatchVariables();
433 --depth_.catch_;
435 }
436 case UntaggedFunction::kInvokeFieldDispatcher: {
437 if (function.IsDynamicClosureCallDispatcher()) {
438 auto const vars = parsed_function_->EnsureDynamicClosureCallVars();
439 ASSERT(vars != nullptr);
440#define ADD_VAR(Name, _, __) scope_->AddVariable(vars->Name);
442#undef ADD_VAR
443 for (auto const& v : vars->named_argument_parameter_indices) {
444 scope_->AddVariable(v);
445 }
446 }
447 }
449 case UntaggedFunction::kNoSuchMethodDispatcher: {
450 for (intptr_t i = 0; i < function.NumParameters(); ++i) {
451 LocalVariable* variable = MakeVariable(
452 TokenPosition::kNoSource, TokenPosition::kNoSource,
453 String::ZoneHandle(Z, function.ParameterNameAt(i)),
454 AbstractType::ZoneHandle(Z, function.IsFfiCallbackTrampoline()
455 ? function.ParameterTypeAt(i)
456 : Object::dynamic_type().ptr()));
457 bool added = scope_->InsertParameterAt(i, variable);
458 ASSERT(added);
459 }
460 break;
461 }
462 case UntaggedFunction::kRecordFieldGetter: {
463 needs_expr_temp_ = true;
464 // Add a receiver parameter.
465 Class& klass = Class::Handle(Z, function.Owner());
466 parsed_function_->set_receiver_var(
467 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
468 Symbols::This(), H.GetDeclarationType(klass)));
469 scope_->InsertParameterAt(0, parsed_function_->receiver_var());
470 break;
471 }
472 case UntaggedFunction::kIrregexpFunction:
473 UNREACHABLE();
474 }
475 if (needs_expr_temp_) {
476 parsed_function_->EnsureExpressionTemp();
477 }
478 if (parsed_function_->has_expression_temp_var()) {
479 scope_->AddVariable(parsed_function_->expression_temp_var());
480 }
481 if (parsed_function_->function().MayHaveUncheckedEntryPoint()) {
482 scope_->AddVariable(parsed_function_->EnsureEntryPointsTemp());
483 }
484
485 parsed_function_->AllocateVariables();
486
487 // :suspend_state variable should be allocated to a fixed location in
488 // the stack frame.
489 RELEASE_ASSERT((parsed_function_->suspend_state_var() == nullptr) ||
490 (parsed_function_->suspend_state_var()->index().value() ==
492
493 return result_;
494}
495
496void ScopeBuilder::ReportUnexpectedTag(const char* variant, Tag tag) {
497 const auto& script = Script::Handle(Z, Script());
498 H.ReportError(script, TokenPosition::kNoSource,
499 "Unexpected tag %d (%s) in %s, expected %s", tag,
500 Reader::TagName(tag),
501 parsed_function_->function().ToQualifiedCString(), variant);
502}
503
504void ScopeBuilder::VisitNode() {
505 Tag tag = helper_.PeekTag();
506 switch (tag) {
507 case kConstructor:
508 VisitConstructor();
509 return;
510 case kProcedure:
511 VisitProcedure();
512 return;
513 case kField:
514 VisitField();
515 return;
516 case kFunctionNode:
517 VisitFunctionNode();
518 return;
519 default:
521 return;
522 }
523}
524
525void ScopeBuilder::VisitConstructor() {
526 // Field initializers that come from non-static field declarations are
527 // compiled as if they appear in the constructor initializer list. This is
528 // important for closure-valued field initializers because the VM expects the
529 // corresponding closure functions to appear as if they were nested inside the
530 // constructor.
531 ConstructorHelper constructor_helper(&helper_);
532 constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
533 {
534 const Function& function = parsed_function_->function();
535 Class& parent_class = Class::Handle(Z, function.Owner());
536 Array& class_fields = Array::Handle(Z, parent_class.fields());
537 Field& class_field = Field::Handle(Z);
538 for (intptr_t i = 0; i < class_fields.Length(); ++i) {
539 class_field ^= class_fields.At(i);
540 if (!class_field.is_static()) {
541 const auto& kernel_data =
542 TypedDataView::Handle(Z, class_field.KernelLibrary());
543 ASSERT(!kernel_data.IsNull());
544 intptr_t field_offset = class_field.kernel_offset();
545 AlternativeReadingScopeWithNewData alt(&helper_.reader_, &kernel_data,
546 field_offset);
547 FieldHelper field_helper(&helper_);
548 field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
549 Tag initializer_tag = helper_.ReadTag();
550 if (initializer_tag == kSomething) {
551 VisitExpression(); // read initializer.
552 }
553 }
554 }
555 }
556
557 // Visit children (note that there's no reason to visit the name).
558 VisitFunctionNode();
559 intptr_t list_length =
560 helper_.ReadListLength(); // read initializers list length.
561 for (intptr_t i = 0; i < list_length; i++) {
562 VisitInitializer();
563 }
564}
565
566void ScopeBuilder::VisitProcedure() {
567 ProcedureHelper procedure_helper(&helper_);
568 procedure_helper.ReadUntilExcluding(ProcedureHelper::kFunction);
569 VisitFunctionNode();
570}
571
572void ScopeBuilder::VisitField() {
573 FieldHelper field_helper(&helper_);
574 field_helper.ReadUntilExcluding(FieldHelper::kType);
575 VisitDartType(); // read type.
576 Tag tag = helper_.ReadTag(); // read initializer (part 1).
577 if (tag == kSomething) {
578 VisitExpression(); // read initializer (part 2).
579 }
580}
581
582void ScopeBuilder::VisitFunctionNode() {
583 FunctionNodeHelper function_node_helper(&helper_);
584 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
585
586 intptr_t list_length =
587 helper_.ReadListLength(); // read type_parameters list length.
588 for (intptr_t i = 0; i < list_length; ++i) {
589 TypeParameterHelper helper(&helper_);
590 helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
591 VisitDartType(); // read ith bound.
592 helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kDefaultType);
593 VisitDartType(); // read ith default type.
594 helper.Finish();
595 }
596 function_node_helper.SetJustRead(FunctionNodeHelper::kTypeParameters);
597
598 // Read (but don't visit) the positional and named parameters, because they've
599 // already been added to the scope.
600 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kBody);
601
602 if (helper_.ReadTag() == kSomething) {
603 PositionScope scope(&helper_.reader_);
604 VisitStatement(); // Read body
605 first_body_token_position_ = helper_.reader_.min_position();
606 }
607}
608
609void ScopeBuilder::VisitInitializer() {
610 Tag tag = helper_.ReadTag();
611 helper_.ReadByte(); // read isSynthetic flag.
612 switch (tag) {
613 case kInvalidInitializer:
614 return;
615 case kFieldInitializer:
616 helper_.ReadPosition(); // read position.
617 helper_.SkipCanonicalNameReference(); // read field_reference.
618 VisitExpression(); // read value.
619 return;
620 case kSuperInitializer:
621 helper_.ReadPosition(); // read position.
622 helper_.SkipCanonicalNameReference(); // read target_reference.
623 VisitArguments(); // read arguments.
624 return;
625 case kRedirectingInitializer:
626 helper_.ReadPosition(); // read position.
627 helper_.SkipCanonicalNameReference(); // read target_reference.
628 VisitArguments(); // read arguments.
629 return;
630 case kLocalInitializer:
631 VisitVariableDeclaration(); // read variable.
632 return;
633 case kAssertInitializer:
634 VisitStatement();
635 return;
636 default:
637 ReportUnexpectedTag("initializer", tag);
638 UNREACHABLE();
639 }
640}
641
642void ScopeBuilder::VisitExpression() {
643 uint8_t payload = 0;
644 Tag tag = helper_.ReadTag(&payload);
645 switch (tag) {
646 case kInvalidExpression:
647 helper_.ReadPosition();
648 helper_.SkipStringReference();
649 if (helper_.ReadTag() == kSomething) {
650 VisitExpression(); // read expression.
651 }
652 return;
653 case kVariableGet: {
654 helper_.ReadPosition(); // read position.
655 intptr_t variable_kernel_offset =
656 helper_.ReadUInt(); // read kernel position.
657 helper_.ReadUInt(); // read relative variable index.
658 helper_.SkipOptionalDartType(); // read promoted type.
659 VisitVariableGet(variable_kernel_offset);
660 return;
661 }
662 case kSpecializedVariableGet: {
663 helper_.ReadPosition(); // read position.
664 intptr_t variable_kernel_offset =
665 helper_.ReadUInt(); // read kernel position.
666 VisitVariableGet(variable_kernel_offset);
667 return;
668 }
669 case kVariableSet: {
670 helper_.ReadPosition(); // read position.
671 intptr_t variable_kernel_offset =
672 helper_.ReadUInt(); // read kernel position.
673 helper_.ReadUInt(); // read relative variable index.
674 LookupVariable(variable_kernel_offset);
675 VisitExpression(); // read expression.
676 return;
677 }
678 case kSpecializedVariableSet: {
679 helper_.ReadPosition(); // read position.
680 intptr_t variable_kernel_offset =
681 helper_.ReadUInt(); // read kernel position.
682 LookupVariable(variable_kernel_offset);
683 VisitExpression(); // read expression.
684 return;
685 }
686 case kInstanceGet:
687 helper_.ReadByte(); // read kind.
688 helper_.ReadPosition(); // read position.
689 VisitExpression(); // read receiver.
690 helper_.SkipName(); // read name.
691 helper_.SkipDartType(); // read result_type.
692 // read interface_target_reference.
694 return;
695 case kDynamicGet:
696 helper_.ReadByte(); // read kind.
697 helper_.ReadPosition(); // read position.
698 VisitExpression(); // read receiver.
699 helper_.SkipName(); // read name.
700 return;
701 case kInstanceTearOff:
702 helper_.ReadByte(); // read kind.
703 helper_.ReadPosition(); // read position.
704 VisitExpression(); // read receiver.
705 helper_.SkipName(); // read name.
706 helper_.SkipDartType(); // read result_type.
707 // read interface_target_reference.
709 return;
710 case kFunctionTearOff:
711 // Removed by lowering kernel transformation.
712 UNREACHABLE();
713 break;
714 case kInstanceSet:
715 helper_.ReadByte(); // read kind.
716 helper_.ReadPosition(); // read position.
717 VisitExpression(); // read receiver.
718 helper_.SkipName(); // read name.
719 VisitExpression(); // read value.
720 // read interface_target_reference.
722 return;
723 case kDynamicSet:
724 helper_.ReadByte(); // read kind.
725 helper_.ReadPosition(); // read position.
726 VisitExpression(); // read receiver.
727 helper_.SkipName(); // read name.
728 VisitExpression(); // read value.
729 return;
730 case kAbstractSuperPropertyGet:
731 // Abstract super property getters must be converted into super property
732 // getters during mixin transformation.
733 UNREACHABLE();
734 break;
735 case kAbstractSuperPropertySet:
736 // Abstract super property setters must be converted into super property
737 // setters during mixin transformation.
738 UNREACHABLE();
739 break;
740 case kSuperPropertyGet:
741 HandleLoadReceiver();
742 helper_.ReadPosition(); // read position.
743 helper_.SkipName(); // read name.
744 helper_.SkipInterfaceMemberNameReference(); // read target_reference.
745 return;
746 case kSuperPropertySet:
747 HandleLoadReceiver();
748 helper_.ReadPosition(); // read position.
749 helper_.SkipName(); // read name.
750 VisitExpression(); // read value.
751 helper_.SkipInterfaceMemberNameReference(); // read target_reference.
752 return;
753 case kStaticGet:
754 helper_.ReadPosition(); // read position.
755 helper_.SkipCanonicalNameReference(); // read target_reference.
756 return;
757 case kStaticSet:
758 helper_.ReadPosition(); // read position.
759 helper_.SkipCanonicalNameReference(); // read target_reference.
760 VisitExpression(); // read expression.
761 return;
762 case kInstanceInvocation:
763 helper_.ReadByte(); // read kind.
764 helper_.ReadFlags(); // read flags.
765 helper_.ReadPosition(); // read position.
766 VisitExpression(); // read receiver.
767 helper_.SkipName(); // read name.
768 VisitArguments(); // read arguments.
769 helper_.SkipDartType(); // read function_type.
770 // read interface_target_reference.
772 return;
773 case kDynamicInvocation:
774 helper_.ReadByte(); // read kind.
775 helper_.ReadByte(); // read flags.
776 helper_.ReadPosition(); // read position.
777 VisitExpression(); // read receiver.
778 helper_.SkipName(); // read name.
779 VisitArguments(); // read arguments.
780 return;
781 case kLocalFunctionInvocation: {
782 helper_.ReadPosition(); // read position.
783 intptr_t variable_kernel_offset =
784 helper_.ReadUInt(); // read variable kernel position.
785 helper_.ReadUInt(); // read relative variable index.
786 VisitArguments(); // read arguments.
787 helper_.SkipDartType(); // read function_type.
788 VisitVariableGet(variable_kernel_offset);
789 return;
790 }
791 case kFunctionInvocation:
792 helper_.ReadByte(); // read kind.
793 helper_.ReadPosition(); // read position.
794 VisitExpression(); // read receiver.
795 VisitArguments(); // read arguments.
796 helper_.SkipDartType(); // read function_type.
797 return;
798 case kEqualsCall:
799 helper_.ReadPosition(); // read position.
800 VisitExpression(); // read left.
801 VisitExpression(); // read right.
802 helper_.SkipDartType(); // read function_type.
803 // read interface_target_reference.
805 return;
806 case kEqualsNull:
807 helper_.ReadPosition(); // read position.
808 VisitExpression(); // read expression.
809 return;
810 case kAbstractSuperMethodInvocation:
811 // Abstract super method invocations must be converted into super
812 // method invocations during mixin transformation.
813 UNREACHABLE();
814 break;
815 case kSuperMethodInvocation:
816 HandleLoadReceiver();
817 helper_.ReadPosition(); // read position.
818 helper_.SkipName(); // read name.
819 VisitArguments(); // read arguments.
820 // read interface_target_reference.
822 return;
823 case kStaticInvocation:
824 helper_.ReadPosition(); // read position.
825 helper_.SkipCanonicalNameReference(); // read procedure_reference.
826 VisitArguments(); // read arguments.
827 return;
828 case kConstructorInvocation:
829 helper_.ReadPosition(); // read position.
830 helper_.SkipCanonicalNameReference(); // read target_reference.
831 VisitArguments(); // read arguments.
832 return;
833 case kNot:
834 helper_.ReadPosition(); // read position.
835 VisitExpression(); // read expression.
836 return;
837 case kNullCheck:
838 helper_.ReadPosition(); // read position.
839 VisitExpression(); // read expression.
840 return;
841 case kLogicalExpression:
842 needs_expr_temp_ = true;
843 helper_.ReadPosition(); // read position.
844 VisitExpression(); // read left.
845 helper_.SkipBytes(1); // read operator.
846 VisitExpression(); // read right.
847 return;
848 case kConditionalExpression: {
849 needs_expr_temp_ = true;
850 helper_.ReadPosition(); // read position.
851 VisitExpression(); // read condition.
852 VisitExpression(); // read then.
853 VisitExpression(); // read otherwise.
854 helper_.SkipOptionalDartType(); // read unused static type.
855 return;
856 }
857 case kStringConcatenation: {
858 helper_.ReadPosition(); // read position.
859 VisitListOfExpressions();
860 return;
861 }
862 case kIsExpression:
863 needs_expr_temp_ = true;
864 helper_.ReadPosition(); // read position.
865 VisitExpression(); // read operand.
866 VisitDartType(); // read type.
867 return;
868 case kAsExpression:
869 helper_.ReadPosition(); // read position.
870 helper_.ReadFlags(); // read flags.
871 VisitExpression(); // read operand.
872 VisitDartType(); // read type.
873 return;
874 case kTypeLiteral:
875 helper_.ReadPosition(); // read file offset.
876 VisitDartType(); // read type.
877 return;
878 case kThisExpression:
879 HandleLoadReceiver();
880 helper_.ReadPosition(); // read file offset.
881 return;
882 case kRethrow:
883 helper_.ReadPosition(); // read position.
884 return;
885 case kThrow:
886 helper_.ReadPosition(); // read position.
887 helper_.ReadFlags(); // read flags.
888 VisitExpression(); // read expression.
889 return;
890 case kListLiteral: {
891 helper_.ReadPosition(); // read position.
892 VisitDartType(); // read type.
893 VisitListOfExpressions();
894 return;
895 }
896 case kSetLiteral: {
897 // Set literals are currently desugared in the frontend and will not
898 // reach the VM. See http://dartbug.com/35124 for discussion.
899 UNREACHABLE();
900 return;
901 }
902 case kMapLiteral: {
903 helper_.ReadPosition(); // read position.
904 VisitDartType(); // read key type.
905 VisitDartType(); // read value type.
906 intptr_t list_length = helper_.ReadListLength(); // read list length.
907 for (intptr_t i = 0; i < list_length; ++i) {
908 VisitExpression(); // read ith key.
909 VisitExpression(); // read ith value.
910 }
911 return;
912 }
913 case kRecordLiteral:
914 helper_.ReadPosition(); // read position.
915 VisitListOfExpressions(); // read positionals.
916 VisitListOfNamedExpressions(); // read named.
917 VisitDartType(); // read recordType.
918 return;
919 case kRecordIndexGet:
920 helper_.ReadPosition(); // read position.
921 VisitExpression(); // read receiver.
922 helper_.SkipDartType(); // read recordType.
923 helper_.ReadUInt(); // read index.
924 return;
925 case kRecordNameGet:
926 helper_.ReadPosition(); // read position.
927 VisitExpression(); // read receiver.
928 helper_.SkipDartType(); // read recordType.
929 helper_.SkipStringReference(); // read name.
930 return;
931 case kFunctionExpression: {
932 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
933 helper_.ReadPosition(); // read position.
934 HandleLocalFunction(offset); // read function node.
935 return;
936 }
937 case kLet: {
938 PositionScope scope(&helper_.reader_);
939 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
940
941 EnterScope(offset);
942
943 helper_.ReadPosition(); // read position.
944 VisitVariableDeclaration(); // read variable declaration.
945 VisitExpression(); // read expression.
946
947 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
948 return;
949 }
950 case kBlockExpression: {
951 PositionScope scope(&helper_.reader_);
952 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
953
954 EnterScope(offset);
955
956 helper_.ReadPosition(); // read position.
957 intptr_t list_length =
958 helper_.ReadListLength(); // read number of statements.
959 for (intptr_t i = 0; i < list_length; ++i) {
960 VisitStatement(); // read ith statement.
961 }
962 VisitExpression(); // read expression.
963
964 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
965 return;
966 }
967 case kBigIntLiteral:
968 helper_.ReadPosition(); // read position.
969 helper_.SkipStringReference(); // read string reference.
970 return;
971 case kStringLiteral:
972 helper_.ReadPosition(); // read position.
973 helper_.SkipStringReference(); // read string reference.
974 return;
975 case kSpecializedIntLiteral:
976 helper_.ReadPosition(); // read position.
977 return;
978 case kNegativeIntLiteral:
979 helper_.ReadPosition(); // read position.
980 helper_.ReadUInt(); // read value.
981 return;
982 case kPositiveIntLiteral:
983 helper_.ReadPosition(); // read position.
984 helper_.ReadUInt(); // read value.
985 return;
986 case kDoubleLiteral:
987 helper_.ReadPosition(); // read position.
988 helper_.ReadDouble(); // read value.
989 return;
990 case kTrueLiteral:
991 helper_.ReadPosition(); // read position.
992 return;
993 case kFalseLiteral:
994 helper_.ReadPosition(); // read position.
995 return;
996 case kNullLiteral:
997 helper_.ReadPosition(); // read position.
998 return;
999 case kConstantExpression:
1000 helper_.ReadPosition();
1001 helper_.SkipDartType();
1002 helper_.SkipConstantReference();
1003 return;
1004 case kFileUriConstantExpression:
1005 helper_.ReadPosition();
1006 helper_.ReadUInt();
1007 helper_.SkipDartType();
1008 helper_.SkipConstantReference();
1009 return;
1010 case kInstantiation: {
1011 helper_.ReadPosition(); // read position.
1012 VisitExpression();
1013 const intptr_t list_length =
1014 helper_.ReadListLength(); // read list length.
1015 for (intptr_t i = 0; i < list_length; ++i) {
1016 VisitDartType(); // read ith type.
1017 }
1018 return;
1019 }
1020 case kLoadLibrary:
1021 case kCheckLibraryIsLoaded:
1022 helper_.ReadPosition(); // read file offset.
1023 helper_.ReadUInt(); // library index
1024 break;
1025 case kAwaitExpression:
1026 helper_.ReadPosition(); // read position.
1027 VisitExpression(); // read operand.
1028 if (helper_.ReadTag() == kSomething) {
1029 VisitDartType(); // read runtime check type.
1030 }
1031 return;
1032 case kFileUriExpression:
1033 helper_.ReadUInt(); // read uri.
1034 helper_.ReadPosition(); // read position.
1035 VisitExpression(); // read expression.
1036 return;
1037 case kConstStaticInvocation:
1038 case kConstConstructorInvocation:
1039 case kConstListLiteral:
1040 case kConstSetLiteral:
1041 case kConstMapLiteral:
1042 case kSymbolLiteral:
1043 case kListConcatenation:
1044 case kSetConcatenation:
1045 case kMapConcatenation:
1046 case kInstanceCreation:
1047 case kStaticTearOff:
1048 case kSwitchExpression:
1049 case kPatternAssignment:
1050 // These nodes are internal to the front end and
1051 // removed by the constant evaluator.
1052 default:
1053 ReportUnexpectedTag("expression", tag);
1054 UNREACHABLE();
1055 }
1056}
1057
1058void ScopeBuilder::VisitStatement() {
1059 Tag tag = helper_.ReadTag(); // read tag.
1060 switch (tag) {
1061 case kExpressionStatement:
1062 VisitExpression(); // read expression.
1063 return;
1064 case kBlock: {
1065 PositionScope scope(&helper_.reader_);
1066 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1067
1068 EnterScope(offset);
1069 helper_.ReadPosition(); // read block start offset.
1070 helper_.ReadPosition(); // read block end offset.
1071 intptr_t list_length =
1072 helper_.ReadListLength(); // read number of statements.
1073 for (intptr_t i = 0; i < list_length; ++i) {
1074 VisitStatement(); // read ith statement.
1075 }
1076
1077 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
1078 return;
1079 }
1080 case kEmptyStatement:
1081 return;
1082 case kAssertBlock:
1083 if (IG->asserts()) {
1084 PositionScope scope(&helper_.reader_);
1085 intptr_t offset =
1086 helper_.ReaderOffset() - 1; // -1 to include tag byte.
1087
1088 EnterScope(offset);
1089
1090 intptr_t list_length =
1091 helper_.ReadListLength(); // read number of statements.
1092 for (intptr_t i = 0; i < list_length; ++i) {
1093 VisitStatement(); // read ith statement.
1094 }
1095
1096 ExitScope(helper_.reader_.min_position(),
1097 helper_.reader_.max_position());
1098 } else {
1099 helper_.SkipStatementList();
1100 }
1101 return;
1102 case kAssertStatement:
1103 if (IG->asserts()) {
1104 VisitExpression(); // Read condition.
1105 helper_.ReadPosition(); // read condition start offset.
1106 helper_.ReadPosition(); // read condition end offset.
1107 Tag tag = helper_.ReadTag(); // read (first part of) message.
1108 if (tag == kSomething) {
1109 VisitExpression(); // read (rest of) message.
1110 }
1111 } else {
1112 helper_.SkipExpression(); // Read condition.
1113 helper_.ReadPosition(); // read condition start offset.
1114 helper_.ReadPosition(); // read condition end offset.
1115 Tag tag = helper_.ReadTag(); // read (first part of) message.
1116 if (tag == kSomething) {
1117 helper_.SkipExpression(); // read (rest of) message.
1118 }
1119 }
1120 return;
1121 case kLabeledStatement:
1122 helper_.ReadPosition(); // read position.
1123 VisitStatement(); // read body.
1124 return;
1125 case kBreakStatement:
1126 helper_.ReadPosition(); // read position.
1127 helper_.ReadUInt(); // read target_index.
1128 return;
1129 case kWhileStatement:
1130 ++depth_.loop_;
1131 helper_.ReadPosition(); // read position.
1132 VisitExpression(); // read condition.
1133 VisitStatement(); // read body.
1134 --depth_.loop_;
1135 return;
1136 case kDoStatement:
1137 ++depth_.loop_;
1138 helper_.ReadPosition(); // read position.
1139 VisitStatement(); // read body.
1140 VisitExpression(); // read condition.
1141 --depth_.loop_;
1142 return;
1143 case kForStatement: {
1144 PositionScope scope(&helper_.reader_);
1145
1146 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1147
1148 ++depth_.loop_;
1149 EnterScope(offset);
1150
1151 TokenPosition position = helper_.ReadPosition(); // read position.
1152 intptr_t list_length =
1153 helper_.ReadListLength(); // read number of variables.
1154 for (intptr_t i = 0; i < list_length; ++i) {
1155 VisitVariableDeclaration(); // read ith variable.
1156 }
1157
1158 Tag tag = helper_.ReadTag(); // Read first part of condition.
1159 if (tag == kSomething) {
1160 VisitExpression(); // read rest of condition.
1161 }
1162 VisitListOfExpressions(); // read updates.
1163 VisitStatement(); // read body.
1164
1165 ExitScope(position, helper_.reader_.max_position());
1166 --depth_.loop_;
1167 return;
1168 }
1169 case kSwitchStatement: {
1170 AddSwitchVariable();
1171 helper_.ReadPosition(); // read position.
1172 helper_.ReadBool(); // read exhaustive flag.
1173 VisitExpression(); // read condition.
1174 helper_.SkipOptionalDartType(); // read expression type.
1175 int case_count = helper_.ReadListLength(); // read number of cases.
1176 for (intptr_t i = 0; i < case_count; ++i) {
1177 helper_.ReadPosition(); // read file offset.
1178 int expression_count =
1179 helper_.ReadListLength(); // read number of expressions.
1180 for (intptr_t j = 0; j < expression_count; ++j) {
1181 helper_.ReadPosition(); // read jth position.
1182 VisitExpression(); // read jth expression.
1183 }
1184 helper_.ReadBool(); // read is_default.
1185 VisitStatement(); // read body.
1186 }
1187 return;
1188 }
1189 case kContinueSwitchStatement:
1190 helper_.ReadPosition(); // read position.
1191 helper_.ReadUInt(); // read target_index.
1192 return;
1193 case kIfStatement:
1194 helper_.ReadPosition(); // read position.
1195 VisitExpression(); // read condition.
1196 VisitStatement(); // read then.
1197 VisitStatement(); // read otherwise.
1198 return;
1199 case kReturnStatement: {
1200 if ((depth_.function_ == 0) && (depth_.finally_ > 0) &&
1201 (result_->finally_return_variable == nullptr)) {
1202 const String& name = Symbols::TryFinallyReturnValue();
1203 LocalVariable* variable =
1204 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1205 name, AbstractType::dynamic_type());
1206 current_function_scope_->AddVariable(variable);
1207 result_->finally_return_variable = variable;
1208 }
1209
1210 helper_.ReadPosition(); // read position
1211 Tag tag = helper_.ReadTag(); // read (first part of) expression.
1212 if (tag == kSomething) {
1213 VisitExpression(); // read (rest of) expression.
1214 }
1215 return;
1216 }
1217 case kTryCatch: {
1218 ++depth_.try_;
1219 AddTryVariables();
1220 helper_.ReadPosition(); // read position.
1221 VisitStatement(); // read body.
1222 --depth_.try_;
1223
1224 ++depth_.catch_;
1225 AddCatchVariables();
1226
1227 helper_.ReadByte(); // read flags
1228 intptr_t catch_count =
1229 helper_.ReadListLength(); // read number of catches.
1230 for (intptr_t i = 0; i < catch_count; ++i) {
1231 PositionScope scope(&helper_.reader_);
1232 intptr_t offset = helper_.ReaderOffset(); // Catch has no tag.
1233
1234 EnterScope(offset);
1235
1236 helper_.ReadPosition(); // read position.
1237 VisitDartType(); // Read the guard.
1238 tag = helper_.ReadTag(); // read first part of exception.
1239 if (tag == kSomething) {
1240 VisitVariableDeclaration(); // read exception.
1241 }
1242 tag = helper_.ReadTag(); // read first part of stack trace.
1243 if (tag == kSomething) {
1244 VisitVariableDeclaration(); // read stack trace.
1245 }
1246 VisitStatement(); // read body.
1247
1248 ExitScope(helper_.reader_.min_position(),
1249 helper_.reader_.max_position());
1250 }
1251
1252 FinalizeCatchVariables();
1253
1254 --depth_.catch_;
1255 return;
1256 }
1257 case kTryFinally: {
1258 ++depth_.try_;
1259 ++depth_.finally_;
1260 AddTryVariables();
1261
1262 helper_.ReadPosition(); // read position.
1263 VisitStatement(); // read body.
1264
1265 --depth_.finally_;
1266 --depth_.try_;
1267 ++depth_.catch_;
1268 AddCatchVariables();
1269
1270 VisitStatement(); // read finalizer.
1271
1272 FinalizeCatchVariables();
1273
1274 --depth_.catch_;
1275 return;
1276 }
1277 case kYieldStatement: {
1278 helper_.ReadPosition(); // read position.
1279 helper_.ReadByte(); // read flags.
1280 VisitExpression(); // read expression.
1281 return;
1282 }
1283 case kVariableDeclaration:
1284 VisitVariableDeclaration(); // read variable declaration.
1285 return;
1286 case kFunctionDeclaration: {
1287 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1288 helper_.ReadPosition(); // read position.
1289 VisitVariableDeclaration(); // read variable declaration.
1290 HandleLocalFunction(offset); // read function node.
1291 return;
1292 }
1293 case kForInStatement:
1294 case kAsyncForInStatement:
1295 case kIfCaseStatement:
1296 case kPatternSwitchStatement:
1297 case kPatternVariableDeclaration:
1298 // These nodes are internal to the front end and
1299 // removed by the constant evaluator.
1300 default:
1301 ReportUnexpectedTag("declaration", tag);
1302 UNREACHABLE();
1303 }
1304}
1305
1306void ScopeBuilder::VisitListOfExpressions() {
1307 const intptr_t list_length = helper_.ReadListLength(); // read list length.
1308 for (intptr_t i = 0; i < list_length; ++i) {
1309 VisitExpression();
1310 }
1311}
1312
1313void ScopeBuilder::VisitListOfNamedExpressions() {
1314 const intptr_t list_length = helper_.ReadListLength(); // read list length.
1315 for (intptr_t i = 0; i < list_length; ++i) {
1316 helper_.SkipStringReference(); // read ith name index.
1317 VisitExpression(); // read ith expression.
1318 }
1319}
1320
1321void ScopeBuilder::VisitArguments() {
1322 helper_.ReadUInt(); // read argument_count.
1323
1324 // Types
1325 intptr_t list_length = helper_.ReadListLength(); // read list length.
1326 for (intptr_t i = 0; i < list_length; ++i) {
1327 VisitDartType(); // read ith type.
1328 }
1329
1330 VisitListOfExpressions(); // Positional.
1331 VisitListOfNamedExpressions(); // Named.
1332}
1333
1334void ScopeBuilder::VisitVariableDeclaration() {
1335 PositionScope scope(&helper_.reader_);
1336
1337 const intptr_t kernel_offset =
1338 helper_.data_program_offset_ + helper_.ReaderOffset();
1339 // MetadataHelper expects relative offsets and adjusts them internally
1340 const InferredTypeMetadata inferred_type =
1341 inferred_type_metadata_helper_.GetInferredType(helper_.ReaderOffset());
1342 VariableDeclarationHelper helper(&helper_);
1343 helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
1344 const intptr_t annotations_offset = helper_.ReaderOffset();
1345 helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
1346 AbstractType& type = BuildAndVisitVariableType();
1347
1348 const String& name = (H.StringSize(helper.name_index_) == 0)
1349 ? GenerateName(":var", name_index_++)
1350 : H.DartSymbolObfuscate(helper.name_index_);
1351
1352 intptr_t initializer_offset = helper_.ReaderOffset();
1353 Tag tag = helper_.ReadTag(); // read (first part of) initializer.
1354 if (tag == kSomething) {
1355 VisitExpression(); // read (actual) initializer.
1356 }
1357
1358 // Go to next token position so it ends *after* the last potentially
1359 // debuggable position in the initializer.
1360 TokenPosition end_position = helper_.reader_.max_position();
1361 if (end_position.IsReal()) {
1362 end_position = end_position.Next();
1363 }
1364 LocalVariable* variable =
1365 MakeVariable(helper.position_, end_position, name, type, kernel_offset,
1366 helper.IsLate(), &inferred_type);
1367 if (helper.annotation_count_ > 0) {
1368 variable->set_annotations_offset(annotations_offset);
1369 }
1370 if (helper.IsFinal()) {
1371 variable->set_is_final();
1372 }
1373 if (helper.IsLate()) {
1374 variable->set_is_late();
1375 variable->set_late_init_offset(initializer_offset);
1376 }
1377 if (helper.IsSynthesized()) {
1378 variable->set_invisible(true);
1379 }
1380
1381 scope_->AddVariable(variable);
1382 result_->locals.Insert(kernel_offset, variable);
1383}
1384
1385AbstractType& ScopeBuilder::BuildAndVisitVariableType() {
1386 const intptr_t offset = helper_.ReaderOffset();
1387 AbstractType& type = T.BuildType();
1388 helper_.SetOffset(offset); // rewind
1389 VisitDartType();
1390 return type;
1391}
1392
1393void ScopeBuilder::VisitDartType() {
1394 Tag tag = helper_.ReadTag();
1395 switch (tag) {
1396 case kInvalidType:
1397 case kDynamicType:
1398 case kVoidType:
1399 case kNullType:
1400 // those contain nothing.
1401 return;
1402 case kNeverType:
1403 helper_.ReadNullability();
1404 return;
1405 case kInterfaceType:
1406 VisitInterfaceType(false);
1407 return;
1408 case kSimpleInterfaceType:
1409 VisitInterfaceType(true);
1410 return;
1411 case kFunctionType:
1412 VisitFunctionType(false);
1413 return;
1414 case kSimpleFunctionType:
1415 VisitFunctionType(true);
1416 return;
1417 case kRecordType:
1418 VisitRecordType();
1419 return;
1420 case kTypeParameterType:
1421 VisitTypeParameterType();
1422 return;
1423 case kIntersectionType:
1424 VisitIntersectionType();
1425 return;
1426 case kExtensionType:
1427 VisitExtensionType();
1428 return;
1429 case kFutureOrType:
1430 VisitFutureOrType();
1431 return;
1432 default:
1433 ReportUnexpectedTag("type", tag);
1434 UNREACHABLE();
1435 }
1436}
1437
1438void ScopeBuilder::VisitInterfaceType(bool simple) {
1439 helper_.ReadNullability(); // read nullability.
1440 helper_.ReadUInt(); // read klass_name.
1441 if (!simple) {
1442 intptr_t length = helper_.ReadListLength(); // read number of types.
1443 for (intptr_t i = 0; i < length; ++i) {
1444 VisitDartType(); // read the ith type.
1445 }
1446 }
1447}
1448
1449void ScopeBuilder::VisitFunctionType(bool simple) {
1450 helper_.ReadNullability(); // read nullability.
1451
1452 if (!simple) {
1453 intptr_t list_length =
1454 helper_.ReadListLength(); // read type_parameters list length.
1455 for (int i = 0; i < list_length; ++i) {
1456 TypeParameterHelper helper(&helper_);
1457 helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
1458 VisitDartType(); // read bound.
1459 helper.ReadUntilExcludingAndSetJustRead(
1461 VisitDartType(); // read default type.
1462 helper.Finish();
1463 }
1464 helper_.ReadUInt(); // read required parameter count.
1465 helper_.ReadUInt(); // read total parameter count.
1466 }
1467
1468 const intptr_t positional_count =
1469 helper_.ReadListLength(); // read positional_parameters list length.
1470 for (intptr_t i = 0; i < positional_count; ++i) {
1471 VisitDartType(); // read ith positional parameter.
1472 }
1473
1474 if (!simple) {
1475 const intptr_t named_count =
1476 helper_.ReadListLength(); // read named_parameters list length.
1477 for (intptr_t i = 0; i < named_count; ++i) {
1478 // read string reference (i.e. named_parameters[i].name).
1479 helper_.SkipStringReference();
1480 VisitDartType(); // read named_parameters[i].type.
1481 helper_.ReadByte(); // read flags
1482 }
1483 }
1484
1485 VisitDartType(); // read return type.
1486}
1487
1488void ScopeBuilder::VisitRecordType() {
1489 helper_.ReadNullability(); // read nullability.
1490 const intptr_t positional_count =
1491 helper_.ReadListLength(); // read positional list length.
1492 for (intptr_t i = 0; i < positional_count; ++i) {
1493 VisitDartType(); // read positional[i].
1494 }
1495 const intptr_t named_count =
1496 helper_.ReadListLength(); // read named list length.
1497 for (intptr_t i = 0; i < named_count; ++i) {
1498 helper_.SkipStringReference(); // read named[i].name.
1499 VisitDartType(); // read named[i].type.
1500 helper_.ReadFlags(); // read named[i].flags
1501 }
1502}
1503
1504void ScopeBuilder::VisitTypeParameterType() {
1505 Function& function = Function::Handle(Z, parsed_function_->function().ptr());
1506
1507 helper_.ReadNullability(); // read nullability.
1508
1509 // The index here is the index identifying the type parameter binding site
1510 // inside the DILL file, which uses a different indexing system than the VM
1511 // uses for its 'TypeParameter's internally. This index includes both class
1512 // and function type parameters.
1513
1514 intptr_t index = helper_.ReadUInt(); // read index for parameter.
1515
1516 if (!function.IsImplicitStaticClosureFunction()) {
1517 while (function.IsClosureFunction()) {
1518 function = function.parent_function();
1519 }
1520
1521 if (function.IsFactory()) {
1522 // The type argument vector is passed as the very first argument to the
1523 // factory constructor function.
1524 HandleSpecialLoad(&result_->type_arguments_variable,
1525 Symbols::TypeArgumentsParameter(),
1527 } else {
1528 // If the type parameter is a parameter to this or an enclosing function,
1529 // we can read it directly from the function type arguments vector later.
1530 // Otherwise, the type arguments vector we need is stored on the instance
1531 // object, so we need to capture 'this'.
1532 Class& parent_class = Class::Handle(Z, function.Owner());
1533 if (index < parent_class.NumTypeParameters()) {
1534 HandleLoadReceiver();
1535 }
1536 }
1537 }
1538}
1539
1540void ScopeBuilder::VisitIntersectionType() {
1541 VisitDartType(); // read left.
1542 helper_.SkipDartType(); // read right.
1543}
1544
1545void ScopeBuilder::VisitExtensionType() {
1546 // We skip the extension type and only use the type erasure.
1547 helper_.ReadNullability();
1548 helper_.SkipCanonicalNameReference(); // read index for canonical name.
1549 helper_.SkipListOfDartTypes(); // read type arguments
1550 VisitDartType(); // read type erasure.
1551}
1552
1553void ScopeBuilder::VisitFutureOrType() {
1554 helper_.ReadNullability();
1555 VisitDartType(); // read type argument.
1556}
1557
1558void ScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
1559 // "Peek" ahead into the function node
1560 const intptr_t offset = helper_.ReaderOffset();
1561
1562 FunctionNodeHelper function_node_helper(&helper_);
1563 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
1564
1565 LocalScope* saved_function_scope = current_function_scope_;
1566 DepthState saved_depth_state = depth_;
1567 depth_ = DepthState(depth_.function_ + 1);
1568 EnterScope(parent_kernel_offset);
1569 current_function_scope_ = scope_;
1570 if (depth_.function_ == 1) {
1571 FunctionScope function_scope = {offset, scope_};
1572 result_->function_scopes.Add(function_scope);
1573 }
1574
1575 int num_type_params = 0;
1576 {
1577 AlternativeReadingScope _(&helper_.reader_);
1578 num_type_params = helper_.ReadListLength();
1579 }
1580 // Adding this scope here informs the type translator the type parameters of
1581 // this function are now in scope, although they are not defined and will be
1582 // filled in with dynamic. This is OK, since their definitions are not needed
1583 // for scope building of the enclosing function.
1584 TypeTranslator::TypeParameterScope scope(&type_translator_, num_type_params);
1585
1586 // read positional_parameters and named_parameters.
1587 function_node_helper.ReadUntilExcluding(
1589
1590 ProcedureAttributesMetadata default_attrs;
1591 AddPositionalAndNamedParameters(0, kTypeCheckForNonDynamicallyInvokedMethod,
1592 default_attrs);
1593
1594 if (function_node_helper.async_marker_ != FunctionNodeHelper::kSync) {
1595 // Read return type which is used to create a result of async/async*/sync*
1596 // function. It may reference receiver or type arguments of the enclosing
1597 // function which need to be captured.
1598 VisitDartType();
1599 }
1600
1601 // "Peek" is now done.
1602 helper_.SetOffset(offset);
1603
1604 VisitFunctionNode(); // read function node.
1605
1606 // Remember if this closure and all closures nested within it don't
1607 // capture any variables from outer scopes.
1608 if (scope_->function_level() == 1) {
1609 if (scope_->NumCapturedVariables() == 0) {
1611 }
1612 }
1613
1614 ExitScope(function_node_helper.position_, function_node_helper.end_position_);
1615 depth_ = saved_depth_state;
1616 current_function_scope_ = saved_function_scope;
1617}
1618
1619void ScopeBuilder::EnterScope(intptr_t kernel_offset) {
1620 scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
1621 ASSERT(kernel_offset >= 0);
1622 result_->scopes.Insert(kernel_offset, scope_);
1623}
1624
1625void ScopeBuilder::ExitScope(TokenPosition start_position,
1626 TokenPosition end_position) {
1627 scope_->set_begin_token_pos(start_position);
1628 scope_->set_end_token_pos(end_position);
1629 scope_ = scope_->parent();
1630}
1631
1632void ScopeBuilder::AddPositionalAndNamedParameters(
1633 intptr_t pos,
1634 ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/,
1635 const ProcedureAttributesMetadata& attrs) {
1636 // List of positional.
1637 intptr_t list_length = helper_.ReadListLength(); // read list length.
1638 for (intptr_t i = 0; i < list_length; ++i) {
1639 AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
1640 }
1641
1642 // List of named.
1643 list_length = helper_.ReadListLength(); // read list length.
1644 for (intptr_t i = 0; i < list_length; ++i) {
1645 AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
1646 }
1647}
1648
1649void ScopeBuilder::AddVariableDeclarationParameter(
1650 intptr_t pos,
1651 ParameterTypeCheckMode type_check_mode,
1652 const ProcedureAttributesMetadata& attrs) {
1653 // Convert kernel offset of variable declaration to absolute.
1654 const intptr_t kernel_offset =
1655 helper_.data_program_offset_ + helper_.ReaderOffset();
1656 // MetadataHelper expects relative offsets and adjusts them internally
1657 const InferredTypeMetadata inferred_type =
1658 inferred_type_metadata_helper_.GetInferredType(helper_.ReaderOffset());
1659 const InferredTypeMetadata inferred_arg_type =
1660 inferred_arg_type_metadata_helper_.GetInferredType(
1661 helper_.ReaderOffset());
1662 VariableDeclarationHelper helper(&helper_);
1663 helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
1664 const intptr_t annotations_offset = helper_.ReaderOffset();
1665 helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
1666 String& name = H.DartSymbolObfuscate(helper.name_index_);
1667 ASSERT(name.Length() > 0);
1668 AbstractType& type = BuildAndVisitVariableType(); // read type.
1669 helper.SetJustRead(VariableDeclarationHelper::kType);
1670 helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
1671
1672 LocalVariable* variable = MakeVariable(
1673 helper.position_, helper.position_, name, type, kernel_offset,
1674 /*is_late=*/false, &inferred_type, &inferred_arg_type);
1675 if (helper.annotation_count_ > 0) {
1676 variable->set_annotations_offset(annotations_offset);
1677 }
1678 if (helper.IsFinal()) {
1679 variable->set_is_final();
1680 }
1681 if (helper.IsCovariant()) {
1682 variable->set_is_explicit_covariant_parameter();
1683 }
1684
1685 const bool needs_covariant_check_in_method =
1686 helper.IsCovariant() ||
1687 (helper.IsGenericCovariantImpl() &&
1688 (attrs.has_non_this_uses || attrs.has_tearoff_uses));
1689 if (needs_covariant_check_in_method) {
1690 variable->set_needs_covariant_check_in_method();
1691 }
1692
1693 switch (type_check_mode) {
1694 case kTypeCheckAllParameters:
1695 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1696 break;
1697 case kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod:
1698 if (needs_covariant_check_in_method) {
1699 // Don't type check covariant parameters - they will be checked by
1700 // a function we forward to. Their types however are not known.
1701 variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
1702 } else {
1703 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1704 }
1705 break;
1706 case kTypeCheckForNonDynamicallyInvokedMethod:
1707 if (needs_covariant_check_in_method) {
1708 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1709 } else {
1710 // Types of non-covariant parameters are guaranteed to match by
1711 // front-end enforcing strong mode types at call site.
1712 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1713 }
1714 break;
1715 case kTypeCheckForImplicitClosureFunction:
1716 if (needs_covariant_check_in_method) {
1717 // Don't type check covariant parameters - they will be checked by
1718 // a function we forward to. Their types however are not known.
1719 variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
1720 } else {
1721 // All non-covariant checks are either checked by the type system or
1722 // by a dynamic closure call dispatcher.
1723 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1724 }
1725 break;
1726 case kTypeCheckForStaticFunction:
1727 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1728 break;
1729 }
1730
1731 // TODO(sjindel): We can also skip these checks on dynamic invocations as
1732 // well.
1733 if (inferred_arg_type.IsSkipCheck()) {
1734 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1735 }
1736
1737 scope_->InsertParameterAt(pos, variable);
1738 result_->locals.Insert(kernel_offset, variable);
1739
1740 // The default value may contain 'let' bindings for which the constant
1741 // evaluator needs scope bindings.
1742 Tag tag = helper_.ReadTag();
1743 if (tag == kSomething) {
1744 VisitExpression(); // read initializer.
1745 }
1746}
1747
1748LocalVariable* ScopeBuilder::MakeVariable(
1749 TokenPosition declaration_pos,
1750 TokenPosition token_pos,
1751 const String& name,
1752 const AbstractType& static_type,
1753 intptr_t kernel_offset /* = LocalVariable::kNoKernelOffset */,
1754 bool is_late /* = false */,
1755 const InferredTypeMetadata* inferred_type_md /* = nullptr */,
1756 const InferredTypeMetadata* inferred_arg_type_md /* = nullptr */) {
1757 CompileType* inferred_type = nullptr;
1758 if (inferred_type_md != nullptr && !inferred_type_md->IsTrivial()) {
1759 inferred_type = new (Z)
1760 CompileType(inferred_type_md->ToCompileType(Z, &static_type, is_late));
1761 } else {
1762 inferred_type = new (Z) CompileType(CompileType::FromAbstractType(
1763 static_type, CompileType::kCanBeNull, is_late));
1764 }
1765 CompileType* inferred_arg_type = nullptr;
1766 const Object* inferred_arg_value = nullptr;
1767 if (inferred_arg_type_md != nullptr && !inferred_arg_type_md->IsTrivial()) {
1768 inferred_arg_type =
1769 new (Z) CompileType(inferred_arg_type_md->ToCompileType(Z));
1770 if (inferred_arg_type_md->IsConstant()) {
1771 inferred_arg_value = &inferred_arg_type_md->constant_value;
1772 }
1773 }
1774 return new (Z) LocalVariable(declaration_pos, token_pos, name, static_type,
1775 kernel_offset, inferred_type, inferred_arg_type,
1776 inferred_arg_value);
1777}
1778
1779void ScopeBuilder::AddExceptionVariable(
1780 GrowableArray<LocalVariable*>* variables,
1781 const char* prefix,
1782 intptr_t nesting_depth) {
1783 LocalVariable* v = nullptr;
1784
1785 // No need to create variables for try/catch-statements inside
1786 // nested functions.
1787 if (depth_.function_ > 0) return;
1788 if (variables->length() >= nesting_depth) return;
1789
1790 // If variable was not lifted by the transformer introduce a new
1791 // one into the current function scope.
1792 if (v == nullptr) {
1793 v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1794 GenerateName(prefix, nesting_depth - 1),
1795 AbstractType::dynamic_type());
1796
1797 // If transformer did not lift the variable then there is no need
1798 // to lift it into the context when we encounter a YieldStatement.
1799 v->set_is_forced_stack();
1800 current_function_scope_->AddVariable(v);
1801 }
1802
1803 variables->Add(v);
1804}
1805
1806void ScopeBuilder::FinalizeExceptionVariable(
1807 GrowableArray<LocalVariable*>* variables,
1808 GrowableArray<LocalVariable*>* raw_variables,
1809 const String& symbol,
1810 intptr_t nesting_depth) {
1811 // No need to create variables for try/catch-statements inside
1812 // nested functions.
1813 if (depth_.function_ > 0) return;
1814
1815 LocalVariable* variable = (*variables)[nesting_depth - 1];
1816 LocalVariable* raw_variable;
1817 if (variable->is_captured()) {
1818 raw_variable =
1819 new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1820 symbol, AbstractType::dynamic_type());
1821 raw_variable->set_is_forced_stack();
1822 const bool ok = scope_->AddVariable(raw_variable);
1823 ASSERT(ok);
1824 } else {
1825 raw_variable = variable;
1826 }
1827 raw_variables->EnsureLength(nesting_depth, nullptr);
1828 (*raw_variables)[nesting_depth - 1] = raw_variable;
1829}
1830
1831void ScopeBuilder::AddTryVariables() {
1832 AddExceptionVariable(&result_->catch_context_variables,
1833 ":saved_try_context_var", depth_.try_);
1834}
1835
1836void ScopeBuilder::AddCatchVariables() {
1837 AddExceptionVariable(&result_->exception_variables, ":exception",
1838 depth_.catch_);
1839 AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace",
1840 depth_.catch_);
1841}
1842
1843void ScopeBuilder::FinalizeCatchVariables() {
1844 const intptr_t unique_id = result_->raw_variable_counter_++;
1845 FinalizeExceptionVariable(
1846 &result_->exception_variables, &result_->raw_exception_variables,
1847 GenerateName(":raw_exception", unique_id), depth_.catch_);
1848 FinalizeExceptionVariable(
1850 GenerateName(":raw_stacktrace", unique_id), depth_.catch_);
1851}
1852
1853void ScopeBuilder::AddSwitchVariable() {
1854 if ((depth_.function_ == 0) && (result_->switch_variable == nullptr)) {
1855 LocalVariable* variable =
1856 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1857 Symbols::SwitchExpr(), AbstractType::dynamic_type());
1858 variable->set_is_forced_stack();
1859 current_function_scope_->AddVariable(variable);
1860 result_->switch_variable = variable;
1861 }
1862}
1863
1864void ScopeBuilder::VisitVariableGet(intptr_t declaration_binary_offset) {
1865 LocalVariable* variable = LookupVariable(declaration_binary_offset);
1866 if (variable->is_late()) {
1867 // Late variable initializer expressions may also contain local variables
1868 // that need to be captured.
1869 AlternativeReadingScope alt(&helper_.reader_, variable->late_init_offset());
1870 if (helper_.ReadTag() != kNothing) {
1871 VisitExpression();
1872 }
1873 }
1874}
1875
1876LocalVariable* ScopeBuilder::LookupVariable(
1877 intptr_t declaration_binary_offset) {
1878 LocalVariable* variable = result_->locals.Lookup(declaration_binary_offset);
1879 if (variable == nullptr) {
1880 // We have not seen a declaration of the variable, so it must be the
1881 // case that we are compiling a nested function and the variable is
1882 // declared in an outer scope. In that case, look it up in the scope by
1883 // name and add it to the variable map to simplify later lookup.
1884 ASSERT(current_function_scope_->parent() != nullptr);
1885 StringIndex var_name = GetNameFromVariableDeclaration(
1886 declaration_binary_offset - helper_.data_program_offset_,
1887 parsed_function_->function());
1888
1889 const String& name = H.DartSymbolObfuscate(var_name);
1890 variable = current_function_scope_->parent()->LookupVariable(
1891 name, declaration_binary_offset, true);
1892 ASSERT(variable != nullptr);
1893 result_->locals.Insert(declaration_binary_offset, variable);
1894 }
1895
1896 ASSERT(variable->owner() != nullptr);
1897 if (variable->owner()->function_level() < scope_->function_level()) {
1898 // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two
1899 // different reasons:
1900 // Scenario 1:
1901 // We need to know which variables defined in this function
1902 // are closed over by nested closures in order to ensure we will
1903 // create a [Context] object of appropriate size and store captured
1904 // variables there instead of the stack.
1905 // Scenario 2:
1906 // We need to find out which variables defined in enclosing functions
1907 // are closed over by this function/closure or nested closures. This
1908 // is necessary in order to build a fat flattened [ContextScope]
1909 // object.
1910 scope_->CaptureVariable(variable);
1911 } else {
1912 ASSERT(variable->owner()->function_level() == scope_->function_level());
1913 }
1914 return variable;
1915}
1916
1917StringIndex ScopeBuilder::GetNameFromVariableDeclaration(
1918 intptr_t kernel_offset,
1919 const Function& function) {
1920 const auto& kernel_data = TypedDataView::Handle(Z, function.KernelLibrary());
1921 ASSERT(!kernel_data.IsNull());
1922
1923 // Temporarily go to the variable declaration, read the name.
1924 AlternativeReadingScopeWithNewData alt(&helper_.reader_, &kernel_data,
1925 kernel_offset);
1926 VariableDeclarationHelper helper(&helper_);
1927 helper.ReadUntilIncluding(VariableDeclarationHelper::kNameIndex);
1928 return helper.name_index_;
1929}
1930
1931const String& ScopeBuilder::GenerateName(const char* prefix, intptr_t suffix) {
1932 char name[64];
1933 Utils::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
1934 return H.DartSymbolObfuscate(name);
1935}
1936
1937void ScopeBuilder::HandleLoadReceiver() {
1938 if (!parsed_function_->has_receiver_var() &&
1939 current_function_scope_->parent() != nullptr) {
1940 // Lazily populate receiver variable using the parent function scope.
1941 parsed_function_->set_receiver_var(
1942 current_function_scope_->parent()->LookupVariable(
1944 }
1945
1946 if ((current_function_scope_->parent() != nullptr) ||
1947 (scope_->function_level() > 0)) {
1948 // Every scope we use the [receiver] from needs to be notified of the usage
1949 // in order to ensure that preserving the context scope on that particular
1950 // use-site also includes the [receiver].
1951 scope_->CaptureVariable(parsed_function_->receiver_var());
1952 }
1953
1954 parsed_function_->set_receiver_used();
1955}
1956
1957void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
1958 const String& symbol,
1959 intptr_t kernel_offset) {
1960 if (current_function_scope_->parent() != nullptr) {
1961 // We are building the scope tree of a closure function and saw [node]. We
1962 // lazily populate the variable using the parent function scope.
1963 if (*variable == nullptr) {
1964 *variable = current_function_scope_->parent()->LookupVariable(
1965 symbol, kernel_offset, true);
1966 ASSERT(*variable != nullptr);
1967 }
1968 }
1969
1970 if ((current_function_scope_->parent() != nullptr) ||
1971 (scope_->function_level() > 0)) {
1972 // Every scope we use the [variable] from needs to be notified of the usage
1973 // in order to ensure that preserving the context scope on that particular
1974 // use-site also includes the [variable].
1975 scope_->CaptureVariable(*variable);
1976 }
1977}
1978
1979} // namespace kernel
1980} // namespace dart
SkPoint pos
static bool ok(int result)
#define UNREACHABLE()
Definition: assert.h:248
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
GLenum type
ObjectPtr At(intptr_t index) const
Definition: object.h:10875
intptr_t Length() const
Definition: object.h:10829
void Add(const T &value)
ArrayPtr fields() const
Definition: object.h:1615
static constexpr bool kCanBeNull
Definition: compile_type.h:45
static CompileType FromAbstractType(const AbstractType &type, bool can_be_null, bool can_be_sentinel)
static CompilerState & Current()
intptr_t kernel_offset() const
Definition: object.h:4495
bool is_static() const
Definition: object.h:4440
TypedDataViewPtr KernelLibrary() const
Definition: object.cc:11907
static bool IsDynamicInvocationForwarderName(const String &name)
Definition: object.cc:4190
bool MayHaveUncheckedEntryPoint() const
Definition: object.cc:11448
KernelProgramInfoPtr KernelProgramInfo() const
Definition: object.cc:10919
const char * ToQualifiedCString() const
Definition: object.cc:9776
LocalScope * parent() const
Definition: scopes.h:319
void set_begin_token_pos(TokenPosition value)
Definition: scopes.h:344
void set_end_token_pos(TokenPosition value)
Definition: scopes.h:347
TokenPosition end_token_pos() const
Definition: scopes.h:346
int NumCapturedVariables() const
Definition: scopes.cc:409
int function_level() const
Definition: scopes.h:322
static LocalScope * RestoreOuterScope(const ContextScope &context_scope)
Definition: scopes.cc:518
LocalVariable * LookupVariable(const String &name, intptr_t kernel_offset, bool test_only)
Definition: scopes.cc:350
bool AddVariable(LocalVariable *variable)
Definition: scopes.cc:57
void CaptureVariable(LocalVariable *variable)
Definition: scopes.cc:383
bool InsertParameterAt(intptr_t pos, LocalVariable *parameter)
Definition: scopes.cc:72
void set_context_level(int context_level)
Definition: scopes.h:337
void AddContextVariable(LocalVariable *var)
Definition: scopes.cc:126
VariableIndex index() const
Definition: scopes.h:202
void set_is_captured()
Definition: scopes.h:144
void set_is_explicit_covariant_parameter()
Definition: scopes.h:171
void set_type_check_mode(TypeCheckMode mode)
Definition: scopes.h:199
void set_invisible(bool value)
Definition: scopes.h:216
static constexpr intptr_t kNoKernelOffset
Definition: scopes.h:77
void set_is_forced_stack()
Definition: scopes.h:156
ObjectPtr ptr() const
Definition: object.h:332
static Object & Handle()
Definition: object.h:407
static Object & ZoneHandle()
Definition: object.h:419
void set_function_type_arguments(LocalVariable *function_type_arguments)
Definition: parser.h:91
LocalVariable * expression_temp_var() const
Definition: parser.h:151
const Function & function() const
Definition: parser.h:73
LocalVariable * EnsureExpressionTemp()
Definition: parser.cc:134
LocalVariable * EnsureEntryPointsTemp()
Definition: parser.cc:146
bool has_receiver_var() const
Definition: parser.h:142
void set_receiver_used()
Definition: parser.h:144
LocalVariable * arg_desc_var() const
Definition: parser.h:131
bool has_arg_desc_var() const
Definition: parser.h:130
void set_receiver_var(LocalVariable *value)
Definition: parser.h:137
void set_scope(LocalScope *scope)
Definition: parser.h:77
void AllocateVariables()
Definition: parser.cc:180
LocalVariable * current_context_var() const
Definition: parser.h:128
LocalVariable * suspend_state_var() const
Definition: parser.h:103
LocalVariable * receiver_var() const
Definition: parser.h:133
bool has_expression_temp_var() const
Definition: parser.h:159
void set_suspend_state_var(LocalVariable *suspend_state_var)
Definition: parser.h:104
DynamicClosureCallVars * EnsureDynamicClosureCallVars()
Definition: parser.cc:336
static constexpr intptr_t kSuspendStateVarIndex
Definition: object.h:12617
static const String & This()
Definition: symbols.h:692
TokenPosition Next()
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
int value() const
Definition: scopes.h:69
static bool IsExpressionTempVarUsedInRecognizedMethodFlowGraph(const Function &function)
static bool IsRecognizedMethodForFlowGraph(const Function &function)
InferredTypeMetadata GetInferredType(intptr_t node_offset, bool read_constant=true)
Tag ReadTag(uint8_t *payload=nullptr)
Tag PeekTag(uint8_t *payload=nullptr)
ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset)
TokenPosition min_position()
TokenPosition max_position()
static const char * TagName(Tag tag)
virtual void ReportUnexpectedTag(const char *variant, Tag tag)
ScopeBuildingResult * BuildScopes()
ScopeBuilder(ParsedFunction *parsed_function)
IntMap< LocalScope * > scopes
GrowableArray< LocalVariable * > catch_context_variables
GrowableArray< LocalVariable * > stack_trace_variables
GrowableArray< LocalVariable * > raw_exception_variables
GrowableArray< intptr_t > closure_offsets_without_captures
GrowableArray< LocalVariable * > exception_variables
IntMap< LocalVariable * > locals
GrowableArray< LocalVariable * > raw_stack_trace_variables
GrowableArray< FunctionScope > function_scopes
#define UNIMPLEMENTED
#define ASSERT(E)
uint32_t * target
Dart_NativeFunction function
Definition: fuchsia.cc:51
size_t length
Definition: dart_vm.cc:33
const char *const name
Definition: __init__.py:1
#define FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(V)
Definition: parser.h:273
#define FALL_THROUGH
Definition: globals.h:15
#define Pd
Definition: globals.h:408
#define T
#define IG
#define Z
#define ADD_VAR(Name, _, __)
SeparatedVector2 offset
Definition: SkMD5.cpp:130