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

Side by Side Diff: runtime/vm/kernel_to_il.cc

Issue 2886873008: [kernel] Streaming ScopeBuilder (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 6
7 #include "vm/kernel_to_il.h" 7 #include "vm/kernel_to_il.h"
8 8
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/intermediate_language.h" 10 #include "vm/intermediate_language.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 } else if ((*outermost_node)->IsConstructor()) { 50 } else if ((*outermost_node)->IsConstructor()) {
51 parent = Constructor::Cast(*outermost_node)->parent(); 51 parent = Constructor::Cast(*outermost_node)->parent();
52 } else if ((*outermost_node)->IsField()) { 52 } else if ((*outermost_node)->IsField()) {
53 parent = Field::Cast(*outermost_node)->parent(); 53 parent = Field::Cast(*outermost_node)->parent();
54 } 54 }
55 if (parent != NULL && parent->IsClass()) *klass = Class::Cast(parent); 55 if (parent != NULL && parent->IsClass()) *klass = Class::Cast(parent);
56 } 56 }
57 } 57 }
58 58
59 59
60 ScopeBuilder::ScopeBuilder(ParsedFunction* parsed_function, TreeNode* node)
61 : result_(NULL),
62 parsed_function_(parsed_function),
63 node_(node),
64 translation_helper_(Thread::Current()),
65 zone_(translation_helper_.zone()),
66 type_translator_(&translation_helper_, &active_class_, /*finalize=*/true),
67 current_function_scope_(NULL),
68 scope_(NULL),
69 depth_(0),
70 name_index_(0),
71 needs_expr_temp_(false) {
72 Script& script = Script::Handle(Z, parsed_function->function().script());
73 H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets()));
74 H.SetStringData(TypedData::Handle(Z, script.kernel_string_data()));
75 H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names()));
76 }
77
78
79 void ScopeBuilder::EnterScope(TreeNode* node, TokenPosition start_position) {
80 scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
81 scope_->set_begin_token_pos(start_position);
82 ASSERT(node->kernel_offset() >= 0);
83 result_->scopes.Insert(node->kernel_offset(), scope_);
84 }
85
86
87 void ScopeBuilder::ExitScope(TokenPosition end_position) {
88 scope_->set_end_token_pos(end_position);
89 scope_ = scope_->parent();
90 }
91
92
93 LocalVariable* ScopeBuilder::MakeVariable(TokenPosition declaration_pos,
94 TokenPosition token_pos,
95 const dart::String& name,
96 const AbstractType& type) {
97 return new (Z) LocalVariable(declaration_pos, token_pos, name, type);
98 }
99
100
101 void ScopeBuilder::AddParameters(FunctionNode* function, intptr_t pos) {
102 List<VariableDeclaration>& positional = function->positional_parameters();
103 for (intptr_t i = 0; i < positional.length(); ++i) {
104 AddParameter(positional[i], pos++);
105 }
106 List<VariableDeclaration>& named = function->named_parameters();
107 for (intptr_t i = 0; i < named.length(); ++i) {
108 AddParameter(named[i], pos++);
109 }
110 }
111
112
113 void ScopeBuilder::AddParameter(VariableDeclaration* declaration,
114 intptr_t pos) {
115 LocalVariable* variable = MakeVariable(
116 declaration->position(), declaration->position(),
117 H.DartSymbol(declaration->name()), T.TranslateVariableType(declaration));
118 if (declaration->IsFinal()) {
119 variable->set_is_final();
120 }
121 if (variable->name().raw() == Symbols::IteratorParameter().raw()) {
122 variable->set_is_forced_stack();
123 }
124 scope_->InsertParameterAt(pos, variable);
125 result_->locals.Insert(declaration->kernel_offset(), variable);
126
127 // The default value may contain 'let' bindings for which the constant
128 // evaluator needs scope bindings.
129 Expression* defaultValue = declaration->initializer();
130 if (defaultValue != NULL) {
131 defaultValue->AcceptExpressionVisitor(this);
132 }
133 }
134
135
136 void ScopeBuilder::AddExceptionVariable(
137 GrowableArray<LocalVariable*>* variables,
138 const char* prefix,
139 intptr_t nesting_depth) {
140 LocalVariable* v = NULL;
141
142 // If we are inside a function with yield points then Kernel transformer
143 // could have lifted some of the auxiliary exception variables into the
144 // context to preserve them across yield points because they might
145 // be needed for rethrow.
146 // Check if it did and capture such variables instead of introducing
147 // new local ones.
148 // Note: function that wrap kSyncYielding function does not contain
149 // its own try/catches.
150 if (current_function_node_->async_marker() == FunctionNode::kSyncYielding) {
151 ASSERT(current_function_scope_->parent() != NULL);
152 v = current_function_scope_->parent()->LocalLookupVariable(
153 GenerateName(prefix, nesting_depth - 1));
154 if (v != NULL) {
155 scope_->CaptureVariable(v);
156 }
157 }
158
159 // No need to create variables for try/catch-statements inside
160 // nested functions.
161 if (depth_.function_ > 0) return;
162 if (variables->length() >= nesting_depth) return;
163
164 // If variable was not lifted by the transformer introduce a new
165 // one into the current function scope.
166 if (v == NULL) {
167 v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
168 GenerateName(prefix, nesting_depth - 1),
169 AbstractType::dynamic_type());
170
171 // If transformer did not lift the variable then there is no need
172 // to lift it into the context when we encouter a YieldStatement.
173 v->set_is_forced_stack();
174 current_function_scope_->AddVariable(v);
175 }
176
177 variables->Add(v);
178 }
179
180
181 void ScopeBuilder::AddTryVariables() {
182 AddExceptionVariable(&result_->catch_context_variables,
183 ":saved_try_context_var", depth_.try_);
184 }
185
186
187 void ScopeBuilder::AddCatchVariables() {
188 AddExceptionVariable(&result_->exception_variables, ":exception",
189 depth_.catch_);
190 AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace",
191 depth_.catch_);
192 }
193
194
195 void ScopeBuilder::AddIteratorVariable() {
196 if (depth_.function_ > 0) return;
197 if (result_->iterator_variables.length() >= depth_.for_in_) return;
198
199 ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1);
200 LocalVariable* iterator =
201 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
202 GenerateName(":iterator", depth_.for_in_ - 1),
203 AbstractType::dynamic_type());
204 current_function_scope_->AddVariable(iterator);
205 result_->iterator_variables.Add(iterator);
206 }
207
208
209 void ScopeBuilder::LookupVariable(VariableDeclaration* declaration) {
210 LocalVariable* variable =
211 result_->locals.Lookup(declaration->kernel_offset());
212 if (variable == NULL) {
213 // We have not seen a declaration of the variable, so it must be the
214 // case that we are compiling a nested function and the variable is
215 // declared in an outer scope. In that case, look it up in the scope by
216 // name and add it to the variable map to simplify later lookup.
217 ASSERT(current_function_scope_->parent() != NULL);
218 const dart::String& name = H.DartSymbol(declaration->name());
219 variable = current_function_scope_->parent()->LookupVariable(name, true);
220 ASSERT(variable != NULL);
221 result_->locals.Insert(declaration->kernel_offset(), variable);
222 }
223 if (variable->owner()->function_level() < scope_->function_level()) {
224 // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two
225 // different reasons:
226 // Scenario 1:
227 // We need to know which variables defined in this function
228 // are closed over by nested closures in order to ensure we will
229 // create a [Context] object of appropriate size and store captured
230 // variables there instead of the stack.
231 // Scenario 2:
232 // We need to find out which variables defined in enclosing functions
233 // are closed over by this function/closure or nested closures. This
234 // is necessary in order to build a fat flattened [ContextScope]
235 // object.
236 scope_->CaptureVariable(variable);
237 } else {
238 ASSERT(variable->owner()->function_level() == scope_->function_level());
239 }
240 }
241
242
243 void ScopeBuilder::LookupCapturedVariableByName(LocalVariable** variable,
244 const dart::String& name) {
245 if (*variable == NULL) {
246 *variable = scope_->LookupVariable(name, true);
247 ASSERT(*variable != NULL);
248 scope_->CaptureVariable(*variable);
249 }
250 }
251
252
253 const dart::String& ScopeBuilder::GenerateName(const char* prefix,
254 intptr_t suffix) {
255 char name[64];
256 OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
257 return H.DartSymbol(name);
258 }
259
260
261 void ScopeBuilder::AddVariable(VariableDeclaration* declaration) {
262 // In case `declaration->IsConst()` the flow graph building will take care of
263 // evaluating the constant and setting it via
264 // `declaration->SetConstantValue()`.
265 const dart::String& name = (H.StringSize(declaration->name()) == 0)
266 ? GenerateName(":var", name_index_++)
267 : H.DartSymbol(declaration->name());
268 LocalVariable* variable =
269 MakeVariable(declaration->position(), declaration->end_position(), name,
270 T.TranslateVariableType(declaration));
271 if (declaration->IsFinal()) {
272 variable->set_is_final();
273 }
274 scope_->AddVariable(variable);
275 result_->locals.Insert(declaration->kernel_offset(), variable);
276 }
277
278
279 static bool IsStaticInitializer(const Function& function, Zone* zone) { 60 static bool IsStaticInitializer(const Function& function, Zone* zone) {
280 return (function.kind() == RawFunction::kImplicitStaticFinalGetter) && 61 return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
281 dart::String::Handle(zone, function.name()) 62 dart::String::Handle(zone, function.name())
282 .StartsWith(Symbols::InitPrefix()); 63 .StartsWith(Symbols::InitPrefix());
283 } 64 }
284 65
285 66
286 ScopeBuildingResult* ScopeBuilder::BuildScopes() {
287 if (result_ != NULL) return result_;
288
289 ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0);
290 result_ = new (Z) ScopeBuildingResult();
291
292 ParsedFunction* parsed_function = parsed_function_;
293 const Function& function = parsed_function->function();
294
295 // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
296 // e.g. for type translation.
297 const dart::Class& klass =
298 dart::Class::Handle(zone_, parsed_function_->function().Owner());
299 Function& outermost_function = Function::Handle(Z);
300 TreeNode* outermost_node = NULL;
301 Class* kernel_class = NULL;
302 DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node,
303 &kernel_class);
304 // Use [klass]/[kernel_class] as active class. Type parameters will get
305 // resolved via [kernel_class] unless we are nested inside a static factory
306 // in which case we will use [member].
307 ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass);
308 Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
309 ? Member::Cast(outermost_node)
310 : NULL;
311 ActiveMemberScope active_member(&active_class_, member);
312
313
314 LocalScope* enclosing_scope = NULL;
315 if (function.IsLocalFunction()) {
316 enclosing_scope = LocalScope::RestoreOuterScope(
317 ContextScope::Handle(Z, function.context_scope()));
318 }
319 current_function_scope_ = scope_ = new (Z) LocalScope(enclosing_scope, 0, 0);
320 scope_->set_begin_token_pos(function.token_pos());
321 scope_->set_end_token_pos(function.end_token_pos());
322
323 LocalVariable* context_var = parsed_function->current_context_var();
324 context_var->set_is_forced_stack();
325 scope_->AddVariable(context_var);
326
327 parsed_function->SetNodeSequence(
328 new SequenceNode(TokenPosition::kNoSource, scope_));
329
330 switch (function.kind()) {
331 case RawFunction::kClosureFunction:
332 case RawFunction::kRegularFunction:
333 case RawFunction::kGetterFunction:
334 case RawFunction::kSetterFunction:
335 case RawFunction::kConstructor: {
336 FunctionNode* node;
337 if (node_->IsProcedure()) {
338 node = Procedure::Cast(node_)->function();
339 } else if (node_->IsConstructor()) {
340 node = Constructor::Cast(node_)->function();
341 } else {
342 node = FunctionNode::Cast(node_);
343 }
344 current_function_node_ = node;
345
346 intptr_t pos = 0;
347 if (function.IsClosureFunction()) {
348 LocalVariable* variable = MakeVariable(
349 TokenPosition::kNoSource, TokenPosition::kNoSource,
350 Symbols::ClosureParameter(), AbstractType::dynamic_type());
351 variable->set_is_forced_stack();
352 scope_->InsertParameterAt(pos++, variable);
353 } else if (!function.is_static()) {
354 // We use [is_static] instead of [IsStaticFunction] because the latter
355 // returns `false` for constructors.
356 dart::Class& klass = dart::Class::Handle(Z, function.Owner());
357 Type& klass_type = H.GetCanonicalType(klass);
358 LocalVariable* variable =
359 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
360 Symbols::This(), klass_type);
361 scope_->InsertParameterAt(pos++, variable);
362 result_->this_variable = variable;
363
364 // We visit instance field initializers because they might contain
365 // [Let] expressions and we need to have a mapping.
366 if (node_->IsConstructor()) {
367 Class* klass = Class::Cast(Constructor::Cast(node_)->parent());
368
369 for (intptr_t i = 0; i < klass->fields().length(); i++) {
370 Field* field = klass->fields()[i];
371 if (!field->IsStatic() && (field->initializer() != NULL)) {
372 EnterScope(field, field->position());
373 field->initializer()->AcceptExpressionVisitor(this);
374 ExitScope(field->end_position());
375 }
376 }
377 }
378 } else if (function.IsFactory()) {
379 LocalVariable* variable = MakeVariable(
380 TokenPosition::kNoSource, TokenPosition::kNoSource,
381 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
382 scope_->InsertParameterAt(pos++, variable);
383 result_->type_arguments_variable = variable;
384 }
385 AddParameters(node, pos);
386
387 // We generate a syntethic body for implicit closure functions - which
388 // will forward the call to the real function.
389 // -> see BuildGraphOfImplicitClosureFunction
390 if (!function.IsImplicitClosureFunction()) {
391 // TODO(jensj): HACK: Push the begin token to after any parameters to
392 // avoid crash when breaking on definition line of async method in
393 // debugger. It seems that another scope needs to be added
394 // in which captures are made, but I can't make that work.
395 // This 'solution' doesn't crash, but I cannot see the parameters at
396 // that particular breakpoint either.
397 // Also push the end token to after the "}" to avoid crashing on
398 // stepping past the last line (to the "}" character).
399 if (node->body() != NULL && node->body()->position().IsReal()) {
400 scope_->set_begin_token_pos(node->body()->position());
401 }
402 if (scope_->end_token_pos().IsReal()) {
403 scope_->set_end_token_pos(scope_->end_token_pos().Next());
404 }
405 node_->AcceptVisitor(this);
406 }
407 break;
408 }
409 case RawFunction::kImplicitGetter:
410 case RawFunction::kImplicitStaticFinalGetter:
411 case RawFunction::kImplicitSetter: {
412 ASSERT(node_->IsField());
413 if (IsStaticInitializer(function, Z)) {
414 node_->AcceptVisitor(this);
415 break;
416 }
417 bool is_setter = function.IsImplicitSetterFunction();
418 bool is_method = !function.IsStaticFunction();
419 intptr_t pos = 0;
420 if (is_method) {
421 dart::Class& klass = dart::Class::Handle(Z, function.Owner());
422 Type& klass_type = H.GetCanonicalType(klass);
423 LocalVariable* variable =
424 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
425 Symbols::This(), klass_type);
426 scope_->InsertParameterAt(pos++, variable);
427 result_->this_variable = variable;
428 }
429 if (is_setter) {
430 result_->setter_value =
431 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
432 Symbols::Value(), AbstractType::dynamic_type());
433 scope_->InsertParameterAt(pos++, result_->setter_value);
434 }
435 break;
436 }
437 case RawFunction::kMethodExtractor: {
438 // Add a receiver parameter. Though it is captured, we emit code to
439 // explicitly copy it to a fixed offset in a freshly-allocated context
440 // instead of using the generic code for regular functions.
441 // Therefore, it isn't necessary to mark it as captured here.
442 dart::Class& klass = dart::Class::Handle(Z, function.Owner());
443 Type& klass_type = H.GetCanonicalType(klass);
444 LocalVariable* variable =
445 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
446 Symbols::This(), klass_type);
447 scope_->InsertParameterAt(0, variable);
448 result_->this_variable = variable;
449 break;
450 }
451 case RawFunction::kNoSuchMethodDispatcher:
452 case RawFunction::kInvokeFieldDispatcher:
453 for (intptr_t i = 0; i < function.NumParameters(); ++i) {
454 LocalVariable* variable = MakeVariable(
455 TokenPosition::kNoSource, TokenPosition::kNoSource,
456 dart::String::ZoneHandle(Z, function.ParameterNameAt(i)),
457 AbstractType::dynamic_type());
458 scope_->InsertParameterAt(i, variable);
459 }
460 break;
461 case RawFunction::kSignatureFunction:
462 case RawFunction::kIrregexpFunction:
463 UNREACHABLE();
464 }
465 if (needs_expr_temp_) {
466 scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
467 }
468 parsed_function->AllocateVariables();
469
470 return result_;
471 }
472
473
474 void ScopeBuilder::VisitThisExpression(ThisExpression* node) {
475 HandleSpecialLoad(&result_->this_variable, Symbols::This());
476 }
477
478
479 void ScopeBuilder::VisitTypeParameterType(TypeParameterType* node) {
480 Function& function = Function::Handle(Z, parsed_function_->function().raw());
481 while (function.IsClosureFunction()) {
482 function = function.parent_function();
483 }
484
485 if (function.IsFactory()) {
486 // The type argument vector is passed as the very first argument to the
487 // factory constructor function.
488 HandleSpecialLoad(&result_->type_arguments_variable,
489 Symbols::TypeArgumentsParameter());
490 } else {
491 // The type argument vector is stored on the instance object. We therefore
492 // need to capture `this`.
493 HandleSpecialLoad(&result_->this_variable, Symbols::This());
494 }
495 }
496
497
498 void ScopeBuilder::VisitVariableGet(VariableGet* node) {
499 LookupVariable(node->variable());
500 }
501
502
503 void ScopeBuilder::VisitVariableSet(VariableSet* node) {
504 LookupVariable(node->variable());
505 node->VisitChildren(this);
506 }
507
508
509 void ScopeBuilder::VisitConditionalExpression(ConditionalExpression* node) {
510 needs_expr_temp_ = true;
511 node->VisitChildren(this);
512 }
513
514
515 void ScopeBuilder::VisitLogicalExpression(LogicalExpression* node) {
516 needs_expr_temp_ = true;
517 node->VisitChildren(this);
518 }
519
520
521 void ScopeBuilder::HandleLocalFunction(TreeNode* parent,
522 FunctionNode* function) {
523 LocalScope* saved_function_scope = current_function_scope_;
524 FunctionNode* saved_function_node = current_function_node_;
525 ScopeBuilder::DepthState saved_depth_state = depth_;
526 depth_ = DepthState(depth_.function_ + 1);
527 EnterScope(parent, function->position());
528 current_function_scope_ = scope_;
529 current_function_node_ = function;
530 if (depth_.function_ == 1) {
531 FunctionScope function_scope = {function->kernel_offset(), scope_};
532 result_->function_scopes.Add(function_scope);
533 }
534 AddParameters(function);
535 VisitFunctionNode(function);
536 ExitScope(function->end_position());
537 depth_ = saved_depth_state;
538 current_function_scope_ = saved_function_scope;
539 current_function_node_ = saved_function_node;
540 }
541
542
543 void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable,
544 const dart::String& symbol) {
545 if (current_function_scope_->parent() != NULL) {
546 // We are building the scope tree of a closure function and saw [node]. We
547 // lazily populate the variable using the parent function scope.
548 if (*variable == NULL) {
549 *variable =
550 current_function_scope_->parent()->LookupVariable(symbol, true);
551 ASSERT(*variable != NULL);
552 }
553 }
554
555 if ((current_function_scope_->parent() != NULL) ||
556 (scope_->function_level() > 0)) {
557 // Every scope we use the [variable] from needs to be notified of the usage
558 // in order to ensure that preserving the context scope on that particular
559 // use-site also includes the [variable].
560 scope_->CaptureVariable(*variable);
561 }
562 }
563
564
565 void ScopeBuilder::VisitFunctionExpression(FunctionExpression* node) {
566 HandleLocalFunction(node, node->function());
567 }
568
569
570 void ScopeBuilder::VisitLet(Let* node) {
571 EnterScope(node, node->position());
572 node->VisitChildren(this);
573 ExitScope(node->end_position());
574 }
575
576
577 void ScopeBuilder::VisitBlock(Block* node) {
578 EnterScope(node, node->position());
579 node->VisitChildren(this);
580 ExitScope(node->end_position());
581 }
582
583
584 void ScopeBuilder::VisitVariableDeclaration(VariableDeclaration* node) {
585 AddVariable(node);
586 node->VisitChildren(this);
587 }
588
589
590 void ScopeBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) {
591 VisitVariableDeclaration(node->variable());
592 HandleLocalFunction(node, node->function());
593 }
594
595
596 void ScopeBuilder::VisitWhileStatement(WhileStatement* node) {
597 ++depth_.loop_;
598 node->VisitChildren(this);
599 --depth_.loop_;
600 }
601
602
603 void ScopeBuilder::VisitDoStatement(DoStatement* node) {
604 ++depth_.loop_;
605 node->VisitChildren(this);
606 --depth_.loop_;
607 }
608
609
610 void ScopeBuilder::VisitForStatement(ForStatement* node) {
611 EnterScope(node, node->position());
612 List<VariableDeclaration>& variables = node->variables();
613 for (intptr_t i = 0; i < variables.length(); ++i) {
614 VisitVariableDeclaration(variables[i]);
615 }
616 ++depth_.loop_;
617 if (node->condition() != NULL) {
618 node->condition()->AcceptExpressionVisitor(this);
619 }
620 node->body()->AcceptStatementVisitor(this);
621 List<Expression>& updates = node->updates();
622 for (intptr_t i = 0; i < updates.length(); ++i) {
623 updates[i]->AcceptExpressionVisitor(this);
624 }
625 --depth_.loop_;
626 ExitScope(node->end_position());
627 }
628
629
630 void ScopeBuilder::VisitForInStatement(ForInStatement* node) {
631 node->iterable()->AcceptExpressionVisitor(this);
632 ++depth_.for_in_;
633 AddIteratorVariable();
634 ++depth_.loop_;
635 EnterScope(node, node->position());
636 VisitVariableDeclaration(node->variable());
637 node->body()->AcceptStatementVisitor(this);
638 ExitScope(node->end_position());
639 --depth_.loop_;
640 --depth_.for_in_;
641 }
642
643
644 void ScopeBuilder::AddSwitchVariable() {
645 if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) {
646 LocalVariable* variable =
647 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
648 Symbols::SwitchExpr(), AbstractType::dynamic_type());
649 variable->set_is_forced_stack();
650 current_function_scope_->AddVariable(variable);
651 result_->switch_variable = variable;
652 }
653 }
654
655
656 void ScopeBuilder::VisitSwitchStatement(SwitchStatement* node) {
657 AddSwitchVariable();
658 node->VisitChildren(this);
659 }
660
661
662 void ScopeBuilder::VisitReturnStatement(ReturnStatement* node) {
663 if ((depth_.function_ == 0) && (depth_.finally_ > 0) &&
664 (result_->finally_return_variable == NULL)) {
665 const dart::String& name = H.DartSymbol(":try_finally_return_value");
666 LocalVariable* variable =
667 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, name,
668 AbstractType::dynamic_type());
669 current_function_scope_->AddVariable(variable);
670 result_->finally_return_variable = variable;
671 }
672 node->VisitChildren(this);
673 }
674
675
676 void ScopeBuilder::VisitTryCatch(TryCatch* node) {
677 ++depth_.try_;
678 AddTryVariables();
679 node->body()->AcceptStatementVisitor(this);
680 --depth_.try_;
681
682 ++depth_.catch_;
683 AddCatchVariables();
684 List<Catch>& catches = node->catches();
685 for (intptr_t i = 0; i < catches.length(); ++i) {
686 Catch* ketch = catches[i];
687 EnterScope(ketch, ketch->position());
688 if (ketch->exception() != NULL) {
689 VisitVariableDeclaration(ketch->exception());
690 }
691 if (ketch->stack_trace() != NULL) {
692 VisitVariableDeclaration(ketch->stack_trace());
693 }
694 ketch->body()->AcceptStatementVisitor(this);
695 ExitScope(ketch->end_position());
696 }
697 --depth_.catch_;
698 }
699
700
701 void ScopeBuilder::VisitTryFinally(TryFinally* node) {
702 ++depth_.try_;
703 ++depth_.finally_;
704 AddTryVariables();
705 node->body()->AcceptStatementVisitor(this);
706 --depth_.finally_;
707 --depth_.try_;
708
709 ++depth_.catch_;
710 AddCatchVariables();
711 node->finalizer()->AcceptStatementVisitor(this);
712 --depth_.catch_;
713 }
714
715
716 void ScopeBuilder::VisitFunctionNode(FunctionNode* node) {
717 List<TypeParameter>& type_parameters = node->type_parameters();
718 for (intptr_t i = 0; i < type_parameters.length(); ++i) {
719 VisitTypeParameter(type_parameters[i]);
720 }
721
722 if (FLAG_causal_async_stacks &&
723 (node->dart_async_marker() == FunctionNode::kAsync ||
724 node->dart_async_marker() == FunctionNode::kAsyncStar)) {
725 LocalVariable* asyncStackTraceVar = MakeVariable(
726 TokenPosition::kNoSource, TokenPosition::kNoSource,
727 Symbols::AsyncStackTraceVar(), AbstractType::dynamic_type());
728 scope_->AddVariable(asyncStackTraceVar);
729 }
730
731 if (node->async_marker() == FunctionNode::kSyncYielding) {
732 LocalScope* scope = parsed_function_->node_sequence()->scope();
733 intptr_t offset = parsed_function_->function().num_fixed_parameters();
734 for (intptr_t i = 0;
735 i < parsed_function_->function().NumOptionalPositionalParameters();
736 i++) {
737 scope->VariableAt(offset + i)->set_is_forced_stack();
738 }
739 }
740
741 // Do not visit the positional and named parameters, because they've
742 // already been added to the scope.
743 if (node->body() != NULL) {
744 node->body()->AcceptStatementVisitor(this);
745 }
746
747 // Ensure that :await_jump_var, :await_ctx_var, :async_op and
748 // :async_stack_trace are captured.
749 if (node->async_marker() == FunctionNode::kSyncYielding) {
750 {
751 LocalVariable* temp = NULL;
752 LookupCapturedVariableByName(
753 (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp,
754 Symbols::AwaitJumpVar());
755 }
756 {
757 LocalVariable* temp = NULL;
758 LookupCapturedVariableByName(
759 (depth_.function_ == 0) ? &result_->yield_context_variable : &temp,
760 Symbols::AwaitContextVar());
761 }
762 {
763 LocalVariable* temp =
764 scope_->LookupVariable(Symbols::AsyncOperation(), true);
765 if (temp != NULL) {
766 scope_->CaptureVariable(temp);
767 }
768 }
769 if (FLAG_causal_async_stacks) {
770 LocalVariable* temp =
771 scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true);
772 if (temp != NULL) {
773 scope_->CaptureVariable(temp);
774 }
775 }
776 }
777 }
778
779
780 void ScopeBuilder::VisitYieldStatement(YieldStatement* node) {
781 ASSERT(node->is_native());
782 if (depth_.function_ == 0) {
783 AddSwitchVariable();
784 // Promote all currently visible local variables into the context.
785 // TODO(27590) CaptureLocalVariables promotes to many variables into
786 // the scope. Mark those variables as stack_local.
787 // TODO(27590) we don't need to promote those variables that are
788 // not used across yields.
789 scope_->CaptureLocalVariables(current_function_scope_);
790 }
791 }
792
793
794 void ScopeBuilder::VisitAssertStatement(AssertStatement* node) {
795 if (I->asserts()) {
796 RecursiveVisitor::VisitAssertStatement(node);
797 }
798 }
799
800
801 void ScopeBuilder::VisitConstructor(Constructor* node) {
802 // Field initializers that come from non-static field declarations are
803 // compiled as if they appear in the constructor initializer list. This is
804 // important for closure-valued field initializers because the VM expects the
805 // corresponding closure functions to appear as if they were nested inside the
806 // constructor.
807 List<Field>& fields = Class::Cast(node->parent())->fields();
808 for (intptr_t i = 0; i < fields.length(); ++i) {
809 Field* field = fields[i];
810 Expression* initializer = field->initializer();
811 if (!field->IsStatic() && (initializer != NULL)) {
812 initializer->AcceptExpressionVisitor(this);
813 }
814 }
815 node->VisitChildren(this);
816 }
817
818
819 Fragment& Fragment::operator+=(const Fragment& other) { 67 Fragment& Fragment::operator+=(const Fragment& other) {
820 if (entry == NULL) { 68 if (entry == NULL) {
821 entry = other.entry; 69 entry = other.entry;
822 current = other.current; 70 current = other.current;
823 } else if (current != NULL && other.entry != NULL) { 71 } else if (current != NULL && other.entry != NULL) {
824 current->LinkTo(other.entry); 72 current->LinkTo(other.entry);
825 current = other.current; 73 current = other.current;
826 } 74 }
827 return *this; 75 return *this;
828 } 76 }
(...skipping 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after
3017 intptr_t FlowGraphBuilder::CurrentTryIndex() { 2265 intptr_t FlowGraphBuilder::CurrentTryIndex() {
3018 if (try_catch_block_ == NULL) { 2266 if (try_catch_block_ == NULL) {
3019 return CatchClauseNode::kInvalidTryIndex; 2267 return CatchClauseNode::kInvalidTryIndex;
3020 } else { 2268 } else {
3021 return try_catch_block_->try_index(); 2269 return try_catch_block_->try_index();
3022 } 2270 }
3023 } 2271 }
3024 2272
3025 2273
3026 LocalVariable* FlowGraphBuilder::LookupVariable(VariableDeclaration* var) { 2274 LocalVariable* FlowGraphBuilder::LookupVariable(VariableDeclaration* var) {
3027 LocalVariable* local = scopes_->locals.Lookup(var->kernel_offset()); 2275 LocalVariable* local = scopes_->locals.Lookup(var->kernel_offset_no_tag());
3028 ASSERT(local != NULL); 2276 ASSERT(local != NULL);
3029 return local; 2277 return local;
3030 } 2278 }
3031 2279
3032 2280
3033 dart::LocalVariable* FlowGraphBuilder::LookupVariable(intptr_t kernel_offset) { 2281 dart::LocalVariable* FlowGraphBuilder::LookupVariable(intptr_t kernel_offset) {
3034 LocalVariable* local = scopes_->locals.Lookup(kernel_offset); 2282 LocalVariable* local = scopes_->locals.Lookup(kernel_offset);
3035 ASSERT(local != NULL); 2283 ASSERT(local != NULL);
3036 return local; 2284 return local;
3037 } 2285 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
3200 scopes_ = parsed_function_->EnsureKernelScopes(); 2448 scopes_ = parsed_function_->EnsureKernelScopes();
3201 2449
3202 switch (function.kind()) { 2450 switch (function.kind()) {
3203 case RawFunction::kClosureFunction: 2451 case RawFunction::kClosureFunction:
3204 case RawFunction::kRegularFunction: 2452 case RawFunction::kRegularFunction:
3205 case RawFunction::kGetterFunction: 2453 case RawFunction::kGetterFunction:
3206 case RawFunction::kSetterFunction: { 2454 case RawFunction::kSetterFunction: {
3207 FunctionNode* kernel_function = node_->IsProcedure() 2455 FunctionNode* kernel_function = node_->IsProcedure()
3208 ? Procedure::Cast(node_)->function() 2456 ? Procedure::Cast(node_)->function()
3209 : FunctionNode::Cast(node_); 2457 : FunctionNode::Cast(node_);
3210 ActiveFunctionScope active_function_scope(&active_class_,
3211 kernel_function);
3212 return function.IsImplicitClosureFunction() 2458 return function.IsImplicitClosureFunction()
3213 ? BuildGraphOfImplicitClosureFunction(kernel_function, 2459 ? BuildGraphOfImplicitClosureFunction(kernel_function,
3214 function) 2460 function)
3215 : BuildGraphOfFunction(kernel_function); 2461 : BuildGraphOfFunction(kernel_function);
3216 } 2462 }
3217 case RawFunction::kConstructor: { 2463 case RawFunction::kConstructor: {
3218 bool is_factory = function.IsFactory(); 2464 bool is_factory = function.IsFactory();
3219 if (is_factory) { 2465 if (is_factory) {
3220 Procedure* procedure = Procedure::Cast(node_); 2466 Procedure* procedure = Procedure::Cast(node_);
3221 FunctionNode* function = procedure->function(); 2467 FunctionNode* function = procedure->function();
3222 ActiveFunctionScope active_function_scope(&active_class_, function);
3223 return BuildGraphOfFunction(function, NULL); 2468 return BuildGraphOfFunction(function, NULL);
3224 } else { 2469 } else {
3225 Constructor* constructor = Constructor::Cast(node_); 2470 Constructor* constructor = Constructor::Cast(node_);
3226 FunctionNode* function = constructor->function(); 2471 FunctionNode* function = constructor->function();
3227 ActiveFunctionScope active_function_scope(&active_class_, function);
3228 return BuildGraphOfFunction(function, constructor); 2472 return BuildGraphOfFunction(function, constructor);
3229 } 2473 }
3230 } 2474 }
3231 case RawFunction::kImplicitGetter: 2475 case RawFunction::kImplicitGetter:
3232 case RawFunction::kImplicitStaticFinalGetter: 2476 case RawFunction::kImplicitStaticFinalGetter:
3233 case RawFunction::kImplicitSetter: { 2477 case RawFunction::kImplicitSetter: {
3234 Field* field = Field::Cast(node_); 2478 Field* field = Field::Cast(node_);
3235 return IsStaticInitializer(function, Z) 2479 return IsStaticInitializer(function, Z)
3236 ? BuildGraphOfStaticFieldInitializer(field) 2480 ? BuildGraphOfStaticFieldInitializer(field)
3237 : BuildGraphOfFieldAccessor(field, scopes_->setter_value); 2481 : BuildGraphOfFieldAccessor(field, scopes_->setter_value);
(...skipping 3577 matching lines...) Expand 10 before | Expand all | Expand 10 after
6815 thread->clear_sticky_error(); 6059 thread->clear_sticky_error();
6816 return error.raw(); 6060 return error.raw();
6817 } 6061 }
6818 } 6062 }
6819 6063
6820 6064
6821 } // namespace kernel 6065 } // namespace kernel
6822 } // namespace dart 6066 } // namespace dart
6823 6067
6824 #endif // !defined(DART_PRECOMPILED_RUNTIME) 6068 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698