OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 // ---------------------------------------------------------------------------- | 105 // ---------------------------------------------------------------------------- |
106 // Implementation of Scope | 106 // Implementation of Scope |
107 | 107 |
108 | 108 |
109 // Dummy constructor | 109 // Dummy constructor |
110 Scope::Scope() | 110 Scope::Scope() |
111 : inner_scopes_(0), | 111 : inner_scopes_(0), |
112 locals_(false), | 112 locals_(false), |
113 temps_(0), | 113 temps_(0), |
114 params_(0), | 114 params_(0), |
115 nonlocals_(0), | 115 dynamics_(false), |
| 116 dynamics_local_(false), |
| 117 dynamics_global_(false), |
116 unresolved_(0), | 118 unresolved_(0), |
117 decls_(0) { | 119 decls_(0) { |
118 } | 120 } |
119 | 121 |
120 | 122 |
121 Scope::Scope(Scope* outer_scope, Type type) | 123 Scope::Scope(Scope* outer_scope, Type type) |
122 : outer_scope_(outer_scope), | 124 : outer_scope_(outer_scope), |
123 inner_scopes_(4), | 125 inner_scopes_(4), |
124 type_(type), | 126 type_(type), |
125 scope_name_(Factory::empty_symbol()), | 127 scope_name_(Factory::empty_symbol()), |
126 locals_(), | 128 locals_(), |
127 temps_(4), | 129 temps_(4), |
128 params_(4), | 130 params_(4), |
129 nonlocals_(4), | |
130 unresolved_(16), | 131 unresolved_(16), |
131 decls_(4), | 132 decls_(4), |
132 receiver_(NULL), | 133 receiver_(NULL), |
133 function_(NULL), | 134 function_(NULL), |
134 arguments_(NULL), | 135 arguments_(NULL), |
135 arguments_shadow_(NULL), | 136 arguments_shadow_(NULL), |
136 illegal_redecl_(NULL), | 137 illegal_redecl_(NULL), |
137 scope_inside_with_(false), | 138 scope_inside_with_(false), |
138 scope_contains_with_(false), | 139 scope_contains_with_(false), |
139 scope_calls_eval_(false), | 140 scope_calls_eval_(false), |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, "); | 399 if (var->is_accessed_from_inner_scope()) PrintF("inner scope access, "); |
399 PrintF("var "); | 400 PrintF("var "); |
400 var->var_uses()->Print(); | 401 var->var_uses()->Print(); |
401 PrintF(", obj "); | 402 PrintF(", obj "); |
402 var->obj_uses()->Print(); | 403 var->obj_uses()->Print(); |
403 PrintF("\n"); | 404 PrintF("\n"); |
404 } | 405 } |
405 } | 406 } |
406 | 407 |
407 | 408 |
| 409 static void PrintMap(PrettyPrinter* printer, int indent, LocalsMap* map) { |
| 410 for (LocalsMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |
| 411 Variable* var = reinterpret_cast<Variable*>(p->value); |
| 412 PrintVar(printer, indent, var); |
| 413 } |
| 414 } |
| 415 |
| 416 |
408 void Scope::Print(int n) { | 417 void Scope::Print(int n) { |
409 int n0 = (n > 0 ? n : 0); | 418 int n0 = (n > 0 ? n : 0); |
410 int n1 = n0 + 2; // indentation | 419 int n1 = n0 + 2; // indentation |
411 | 420 |
412 // Print header. | 421 // Print header. |
413 Indent(n0, Header(type_)); | 422 Indent(n0, Header(type_)); |
414 if (scope_name_->length() > 0) { | 423 if (scope_name_->length() > 0) { |
415 PrintF(" "); | 424 PrintF(" "); |
416 PrintName(scope_name_); | 425 PrintName(scope_name_); |
417 } | 426 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 if (function_ != NULL) { | 467 if (function_ != NULL) { |
459 PrintVar(&printer, n1, function_); | 468 PrintVar(&printer, n1, function_); |
460 } | 469 } |
461 | 470 |
462 Indent(n1, "// temporary vars\n"); | 471 Indent(n1, "// temporary vars\n"); |
463 for (int i = 0; i < temps_.length(); i++) { | 472 for (int i = 0; i < temps_.length(); i++) { |
464 PrintVar(&printer, n1, temps_[i]); | 473 PrintVar(&printer, n1, temps_[i]); |
465 } | 474 } |
466 | 475 |
467 Indent(n1, "// local vars\n"); | 476 Indent(n1, "// local vars\n"); |
468 for (LocalsMap::Entry* p = locals_.Start(); p != NULL; p = locals_.Next(p)) { | 477 PrintMap(&printer, n1, &locals_); |
469 Variable* var = reinterpret_cast<Variable*>(p->value); | |
470 PrintVar(&printer, n1, var); | |
471 } | |
472 | 478 |
473 Indent(n1, "// nonlocal vars\n"); | 479 Indent(n1, "// dynamic vars\n"); |
474 for (int i = 0; i < nonlocals_.length(); i++) | 480 PrintMap(&printer, n1, &dynamics_); |
475 PrintVar(&printer, n1, nonlocals_[i]); | 481 PrintMap(&printer, n1, &dynamics_local_); |
| 482 PrintMap(&printer, n1, &dynamics_global_); |
476 | 483 |
477 // Print inner scopes (disable by providing negative n). | 484 // Print inner scopes (disable by providing negative n). |
478 if (n >= 0) { | 485 if (n >= 0) { |
479 for (int i = 0; i < inner_scopes_.length(); i++) { | 486 for (int i = 0; i < inner_scopes_.length(); i++) { |
480 PrintF("\n"); | 487 PrintF("\n"); |
481 inner_scopes_[i]->Print(n1); | 488 inner_scopes_[i]->Print(n1); |
482 } | 489 } |
483 } | 490 } |
484 | 491 |
485 Indent(n0, "}\n"); | 492 Indent(n0, "}\n"); |
486 } | 493 } |
487 #endif // DEBUG | 494 #endif // DEBUG |
488 | 495 |
489 | 496 |
490 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 497 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
491 // Space optimization: reuse existing non-local with the same name | 498 // Space optimization: reuse existing non-local with the same name |
492 // and mode. | 499 // and mode. |
493 for (int i = 0; i < nonlocals_.length(); i++) { | 500 LocalsMap* map = NULL; |
494 Variable* var = nonlocals_[i]; | 501 switch (mode) { |
495 if (var->name().is_identical_to(name) && var->mode() == mode) { | 502 case Variable::DYNAMIC: |
496 return var; | 503 map = &dynamics_; |
497 } | 504 break; |
| 505 case Variable::DYNAMIC_LOCAL: |
| 506 map = &dynamics_local_; |
| 507 break; |
| 508 case Variable::DYNAMIC_GLOBAL: |
| 509 map = &dynamics_global_; |
| 510 break; |
| 511 default: |
| 512 UNREACHABLE(); |
| 513 break; |
498 } | 514 } |
499 | 515 Variable* var = map->Lookup(name); |
500 // Otherwise create a new non-local and add it to the list. | 516 if (var == NULL) { |
501 Variable* var = new Variable(NULL, name, mode, true, false); | 517 // Declare a new non-local. |
502 nonlocals_.Add(var); | 518 var = map->Declare(NULL, name, mode, true, false); |
503 | 519 // Allocate it by giving it a dynamic lookup. |
504 // Allocate it by giving it a dynamic lookup. | 520 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); |
505 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 521 } |
506 | |
507 return var; | 522 return var; |
508 } | 523 } |
509 | 524 |
510 | 525 |
511 // Lookup a variable starting with this scope. The result is either | 526 // Lookup a variable starting with this scope. The result is either |
512 // the statically resolved (local!) variable belonging to an outer scope, | 527 // the statically resolved (local!) variable belonging to an outer scope, |
513 // or NULL. It may be NULL because a) we couldn't find a variable, or b) | 528 // or NULL. It may be NULL because a) we couldn't find a variable, or b) |
514 // because the variable is just a guess (and may be shadowed by another | 529 // because the variable is just a guess (and may be shadowed by another |
515 // variable that is introduced dynamically via an 'eval' call or a 'with' | 530 // variable that is introduced dynamically via an 'eval' call or a 'with' |
516 // statement). | 531 // statement). |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 // a local or outer eval() call, or an outer 'with' statement), | 625 // a local or outer eval() call, or an outer 'with' statement), |
611 // or we don't know about the outer scope (because we are | 626 // or we don't know about the outer scope (because we are |
612 // in an eval scope). | 627 // in an eval scope). |
613 if (is_global_scope() || | 628 if (is_global_scope() || |
614 !(scope_inside_with_ || outer_scope_is_eval_scope_ || | 629 !(scope_inside_with_ || outer_scope_is_eval_scope_ || |
615 scope_calls_eval_ || outer_scope_calls_eval_)) { | 630 scope_calls_eval_ || outer_scope_calls_eval_)) { |
616 // We must have a global variable. | 631 // We must have a global variable. |
617 ASSERT(global_scope != NULL); | 632 ASSERT(global_scope != NULL); |
618 var = new Variable(global_scope, proxy->name(), | 633 var = new Variable(global_scope, proxy->name(), |
619 Variable::DYNAMIC, true, false); | 634 Variable::DYNAMIC, true, false); |
620 // Ideally we simply rewrite these variables into property | |
621 // accesses. Unfortunately, we cannot do this here at the | |
622 // moment because then we can't differentiate between | |
623 // global variable ('x') and global property ('this.x') access. | |
624 // If 'x' doesn't exist, the former leads to an error, while the | |
625 // latter returns undefined. Sigh... | |
626 // var->rewrite_ = new Property(new Literal(env_->global()), | |
627 // new Literal(proxy->name())); | |
628 | 635 |
629 } else if (scope_inside_with_) { | 636 } else if (scope_inside_with_) { |
630 // If we are inside a with statement we give up and look up | 637 // If we are inside a with statement we give up and look up |
631 // the variable at runtime. | 638 // the variable at runtime. |
632 var = NonLocal(proxy->name(), Variable::DYNAMIC); | 639 var = NonLocal(proxy->name(), Variable::DYNAMIC); |
633 | 640 |
634 } else if (invalidated_local != NULL) { | 641 } else if (invalidated_local != NULL) { |
635 // No with statements are involved and we found a local | 642 // No with statements are involved and we found a local |
636 // variable that might be shadowed by eval introduced | 643 // variable that might be shadowed by eval introduced |
637 // variables. | 644 // variables. |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 944 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
938 !must_have_local_context) { | 945 !must_have_local_context) { |
939 num_heap_slots_ = 0; | 946 num_heap_slots_ = 0; |
940 } | 947 } |
941 | 948 |
942 // Allocation done. | 949 // Allocation done. |
943 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 950 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
944 } | 951 } |
945 | 952 |
946 } } // namespace v8::internal | 953 } } // namespace v8::internal |
OLD | NEW |