Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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 helper_.ReadFlags(); // read flags.
866 VisitExpression(); // read operand.
867 VisitDartType(); // read type.
868 return;
869 case kAsExpression:
870 helper_.ReadPosition(); // read position.
871 helper_.ReadFlags(); // read flags.
872 VisitExpression(); // read operand.
873 VisitDartType(); // read type.
874 return;
875 case kTypeLiteral:
876 helper_.ReadPosition(); // read file offset.
877 VisitDartType(); // read type.
878 return;
879 case kThisExpression:
880 HandleLoadReceiver();
881 helper_.ReadPosition(); // read file offset.
882 return;
883 case kRethrow:
884 helper_.ReadPosition(); // read position.
885 return;
886 case kThrow:
887 helper_.ReadPosition(); // read position.
888 helper_.ReadFlags(); // read flags.
889 VisitExpression(); // read expression.
890 return;
891 case kListLiteral: {
892 helper_.ReadPosition(); // read position.
893 VisitDartType(); // read type.
894 VisitListOfExpressions();
895 return;
896 }
897 case kSetLiteral: {
898 // Set literals are currently desugared in the frontend and will not
899 // reach the VM. See http://dartbug.com/35124 for discussion.
900 UNREACHABLE();
901 return;
902 }
903 case kMapLiteral: {
904 helper_.ReadPosition(); // read position.
905 VisitDartType(); // read key type.
906 VisitDartType(); // read value type.
907 intptr_t list_length = helper_.ReadListLength(); // read list length.
908 for (intptr_t i = 0; i < list_length; ++i) {
909 VisitExpression(); // read ith key.
910 VisitExpression(); // read ith value.
911 }
912 return;
913 }
914 case kRecordLiteral:
915 helper_.ReadPosition(); // read position.
916 VisitListOfExpressions(); // read positionals.
917 VisitListOfNamedExpressions(); // read named.
918 VisitDartType(); // read recordType.
919 return;
920 case kRecordIndexGet:
921 helper_.ReadPosition(); // read position.
922 VisitExpression(); // read receiver.
923 helper_.SkipDartType(); // read recordType.
924 helper_.ReadUInt(); // read index.
925 return;
926 case kRecordNameGet:
927 helper_.ReadPosition(); // read position.
928 VisitExpression(); // read receiver.
929 helper_.SkipDartType(); // read recordType.
930 helper_.SkipStringReference(); // read name.
931 return;
932 case kFunctionExpression: {
933 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
934 helper_.ReadPosition(); // read position.
935 HandleLocalFunction(offset); // read function node.
936 return;
937 }
938 case kLet: {
939 PositionScope scope(&helper_.reader_);
940 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
941
942 EnterScope(offset);
943
944 helper_.ReadPosition(); // read position.
945 VisitVariableDeclaration(); // read variable declaration.
946 VisitExpression(); // read expression.
947
948 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
949 return;
950 }
951 case kBlockExpression: {
952 PositionScope scope(&helper_.reader_);
953 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
954
955 EnterScope(offset);
956
957 helper_.ReadPosition(); // read position.
958 intptr_t list_length =
959 helper_.ReadListLength(); // read number of statements.
960 for (intptr_t i = 0; i < list_length; ++i) {
961 VisitStatement(); // read ith statement.
962 }
963 VisitExpression(); // read expression.
964
965 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
966 return;
967 }
968 case kBigIntLiteral:
969 helper_.ReadPosition(); // read position.
970 helper_.SkipStringReference(); // read string reference.
971 return;
972 case kStringLiteral:
973 helper_.ReadPosition(); // read position.
974 helper_.SkipStringReference(); // read string reference.
975 return;
976 case kSpecializedIntLiteral:
977 helper_.ReadPosition(); // read position.
978 return;
979 case kNegativeIntLiteral:
980 helper_.ReadPosition(); // read position.
981 helper_.ReadUInt(); // read value.
982 return;
983 case kPositiveIntLiteral:
984 helper_.ReadPosition(); // read position.
985 helper_.ReadUInt(); // read value.
986 return;
987 case kDoubleLiteral:
988 helper_.ReadPosition(); // read position.
989 helper_.ReadDouble(); // read value.
990 return;
991 case kTrueLiteral:
992 helper_.ReadPosition(); // read position.
993 return;
994 case kFalseLiteral:
995 helper_.ReadPosition(); // read position.
996 return;
997 case kNullLiteral:
998 helper_.ReadPosition(); // read position.
999 return;
1000 case kConstantExpression:
1001 helper_.ReadPosition();
1002 helper_.SkipDartType();
1003 helper_.SkipConstantReference();
1004 return;
1005 case kFileUriConstantExpression:
1006 helper_.ReadPosition();
1007 helper_.ReadUInt();
1008 helper_.SkipDartType();
1009 helper_.SkipConstantReference();
1010 return;
1011 case kInstantiation: {
1012 helper_.ReadPosition(); // read position.
1013 VisitExpression();
1014 const intptr_t list_length =
1015 helper_.ReadListLength(); // read list length.
1016 for (intptr_t i = 0; i < list_length; ++i) {
1017 VisitDartType(); // read ith type.
1018 }
1019 return;
1020 }
1021 case kLoadLibrary:
1022 case kCheckLibraryIsLoaded:
1023 helper_.ReadPosition(); // read file offset.
1024 helper_.ReadUInt(); // library index
1025 break;
1026 case kAwaitExpression:
1027 helper_.ReadPosition(); // read position.
1028 VisitExpression(); // read operand.
1029 if (helper_.ReadTag() == kSomething) {
1030 VisitDartType(); // read runtime check type.
1031 }
1032 return;
1033 case kFileUriExpression:
1034 helper_.ReadUInt(); // read uri.
1035 helper_.ReadPosition(); // read position.
1036 VisitExpression(); // read expression.
1037 return;
1038 case kConstStaticInvocation:
1039 case kConstConstructorInvocation:
1040 case kConstListLiteral:
1041 case kConstSetLiteral:
1042 case kConstMapLiteral:
1043 case kSymbolLiteral:
1044 case kListConcatenation:
1045 case kSetConcatenation:
1046 case kMapConcatenation:
1047 case kInstanceCreation:
1048 case kStaticTearOff:
1049 case kSwitchExpression:
1050 case kPatternAssignment:
1051 // These nodes are internal to the front end and
1052 // removed by the constant evaluator.
1053 default:
1054 ReportUnexpectedTag("expression", tag);
1055 UNREACHABLE();
1056 }
1057}
1058
1059void ScopeBuilder::VisitStatement() {
1060 Tag tag = helper_.ReadTag(); // read tag.
1061 switch (tag) {
1062 case kExpressionStatement:
1063 VisitExpression(); // read expression.
1064 return;
1065 case kBlock: {
1066 PositionScope scope(&helper_.reader_);
1067 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1068
1069 EnterScope(offset);
1070 helper_.ReadPosition(); // read block start offset.
1071 helper_.ReadPosition(); // read block end offset.
1072 intptr_t list_length =
1073 helper_.ReadListLength(); // read number of statements.
1074 for (intptr_t i = 0; i < list_length; ++i) {
1075 VisitStatement(); // read ith statement.
1076 }
1077
1078 ExitScope(helper_.reader_.min_position(), helper_.reader_.max_position());
1079 return;
1080 }
1081 case kEmptyStatement:
1082 return;
1083 case kAssertBlock:
1084 if (IG->asserts()) {
1085 PositionScope scope(&helper_.reader_);
1086 intptr_t offset =
1087 helper_.ReaderOffset() - 1; // -1 to include tag byte.
1088
1089 EnterScope(offset);
1090
1091 intptr_t list_length =
1092 helper_.ReadListLength(); // read number of statements.
1093 for (intptr_t i = 0; i < list_length; ++i) {
1094 VisitStatement(); // read ith statement.
1095 }
1096
1097 ExitScope(helper_.reader_.min_position(),
1098 helper_.reader_.max_position());
1099 } else {
1100 helper_.SkipStatementList();
1101 }
1102 return;
1103 case kAssertStatement:
1104 if (IG->asserts()) {
1105 VisitExpression(); // Read condition.
1106 helper_.ReadPosition(); // read condition start offset.
1107 helper_.ReadPosition(); // read condition end offset.
1108 Tag tag = helper_.ReadTag(); // read (first part of) message.
1109 if (tag == kSomething) {
1110 VisitExpression(); // read (rest of) message.
1111 }
1112 } else {
1113 helper_.SkipExpression(); // Read condition.
1114 helper_.ReadPosition(); // read condition start offset.
1115 helper_.ReadPosition(); // read condition end offset.
1116 Tag tag = helper_.ReadTag(); // read (first part of) message.
1117 if (tag == kSomething) {
1118 helper_.SkipExpression(); // read (rest of) message.
1119 }
1120 }
1121 return;
1122 case kLabeledStatement:
1123 helper_.ReadPosition(); // read position.
1124 VisitStatement(); // read body.
1125 return;
1126 case kBreakStatement:
1127 helper_.ReadPosition(); // read position.
1128 helper_.ReadUInt(); // read target_index.
1129 return;
1130 case kWhileStatement:
1131 ++depth_.loop_;
1132 helper_.ReadPosition(); // read position.
1133 VisitExpression(); // read condition.
1134 VisitStatement(); // read body.
1135 --depth_.loop_;
1136 return;
1137 case kDoStatement:
1138 ++depth_.loop_;
1139 helper_.ReadPosition(); // read position.
1140 VisitStatement(); // read body.
1141 VisitExpression(); // read condition.
1142 --depth_.loop_;
1143 return;
1144 case kForStatement: {
1145 PositionScope scope(&helper_.reader_);
1146
1147 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1148
1149 ++depth_.loop_;
1150 EnterScope(offset);
1151
1152 TokenPosition position = helper_.ReadPosition(); // read position.
1153 intptr_t list_length =
1154 helper_.ReadListLength(); // read number of variables.
1155 for (intptr_t i = 0; i < list_length; ++i) {
1156 VisitVariableDeclaration(); // read ith variable.
1157 }
1158
1159 Tag tag = helper_.ReadTag(); // Read first part of condition.
1160 if (tag == kSomething) {
1161 VisitExpression(); // read rest of condition.
1162 }
1163 VisitListOfExpressions(); // read updates.
1164 VisitStatement(); // read body.
1165
1166 ExitScope(position, helper_.reader_.max_position());
1167 --depth_.loop_;
1168 return;
1169 }
1170 case kSwitchStatement: {
1171 AddSwitchVariable();
1172 helper_.ReadPosition(); // read position.
1173 helper_.ReadBool(); // read exhaustive flag.
1174 VisitExpression(); // read condition.
1175 helper_.SkipOptionalDartType(); // read expression type.
1176 int case_count = helper_.ReadListLength(); // read number of cases.
1177 for (intptr_t i = 0; i < case_count; ++i) {
1178 helper_.ReadPosition(); // read file offset.
1179 int expression_count =
1180 helper_.ReadListLength(); // read number of expressions.
1181 for (intptr_t j = 0; j < expression_count; ++j) {
1182 helper_.ReadPosition(); // read jth position.
1183 VisitExpression(); // read jth expression.
1184 }
1185 helper_.ReadBool(); // read is_default.
1186 VisitStatement(); // read body.
1187 }
1188 return;
1189 }
1190 case kContinueSwitchStatement:
1191 helper_.ReadPosition(); // read position.
1192 helper_.ReadUInt(); // read target_index.
1193 return;
1194 case kIfStatement:
1195 helper_.ReadPosition(); // read position.
1196 VisitExpression(); // read condition.
1197 VisitStatement(); // read then.
1198 VisitStatement(); // read otherwise.
1199 return;
1200 case kReturnStatement: {
1201 if ((depth_.function_ == 0) && (depth_.finally_ > 0) &&
1202 (result_->finally_return_variable == nullptr)) {
1203 const String& name = Symbols::TryFinallyReturnValue();
1204 LocalVariable* variable =
1205 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1206 name, AbstractType::dynamic_type());
1207 current_function_scope_->AddVariable(variable);
1208 result_->finally_return_variable = variable;
1209 }
1210
1211 helper_.ReadPosition(); // read position
1212 Tag tag = helper_.ReadTag(); // read (first part of) expression.
1213 if (tag == kSomething) {
1214 VisitExpression(); // read (rest of) expression.
1215 }
1216 return;
1217 }
1218 case kTryCatch: {
1219 ++depth_.try_;
1220 AddTryVariables();
1221 helper_.ReadPosition(); // read position.
1222 VisitStatement(); // read body.
1223 --depth_.try_;
1224
1225 ++depth_.catch_;
1226 AddCatchVariables();
1227
1228 helper_.ReadByte(); // read flags
1229 intptr_t catch_count =
1230 helper_.ReadListLength(); // read number of catches.
1231 for (intptr_t i = 0; i < catch_count; ++i) {
1232 PositionScope scope(&helper_.reader_);
1233 intptr_t offset = helper_.ReaderOffset(); // Catch has no tag.
1234
1235 EnterScope(offset);
1236
1237 helper_.ReadPosition(); // read position.
1238 VisitDartType(); // Read the guard.
1239 tag = helper_.ReadTag(); // read first part of exception.
1240 if (tag == kSomething) {
1241 VisitVariableDeclaration(); // read exception.
1242 }
1243 tag = helper_.ReadTag(); // read first part of stack trace.
1244 if (tag == kSomething) {
1245 VisitVariableDeclaration(); // read stack trace.
1246 }
1247 VisitStatement(); // read body.
1248
1249 ExitScope(helper_.reader_.min_position(),
1250 helper_.reader_.max_position());
1251 }
1252
1253 FinalizeCatchVariables();
1254
1255 --depth_.catch_;
1256 return;
1257 }
1258 case kTryFinally: {
1259 ++depth_.try_;
1260 ++depth_.finally_;
1261 AddTryVariables();
1262
1263 helper_.ReadPosition(); // read position.
1264 VisitStatement(); // read body.
1265
1266 --depth_.finally_;
1267 --depth_.try_;
1268 ++depth_.catch_;
1269 AddCatchVariables();
1270
1271 VisitStatement(); // read finalizer.
1272
1273 FinalizeCatchVariables();
1274
1275 --depth_.catch_;
1276 return;
1277 }
1278 case kYieldStatement: {
1279 helper_.ReadPosition(); // read position.
1280 helper_.ReadByte(); // read flags.
1281 VisitExpression(); // read expression.
1282 return;
1283 }
1284 case kVariableDeclaration:
1285 VisitVariableDeclaration(); // read variable declaration.
1286 return;
1287 case kFunctionDeclaration: {
1288 intptr_t offset = helper_.ReaderOffset() - 1; // -1 to include tag byte.
1289 helper_.ReadPosition(); // read position.
1290 VisitVariableDeclaration(); // read variable declaration.
1291 HandleLocalFunction(offset); // read function node.
1292 return;
1293 }
1294 case kForInStatement:
1295 case kAsyncForInStatement:
1296 case kIfCaseStatement:
1297 case kPatternSwitchStatement:
1298 case kPatternVariableDeclaration:
1299 // These nodes are internal to the front end and
1300 // removed by the constant evaluator.
1301 default:
1302 ReportUnexpectedTag("declaration", tag);
1303 UNREACHABLE();
1304 }
1305}
1306
1307void ScopeBuilder::VisitListOfExpressions() {
1308 const intptr_t list_length = helper_.ReadListLength(); // read list length.
1309 for (intptr_t i = 0; i < list_length; ++i) {
1310 VisitExpression();
1311 }
1312}
1313
1314void ScopeBuilder::VisitListOfNamedExpressions() {
1315 const intptr_t list_length = helper_.ReadListLength(); // read list length.
1316 for (intptr_t i = 0; i < list_length; ++i) {
1317 helper_.SkipStringReference(); // read ith name index.
1318 VisitExpression(); // read ith expression.
1319 }
1320}
1321
1322void ScopeBuilder::VisitArguments() {
1323 helper_.ReadUInt(); // read argument_count.
1324
1325 // Types
1326 intptr_t list_length = helper_.ReadListLength(); // read list length.
1327 for (intptr_t i = 0; i < list_length; ++i) {
1328 VisitDartType(); // read ith type.
1329 }
1330
1331 VisitListOfExpressions(); // Positional.
1332 VisitListOfNamedExpressions(); // Named.
1333}
1334
1335void ScopeBuilder::VisitVariableDeclaration() {
1336 PositionScope scope(&helper_.reader_);
1337
1338 const intptr_t kernel_offset =
1339 helper_.data_program_offset_ + helper_.ReaderOffset();
1340 // MetadataHelper expects relative offsets and adjusts them internally
1341 const InferredTypeMetadata inferred_type =
1342 inferred_type_metadata_helper_.GetInferredType(helper_.ReaderOffset());
1343 VariableDeclarationHelper helper(&helper_);
1344 helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
1345 const intptr_t annotations_offset = helper_.ReaderOffset();
1346 helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
1347 AbstractType& type = BuildAndVisitVariableType();
1348
1349 const String& name = (H.StringSize(helper.name_index_) == 0)
1350 ? GenerateName(":var", name_index_++)
1351 : H.DartSymbolObfuscate(helper.name_index_);
1352
1353 intptr_t initializer_offset = helper_.ReaderOffset();
1354 Tag tag = helper_.ReadTag(); // read (first part of) initializer.
1355 if (tag == kSomething) {
1356 VisitExpression(); // read (actual) initializer.
1357 }
1358
1359 // Go to next token position so it ends *after* the last potentially
1360 // debuggable position in the initializer.
1361 TokenPosition end_position = helper_.reader_.max_position();
1362 if (end_position.IsReal()) {
1363 end_position = end_position.Next();
1364 }
1365 LocalVariable* variable =
1366 MakeVariable(helper.position_, end_position, name, type, kernel_offset,
1367 helper.IsLate(), &inferred_type);
1368 if (helper.annotation_count_ > 0) {
1369 variable->set_annotations_offset(annotations_offset);
1370 }
1371 if (helper.IsFinal()) {
1372 variable->set_is_final();
1373 }
1374 if (helper.IsLate()) {
1375 variable->set_is_late();
1376 variable->set_late_init_offset(initializer_offset);
1377 }
1378 if (helper.IsSynthesized()) {
1379 variable->set_invisible(true);
1380 }
1381
1382 scope_->AddVariable(variable);
1383 result_->locals.Insert(kernel_offset, variable);
1384}
1385
1386AbstractType& ScopeBuilder::BuildAndVisitVariableType() {
1387 const intptr_t offset = helper_.ReaderOffset();
1388 AbstractType& type = T.BuildType();
1389 helper_.SetOffset(offset); // rewind
1390 VisitDartType();
1391 return type;
1392}
1393
1394void ScopeBuilder::VisitDartType() {
1395 Tag tag = helper_.ReadTag();
1396 switch (tag) {
1397 case kInvalidType:
1398 case kDynamicType:
1399 case kVoidType:
1400 case kNullType:
1401 // those contain nothing.
1402 return;
1403 case kNeverType:
1404 helper_.ReadNullability();
1405 return;
1406 case kInterfaceType:
1407 VisitInterfaceType(false);
1408 return;
1409 case kSimpleInterfaceType:
1410 VisitInterfaceType(true);
1411 return;
1412 case kFunctionType:
1413 VisitFunctionType(false);
1414 return;
1415 case kSimpleFunctionType:
1416 VisitFunctionType(true);
1417 return;
1418 case kRecordType:
1419 VisitRecordType();
1420 return;
1421 case kTypeParameterType:
1422 VisitTypeParameterType();
1423 return;
1424 case kIntersectionType:
1425 VisitIntersectionType();
1426 return;
1427 case kExtensionType:
1428 VisitExtensionType();
1429 return;
1430 case kFutureOrType:
1431 VisitFutureOrType();
1432 return;
1433 default:
1434 ReportUnexpectedTag("type", tag);
1435 UNREACHABLE();
1436 }
1437}
1438
1439void ScopeBuilder::VisitInterfaceType(bool simple) {
1440 helper_.ReadNullability(); // read nullability.
1441 helper_.ReadUInt(); // read klass_name.
1442 if (!simple) {
1443 intptr_t length = helper_.ReadListLength(); // read number of types.
1444 for (intptr_t i = 0; i < length; ++i) {
1445 VisitDartType(); // read the ith type.
1446 }
1447 }
1448}
1449
1450void ScopeBuilder::VisitFunctionType(bool simple) {
1451 helper_.ReadNullability(); // read nullability.
1452
1453 if (!simple) {
1454 intptr_t list_length =
1455 helper_.ReadListLength(); // read type_parameters list length.
1456 for (int i = 0; i < list_length; ++i) {
1457 TypeParameterHelper helper(&helper_);
1458 helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
1459 VisitDartType(); // read bound.
1460 helper.ReadUntilExcludingAndSetJustRead(
1462 VisitDartType(); // read default type.
1463 helper.Finish();
1464 }
1465 helper_.ReadUInt(); // read required parameter count.
1466 helper_.ReadUInt(); // read total parameter count.
1467 }
1468
1469 const intptr_t positional_count =
1470 helper_.ReadListLength(); // read positional_parameters list length.
1471 for (intptr_t i = 0; i < positional_count; ++i) {
1472 VisitDartType(); // read ith positional parameter.
1473 }
1474
1475 if (!simple) {
1476 const intptr_t named_count =
1477 helper_.ReadListLength(); // read named_parameters list length.
1478 for (intptr_t i = 0; i < named_count; ++i) {
1479 // read string reference (i.e. named_parameters[i].name).
1480 helper_.SkipStringReference();
1481 VisitDartType(); // read named_parameters[i].type.
1482 helper_.ReadByte(); // read flags
1483 }
1484 }
1485
1486 VisitDartType(); // read return type.
1487}
1488
1489void ScopeBuilder::VisitRecordType() {
1490 helper_.ReadNullability(); // read nullability.
1491 const intptr_t positional_count =
1492 helper_.ReadListLength(); // read positional list length.
1493 for (intptr_t i = 0; i < positional_count; ++i) {
1494 VisitDartType(); // read positional[i].
1495 }
1496 const intptr_t named_count =
1497 helper_.ReadListLength(); // read named list length.
1498 for (intptr_t i = 0; i < named_count; ++i) {
1499 helper_.SkipStringReference(); // read named[i].name.
1500 VisitDartType(); // read named[i].type.
1501 helper_.ReadFlags(); // read named[i].flags
1502 }
1503}
1504
1505void ScopeBuilder::VisitTypeParameterType() {
1506 Function& function = Function::Handle(Z, parsed_function_->function().ptr());
1507
1508 helper_.ReadNullability(); // read nullability.
1509
1510 // The index here is the index identifying the type parameter binding site
1511 // inside the DILL file, which uses a different indexing system than the VM
1512 // uses for its 'TypeParameter's internally. This index includes both class
1513 // and function type parameters.
1514
1515 intptr_t index = helper_.ReadUInt(); // read index for parameter.
1516
1517 if (!function.IsImplicitStaticClosureFunction()) {
1518 while (function.IsClosureFunction()) {
1519 function = function.parent_function();
1520 }
1521
1522 if (function.IsFactory()) {
1523 // The type argument vector is passed as the very first argument to the
1524 // factory constructor function.
1525 HandleSpecialLoad(&result_->type_arguments_variable,
1526 Symbols::TypeArgumentsParameter(),
1528 } else {
1529 // If the type parameter is a parameter to this or an enclosing function,
1530 // we can read it directly from the function type arguments vector later.
1531 // Otherwise, the type arguments vector we need is stored on the instance
1532 // object, so we need to capture 'this'.
1533 Class& parent_class = Class::Handle(Z, function.Owner());
1534 if (index < parent_class.NumTypeParameters()) {
1535 HandleLoadReceiver();
1536 }
1537 }
1538 }
1539}
1540
1541void ScopeBuilder::VisitIntersectionType() {
1542 VisitDartType(); // read left.
1543 helper_.SkipDartType(); // read right.
1544}
1545
1546void ScopeBuilder::VisitExtensionType() {
1547 // We skip the extension type and only use the type erasure.
1548 helper_.ReadNullability();
1549 helper_.SkipCanonicalNameReference(); // read index for canonical name.
1550 helper_.SkipListOfDartTypes(); // read type arguments
1551 VisitDartType(); // read type erasure.
1552}
1553
1554void ScopeBuilder::VisitFutureOrType() {
1555 helper_.ReadNullability();
1556 VisitDartType(); // read type argument.
1557}
1558
1559void ScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
1560 // "Peek" ahead into the function node
1561 const intptr_t offset = helper_.ReaderOffset();
1562
1563 FunctionNodeHelper function_node_helper(&helper_);
1564 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
1565
1566 LocalScope* saved_function_scope = current_function_scope_;
1567 DepthState saved_depth_state = depth_;
1568 depth_ = DepthState(depth_.function_ + 1);
1569 EnterScope(parent_kernel_offset);
1570 current_function_scope_ = scope_;
1571 if (depth_.function_ == 1) {
1572 FunctionScope function_scope = {offset, scope_};
1573 result_->function_scopes.Add(function_scope);
1574 }
1575
1576 int num_type_params = 0;
1577 {
1578 AlternativeReadingScope _(&helper_.reader_);
1579 num_type_params = helper_.ReadListLength();
1580 }
1581 // Adding this scope here informs the type translator the type parameters of
1582 // this function are now in scope, although they are not defined and will be
1583 // filled in with dynamic. This is OK, since their definitions are not needed
1584 // for scope building of the enclosing function.
1585 TypeTranslator::TypeParameterScope scope(&type_translator_, num_type_params);
1586
1587 // read positional_parameters and named_parameters.
1588 function_node_helper.ReadUntilExcluding(
1590
1591 ProcedureAttributesMetadata default_attrs;
1592 AddPositionalAndNamedParameters(0, kTypeCheckForNonDynamicallyInvokedMethod,
1593 default_attrs);
1594
1595 if (function_node_helper.async_marker_ != FunctionNodeHelper::kSync) {
1596 // Read return type which is used to create a result of async/async*/sync*
1597 // function. It may reference receiver or type arguments of the enclosing
1598 // function which need to be captured.
1599 VisitDartType();
1600 }
1601
1602 // "Peek" is now done.
1603 helper_.SetOffset(offset);
1604
1605 VisitFunctionNode(); // read function node.
1606
1607 // Remember if this closure and all closures nested within it don't
1608 // capture any variables from outer scopes.
1609 if (scope_->function_level() == 1) {
1610 if (scope_->NumCapturedVariables() == 0) {
1612 }
1613 }
1614
1615 ExitScope(function_node_helper.position_, function_node_helper.end_position_);
1616 depth_ = saved_depth_state;
1617 current_function_scope_ = saved_function_scope;
1618}
1619
1620void ScopeBuilder::EnterScope(intptr_t kernel_offset) {
1621 scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
1622 ASSERT(kernel_offset >= 0);
1623 result_->scopes.Insert(kernel_offset, scope_);
1624}
1625
1626void ScopeBuilder::ExitScope(TokenPosition start_position,
1627 TokenPosition end_position) {
1628 scope_->set_begin_token_pos(start_position);
1629 scope_->set_end_token_pos(end_position);
1630 scope_ = scope_->parent();
1631}
1632
1633void ScopeBuilder::AddPositionalAndNamedParameters(
1634 intptr_t pos,
1635 ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/,
1636 const ProcedureAttributesMetadata& attrs) {
1637 // List of positional.
1638 intptr_t list_length = helper_.ReadListLength(); // read list length.
1639 for (intptr_t i = 0; i < list_length; ++i) {
1640 AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
1641 }
1642
1643 // List of named.
1644 list_length = helper_.ReadListLength(); // read list length.
1645 for (intptr_t i = 0; i < list_length; ++i) {
1646 AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
1647 }
1648}
1649
1650void ScopeBuilder::AddVariableDeclarationParameter(
1651 intptr_t pos,
1652 ParameterTypeCheckMode type_check_mode,
1653 const ProcedureAttributesMetadata& attrs) {
1654 // Convert kernel offset of variable declaration to absolute.
1655 const intptr_t kernel_offset =
1656 helper_.data_program_offset_ + helper_.ReaderOffset();
1657 // MetadataHelper expects relative offsets and adjusts them internally
1658 const InferredTypeMetadata inferred_type =
1659 inferred_type_metadata_helper_.GetInferredType(helper_.ReaderOffset());
1660 const InferredTypeMetadata inferred_arg_type =
1661 inferred_arg_type_metadata_helper_.GetInferredType(
1662 helper_.ReaderOffset());
1663 VariableDeclarationHelper helper(&helper_);
1664 helper.ReadUntilExcluding(VariableDeclarationHelper::kAnnotations);
1665 const intptr_t annotations_offset = helper_.ReaderOffset();
1666 helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
1667 String& name = H.DartSymbolObfuscate(helper.name_index_);
1668 ASSERT(name.Length() > 0);
1669 AbstractType& type = BuildAndVisitVariableType(); // read type.
1670 helper.SetJustRead(VariableDeclarationHelper::kType);
1671 helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
1672
1673 LocalVariable* variable = MakeVariable(
1674 helper.position_, helper.position_, name, type, kernel_offset,
1675 /*is_late=*/false, &inferred_type, &inferred_arg_type);
1676 if (helper.annotation_count_ > 0) {
1677 variable->set_annotations_offset(annotations_offset);
1678 }
1679 if (helper.IsFinal()) {
1680 variable->set_is_final();
1681 }
1682 if (helper.IsCovariant()) {
1683 variable->set_is_explicit_covariant_parameter();
1684 }
1685
1686 const bool needs_covariant_check_in_method =
1687 helper.IsCovariant() ||
1688 (helper.IsGenericCovariantImpl() &&
1689 (attrs.has_non_this_uses || attrs.has_tearoff_uses));
1690 if (needs_covariant_check_in_method) {
1691 variable->set_needs_covariant_check_in_method();
1692 }
1693
1694 switch (type_check_mode) {
1695 case kTypeCheckAllParameters:
1696 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1697 break;
1698 case kTypeCheckEverythingNotCheckedInNonDynamicallyInvokedMethod:
1699 if (needs_covariant_check_in_method) {
1700 // Don't type check covariant parameters - they will be checked by
1701 // a function we forward to. Their types however are not known.
1702 variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
1703 } else {
1704 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1705 }
1706 break;
1707 case kTypeCheckForNonDynamicallyInvokedMethod:
1708 if (needs_covariant_check_in_method) {
1709 variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
1710 } else {
1711 // Types of non-covariant parameters are guaranteed to match by
1712 // front-end enforcing strong mode types at call site.
1713 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1714 }
1715 break;
1716 case kTypeCheckForImplicitClosureFunction:
1717 if (needs_covariant_check_in_method) {
1718 // Don't type check covariant parameters - they will be checked by
1719 // a function we forward to. Their types however are not known.
1720 variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
1721 } else {
1722 // All non-covariant checks are either checked by the type system or
1723 // by a dynamic closure call dispatcher.
1724 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1725 }
1726 break;
1727 case kTypeCheckForStaticFunction:
1728 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1729 break;
1730 }
1731
1732 // TODO(sjindel): We can also skip these checks on dynamic invocations as
1733 // well.
1734 if (inferred_arg_type.IsSkipCheck()) {
1735 variable->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
1736 }
1737
1738 scope_->InsertParameterAt(pos, variable);
1739 result_->locals.Insert(kernel_offset, variable);
1740
1741 // The default value may contain 'let' bindings for which the constant
1742 // evaluator needs scope bindings.
1743 Tag tag = helper_.ReadTag();
1744 if (tag == kSomething) {
1745 VisitExpression(); // read initializer.
1746 }
1747}
1748
1749LocalVariable* ScopeBuilder::MakeVariable(
1750 TokenPosition declaration_pos,
1751 TokenPosition token_pos,
1752 const String& name,
1753 const AbstractType& static_type,
1754 intptr_t kernel_offset /* = LocalVariable::kNoKernelOffset */,
1755 bool is_late /* = false */,
1756 const InferredTypeMetadata* inferred_type_md /* = nullptr */,
1757 const InferredTypeMetadata* inferred_arg_type_md /* = nullptr */) {
1758 CompileType* inferred_type = nullptr;
1759 if (inferred_type_md != nullptr && !inferred_type_md->IsTrivial()) {
1760 inferred_type = new (Z)
1761 CompileType(inferred_type_md->ToCompileType(Z, &static_type, is_late));
1762 } else {
1763 inferred_type = new (Z) CompileType(CompileType::FromAbstractType(
1764 static_type, CompileType::kCanBeNull, is_late));
1765 }
1766 CompileType* inferred_arg_type = nullptr;
1767 const Object* inferred_arg_value = nullptr;
1768 if (inferred_arg_type_md != nullptr && !inferred_arg_type_md->IsTrivial()) {
1769 inferred_arg_type =
1770 new (Z) CompileType(inferred_arg_type_md->ToCompileType(Z));
1771 if (inferred_arg_type_md->IsConstant()) {
1772 inferred_arg_value = &inferred_arg_type_md->constant_value;
1773 }
1774 }
1775 return new (Z) LocalVariable(declaration_pos, token_pos, name, static_type,
1776 kernel_offset, inferred_type, inferred_arg_type,
1777 inferred_arg_value);
1778}
1779
1780void ScopeBuilder::AddExceptionVariable(
1781 GrowableArray<LocalVariable*>* variables,
1782 const char* prefix,
1783 intptr_t nesting_depth) {
1784 LocalVariable* v = nullptr;
1785
1786 // No need to create variables for try/catch-statements inside
1787 // nested functions.
1788 if (depth_.function_ > 0) return;
1789 if (variables->length() >= nesting_depth) return;
1790
1791 // If variable was not lifted by the transformer introduce a new
1792 // one into the current function scope.
1793 if (v == nullptr) {
1794 v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1795 GenerateName(prefix, nesting_depth - 1),
1796 AbstractType::dynamic_type());
1797
1798 // If transformer did not lift the variable then there is no need
1799 // to lift it into the context when we encounter a YieldStatement.
1800 v->set_is_forced_stack();
1801 current_function_scope_->AddVariable(v);
1802 }
1803
1804 variables->Add(v);
1805}
1806
1807void ScopeBuilder::FinalizeExceptionVariable(
1808 GrowableArray<LocalVariable*>* variables,
1809 GrowableArray<LocalVariable*>* raw_variables,
1810 const String& symbol,
1811 intptr_t nesting_depth) {
1812 // No need to create variables for try/catch-statements inside
1813 // nested functions.
1814 if (depth_.function_ > 0) return;
1815
1816 LocalVariable* variable = (*variables)[nesting_depth - 1];
1817 LocalVariable* raw_variable;
1818 if (variable->is_captured()) {
1819 raw_variable =
1820 new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1821 symbol, AbstractType::dynamic_type());
1822 raw_variable->set_is_forced_stack();
1823 const bool ok = scope_->AddVariable(raw_variable);
1824 ASSERT(ok);
1825 } else {
1826 raw_variable = variable;
1827 }
1828 raw_variables->EnsureLength(nesting_depth, nullptr);
1829 (*raw_variables)[nesting_depth - 1] = raw_variable;
1830}
1831
1832void ScopeBuilder::AddTryVariables() {
1833 AddExceptionVariable(&result_->catch_context_variables,
1834 ":saved_try_context_var", depth_.try_);
1835}
1836
1837void ScopeBuilder::AddCatchVariables() {
1838 AddExceptionVariable(&result_->exception_variables, ":exception",
1839 depth_.catch_);
1840 AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace",
1841 depth_.catch_);
1842}
1843
1844void ScopeBuilder::FinalizeCatchVariables() {
1845 const intptr_t unique_id = result_->raw_variable_counter_++;
1846 FinalizeExceptionVariable(
1847 &result_->exception_variables, &result_->raw_exception_variables,
1848 GenerateName(":raw_exception", unique_id), depth_.catch_);
1849 FinalizeExceptionVariable(
1851 GenerateName(":raw_stacktrace", unique_id), depth_.catch_);
1852}
1853
1854void ScopeBuilder::AddSwitchVariable() {
1855 if ((depth_.function_ == 0) && (result_->switch_variable == nullptr)) {
1856 LocalVariable* variable =
1857 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
1858 Symbols::SwitchExpr(), AbstractType::dynamic_type());
1859 variable->set_is_forced_stack();
1860 current_function_scope_->AddVariable(variable);
1861 result_->switch_variable = variable;
1862 }
1863}
1864
1865void ScopeBuilder::VisitVariableGet(intptr_t declaration_binary_offset) {
1866 LocalVariable* variable = LookupVariable(declaration_binary_offset);
1867 if (variable->is_late()) {
1868 // Late variable initializer expressions may also contain local variables
1869 // that need to be captured.
1870 AlternativeReadingScope alt(&helper_.reader_, variable->late_init_offset());
1871 if (helper_.ReadTag() != kNothing) {
1872 VisitExpression();
1873 }
1874 }
1875}
1876
1877LocalVariable* ScopeBuilder::LookupVariable(
1878 intptr_t declaration_binary_offset) {
1879 LocalVariable* variable = result_->locals.Lookup(declaration_binary_offset);
1880 if (variable == nullptr) {
1881 // We have not seen a declaration of the variable, so it must be the
1882 // case that we are compiling a nested function and the variable is
1883 // declared in an outer scope. In that case, look it up in the scope by
1884 // name and add it to the variable map to simplify later lookup.
1885 ASSERT(current_function_scope_->parent() != nullptr);
1886 StringIndex var_name = GetNameFromVariableDeclaration(
1887 declaration_binary_offset - helper_.data_program_offset_,
1888 parsed_function_->function());
1889
1890 const String& name = H.DartSymbolObfuscate(var_name);
1891 variable = current_function_scope_->parent()->LookupVariable(
1892 name, declaration_binary_offset, true);
1893 ASSERT(variable != nullptr);
1894 result_->locals.Insert(declaration_binary_offset, variable);
1895 }
1896
1897 ASSERT(variable->owner() != nullptr);
1898 if (variable->owner()->function_level() < scope_->function_level()) {
1899 // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two
1900 // different reasons:
1901 // Scenario 1:
1902 // We need to know which variables defined in this function
1903 // are closed over by nested closures in order to ensure we will
1904 // create a [Context] object of appropriate size and store captured
1905 // variables there instead of the stack.
1906 // Scenario 2:
1907 // We need to find out which variables defined in enclosing functions
1908 // are closed over by this function/closure or nested closures. This
1909 // is necessary in order to build a fat flattened [ContextScope]
1910 // object.
1911 scope_->CaptureVariable(variable);
1912 } else {
1913 ASSERT(variable->owner()->function_level() == scope_->function_level());
1914 }
1915 return variable;
1916}
1917
1918StringIndex ScopeBuilder::GetNameFromVariableDeclaration(
1919 intptr_t kernel_offset,
1920 const Function& function) {
1921 const auto& kernel_data = TypedDataView::Handle(Z, function.KernelLibrary());
1922 ASSERT(!kernel_data.IsNull());
1923
1924 // Temporarily go to the variable declaration, read the name.
1925 AlternativeReadingScopeWithNewData alt(&helper_.reader_, &kernel_data,
1926 kernel_offset);
1927 VariableDeclarationHelper helper(&helper_);
1928 helper.ReadUntilIncluding(VariableDeclarationHelper::kNameIndex);
1929 return helper.name_index_;
1930}
1931
1932const String& ScopeBuilder::GenerateName(const char* prefix, intptr_t suffix) {
1933 char name[64];
1934 Utils::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
1935 return H.DartSymbolObfuscate(name);
1936}
1937
1938void ScopeBuilder::HandleLoadReceiver() {
1939 if (!parsed_function_->has_receiver_var() &&
1940 current_function_scope_->parent() != nullptr) {
1941 // Lazily populate receiver variable using the parent function scope.
1942 parsed_function_->set_receiver_var(
1943 current_function_scope_->parent()->LookupVariable(
1945 }
1946
1947 if ((current_function_scope_->parent() != nullptr) ||
1948 (scope_->function_level() > 0)) {
1949 // Every scope we use the [receiver] from needs to be notified of the usage
1950 // in order to ensure that preserving the context scope on that particular
1951 // use-site also includes the [receiver].
1952 scope_->CaptureVariable(parsed_function_->receiver_var());
1953 }
1954
1955 parsed_function_->set_receiver_used();
1956}
1957
1958void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
1959 const String& symbol,
1960 intptr_t kernel_offset) {
1961 if (current_function_scope_->parent() != nullptr) {
1962 // We are building the scope tree of a closure function and saw [node]. We
1963 // lazily populate the variable using the parent function scope.
1964 if (*variable == nullptr) {
1965 *variable = current_function_scope_->parent()->LookupVariable(
1966 symbol, kernel_offset, true);
1967 ASSERT(*variable != nullptr);
1968 }
1969 }
1970
1971 if ((current_function_scope_->parent() != nullptr) ||
1972 (scope_->function_level() > 0)) {
1973 // Every scope we use the [variable] from needs to be notified of the usage
1974 // in order to ensure that preserving the context scope on that particular
1975 // use-site also includes the [variable].
1976 scope_->CaptureVariable(*variable);
1977 }
1978}
1979
1980} // namespace kernel
1981} // namespace dart
SkPoint pos
static bool ok(int result)
#define IG
#define UNREACHABLE()
Definition assert.h:248
#define RELEASE_ASSERT(cond)
Definition assert.h:327
#define Z
ObjectPtr At(intptr_t index) const
Definition object.h:10854
intptr_t Length() const
Definition object.h:10808
void Add(const T &value)
ArrayPtr fields() const
Definition object.h:1617
static constexpr bool kCanBeNull
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:4468
bool is_static() const
Definition object.h:4418
TypedDataViewPtr KernelLibrary() const
Definition object.cc:11958
static bool IsDynamicInvocationForwarderName(const String &name)
Definition object.cc:4240
bool MayHaveUncheckedEntryPoint() const
Definition object.cc:11499
KernelProgramInfoPtr KernelProgramInfo() const
Definition object.cc:10977
const char * ToQualifiedCString() const
Definition object.cc:9834
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:12591
static const String & This()
Definition symbols.h:691
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
const char *const name
#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 ADD_VAR(Name, _, __)
Point offset
Definition SkMD5.cpp:130