| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/v8.h" | 5 #include "src/v8.h" | 
| 6 | 6 | 
| 7 #include "src/scopes.h" | 7 #include "src/scopes.h" | 
| 8 | 8 | 
| 9 #include "src/accessors.h" | 9 #include "src/accessors.h" | 
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 27 VariableMap::VariableMap(Zone* zone) | 27 VariableMap::VariableMap(Zone* zone) | 
| 28     : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), | 28     : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), | 
| 29       zone_(zone) {} | 29       zone_(zone) {} | 
| 30 VariableMap::~VariableMap() {} | 30 VariableMap::~VariableMap() {} | 
| 31 | 31 | 
| 32 | 32 | 
| 33 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, | 33 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, | 
| 34                                VariableMode mode, bool is_valid_lhs, | 34                                VariableMode mode, bool is_valid_lhs, | 
| 35                                Variable::Kind kind, | 35                                Variable::Kind kind, | 
| 36                                InitializationFlag initialization_flag, | 36                                InitializationFlag initialization_flag, | 
|  | 37                                int position, | 
| 37                                MaybeAssignedFlag maybe_assigned_flag) { | 38                                MaybeAssignedFlag maybe_assigned_flag) { | 
| 38   // AstRawStrings are unambiguous, i.e., the same string is always represented | 39   // AstRawStrings are unambiguous, i.e., the same string is always represented | 
| 39   // by the same AstRawString*. | 40   // by the same AstRawString*. | 
| 40   // FIXME(marja): fix the type of Lookup. | 41   // FIXME(marja): fix the type of Lookup. | 
| 41   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 42   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 
| 42                                  true, ZoneAllocationPolicy(zone())); | 43                                  true, ZoneAllocationPolicy(zone())); | 
| 43   if (p->value == NULL) { | 44   if (p->value == NULL) { | 
| 44     // The variable has not been declared yet -> insert it. | 45     // The variable has not been declared yet -> insert it. | 
| 45     DCHECK(p->key == name); | 46     DCHECK(p->key == name); | 
| 46     p->value = new (zone()) Variable(scope, name, mode, is_valid_lhs, kind, | 47     Variable* variable = | 
| 47                                      initialization_flag, maybe_assigned_flag); | 48         new (zone()) Variable(scope, name, mode, is_valid_lhs, kind, | 
|  | 49                               initialization_flag, maybe_assigned_flag); | 
|  | 50     variable->set_initializer_position(position); | 
|  | 51     p->value = variable; | 
| 48   } | 52   } | 
| 49   return reinterpret_cast<Variable*>(p->value); | 53   return reinterpret_cast<Variable*>(p->value); | 
| 50 } | 54 } | 
| 51 | 55 | 
| 52 | 56 | 
| 53 Variable* VariableMap::Lookup(const AstRawString* name) { | 57 Variable* VariableMap::Lookup(const AstRawString* name) { | 
| 54   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 58   Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash(), | 
| 55                                  false, ZoneAllocationPolicy(NULL)); | 59                                  false, ZoneAllocationPolicy(NULL)); | 
| 56   if (p != NULL) { | 60   if (p != NULL) { | 
| 57     DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); | 61     DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); | 
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 256   // Traverse the scope tree up to the first unresolved scope or the global | 260   // Traverse the scope tree up to the first unresolved scope or the global | 
| 257   // scope and start scope resolution and variable allocation from that scope. | 261   // scope and start scope resolution and variable allocation from that scope. | 
| 258   while (!top->is_script_scope() && | 262   while (!top->is_script_scope() && | 
| 259          !top->outer_scope()->already_resolved()) { | 263          !top->outer_scope()->already_resolved()) { | 
| 260     top = top->outer_scope(); | 264     top = top->outer_scope(); | 
| 261   } | 265   } | 
| 262 | 266 | 
| 263   // Allocate the variables. | 267   // Allocate the variables. | 
| 264   { | 268   { | 
| 265     AstNodeFactory ast_node_factory(info->ast_value_factory()); | 269     AstNodeFactory ast_node_factory(info->ast_value_factory()); | 
| 266     if (!top->AllocateVariables(info, &ast_node_factory)) return false; | 270     if (!top->AllocateVariables(info, &ast_node_factory)) { | 
|  | 271       DCHECK(top->pending_error_handler_.has_pending_error()); | 
|  | 272       top->pending_error_handler_.ThrowPendingError(info->isolate(), | 
|  | 273                                                     info->script()); | 
|  | 274       return false; | 
|  | 275     } | 
| 267   } | 276   } | 
| 268 | 277 | 
| 269 #ifdef DEBUG | 278 #ifdef DEBUG | 
| 270   if (info->isolate()->bootstrapper()->IsActive() | 279   if (info->isolate()->bootstrapper()->IsActive() | 
| 271           ? FLAG_print_builtin_scopes | 280           ? FLAG_print_builtin_scopes | 
| 272           : FLAG_print_scopes) { | 281           : FLAG_print_scopes) { | 
| 273     scope->Print(); | 282     scope->Print(); | 
| 274   } | 283   } | 
| 275 #endif | 284 #endif | 
| 276 | 285 | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 395 | 404 | 
| 396     mode = DYNAMIC; | 405     mode = DYNAMIC; | 
| 397     location = Variable::LOOKUP; | 406     location = Variable::LOOKUP; | 
| 398     init_flag = kCreatedInitialized; | 407     init_flag = kCreatedInitialized; | 
| 399     // Be conservative and flag parameters as maybe assigned. Better information | 408     // Be conservative and flag parameters as maybe assigned. Better information | 
| 400     // would require ScopeInfo to serialize the maybe_assigned bit also for | 409     // would require ScopeInfo to serialize the maybe_assigned bit also for | 
| 401     // parameters. | 410     // parameters. | 
| 402     maybe_assigned_flag = kMaybeAssigned; | 411     maybe_assigned_flag = kMaybeAssigned; | 
| 403   } | 412   } | 
| 404 | 413 | 
| 405   Variable* var = variables_.Declare(this, name, mode, true, Variable::NORMAL, | 414   Variable* var = | 
| 406                                      init_flag, maybe_assigned_flag); | 415       variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 
|  | 416                          RelocInfo::kNoPosition, maybe_assigned_flag); | 
| 407   var->AllocateTo(location, index); | 417   var->AllocateTo(location, index); | 
| 408   return var; | 418   return var; | 
| 409 } | 419 } | 
| 410 | 420 | 
| 411 | 421 | 
| 412 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 422 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 
| 413                                    AstNodeFactory* factory) { | 423                                    AstNodeFactory* factory) { | 
| 414   if (function_ != NULL && function_->proxy()->raw_name() == name) { | 424   if (function_ != NULL && function_->proxy()->raw_name() == name) { | 
| 415     return function_->proxy()->var(); | 425     return function_->proxy()->var(); | 
| 416   } else if (!scope_info_.is_null()) { | 426   } else if (!scope_info_.is_null()) { | 
| 417     // If we are backed by a scope info, try to lookup the variable there. | 427     // If we are backed by a scope info, try to lookup the variable there. | 
| 418     VariableMode mode; | 428     VariableMode mode; | 
| 419     int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 429     int index = scope_info_->FunctionContextSlotIndex(*(name->string()), &mode); | 
| 420     if (index < 0) return NULL; | 430     if (index < 0) return NULL; | 
| 421     Variable* var = new(zone()) Variable( | 431     Variable* var = | 
| 422         this, name, mode, true /* is valid LHS */, | 432         new (zone()) Variable(this, name, mode, true /* is valid LHS */, | 
| 423         Variable::NORMAL, kCreatedInitialized); | 433                               Variable::NORMAL, kCreatedInitialized); | 
| 424     VariableProxy* proxy = factory->NewVariableProxy(var); | 434     VariableProxy* proxy = factory->NewVariableProxy(var); | 
| 425     VariableDeclaration* declaration = factory->NewVariableDeclaration( | 435     VariableDeclaration* declaration = factory->NewVariableDeclaration( | 
| 426         proxy, mode, this, RelocInfo::kNoPosition); | 436         proxy, mode, this, RelocInfo::kNoPosition); | 
| 427     DeclareFunctionVar(declaration); | 437     DeclareFunctionVar(declaration); | 
| 428     var->AllocateTo(Variable::CONTEXT, index); | 438     var->AllocateTo(Variable::CONTEXT, index); | 
| 429     return var; | 439     return var; | 
| 430   } else { | 440   } else { | 
| 431     return NULL; | 441     return NULL; | 
| 432   } | 442   } | 
| 433 } | 443 } | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 454     DCHECK_NULL(rest_parameter_); | 464     DCHECK_NULL(rest_parameter_); | 
| 455     rest_parameter_ = var; | 465     rest_parameter_ = var; | 
| 456     rest_index_ = num_parameters(); | 466     rest_index_ = num_parameters(); | 
| 457   } | 467   } | 
| 458   params_.Add(var, zone()); | 468   params_.Add(var, zone()); | 
| 459   return var; | 469   return var; | 
| 460 } | 470 } | 
| 461 | 471 | 
| 462 | 472 | 
| 463 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 473 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 
| 464                               InitializationFlag init_flag, | 474                               InitializationFlag init_flag, int position, | 
|  | 475                               bool is_function, | 
| 465                               MaybeAssignedFlag maybe_assigned_flag) { | 476                               MaybeAssignedFlag maybe_assigned_flag) { | 
| 466   DCHECK(!already_resolved()); | 477   DCHECK(!already_resolved()); | 
| 467   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are | 478   // This function handles VAR, LET, and CONST modes.  DYNAMIC variables are | 
| 468   // introduces during variable allocation, INTERNAL variables are allocated | 479   // introduces during variable allocation, INTERNAL variables are allocated | 
| 469   // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 480   // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 
| 470   DCHECK(IsDeclaredVariableMode(mode)); | 481   DCHECK(IsDeclaredVariableMode(mode)); | 
| 471   ++num_var_or_const_; | 482   ++num_var_or_const_; | 
| 472   return variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag, | 483   return variables_.Declare(this, name, mode, true, | 
| 473                             maybe_assigned_flag); | 484                             is_function ? Variable::FUNCTION : Variable::NORMAL, | 
|  | 485                             init_flag, position, maybe_assigned_flag); | 
| 474 } | 486 } | 
| 475 | 487 | 
| 476 | 488 | 
| 477 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 489 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 
| 478   DCHECK(is_script_scope()); | 490   DCHECK(is_script_scope()); | 
| 479   return variables_.Declare(this, | 491   return variables_.Declare(this, | 
| 480                             name, | 492                             name, | 
| 481                             DYNAMIC_GLOBAL, | 493                             DYNAMIC_GLOBAL, | 
| 482                             true, | 494                             true, | 
| 483                             Variable::NORMAL, | 495                             Variable::NORMAL, | 
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 761     int end_pos = scope->end_position(); | 773     int end_pos = scope->end_position(); | 
| 762     DCHECK(beg_pos >= 0 && end_pos >= 0); | 774     DCHECK(beg_pos >= 0 && end_pos >= 0); | 
| 763     if (beg_pos <= position && position < end_pos) { | 775     if (beg_pos <= position && position < end_pos) { | 
| 764       scope->GetNestedScopeChain(isolate, chain, position); | 776       scope->GetNestedScopeChain(isolate, chain, position); | 
| 765       return; | 777       return; | 
| 766     } | 778     } | 
| 767   } | 779   } | 
| 768 } | 780 } | 
| 769 | 781 | 
| 770 | 782 | 
|  | 783 void Scope::ReportMessage(int start_position, int end_position, | 
|  | 784                           const char* message, const AstRawString* arg) { | 
|  | 785   // Propagate the error to the topmost scope targeted by this scope analysis | 
|  | 786   // phase. | 
|  | 787   Scope* top = this; | 
|  | 788   while (!top->is_script_scope() && !top->outer_scope()->already_resolved()) { | 
|  | 789     top = top->outer_scope(); | 
|  | 790   } | 
|  | 791 | 
|  | 792   top->pending_error_handler_.ReportMessageAt(start_position, end_position, | 
|  | 793                                               message, arg, kReferenceError); | 
|  | 794 } | 
|  | 795 | 
|  | 796 | 
| 771 #ifdef DEBUG | 797 #ifdef DEBUG | 
| 772 static const char* Header(ScopeType scope_type) { | 798 static const char* Header(ScopeType scope_type) { | 
| 773   switch (scope_type) { | 799   switch (scope_type) { | 
| 774     case EVAL_SCOPE: return "eval"; | 800     case EVAL_SCOPE: return "eval"; | 
| 775     case FUNCTION_SCOPE: return "function"; | 801     case FUNCTION_SCOPE: return "function"; | 
| 776     case MODULE_SCOPE: return "module"; | 802     case MODULE_SCOPE: return "module"; | 
| 777     case SCRIPT_SCOPE: return "global"; | 803     case SCRIPT_SCOPE: return "global"; | 
| 778     case CATCH_SCOPE: return "catch"; | 804     case CATCH_SCOPE: return "catch"; | 
| 779     case BLOCK_SCOPE: return "block"; | 805     case BLOCK_SCOPE: return "block"; | 
| 780     case WITH_SCOPE: return "with"; | 806     case WITH_SCOPE: return "with"; | 
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1043   // If the proxy is already resolved there's nothing to do | 1069   // If the proxy is already resolved there's nothing to do | 
| 1044   // (functions and consts may be resolved by the parser). | 1070   // (functions and consts may be resolved by the parser). | 
| 1045   if (proxy->is_resolved()) return true; | 1071   if (proxy->is_resolved()) return true; | 
| 1046 | 1072 | 
| 1047   // Otherwise, try to resolve the variable. | 1073   // Otherwise, try to resolve the variable. | 
| 1048   BindingKind binding_kind; | 1074   BindingKind binding_kind; | 
| 1049   Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 1075   Variable* var = LookupRecursive(proxy, &binding_kind, factory); | 
| 1050   switch (binding_kind) { | 1076   switch (binding_kind) { | 
| 1051     case BOUND: | 1077     case BOUND: | 
| 1052       // We found a variable binding. | 1078       // We found a variable binding. | 
|  | 1079       if (is_strong(language_mode())) { | 
|  | 1080         // Check for declaration-after use (for variables) in strong mode. Note | 
|  | 1081         // that we can only do this in the case where we have seen the | 
|  | 1082         // declaration. And we always allow referencing functions (for now). | 
|  | 1083 | 
|  | 1084         // If both the use and the declaration are inside an eval scope | 
|  | 1085         // (possibly indirectly), or one of them is, we need to check whether | 
|  | 1086         // they are inside the same eval scope or different | 
|  | 1087         // ones. TODO(marja,rossberg): Detect errors across different evals | 
|  | 1088         // (depends on the future of eval in strong mode). | 
|  | 1089         const Scope* eval_for_use = NearestOuterEvalScope(); | 
|  | 1090         const Scope* eval_for_declaration = | 
|  | 1091             var->scope()->NearestOuterEvalScope(); | 
|  | 1092 | 
|  | 1093         if (proxy->position() != RelocInfo::kNoPosition && | 
|  | 1094             proxy->position() < var->initializer_position() && | 
|  | 1095             !var->is_function() && eval_for_use == eval_for_declaration) { | 
|  | 1096           DCHECK(proxy->end_position() != RelocInfo::kNoPosition); | 
|  | 1097           ReportMessage(proxy->position(), proxy->end_position(), | 
|  | 1098                         "strong_use_before_declaration", proxy->raw_name()); | 
|  | 1099           return false; | 
|  | 1100         } | 
|  | 1101       } | 
| 1053       break; | 1102       break; | 
| 1054 | 1103 | 
| 1055     case BOUND_EVAL_SHADOWED: | 1104     case BOUND_EVAL_SHADOWED: | 
| 1056       // We either found a variable binding that might be shadowed by eval  or | 1105       // We either found a variable binding that might be shadowed by eval  or | 
| 1057       // gave up on it (e.g. by encountering a local with the same in the outer | 1106       // gave up on it (e.g. by encountering a local with the same in the outer | 
| 1058       // scope which was not promoted to a context, this can happen if we use | 1107       // scope which was not promoted to a context, this can happen if we use | 
| 1059       // debugger to evaluate arbitrary expressions at a break point). | 1108       // debugger to evaluate arbitrary expressions at a break point). | 
| 1060       if (var->IsGlobalObjectProperty()) { | 1109       if (var->IsGlobalObjectProperty()) { | 
| 1061         var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 1110         var = NonLocal(proxy->raw_name(), DYNAMIC_GLOBAL); | 
| 1062       } else if (var->is_dynamic()) { | 1111       } else if (var->is_dynamic()) { | 
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1381 } | 1430 } | 
| 1382 | 1431 | 
| 1383 | 1432 | 
| 1384 int Scope::ContextLocalCount() const { | 1433 int Scope::ContextLocalCount() const { | 
| 1385   if (num_heap_slots() == 0) return 0; | 1434   if (num_heap_slots() == 0) return 0; | 
| 1386   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1435   return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 
| 1387       (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1436       (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 
| 1388 } | 1437 } | 
| 1389 | 1438 | 
| 1390 } }  // namespace v8::internal | 1439 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|