OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS 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 | 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 "vm/scopes.h" | 5 #include "vm/scopes.h" |
6 | 6 |
7 #include "vm/object.h" | 7 #include "vm/object.h" |
8 #include "vm/stack_frame.h" | 8 #include "vm/stack_frame.h" |
9 #include "vm/symbols.h" | 9 #include "vm/symbols.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_FLAG(bool, | 13 DEFINE_FLAG(bool, |
14 share_enclosing_context, | 14 share_enclosing_context, |
15 true, | 15 true, |
16 "Allocate captured variables in the existing context of an " | 16 "Allocate captured variables in the existing context of an " |
17 "enclosing scope (up to innermost loop) and spare the allocation " | 17 "enclosing scope (up to innermost loop) and spare the allocation " |
18 "of a local context."); | 18 "of a local context."); |
19 | 19 |
20 int SourceLabel::FunctionLevel() const { | 20 int SourceLabel::FunctionLevel() const { |
21 ASSERT(owner() != NULL); | 21 ASSERT(owner() != NULL); |
22 return owner()->function_level(); | 22 return owner()->function_level(); |
23 } | 23 } |
24 | 24 |
25 | |
26 LocalScope::LocalScope(LocalScope* parent, int function_level, int loop_level) | 25 LocalScope::LocalScope(LocalScope* parent, int function_level, int loop_level) |
27 : parent_(parent), | 26 : parent_(parent), |
28 child_(NULL), | 27 child_(NULL), |
29 sibling_(NULL), | 28 sibling_(NULL), |
30 function_level_(function_level), | 29 function_level_(function_level), |
31 loop_level_(loop_level), | 30 loop_level_(loop_level), |
32 context_level_(LocalScope::kUnitializedContextLevel), | 31 context_level_(LocalScope::kUnitializedContextLevel), |
33 num_context_variables_(0), | 32 num_context_variables_(0), |
34 begin_token_pos_(TokenPosition::kNoSourcePos), | 33 begin_token_pos_(TokenPosition::kNoSourcePos), |
35 end_token_pos_(TokenPosition::kNoSourcePos), | 34 end_token_pos_(TokenPosition::kNoSourcePos), |
36 variables_(), | 35 variables_(), |
37 labels_(), | 36 labels_(), |
38 referenced_() { | 37 referenced_() { |
39 // Hook this node into the children of the parent, unless the parent has a | 38 // Hook this node into the children of the parent, unless the parent has a |
40 // different function_level, since the local scope of a nested function can | 39 // different function_level, since the local scope of a nested function can |
41 // be discarded after it has been parsed. | 40 // be discarded after it has been parsed. |
42 if ((parent != NULL) && (parent->function_level() == function_level)) { | 41 if ((parent != NULL) && (parent->function_level() == function_level)) { |
43 sibling_ = parent->child_; | 42 sibling_ = parent->child_; |
44 parent->child_ = this; | 43 parent->child_ = this; |
45 } | 44 } |
46 } | 45 } |
47 | 46 |
48 | |
49 bool LocalScope::IsNestedWithin(LocalScope* scope) const { | 47 bool LocalScope::IsNestedWithin(LocalScope* scope) const { |
50 const LocalScope* current_scope = this; | 48 const LocalScope* current_scope = this; |
51 while (current_scope != NULL) { | 49 while (current_scope != NULL) { |
52 if (current_scope == scope) { | 50 if (current_scope == scope) { |
53 return true; | 51 return true; |
54 } | 52 } |
55 current_scope = current_scope->parent(); | 53 current_scope = current_scope->parent(); |
56 } | 54 } |
57 return false; | 55 return false; |
58 } | 56 } |
59 | 57 |
60 | |
61 bool LocalScope::AddVariable(LocalVariable* variable) { | 58 bool LocalScope::AddVariable(LocalVariable* variable) { |
62 ASSERT(variable != NULL); | 59 ASSERT(variable != NULL); |
63 if (LocalLookupVariable(variable->name()) != NULL) { | 60 if (LocalLookupVariable(variable->name()) != NULL) { |
64 return false; | 61 return false; |
65 } | 62 } |
66 variables_.Add(variable); | 63 variables_.Add(variable); |
67 if (variable->owner() == NULL) { | 64 if (variable->owner() == NULL) { |
68 // Variables must be added to their owner scope first. Subsequent calls | 65 // Variables must be added to their owner scope first. Subsequent calls |
69 // to 'add' treat the variable as an alias. | 66 // to 'add' treat the variable as an alias. |
70 variable->set_owner(this); | 67 variable->set_owner(this); |
71 } | 68 } |
72 return true; | 69 return true; |
73 } | 70 } |
74 | 71 |
75 | |
76 bool LocalScope::InsertParameterAt(intptr_t pos, LocalVariable* parameter) { | 72 bool LocalScope::InsertParameterAt(intptr_t pos, LocalVariable* parameter) { |
77 ASSERT(parameter != NULL); | 73 ASSERT(parameter != NULL); |
78 if (LocalLookupVariable(parameter->name()) != NULL) { | 74 if (LocalLookupVariable(parameter->name()) != NULL) { |
79 return false; | 75 return false; |
80 } | 76 } |
81 variables_.InsertAt(pos, parameter); | 77 variables_.InsertAt(pos, parameter); |
82 // InsertParameterAt is not used to add aliases of parameters. | 78 // InsertParameterAt is not used to add aliases of parameters. |
83 ASSERT(parameter->owner() == NULL); | 79 ASSERT(parameter->owner() == NULL); |
84 parameter->set_owner(this); | 80 parameter->set_owner(this); |
85 return true; | 81 return true; |
86 } | 82 } |
87 | 83 |
88 | |
89 bool LocalScope::AddLabel(SourceLabel* label) { | 84 bool LocalScope::AddLabel(SourceLabel* label) { |
90 if (LocalLookupLabel(label->name()) != NULL) { | 85 if (LocalLookupLabel(label->name()) != NULL) { |
91 return false; | 86 return false; |
92 } | 87 } |
93 labels_.Add(label); | 88 labels_.Add(label); |
94 if (label->owner() == NULL) { | 89 if (label->owner() == NULL) { |
95 // Labels must be added to their owner scope first. Subsequent calls | 90 // Labels must be added to their owner scope first. Subsequent calls |
96 // to 'add' treat the label as an alias. | 91 // to 'add' treat the label as an alias. |
97 label->set_owner(this); | 92 label->set_owner(this); |
98 } | 93 } |
99 return true; | 94 return true; |
100 } | 95 } |
101 | 96 |
102 | |
103 void LocalScope::MoveLabel(SourceLabel* label) { | 97 void LocalScope::MoveLabel(SourceLabel* label) { |
104 ASSERT(LocalLookupLabel(label->name()) == NULL); | 98 ASSERT(LocalLookupLabel(label->name()) == NULL); |
105 ASSERT(label->kind() == SourceLabel::kForward); | 99 ASSERT(label->kind() == SourceLabel::kForward); |
106 labels_.Add(label); | 100 labels_.Add(label); |
107 label->set_owner(this); | 101 label->set_owner(this); |
108 } | 102 } |
109 | 103 |
110 | |
111 NameReference* LocalScope::FindReference(const String& name) const { | 104 NameReference* LocalScope::FindReference(const String& name) const { |
112 ASSERT(name.IsSymbol()); | 105 ASSERT(name.IsSymbol()); |
113 intptr_t num_references = referenced_.length(); | 106 intptr_t num_references = referenced_.length(); |
114 for (intptr_t i = 0; i < num_references; i++) { | 107 for (intptr_t i = 0; i < num_references; i++) { |
115 if (name.raw() == referenced_[i]->name().raw()) { | 108 if (name.raw() == referenced_[i]->name().raw()) { |
116 return referenced_[i]; | 109 return referenced_[i]; |
117 } | 110 } |
118 } | 111 } |
119 return NULL; | 112 return NULL; |
120 } | 113 } |
121 | 114 |
122 | |
123 void LocalScope::AddReferencedName(TokenPosition token_pos, | 115 void LocalScope::AddReferencedName(TokenPosition token_pos, |
124 const String& name) { | 116 const String& name) { |
125 if (LocalLookupVariable(name) != NULL) { | 117 if (LocalLookupVariable(name) != NULL) { |
126 return; | 118 return; |
127 } | 119 } |
128 NameReference* ref = FindReference(name); | 120 NameReference* ref = FindReference(name); |
129 if (ref != NULL) { | 121 if (ref != NULL) { |
130 ref->set_token_pos(token_pos); | 122 ref->set_token_pos(token_pos); |
131 return; | 123 return; |
132 } | 124 } |
133 ref = new NameReference(token_pos, name); | 125 ref = new NameReference(token_pos, name); |
134 referenced_.Add(ref); | 126 referenced_.Add(ref); |
135 // Add name reference in innermost enclosing scopes that do not | 127 // Add name reference in innermost enclosing scopes that do not |
136 // define a local variable with this name. | 128 // define a local variable with this name. |
137 LocalScope* scope = this->parent(); | 129 LocalScope* scope = this->parent(); |
138 while (scope != NULL && (scope->LocalLookupVariable(name) == NULL)) { | 130 while (scope != NULL && (scope->LocalLookupVariable(name) == NULL)) { |
139 scope->referenced_.Add(ref); | 131 scope->referenced_.Add(ref); |
140 scope = scope->parent(); | 132 scope = scope->parent(); |
141 } | 133 } |
142 } | 134 } |
143 | 135 |
144 | |
145 TokenPosition LocalScope::PreviousReferencePos(const String& name) const { | 136 TokenPosition LocalScope::PreviousReferencePos(const String& name) const { |
146 NameReference* ref = FindReference(name); | 137 NameReference* ref = FindReference(name); |
147 if (ref != NULL) { | 138 if (ref != NULL) { |
148 return ref->token_pos(); | 139 return ref->token_pos(); |
149 } | 140 } |
150 return TokenPosition::kNoSource; | 141 return TokenPosition::kNoSource; |
151 } | 142 } |
152 | 143 |
153 | |
154 void LocalScope::AllocateContextVariable(LocalVariable* variable, | 144 void LocalScope::AllocateContextVariable(LocalVariable* variable, |
155 LocalScope** context_owner) { | 145 LocalScope** context_owner) { |
156 ASSERT(variable->is_captured()); | 146 ASSERT(variable->is_captured()); |
157 ASSERT(variable->owner() == this); | 147 ASSERT(variable->owner() == this); |
158 // The context level in the owner scope of a captured variable indicates at | 148 // The context level in the owner scope of a captured variable indicates at |
159 // code generation time how far to walk up the context chain in order to | 149 // code generation time how far to walk up the context chain in order to |
160 // access the variable from the current context level. | 150 // access the variable from the current context level. |
161 if ((*context_owner) == NULL) { | 151 if ((*context_owner) == NULL) { |
162 ASSERT(num_context_variables_ == 0); | 152 ASSERT(num_context_variables_ == 0); |
163 // This scope becomes the current context owner. | 153 // This scope becomes the current context owner. |
(...skipping 20 matching lines...) Expand all Loading... |
184 if (!HasContextLevel()) { | 174 if (!HasContextLevel()) { |
185 ASSERT(variable->owner() != *context_owner); | 175 ASSERT(variable->owner() != *context_owner); |
186 set_context_level((*context_owner)->context_level()); | 176 set_context_level((*context_owner)->context_level()); |
187 } else { | 177 } else { |
188 ASSERT(context_level() == (*context_owner)->context_level()); | 178 ASSERT(context_level() == (*context_owner)->context_level()); |
189 } | 179 } |
190 } | 180 } |
191 variable->set_index((*context_owner)->num_context_variables_++); | 181 variable->set_index((*context_owner)->num_context_variables_++); |
192 } | 182 } |
193 | 183 |
194 | |
195 int LocalScope::AllocateVariables(int first_parameter_index, | 184 int LocalScope::AllocateVariables(int first_parameter_index, |
196 int num_parameters, | 185 int num_parameters, |
197 int first_frame_index, | 186 int first_frame_index, |
198 LocalScope* context_owner, | 187 LocalScope* context_owner, |
199 bool* found_captured_variables) { | 188 bool* found_captured_variables) { |
200 // We should not allocate variables of nested functions while compiling an | 189 // We should not allocate variables of nested functions while compiling an |
201 // enclosing function. | 190 // enclosing function. |
202 ASSERT(function_level() == 0); | 191 ASSERT(function_level() == 0); |
203 ASSERT(num_parameters >= 0); | 192 ASSERT(num_parameters >= 0); |
204 // Parameters must be listed first and must all appear in the top scope. | 193 // Parameters must be listed first and must all appear in the top scope. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 dummy_parameter_index, num_parameters_in_child, frame_index, | 248 dummy_parameter_index, num_parameters_in_child, frame_index, |
260 context_owner, found_captured_variables); | 249 context_owner, found_captured_variables); |
261 if (child_frame_index < min_frame_index) { | 250 if (child_frame_index < min_frame_index) { |
262 min_frame_index = child_frame_index; | 251 min_frame_index = child_frame_index; |
263 } | 252 } |
264 child = child->sibling(); | 253 child = child->sibling(); |
265 } | 254 } |
266 return min_frame_index; | 255 return min_frame_index; |
267 } | 256 } |
268 | 257 |
269 | |
270 // The parser creates internal variables that start with ":" | 258 // The parser creates internal variables that start with ":" |
271 static bool IsFilteredIdentifier(const String& str) { | 259 static bool IsFilteredIdentifier(const String& str) { |
272 ASSERT(str.Length() > 0); | 260 ASSERT(str.Length() > 0); |
273 if (str.raw() == Symbols::AsyncOperation().raw()) { | 261 if (str.raw() == Symbols::AsyncOperation().raw()) { |
274 // Keep :async_op for asynchronous debugging. | 262 // Keep :async_op for asynchronous debugging. |
275 return false; | 263 return false; |
276 } | 264 } |
277 if (str.raw() == Symbols::AsyncCompleter().raw()) { | 265 if (str.raw() == Symbols::AsyncCompleter().raw()) { |
278 // Keep :async_completer for asynchronous debugging. | 266 // Keep :async_completer for asynchronous debugging. |
279 return false; | 267 return false; |
280 } | 268 } |
281 if (str.raw() == Symbols::ControllerStream().raw()) { | 269 if (str.raw() == Symbols::ControllerStream().raw()) { |
282 // Keep :controller_stream for asynchronous debugging. | 270 // Keep :controller_stream for asynchronous debugging. |
283 return false; | 271 return false; |
284 } | 272 } |
285 if (str.raw() == Symbols::AwaitJumpVar().raw()) { | 273 if (str.raw() == Symbols::AwaitJumpVar().raw()) { |
286 // Keep :await_jump_var for asynchronous debugging. | 274 // Keep :await_jump_var for asynchronous debugging. |
287 return false; | 275 return false; |
288 } | 276 } |
289 if (str.raw() == Symbols::AsyncStackTraceVar().raw()) { | 277 if (str.raw() == Symbols::AsyncStackTraceVar().raw()) { |
290 // Keep :async_stack_trace for asynchronous debugging. | 278 // Keep :async_stack_trace for asynchronous debugging. |
291 return false; | 279 return false; |
292 } | 280 } |
293 return str.CharAt(0) == ':'; | 281 return str.CharAt(0) == ':'; |
294 } | 282 } |
295 | 283 |
296 | |
297 RawLocalVarDescriptors* LocalScope::GetVarDescriptors( | 284 RawLocalVarDescriptors* LocalScope::GetVarDescriptors( |
298 const Function& func, | 285 const Function& func, |
299 ZoneGrowableArray<intptr_t>* context_level_array) { | 286 ZoneGrowableArray<intptr_t>* context_level_array) { |
300 GrowableArray<VarDesc> vars(8); | 287 GrowableArray<VarDesc> vars(8); |
301 | 288 |
302 // Record deopt-id -> context-level mappings, using ranges of deopt-ids with | 289 // Record deopt-id -> context-level mappings, using ranges of deopt-ids with |
303 // the same context-level. [context_level_array] contains (deopt_id, | 290 // the same context-level. [context_level_array] contains (deopt_id, |
304 // context_level) tuples. | 291 // context_level) tuples. |
305 for (intptr_t start = 0; start < context_level_array->length();) { | 292 for (intptr_t start = 0; start < context_level_array->length();) { |
306 intptr_t start_deopt_id = (*context_level_array)[start]; | 293 intptr_t start_deopt_id = (*context_level_array)[start]; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 return Object::empty_var_descriptors().raw(); | 351 return Object::empty_var_descriptors().raw(); |
365 } | 352 } |
366 const LocalVarDescriptors& var_desc = | 353 const LocalVarDescriptors& var_desc = |
367 LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars.length())); | 354 LocalVarDescriptors::Handle(LocalVarDescriptors::New(vars.length())); |
368 for (int i = 0; i < vars.length(); i++) { | 355 for (int i = 0; i < vars.length(); i++) { |
369 var_desc.SetVar(i, *(vars[i].name), &vars[i].info); | 356 var_desc.SetVar(i, *(vars[i].name), &vars[i].info); |
370 } | 357 } |
371 return var_desc.raw(); | 358 return var_desc.raw(); |
372 } | 359 } |
373 | 360 |
374 | |
375 // Add visible variables that are declared in this scope to vars, then | 361 // Add visible variables that are declared in this scope to vars, then |
376 // collect visible variables of children, followed by siblings. | 362 // collect visible variables of children, followed by siblings. |
377 void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars, | 363 void LocalScope::CollectLocalVariables(GrowableArray<VarDesc>* vars, |
378 int16_t* scope_id) { | 364 int16_t* scope_id) { |
379 (*scope_id)++; | 365 (*scope_id)++; |
380 for (int i = 0; i < this->variables_.length(); i++) { | 366 for (int i = 0; i < this->variables_.length(); i++) { |
381 LocalVariable* var = variables_[i]; | 367 LocalVariable* var = variables_[i]; |
382 if ((var->owner() == this) && !var->is_invisible()) { | 368 if ((var->owner() == this) && !var->is_invisible()) { |
383 if (var->name().raw() == Symbols::CurrentContextVar().raw()) { | 369 if (var->name().raw() == Symbols::CurrentContextVar().raw()) { |
384 // This is the local variable in which the function saves its | 370 // This is the local variable in which the function saves its |
(...skipping 28 matching lines...) Expand all Loading... |
413 } | 399 } |
414 } | 400 } |
415 } | 401 } |
416 LocalScope* child = this->child(); | 402 LocalScope* child = this->child(); |
417 while (child != NULL) { | 403 while (child != NULL) { |
418 child->CollectLocalVariables(vars, scope_id); | 404 child->CollectLocalVariables(vars, scope_id); |
419 child = child->sibling(); | 405 child = child->sibling(); |
420 } | 406 } |
421 } | 407 } |
422 | 408 |
423 | |
424 SourceLabel* LocalScope::LocalLookupLabel(const String& name) const { | 409 SourceLabel* LocalScope::LocalLookupLabel(const String& name) const { |
425 ASSERT(name.IsSymbol()); | 410 ASSERT(name.IsSymbol()); |
426 for (intptr_t i = 0; i < labels_.length(); i++) { | 411 for (intptr_t i = 0; i < labels_.length(); i++) { |
427 SourceLabel* label = labels_[i]; | 412 SourceLabel* label = labels_[i]; |
428 if (label->name().raw() == name.raw()) { | 413 if (label->name().raw() == name.raw()) { |
429 return label; | 414 return label; |
430 } | 415 } |
431 } | 416 } |
432 return NULL; | 417 return NULL; |
433 } | 418 } |
434 | 419 |
435 | |
436 LocalVariable* LocalScope::LocalLookupVariable(const String& name) const { | 420 LocalVariable* LocalScope::LocalLookupVariable(const String& name) const { |
437 ASSERT(name.IsSymbol()); | 421 ASSERT(name.IsSymbol()); |
438 for (intptr_t i = 0; i < variables_.length(); i++) { | 422 for (intptr_t i = 0; i < variables_.length(); i++) { |
439 LocalVariable* var = variables_[i]; | 423 LocalVariable* var = variables_[i]; |
440 ASSERT(var->name().IsSymbol()); | 424 ASSERT(var->name().IsSymbol()); |
441 if (var->name().raw() == name.raw()) { | 425 if (var->name().raw() == name.raw()) { |
442 return var; | 426 return var; |
443 } | 427 } |
444 } | 428 } |
445 return NULL; | 429 return NULL; |
446 } | 430 } |
447 | 431 |
448 | |
449 LocalVariable* LocalScope::LookupVariable(const String& name, bool test_only) { | 432 LocalVariable* LocalScope::LookupVariable(const String& name, bool test_only) { |
450 LocalScope* current_scope = this; | 433 LocalScope* current_scope = this; |
451 while (current_scope != NULL) { | 434 while (current_scope != NULL) { |
452 LocalVariable* var = current_scope->LocalLookupVariable(name); | 435 LocalVariable* var = current_scope->LocalLookupVariable(name); |
453 // If testing only, return the variable even if invisible. | 436 // If testing only, return the variable even if invisible. |
454 if ((var != NULL) && (!var->is_invisible_ || test_only)) { | 437 if ((var != NULL) && (!var->is_invisible_ || test_only)) { |
455 if (!test_only && (var->owner()->function_level() != function_level())) { | 438 if (!test_only && (var->owner()->function_level() != function_level())) { |
456 CaptureVariable(var); | 439 CaptureVariable(var); |
457 } | 440 } |
458 return var; | 441 return var; |
459 } | 442 } |
460 current_scope = current_scope->parent(); | 443 current_scope = current_scope->parent(); |
461 } | 444 } |
462 return NULL; | 445 return NULL; |
463 } | 446 } |
464 | 447 |
465 | |
466 void LocalScope::CaptureVariable(LocalVariable* variable) { | 448 void LocalScope::CaptureVariable(LocalVariable* variable) { |
467 ASSERT(variable != NULL); | 449 ASSERT(variable != NULL); |
468 // The variable must exist in an enclosing scope, not necessarily in this one. | 450 // The variable must exist in an enclosing scope, not necessarily in this one. |
469 variable->set_is_captured(); | 451 variable->set_is_captured(); |
470 const int variable_function_level = variable->owner()->function_level(); | 452 const int variable_function_level = variable->owner()->function_level(); |
471 LocalScope* scope = this; | 453 LocalScope* scope = this; |
472 while (scope->function_level() != variable_function_level) { | 454 while (scope->function_level() != variable_function_level) { |
473 // Insert an alias of the variable in the top scope of each function | 455 // Insert an alias of the variable in the top scope of each function |
474 // level so that the variable is found in the context. | 456 // level so that the variable is found in the context. |
475 LocalScope* parent_scope = scope->parent(); | 457 LocalScope* parent_scope = scope->parent(); |
476 while ((parent_scope != NULL) && | 458 while ((parent_scope != NULL) && |
477 (parent_scope->function_level() == scope->function_level())) { | 459 (parent_scope->function_level() == scope->function_level())) { |
478 scope = parent_scope; | 460 scope = parent_scope; |
479 parent_scope = scope->parent(); | 461 parent_scope = scope->parent(); |
480 } | 462 } |
481 // An alias may already have been added in this scope, and in that case, | 463 // An alias may already have been added in this scope, and in that case, |
482 // in parent scopes as needed. If so, we are done. | 464 // in parent scopes as needed. If so, we are done. |
483 if (!scope->AddVariable(variable)) { | 465 if (!scope->AddVariable(variable)) { |
484 return; | 466 return; |
485 } | 467 } |
486 ASSERT(variable->owner() != scope); // Item is an alias. | 468 ASSERT(variable->owner() != scope); // Item is an alias. |
487 scope = parent_scope; | 469 scope = parent_scope; |
488 } | 470 } |
489 } | 471 } |
490 | 472 |
491 | |
492 SourceLabel* LocalScope::LookupLabel(const String& name) { | 473 SourceLabel* LocalScope::LookupLabel(const String& name) { |
493 LocalScope* current_scope = this; | 474 LocalScope* current_scope = this; |
494 while (current_scope != NULL) { | 475 while (current_scope != NULL) { |
495 SourceLabel* label = current_scope->LocalLookupLabel(name); | 476 SourceLabel* label = current_scope->LocalLookupLabel(name); |
496 if (label != NULL) { | 477 if (label != NULL) { |
497 return label; | 478 return label; |
498 } | 479 } |
499 current_scope = current_scope->parent(); | 480 current_scope = current_scope->parent(); |
500 } | 481 } |
501 return NULL; | 482 return NULL; |
502 } | 483 } |
503 | 484 |
504 | |
505 SourceLabel* LocalScope::LookupInnermostLabel(Token::Kind jump_kind) { | 485 SourceLabel* LocalScope::LookupInnermostLabel(Token::Kind jump_kind) { |
506 ASSERT((jump_kind == Token::kCONTINUE) || (jump_kind == Token::kBREAK)); | 486 ASSERT((jump_kind == Token::kCONTINUE) || (jump_kind == Token::kBREAK)); |
507 LocalScope* current_scope = this; | 487 LocalScope* current_scope = this; |
508 while (current_scope != NULL) { | 488 while (current_scope != NULL) { |
509 for (intptr_t i = 0; i < current_scope->labels_.length(); i++) { | 489 for (intptr_t i = 0; i < current_scope->labels_.length(); i++) { |
510 SourceLabel* label = current_scope->labels_[i]; | 490 SourceLabel* label = current_scope->labels_[i]; |
511 if ((label->kind() == SourceLabel::kWhile) || | 491 if ((label->kind() == SourceLabel::kWhile) || |
512 (label->kind() == SourceLabel::kFor) || | 492 (label->kind() == SourceLabel::kFor) || |
513 (label->kind() == SourceLabel::kDoWhile) || | 493 (label->kind() == SourceLabel::kDoWhile) || |
514 ((jump_kind == Token::kBREAK) && | 494 ((jump_kind == Token::kBREAK) && |
515 (label->kind() == SourceLabel::kSwitch))) { | 495 (label->kind() == SourceLabel::kSwitch))) { |
516 return label; | 496 return label; |
517 } | 497 } |
518 } | 498 } |
519 current_scope = current_scope->parent(); | 499 current_scope = current_scope->parent(); |
520 } | 500 } |
521 return NULL; | 501 return NULL; |
522 } | 502 } |
523 | 503 |
524 | |
525 LocalScope* LocalScope::LookupSwitchScope() { | 504 LocalScope* LocalScope::LookupSwitchScope() { |
526 LocalScope* current_scope = this->parent(); | 505 LocalScope* current_scope = this->parent(); |
527 int this_level = this->function_level(); | 506 int this_level = this->function_level(); |
528 while (current_scope != NULL && | 507 while (current_scope != NULL && |
529 current_scope->function_level() == this_level) { | 508 current_scope->function_level() == this_level) { |
530 for (int i = 0; i < current_scope->labels_.length(); i++) { | 509 for (int i = 0; i < current_scope->labels_.length(); i++) { |
531 SourceLabel* label = current_scope->labels_[i]; | 510 SourceLabel* label = current_scope->labels_[i]; |
532 if (label->kind() == SourceLabel::kSwitch) { | 511 if (label->kind() == SourceLabel::kSwitch) { |
533 // This scope contains a label that is bound to a switch statement, | 512 // This scope contains a label that is bound to a switch statement, |
534 // so it is the scope of the a statement body. | 513 // so it is the scope of the a statement body. |
535 return current_scope; | 514 return current_scope; |
536 } | 515 } |
537 } | 516 } |
538 current_scope = current_scope->parent(); | 517 current_scope = current_scope->parent(); |
539 } | 518 } |
540 // We did not find a switch statement scope at the same function level. | 519 // We did not find a switch statement scope at the same function level. |
541 return NULL; | 520 return NULL; |
542 } | 521 } |
543 | 522 |
544 | |
545 SourceLabel* LocalScope::CheckUnresolvedLabels() { | 523 SourceLabel* LocalScope::CheckUnresolvedLabels() { |
546 for (int i = 0; i < this->labels_.length(); i++) { | 524 for (int i = 0; i < this->labels_.length(); i++) { |
547 SourceLabel* label = this->labels_[i]; | 525 SourceLabel* label = this->labels_[i]; |
548 if (label->kind() == SourceLabel::kForward) { | 526 if (label->kind() == SourceLabel::kForward) { |
549 LocalScope* outer_switch = LookupSwitchScope(); | 527 LocalScope* outer_switch = LookupSwitchScope(); |
550 if (outer_switch == NULL) { | 528 if (outer_switch == NULL) { |
551 return label; | 529 return label; |
552 } else { | 530 } else { |
553 outer_switch->MoveLabel(label); | 531 outer_switch->MoveLabel(label); |
554 } | 532 } |
555 } | 533 } |
556 } | 534 } |
557 return NULL; | 535 return NULL; |
558 } | 536 } |
559 | 537 |
560 | |
561 int LocalScope::NumCapturedVariables() const { | 538 int LocalScope::NumCapturedVariables() const { |
562 // It is not necessary to traverse parent scopes, since we are only interested | 539 // It is not necessary to traverse parent scopes, since we are only interested |
563 // in the captured variables referenced in this scope. If this scope is the | 540 // in the captured variables referenced in this scope. If this scope is the |
564 // top scope at function level 1 and it (or its children scopes) references a | 541 // top scope at function level 1 and it (or its children scopes) references a |
565 // captured variable declared in a parent scope at function level 0, it will | 542 // captured variable declared in a parent scope at function level 0, it will |
566 // contain an alias for that variable. | 543 // contain an alias for that variable. |
567 | 544 |
568 // Since code generation for nested functions is postponed until first | 545 // Since code generation for nested functions is postponed until first |
569 // invocation, the function level of the closure scope can only be 1. | 546 // invocation, the function level of the closure scope can only be 1. |
570 ASSERT(function_level() == 1); | 547 ASSERT(function_level() == 1); |
571 | 548 |
572 int num_captured = 0; | 549 int num_captured = 0; |
573 for (int i = 0; i < num_variables(); i++) { | 550 for (int i = 0; i < num_variables(); i++) { |
574 LocalVariable* variable = VariableAt(i); | 551 LocalVariable* variable = VariableAt(i); |
575 // Count the aliases of captured variables belonging to outer scopes. | 552 // Count the aliases of captured variables belonging to outer scopes. |
576 if (variable->owner()->function_level() != 1) { | 553 if (variable->owner()->function_level() != 1) { |
577 ASSERT(variable->is_captured()); | 554 ASSERT(variable->is_captured()); |
578 ASSERT(variable->owner()->function_level() == 0); | 555 ASSERT(variable->owner()->function_level() == 0); |
579 num_captured++; | 556 num_captured++; |
580 } | 557 } |
581 } | 558 } |
582 return num_captured; | 559 return num_captured; |
583 } | 560 } |
584 | 561 |
585 | |
586 RawContextScope* LocalScope::PreserveOuterScope( | 562 RawContextScope* LocalScope::PreserveOuterScope( |
587 int current_context_level) const { | 563 int current_context_level) const { |
588 // Since code generation for nested functions is postponed until first | 564 // Since code generation for nested functions is postponed until first |
589 // invocation, the function level of the closure scope can only be 1. | 565 // invocation, the function level of the closure scope can only be 1. |
590 ASSERT(function_level() == 1); | 566 ASSERT(function_level() == 1); |
591 | 567 |
592 // Count the number of referenced captured variables. | 568 // Count the number of referenced captured variables. |
593 intptr_t num_captured_vars = NumCapturedVariables(); | 569 intptr_t num_captured_vars = NumCapturedVariables(); |
594 | 570 |
595 // Create a ContextScope with space for num_captured_vars descriptors. | 571 // Create a ContextScope with space for num_captured_vars descriptors. |
(...skipping 25 matching lines...) Expand all Loading... |
621 int adjusted_context_level = | 597 int adjusted_context_level = |
622 variable->owner()->context_level() - current_context_level; | 598 variable->owner()->context_level() - current_context_level; |
623 context_scope.SetContextLevelAt(captured_idx, adjusted_context_level); | 599 context_scope.SetContextLevelAt(captured_idx, adjusted_context_level); |
624 captured_idx++; | 600 captured_idx++; |
625 } | 601 } |
626 } | 602 } |
627 ASSERT(context_scope.num_variables() == captured_idx); // Verify count. | 603 ASSERT(context_scope.num_variables() == captured_idx); // Verify count. |
628 return context_scope.raw(); | 604 return context_scope.raw(); |
629 } | 605 } |
630 | 606 |
631 | |
632 LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) { | 607 LocalScope* LocalScope::RestoreOuterScope(const ContextScope& context_scope) { |
633 // The function level of the outer scope is one less than the function level | 608 // The function level of the outer scope is one less than the function level |
634 // of the current function, which is 0. | 609 // of the current function, which is 0. |
635 LocalScope* outer_scope = new LocalScope(NULL, -1, 0); | 610 LocalScope* outer_scope = new LocalScope(NULL, -1, 0); |
636 // Add all variables as aliases to the outer scope. | 611 // Add all variables as aliases to the outer scope. |
637 for (int i = 0; i < context_scope.num_variables(); i++) { | 612 for (int i = 0; i < context_scope.num_variables(); i++) { |
638 LocalVariable* variable; | 613 LocalVariable* variable; |
639 if (context_scope.IsConstAt(i)) { | 614 if (context_scope.IsConstAt(i)) { |
640 variable = new LocalVariable(context_scope.DeclarationTokenIndexAt(i), | 615 variable = new LocalVariable(context_scope.DeclarationTokenIndexAt(i), |
641 context_scope.TokenIndexAt(i), | 616 context_scope.TokenIndexAt(i), |
(...skipping 18 matching lines...) Expand all Loading... |
660 // context level has already been assigned. | 635 // context level has already been assigned. |
661 LocalScope* owner_scope = new LocalScope(NULL, 0, 0); | 636 LocalScope* owner_scope = new LocalScope(NULL, 0, 0); |
662 owner_scope->set_context_level(context_scope.ContextLevelAt(i)); | 637 owner_scope->set_context_level(context_scope.ContextLevelAt(i)); |
663 owner_scope->AddVariable(variable); | 638 owner_scope->AddVariable(variable); |
664 outer_scope->AddVariable(variable); // As alias. | 639 outer_scope->AddVariable(variable); // As alias. |
665 ASSERT(variable->owner() == owner_scope); | 640 ASSERT(variable->owner() == owner_scope); |
666 } | 641 } |
667 return outer_scope; | 642 return outer_scope; |
668 } | 643 } |
669 | 644 |
670 | |
671 void LocalScope::CaptureLocalVariables(LocalScope* top_scope) { | 645 void LocalScope::CaptureLocalVariables(LocalScope* top_scope) { |
672 ASSERT(top_scope->function_level() == function_level()); | 646 ASSERT(top_scope->function_level() == function_level()); |
673 LocalScope* scope = this; | 647 LocalScope* scope = this; |
674 while (scope != top_scope->parent()) { | 648 while (scope != top_scope->parent()) { |
675 for (intptr_t i = 0; i < scope->num_variables(); i++) { | 649 for (intptr_t i = 0; i < scope->num_variables(); i++) { |
676 LocalVariable* variable = scope->VariableAt(i); | 650 LocalVariable* variable = scope->VariableAt(i); |
677 if (variable->is_forced_stack() || | 651 if (variable->is_forced_stack() || |
678 (variable->name().raw() == Symbols::StackTraceVar().raw()) || | 652 (variable->name().raw() == Symbols::StackTraceVar().raw()) || |
679 (variable->name().raw() == Symbols::ExceptionVar().raw()) || | 653 (variable->name().raw() == Symbols::ExceptionVar().raw()) || |
680 (variable->name().raw() == Symbols::SavedTryContextVar().raw())) { | 654 (variable->name().raw() == Symbols::SavedTryContextVar().raw())) { |
681 // Don't capture those variables because the VM expects them to be on | 655 // Don't capture those variables because the VM expects them to be on |
682 // the stack. | 656 // the stack. |
683 continue; | 657 continue; |
684 } | 658 } |
685 scope->CaptureVariable(variable); | 659 scope->CaptureVariable(variable); |
686 } | 660 } |
687 scope = scope->parent(); | 661 scope = scope->parent(); |
688 } | 662 } |
689 } | 663 } |
690 | 664 |
691 | |
692 RawContextScope* LocalScope::CreateImplicitClosureScope(const Function& func) { | 665 RawContextScope* LocalScope::CreateImplicitClosureScope(const Function& func) { |
693 static const intptr_t kNumCapturedVars = 1; | 666 static const intptr_t kNumCapturedVars = 1; |
694 | 667 |
695 // Create a ContextScope with space for kNumCapturedVars descriptors. | 668 // Create a ContextScope with space for kNumCapturedVars descriptors. |
696 const ContextScope& context_scope = | 669 const ContextScope& context_scope = |
697 ContextScope::Handle(ContextScope::New(kNumCapturedVars, true)); | 670 ContextScope::Handle(ContextScope::New(kNumCapturedVars, true)); |
698 | 671 |
699 // Create a descriptor for 'this' variable. | 672 // Create a descriptor for 'this' variable. |
700 context_scope.SetTokenIndexAt(0, func.token_pos()); | 673 context_scope.SetTokenIndexAt(0, func.token_pos()); |
701 context_scope.SetDeclarationTokenIndexAt(0, func.token_pos()); | 674 context_scope.SetDeclarationTokenIndexAt(0, func.token_pos()); |
702 context_scope.SetNameAt(0, Symbols::This()); | 675 context_scope.SetNameAt(0, Symbols::This()); |
703 context_scope.SetIsFinalAt(0, true); | 676 context_scope.SetIsFinalAt(0, true); |
704 context_scope.SetIsConstAt(0, false); | 677 context_scope.SetIsConstAt(0, false); |
705 const AbstractType& type = AbstractType::Handle(func.ParameterTypeAt(0)); | 678 const AbstractType& type = AbstractType::Handle(func.ParameterTypeAt(0)); |
706 context_scope.SetTypeAt(0, type); | 679 context_scope.SetTypeAt(0, type); |
707 context_scope.SetContextIndexAt(0, 0); | 680 context_scope.SetContextIndexAt(0, 0); |
708 context_scope.SetContextLevelAt(0, 0); | 681 context_scope.SetContextLevelAt(0, 0); |
709 ASSERT(context_scope.num_variables() == kNumCapturedVars); // Verify count. | 682 ASSERT(context_scope.num_variables() == kNumCapturedVars); // Verify count. |
710 return context_scope.raw(); | 683 return context_scope.raw(); |
711 } | 684 } |
712 | 685 |
713 | |
714 bool LocalVariable::Equals(const LocalVariable& other) const { | 686 bool LocalVariable::Equals(const LocalVariable& other) const { |
715 if (HasIndex() && other.HasIndex() && (index() == other.index())) { | 687 if (HasIndex() && other.HasIndex() && (index() == other.index())) { |
716 if (is_captured() == other.is_captured()) { | 688 if (is_captured() == other.is_captured()) { |
717 if (!is_captured()) { | 689 if (!is_captured()) { |
718 return true; | 690 return true; |
719 } | 691 } |
720 if (owner()->context_level() == other.owner()->context_level()) { | 692 if (owner()->context_level() == other.owner()->context_level()) { |
721 return true; | 693 return true; |
722 } | 694 } |
723 } | 695 } |
724 } | 696 } |
725 return false; | 697 return false; |
726 } | 698 } |
727 | 699 |
728 | |
729 int LocalVariable::BitIndexIn(intptr_t fixed_parameter_count) const { | 700 int LocalVariable::BitIndexIn(intptr_t fixed_parameter_count) const { |
730 ASSERT(!is_captured()); | 701 ASSERT(!is_captured()); |
731 // Parameters have positive indexes with the lowest index being | 702 // Parameters have positive indexes with the lowest index being |
732 // kParamEndSlotFromFp + 1. Locals and copied parameters have negative | 703 // kParamEndSlotFromFp + 1. Locals and copied parameters have negative |
733 // indexes with the lowest (closest to 0) index being kFirstLocalSlotFromFp. | 704 // indexes with the lowest (closest to 0) index being kFirstLocalSlotFromFp. |
734 if (index() > 0) { | 705 if (index() > 0) { |
735 // Shift non-negative indexes so that the lowest one is 0. | 706 // Shift non-negative indexes so that the lowest one is 0. |
736 return fixed_parameter_count - (index() - kParamEndSlotFromFp); | 707 return fixed_parameter_count - (index() - kParamEndSlotFromFp); |
737 } else { | 708 } else { |
738 // Shift negative indexes so that the lowest one is 0 (they are still | 709 // Shift negative indexes so that the lowest one is 0 (they are still |
739 // non-positive). | 710 // non-positive). |
740 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); | 711 return fixed_parameter_count - (index() - kFirstLocalSlotFromFp); |
741 } | 712 } |
742 } | 713 } |
743 | 714 |
744 | |
745 } // namespace dart | 715 } // namespace dart |
OLD | NEW |