Flutter Engine
The Flutter Engine
scopes.cc
Go to the documentation of this file.
1// Copyright (c) 2012, 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#if !defined(DART_PRECOMPILED_RUNTIME)
5
6#include "vm/scopes.h"
7
9#include "vm/kernel.h"
10#include "vm/object.h"
11#include "vm/object_store.h"
12#include "vm/stack_frame.h"
13#include "vm/symbols.h"
14
15namespace dart {
16
18 share_enclosing_context,
19 true,
20 "Allocate captured variables in the existing context of an "
21 "enclosing scope (up to innermost loop) and spare the allocation "
22 "of a local context.");
23
24LocalScope::LocalScope(LocalScope* parent, int function_level, int loop_level)
25 : parent_(parent),
26 child_(nullptr),
27 sibling_(nullptr),
28 function_level_(function_level),
29 loop_level_(loop_level),
30 context_level_(LocalScope::kUninitializedContextLevel),
31 begin_token_pos_(TokenPosition::kNoSource),
32 end_token_pos_(TokenPosition::kNoSource),
33 variables_(),
34 context_variables_(),
35 context_slots_(new(Thread::Current()->zone())
36 ZoneGrowableArray<const Slot*>()) {
37 // Hook this node into the children of the parent, unless the parent has a
38 // different function_level, since the local scope of a nested function can
39 // be discarded after it has been parsed.
40 if ((parent != nullptr) && (parent->function_level() == function_level)) {
41 sibling_ = parent->child_;
42 parent->child_ = this;
43 }
44}
45
47 const LocalScope* current_scope = this;
48 while (current_scope != nullptr) {
49 if (current_scope == scope) {
50 return true;
51 }
52 current_scope = current_scope->parent();
53 }
54 return false;
55}
56
58 ASSERT(variable != nullptr);
59 if (LocalLookupVariable(variable->name(), variable->kernel_offset()) !=
60 nullptr) {
61 return false;
62 }
63 variables_.Add(variable);
64 if (variable->owner() == nullptr) {
65 // Variables must be added to their owner scope first. Subsequent calls
66 // to 'add' treat the variable as an alias.
67 variable->set_owner(this);
68 }
69 return true;
70}
71
73 ASSERT(parameter != nullptr);
74 if (LocalLookupVariable(parameter->name(), parameter->kernel_offset()) !=
75 nullptr) {
76 return false;
77 }
78 variables_.InsertAt(pos, parameter);
79 // InsertParameterAt is not used to add aliases of parameters.
80 ASSERT(parameter->owner() == nullptr);
81 parameter->set_owner(this);
82 return true;
83}
84
85void LocalScope::AllocateContextVariable(LocalVariable* variable,
86 LocalScope** context_owner) {
87 ASSERT(variable->is_captured());
88 ASSERT(variable->owner() == this);
89 // The context level in the owner scope of a captured variable indicates at
90 // code generation time how far to walk up the context chain in order to
91 // access the variable from the current context level.
92 if ((*context_owner) == nullptr) {
94 // This scope becomes the current context owner.
96 *context_owner = this;
97 } else if (!FLAG_share_enclosing_context && ((*context_owner) != this)) {
98 // The captured variable is in a child scope of the context owner and we do
99 // not share contexts.
100 // This scope will allocate and chain a new context.
102 // This scope becomes the current context owner.
103 set_context_level((*context_owner)->context_level() + 1);
104 *context_owner = this;
105 } else if ((*context_owner)->loop_level() < loop_level()) {
106 ASSERT(FLAG_share_enclosing_context);
107 // The captured variable is at a deeper loop level than the current context.
108 // This scope will allocate and chain a new context.
110 // This scope becomes the current context owner.
111 set_context_level((*context_owner)->context_level() + 1);
112 *context_owner = this;
113 } else {
114 // Allocate the captured variable in the current context.
115 if (!HasContextLevel()) {
116 ASSERT(variable->owner() != *context_owner);
117 set_context_level((*context_owner)->context_level());
118 } else {
119 ASSERT(context_level() == (*context_owner)->context_level());
120 }
121 }
122
123 (*context_owner)->AddContextVariable(variable);
124}
125
127 variable->set_index(VariableIndex(context_variables_.length()));
128 context_variables_.Add(variable);
129 context_slots_->Add(
131}
132
134 VariableIndex first_parameter_index,
135 int num_parameters,
136 VariableIndex first_local_index,
137 LocalScope* context_owner,
138 bool* found_captured_variables) {
139 // We should not allocate variables of nested functions while compiling an
140 // enclosing function.
141 ASSERT(function_level() == 0);
142 ASSERT(num_parameters >= 0);
143 // Parameters must be listed first and must all appear in the top scope.
144 ASSERT(num_parameters <= num_variables());
145 int pos = 0; // Current variable position.
146 VariableIndex next_index =
147 first_parameter_index; // Current free frame index.
148
149 LocalVariable* suspend_state_var = nullptr;
150 for (intptr_t i = 0; i < num_variables(); i++) {
151 LocalVariable* variable = VariableAt(i);
152 if (variable->owner() == this &&
153 variable->name().Equals(Symbols::SuspendStateVar())) {
154 ASSERT(!variable->is_captured());
155 suspend_state_var = variable;
156 }
157 }
158
159 if (suspend_state_var != nullptr) {
160 suspend_state_var->set_index(
163 }
164
165 while (pos < num_parameters) {
166 LocalVariable* parameter = VariableAt(pos);
167 pos++;
168 // Parsing formal parameter default values may add local variable aliases
169 // to the local scope before the formal parameters are added. However,
170 // the parameters get inserted in front of the aliases, therefore, no
171 // aliases can be encountered among the first num_parameters variables.
172 ASSERT(parameter->owner() == this);
173 if (parameter->is_captured()) {
174 // A captured parameter has a slot allocated in the frame and one in the
175 // context, where it gets copied to. The parameter index reflects the
176 // context allocation index.
177 next_index = VariableIndex(next_index.value() - 1);
178 AllocateContextVariable(parameter, &context_owner);
179 *found_captured_variables = true;
180 } else {
181 parameter->set_index(next_index);
182 next_index = VariableIndex(next_index.value() - 1);
183 }
184 }
185 // No overlapping of parameters and locals.
186 ASSERT(next_index.value() >= first_local_index.value());
187 next_index = first_local_index;
188 for (; pos < num_variables(); pos++) {
189 LocalVariable* variable = VariableAt(pos);
190 if (variable == suspend_state_var) {
191 continue;
192 }
193
194 if (variable->owner() == this) {
195 if (variable->is_captured()) {
196 AllocateContextVariable(variable, &context_owner);
197 *found_captured_variables = true;
198 } else {
199 variable->set_index(next_index);
200 next_index = VariableIndex(next_index.value() - 1);
201 }
202 }
203 }
204 // Allocate variables of all children.
205 VariableIndex min_index = next_index;
206 LocalScope* child = this->child();
207 while (child != nullptr) {
208 // Ignored, since no parameters.
209 const VariableIndex dummy_parameter_index(0);
210
211 // No parameters in children scopes.
212 const int num_parameters_in_child = 0;
213 VariableIndex child_next_index = child->AllocateVariables(
214 function, dummy_parameter_index, num_parameters_in_child, next_index,
215 context_owner, found_captured_variables);
216 if (child_next_index.value() < min_index.value()) {
217 min_index = child_next_index;
218 }
219 child = child->sibling();
220 }
221 return min_index;
222}
223
225 TokenPosition token_pos,
226 const String& name,
227 const AbstractType& static_type,
228 intptr_t kernel_offset)
229 : LocalVariable(declaration_pos,
230 token_pos,
231 name,
232 static_type,
233 kernel_offset,
234 new CompileType(CompileType::FromAbstractType(
235 static_type,
236 CompileType::kCanBeNull,
237 CompileType::kCannotBeSentinel))) {}
238
239// VM creates internal variables that start with ":"
240bool LocalVariable::IsFilteredIdentifier(const String& name) {
241 ASSERT(name.Length() > 0);
242 if (name.ptr() == Symbols::FunctionTypeArgumentsVar().ptr()) {
243 // Keep :function_type_arguments for accessing type variables in debugging.
244 return false;
245 }
246 return name.CharAt(0) == ':';
247}
248
249LocalVarDescriptorsPtr LocalScope::GetVarDescriptors(
250 const Function& func,
251 ZoneGrowableArray<intptr_t>* context_level_array) {
253 vars.AddDeoptIdToContextLevelMappings(context_level_array);
254
255 // First enter all variables from scopes of outer functions.
256 const ContextScope& context_scope =
258 if (!context_scope.IsNull()) {
259 ASSERT(func.HasParent());
260 for (int i = 0; i < context_scope.num_variables(); i++) {
261 if (context_scope.IsInvisibleAt(i)) {
262 continue;
263 }
264 String& name = String::Handle(context_scope.NameAt(i));
265 ASSERT(!LocalVariable::IsFilteredIdentifier(name));
266
268 desc.name = &name;
270 desc.info.scope_id = context_scope.ContextLevelAt(i);
271 desc.info.declaration_pos = context_scope.DeclarationTokenIndexAt(i);
272 desc.info.begin_pos = begin_token_pos();
273 desc.info.end_pos = end_token_pos();
274 ASSERT((desc.info.begin_pos.IsReal() != desc.info.end_pos.IsReal()) ||
275 (desc.info.begin_pos <= desc.info.end_pos));
276 desc.info.set_index(context_scope.ContextIndexAt(i));
277 vars.Add(desc);
278 }
279 }
280 // Now collect all variables from local scopes.
281 int16_t scope_id = 0;
282 CollectLocalVariables(&vars, &scope_id);
283
284 return vars.Done();
285}
286
287// Add visible variables that are declared in this scope to vars, then
288// collect visible variables of children, followed by siblings.
289void LocalScope::CollectLocalVariables(LocalVarDescriptorsBuilder* vars,
290 int16_t* scope_id) {
291 (*scope_id)++;
292 for (int i = 0; i < this->variables_.length(); i++) {
293 LocalVariable* var = variables_[i];
294 if (var->owner() == this) {
295 if (var->name().ptr() == Symbols::CurrentContextVar().ptr()) {
296 // This is the local variable in which the function saves its
297 // own context before calling a closure function.
299 desc.name = &var->name();
301 desc.info.scope_id = 0;
302 desc.info.declaration_pos = TokenPosition::kMinSource;
303 desc.info.begin_pos = TokenPosition::kMinSource;
304 desc.info.end_pos = TokenPosition::kMinSource;
305 desc.info.set_index(var->index().value());
306 vars->Add(desc);
307 } else if (!var->is_invisible()) {
308 ASSERT(!LocalVariable::IsFilteredIdentifier(var->name()));
309 // This is a regular Dart variable, either stack-based or captured.
310 LocalVarDescriptorsBuilder::VarDesc desc;
311 desc.name = &var->name();
312 if (var->is_captured()) {
314 ASSERT(var->owner() != nullptr);
315 ASSERT(var->owner()->context_level() >= 0);
316 desc.info.scope_id = var->owner()->context_level();
317 } else {
319 desc.info.scope_id = *scope_id;
320 }
321 desc.info.set_index(var->index().value());
322 desc.info.declaration_pos = var->declaration_token_pos();
323 desc.info.begin_pos = var->token_pos();
324 desc.info.end_pos = var->owner()->end_token_pos();
325 vars->Add(desc);
326 }
327 }
328 }
329 LocalScope* child = this->child();
330 while (child != nullptr) {
331 child->CollectLocalVariables(vars, scope_id);
332 child = child->sibling();
333 }
334}
335
337 intptr_t kernel_offset) const {
338 ASSERT(name.IsSymbol());
339 for (intptr_t i = 0; i < variables_.length(); i++) {
340 LocalVariable* var = variables_[i];
341 ASSERT(var->name().IsSymbol());
342 if ((var->name().ptr() == name.ptr()) &&
343 (var->kernel_offset() == kernel_offset)) {
344 return var;
345 }
346 }
347 return nullptr;
348}
349
351 intptr_t kernel_offset,
352 bool test_only) {
353 LocalScope* current_scope = this;
354 while (current_scope != nullptr) {
355 LocalVariable* var =
356 current_scope->LocalLookupVariable(name, kernel_offset);
357 // If testing only, return the variable even if invisible.
358 if ((var != nullptr) && (!var->is_invisible() || test_only)) {
359 if (!test_only && (var->owner()->function_level() != function_level())) {
360 CaptureVariable(var);
361 }
362 return var;
363 }
364 current_scope = current_scope->parent();
365 }
366 return nullptr;
367}
368
370 ASSERT(name.IsSymbol());
371 for (LocalScope* scope = this; scope != nullptr; scope = scope->parent()) {
372 for (intptr_t i = 0, n = scope->variables_.length(); i < n; ++i) {
373 LocalVariable* var = scope->variables_[i];
374 ASSERT(var->name().IsSymbol());
375 if (var->name().ptr() == name.ptr()) {
376 return var;
377 }
378 }
379 }
380 return nullptr;
381}
382
384 ASSERT(variable != nullptr);
385
386 // The variable must exist in an enclosing scope, not necessarily in this one.
387 variable->set_is_captured();
388 const int variable_function_level = variable->owner()->function_level();
389 LocalScope* scope = this;
390 while (scope->function_level() != variable_function_level) {
391 // Insert an alias of the variable in the top scope of each function
392 // level so that the variable is found in the context.
393 LocalScope* parent_scope = scope->parent();
394 while ((parent_scope != nullptr) &&
395 (parent_scope->function_level() == scope->function_level())) {
396 scope = parent_scope;
397 parent_scope = scope->parent();
398 }
399 // An alias may already have been added in this scope, and in that case,
400 // in parent scopes as needed. If so, we are done.
401 if (!scope->AddVariable(variable)) {
402 return;
403 }
404 ASSERT(variable->owner() != scope); // Item is an alias.
405 scope = parent_scope;
406 }
407}
408
410 // It is not necessary to traverse parent scopes, since we are only interested
411 // in the captured variables referenced in this scope. If this scope is the
412 // top scope at function level 1 and it (or its children scopes) references a
413 // captured variable declared in a parent scope at function level 0, it will
414 // contain an alias for that variable.
415
416 // Since code generation for nested functions is postponed until first
417 // invocation, the function level of the closure scope can only be 1.
418 ASSERT(function_level() == 1);
419
420 int num_captured = 0;
421 for (int i = 0; i < num_variables(); i++) {
422 LocalVariable* variable = VariableAt(i);
423 // Count the aliases of captured variables belonging to outer scopes.
424 if (variable->owner()->function_level() != 1) {
425 ASSERT(variable->is_captured());
426 ASSERT(variable->owner()->function_level() == 0);
427 num_captured++;
428 }
429 }
430 return num_captured;
431}
432
434 const Function& function,
435 intptr_t current_context_level) const {
436 Zone* zone = Thread::Current()->zone();
437 auto& library = Library::Handle(
438 zone, function.IsNull()
439 ? Library::null()
440 : Class::Handle(zone, function.Owner()).library());
441 // Since code generation for nested functions is postponed until first
442 // invocation, the function level of the closure scope can only be 1.
443 ASSERT(function_level() == 1);
444
445 // Count the number of referenced captured variables.
446 intptr_t num_captured_vars = NumCapturedVariables();
447
448 // Create a ContextScope with space for num_captured_vars descriptors.
449 const ContextScope& context_scope =
450 ContextScope::Handle(ContextScope::New(num_captured_vars, false));
451
452 LocalVariable* awaiter_link = nullptr;
453
454 // Create a descriptor for each referenced captured variable of enclosing
455 // functions to preserve its name and its context allocation information.
456 int captured_idx = 0;
457 for (int i = 0; i < num_variables(); i++) {
458 LocalVariable* variable = VariableAt(i);
459 // Preserve the aliases of captured variables belonging to outer scopes.
460 if (variable->owner()->function_level() != 1) {
461 context_scope.SetTokenIndexAt(captured_idx, variable->token_pos());
462 context_scope.SetDeclarationTokenIndexAt(
463 captured_idx, variable->declaration_token_pos());
464 context_scope.SetNameAt(captured_idx, variable->name());
465 context_scope.ClearFlagsAt(captured_idx);
466 context_scope.SetIsFinalAt(captured_idx, variable->is_final());
467 context_scope.SetIsLateAt(captured_idx, variable->is_late());
468 if (variable->is_late()) {
469 context_scope.SetLateInitOffsetAt(captured_idx,
470 variable->late_init_offset());
471 }
472 CompileType* type = variable->inferred_type();
473 context_scope.SetTypeAt(captured_idx, *type->ToAbstractType());
474 context_scope.SetCidAt(captured_idx, type->ToNullableCid());
475 context_scope.SetIsNullableAt(captured_idx, type->is_nullable());
476 context_scope.SetIsInvisibleAt(captured_idx, variable->is_invisible());
477 context_scope.SetContextIndexAt(captured_idx, variable->index().value());
478 // Adjust the context level relative to the current context level,
479 // since the context of the current scope will be at level 0 when
480 // compiling the nested function.
481 intptr_t adjusted_context_level =
482 variable->owner()->context_level() - current_context_level;
483 context_scope.SetContextLevelAt(captured_idx, adjusted_context_level);
484 context_scope.SetKernelOffsetAt(captured_idx, variable->kernel_offset());
485
486 // Handle async frame link.
487 const bool is_awaiter_link = variable->ComputeIfIsAwaiterLink(library);
488 context_scope.SetIsAwaiterLinkAt(captured_idx, is_awaiter_link);
489 if (is_awaiter_link) {
490 awaiter_link = variable;
491 }
492 captured_idx++;
493 }
494 }
495 ASSERT(context_scope.num_variables() == captured_idx); // Verify count.
496
497 if (awaiter_link != nullptr) {
498 const intptr_t depth =
499 current_context_level - awaiter_link->owner()->context_level();
500 const intptr_t index = awaiter_link->index().value();
501 if (Utils::IsUint(8, depth) && Utils::IsUint(8, index)) {
502 function.set_awaiter_link(
503 {static_cast<uint8_t>(depth), static_cast<uint8_t>(index)});
504 } else if (FLAG_precompiled_mode) {
506 "Warning: @pragma('vm:awaiter-link') marked variable %s is visible "
507 "from the function %s but the link {%" Pd ", %" Pd
508 "} can't be encoded\n",
509 awaiter_link->name().ToCString(),
510 function.IsNull() ? "<?>" : function.ToFullyQualifiedCString(), depth,
511 index);
512 }
513 }
514
515 return context_scope.ptr();
516}
517
519 // The function level of the outer scope is one less than the function level
520 // of the current function, which is 0.
521 LocalScope* outer_scope = new LocalScope(nullptr, -1, 0);
522 // Add all variables as aliases to the outer scope.
523 for (int i = 0; i < context_scope.num_variables(); i++) {
524 const bool is_late = context_scope.IsLateAt(i);
525 const auto& static_type = AbstractType::ZoneHandle(context_scope.TypeAt(i));
526 CompileType* inferred_type =
527 new CompileType(context_scope.IsNullableAt(i), is_late,
528 context_scope.CidAt(i), &static_type);
529 LocalVariable* variable = new LocalVariable(
530 context_scope.DeclarationTokenIndexAt(i), context_scope.TokenIndexAt(i),
531 String::ZoneHandle(context_scope.NameAt(i)), static_type,
532 context_scope.KernelOffsetAt(i), inferred_type);
533 variable->set_is_awaiter_link(context_scope.IsAwaiterLinkAt(i));
534 variable->set_is_captured();
535 variable->set_index(VariableIndex(context_scope.ContextIndexAt(i)));
536 if (context_scope.IsFinalAt(i)) {
537 variable->set_is_final();
538 }
539 if (is_late) {
540 variable->set_is_late();
541 variable->set_late_init_offset(context_scope.LateInitOffsetAt(i));
542 }
543 if (context_scope.IsInvisibleAt(i)) {
544 variable->set_invisible(true);
545 }
546 // Create a fake owner scope describing the index and context level of the
547 // variable. Function level and loop level are unused (set to 0), since
548 // context level has already been assigned.
549 LocalScope* owner_scope = new LocalScope(nullptr, 0, 0);
550 owner_scope->set_context_level(context_scope.ContextLevelAt(i));
551 owner_scope->AddVariable(variable);
552 outer_scope->AddVariable(variable); // As alias.
553 ASSERT(variable->owner() == owner_scope);
554 }
555 return outer_scope;
556}
557
559 ASSERT(top_scope->function_level() == function_level());
560 LocalScope* scope = this;
561 while (scope != top_scope->parent()) {
562 for (intptr_t i = 0; i < scope->num_variables(); i++) {
563 LocalVariable* variable = scope->VariableAt(i);
564 if (variable->is_forced_stack() ||
565 (variable->name().ptr() == Symbols::ExceptionVar().ptr()) ||
566 (variable->name().ptr() == Symbols::SavedTryContextVar().ptr()) ||
567 (variable->name().ptr() == Symbols::ArgDescVar().ptr()) ||
568 (variable->name().ptr() ==
569 Symbols::FunctionTypeArgumentsVar().ptr())) {
570 // Don't capture those variables because the VM expects them to be on
571 // the stack.
572 continue;
573 }
574 scope->CaptureVariable(variable);
575 }
576 scope = scope->parent();
577 }
578}
579
581 const intptr_t kNumCapturedVars = 1;
582
583 // Create a ContextScope with space for kNumCapturedVars descriptors.
584 const ContextScope& context_scope =
585 ContextScope::Handle(ContextScope::New(kNumCapturedVars, true));
586
587 // Create a descriptor for 'this' variable.
588 context_scope.SetTokenIndexAt(0, func.token_pos());
589 context_scope.SetDeclarationTokenIndexAt(0, func.token_pos());
590 context_scope.SetNameAt(0, Symbols::This());
591 context_scope.ClearFlagsAt(0);
592 context_scope.SetIsFinalAt(0, true);
594 context_scope.SetTypeAt(0, type);
595 context_scope.SetCidAt(0, kIllegalCid);
596 context_scope.SetContextIndexAt(0, 0);
597 context_scope.SetContextLevelAt(0, 0);
599 ASSERT(context_scope.num_variables() == kNumCapturedVars); // Verify count.
600 return context_scope.ptr();
601}
602
604 if (is_awaiter_link_ == IsAwaiterLink::kUnknown) {
605 RELEASE_ASSERT(annotations_offset_ != kNoKernelOffset);
607 Zone* Z = T->zone();
608 const auto& metadata = Object::Handle(
609 Z, kernel::EvaluateMetadata(library, annotations_offset_,
610 /* is_annotations_offset = */ true));
612 FindPragmaInMetadata(T, metadata, Symbols::vm_awaiter_link()));
613 }
614 return is_awaiter_link_ == IsAwaiterLink::kLink;
615}
616
617bool LocalVariable::Equals(const LocalVariable& other) const {
618 if (HasIndex() && other.HasIndex() && (index() == other.index())) {
619 if (is_captured() == other.is_captured()) {
620 if (!is_captured()) {
621 return true;
622 }
623 if (owner()->context_level() == other.owner()->context_level()) {
624 return true;
625 }
626 }
627 }
628 return false;
629}
630
632 const LocalVarDescriptors& var_descs) {
633 for (intptr_t i = 0, n = var_descs.Length(); i < n; ++i) {
635 desc.name = &String::Handle(zone, var_descs.GetName(i));
636 var_descs.GetInfo(i, &desc.info);
637 Add(desc);
638 }
639}
640
642 ZoneGrowableArray<intptr_t>* context_level_array) {
643 // Record deopt-id -> context-level mappings, using ranges of deopt-ids with
644 // the same context-level. [context_level_array] contains (deopt_id,
645 // context_level) tuples.
646 for (intptr_t start = 0; start < context_level_array->length();) {
647 intptr_t start_deopt_id = (*context_level_array)[start];
648 intptr_t start_context_level = (*context_level_array)[start + 1];
649 intptr_t end = start;
650 intptr_t end_deopt_id = start_deopt_id;
651 for (intptr_t peek = start + 2; peek < context_level_array->length();
652 peek += 2) {
653 intptr_t peek_deopt_id = (*context_level_array)[peek];
654 intptr_t peek_context_level = (*context_level_array)[peek + 1];
655 // The range encoding assumes the tuples have ascending deopt_ids.
656 ASSERT(peek_deopt_id > end_deopt_id);
657 if (peek_context_level != start_context_level) break;
658 end = peek;
659 end_deopt_id = peek_deopt_id;
660 }
661
663 desc.name = &Symbols::Empty(); // No name.
665 desc.info.scope_id = 0;
666 // We repurpose the token position fields to store deopt IDs in this case.
667 desc.info.begin_pos = TokenPosition::Deserialize(start_deopt_id);
668 desc.info.end_pos = TokenPosition::Deserialize(end_deopt_id);
669 desc.info.set_index(start_context_level);
670 Add(desc);
671
672 start = end + 2;
673 }
674}
675
676LocalVarDescriptorsPtr LocalVarDescriptorsBuilder::Done() {
677 if (vars_.is_empty()) {
678 return Object::empty_var_descriptors().ptr();
679 }
680 const LocalVarDescriptors& var_desc =
682 for (int i = 0; i < vars_.length(); i++) {
683 var_desc.SetVar(i, *(vars_[i].name), &vars_[i].info);
684 }
685 return var_desc.ptr();
686}
687
688} // namespace dart
689
690#endif // !defined(DART_PRECOMPILED_RUNTIME)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
SkPoint pos
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
#define Z
GLenum type
intptr_t length() const
intptr_t KernelOffsetAt(intptr_t scope_index) const
Definition: object.cc:18702
StringPtr NameAt(intptr_t scope_index) const
Definition: object.cc:18618
AbstractTypePtr TypeAt(intptr_t scope_index) const
Definition: object.cc:18667
intptr_t LateInitOffsetAt(intptr_t scope_index) const
Definition: object.cc:18658
intptr_t ContextLevelAt(intptr_t scope_index) const
Definition: object.cc:18693
void SetCidAt(intptr_t scope_index, intptr_t cid) const
Definition: object.cc:18680
TokenPosition DeclarationTokenIndexAt(intptr_t scope_index) const
Definition: object.cc:18605
intptr_t CidAt(intptr_t scope_index) const
Definition: object.cc:18676
void ClearFlagsAt(intptr_t scope_index) const
Definition: object.cc:18626
intptr_t ContextIndexAt(intptr_t scope_index) const
Definition: object.cc:18684
TokenPosition TokenIndexAt(intptr_t scope_index) const
Definition: object.cc:18595
void SetContextLevelAt(intptr_t scope_index, intptr_t context_level) const
Definition: object.cc:18697
void SetTypeAt(intptr_t scope_index, const AbstractType &type) const
Definition: object.cc:18671
void SetContextIndexAt(intptr_t scope_index, intptr_t context_index) const
Definition: object.cc:18688
void SetTokenIndexAt(intptr_t scope_index, TokenPosition token_pos) const
Definition: object.cc:18600
void SetLateInitOffsetAt(intptr_t scope_index, intptr_t late_init_offset) const
Definition: object.cc:18662
void SetNameAt(intptr_t scope_index, const String &name) const
Definition: object.cc:18622
intptr_t num_variables() const
Definition: object.h:7484
void SetKernelOffsetAt(intptr_t scope_index, intptr_t kernel_offset) const
Definition: object.cc:18706
void SetDeclarationTokenIndexAt(intptr_t scope_index, TokenPosition declaration_token_pos) const
Definition: object.cc:18611
static ContextScopePtr New(intptr_t num_variables, bool is_implicit)
Definition: object.cc:18577
bool HasParent() const
Definition: object.h:3930
TokenPosition token_pos() const
Definition: object.h:3446
AbstractTypePtr ParameterTypeAt(intptr_t index) const
Definition: object.cc:8580
ContextScopePtr context_scope() const
Definition: object.cc:8048
int context_level() const
Definition: scopes.h:333
LocalScope * parent() const
Definition: scopes.h:319
LocalScope(LocalScope *parent, int function_level, int loop_level)
Definition: scopes.cc:24
bool IsNestedWithin(LocalScope *scope) const
Definition: scopes.cc:46
int loop_level() const
Definition: scopes.h:323
TokenPosition end_token_pos() const
Definition: scopes.h:346
LocalScope * sibling() const
Definition: scopes.h:321
static ContextScopePtr CreateImplicitClosureScope(const Function &func)
Definition: scopes.cc:580
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
VariableIndex AllocateVariables(const Function &function, VariableIndex first_parameter_index, int num_parameters, VariableIndex first_local_index, LocalScope *context_owner, bool *found_captured_variables)
Definition: scopes.cc:133
LocalVarDescriptorsPtr GetVarDescriptors(const Function &func, ZoneGrowableArray< intptr_t > *context_level_array)
Definition: scopes.cc:249
LocalVariable * LookupVariableByName(const String &name)
Definition: scopes.cc:369
LocalVariable * VariableAt(intptr_t index) const
Definition: scopes.h:398
intptr_t num_variables() const
Definition: scopes.h:397
bool HasContextLevel() const
Definition: scopes.h:330
TokenPosition begin_token_pos() const
Definition: scopes.h:343
LocalVariable * LookupVariable(const String &name, intptr_t kernel_offset, bool test_only)
Definition: scopes.cc:350
bool AddVariable(LocalVariable *variable)
Definition: scopes.cc:57
LocalScope * child() const
Definition: scopes.h:320
void CaptureVariable(LocalVariable *variable)
Definition: scopes.cc:383
bool InsertParameterAt(intptr_t pos, LocalVariable *parameter)
Definition: scopes.cc:72
int num_context_variables() const
Definition: scopes.h:361
ContextScopePtr PreserveOuterScope(const Function &function, intptr_t current_context_level) const
Definition: scopes.cc:433
LocalVariable * LocalLookupVariable(const String &name, intptr_t kernel_offset) const
Definition: scopes.cc:336
void set_context_level(int context_level)
Definition: scopes.h:337
void AddContextVariable(LocalVariable *var)
Definition: scopes.cc:126
void CaptureLocalVariables(LocalScope *top_scope)
Definition: scopes.cc:558
void AddAll(Zone *zone, const LocalVarDescriptors &var_descs)
Definition: scopes.cc:631
LocalVarDescriptorsPtr Done()
Definition: scopes.cc:676
void Add(const VarDesc &var_desc)
Definition: scopes.h:297
void AddDeoptIdToContextLevelMappings(ZoneGrowableArray< intptr_t > *context_level_array)
Definition: scopes.cc:641
static LocalVarDescriptorsPtr New(intptr_t num_variables)
Definition: object.cc:16134
intptr_t Length() const
Definition: object.cc:16149
void SetVar(intptr_t var_index, const String &name, UntaggedLocalVarDescriptors::VarInfo *info) const
Definition: object.cc:16036
StringPtr GetName(intptr_t var_index) const
Definition: object.cc:16030
void GetInfo(intptr_t var_index, UntaggedLocalVarDescriptors::VarInfo *info) const
Definition: object.cc:16046
bool is_late() const
Definition: scopes.h:160
CompileType * inferred_type() const
Definition: scopes.h:136
VariableIndex index() const
Definition: scopes.h:202
void set_late_init_offset(intptr_t late_init_offset)
Definition: scopes.h:164
LocalScope * owner() const
Definition: scopes.h:122
bool HasIndex() const
Definition: scopes.h:201
bool ComputeIfIsAwaiterLink(const Library &library)
Definition: scopes.cc:603
void set_is_captured()
Definition: scopes.h:144
bool is_captured() const
Definition: scopes.h:143
void set_is_late()
Definition: scopes.h:161
bool is_forced_stack() const
Definition: scopes.h:155
TokenPosition declaration_token_pos() const
Definition: scopes.h:118
void set_is_final()
Definition: scopes.h:141
TokenPosition token_pos() const
Definition: scopes.h:117
void set_index(VariableIndex index)
Definition: scopes.h:208
void set_invisible(bool value)
Definition: scopes.h:216
bool is_invisible() const
Definition: scopes.h:215
intptr_t kernel_offset() const
Definition: scopes.h:120
bool Equals(const LocalVariable &other) const
Definition: scopes.cc:617
static constexpr intptr_t kNoKernelOffset
Definition: scopes.h:77
intptr_t late_init_offset() const
Definition: scopes.h:163
const String & name() const
Definition: scopes.h:119
void set_is_awaiter_link(bool value)
Definition: scopes.h:147
bool is_final() const
Definition: scopes.h:140
void set_owner(LocalScope *owner)
Definition: scopes.h:123
LocalVariable(TokenPosition declaration_pos, TokenPosition token_pos, const String &name, const AbstractType &static_type, intptr_t kernel_offset=kNoKernelOffset)
Definition: scopes.cc:224
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static ObjectPtr null()
Definition: object.h:433
ObjectPtr ptr() const
Definition: object.h:332
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
static Object & ZoneHandle()
Definition: object.h:419
static const Slot & GetContextVariableSlotFor(Thread *thread, const LocalVariable &var)
Definition: slot.cc:292
intptr_t Length() const
Definition: object.h:10210
bool Equals(const String &str) const
Definition: object.h:13337
uint16_t CharAt(intptr_t index) const
Definition: object.h:10259
static const char * ToCString(Thread *thread, StringPtr ptr)
Definition: object.cc:24126
bool IsSymbol() const
Definition: object.h:10309
static constexpr intptr_t kSuspendStateVarIndex
Definition: object.h:12617
static const String & This()
Definition: symbols.h:692
static const String & Empty()
Definition: symbols.h:688
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
static TokenPosition Deserialize(int32_t value)
static const TokenPosition kMinSource
static bool IsUint(intptr_t N, T value)
Definition: utils.h:328
int value() const
Definition: scopes.h:69
#define ASSERT(E)
glong glong end
Dart_NativeFunction function
Definition: fuchsia.cc:51
ObjectPtr EvaluateMetadata(const Library &library, intptr_t kernel_offset, bool is_annotations_offset)
Definition: kernel.cc:467
Definition: dart_vm.cc:33
const char *const name
@ kIllegalCid
Definition: class_id.h:214
bool FindPragmaInMetadata(Thread *T, const Object &metadata_obj, const String &pragma_name, bool multiple, Object *options)
Definition: object.cc:4092
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
Definition: __init__.py:1
#define Pd
Definition: globals.h:408
#define T
Definition: precompiler.cc:65