| OLD | NEW | 
|     1 // Copyright 2011 the V8 project authors. All rights reserved. |     1 // Copyright 2011 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 689 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   700 } |   700 } | 
|   701  |   701  | 
|   702  |   702  | 
|   703 static void PrintVar(int indent, Variable* var) { |   703 static void PrintVar(int indent, Variable* var) { | 
|   704   if (var->is_used() || !var->IsUnallocated()) { |   704   if (var->is_used() || !var->IsUnallocated()) { | 
|   705     Indent(indent, Variable::Mode2String(var->mode())); |   705     Indent(indent, Variable::Mode2String(var->mode())); | 
|   706     PrintF(" "); |   706     PrintF(" "); | 
|   707     PrintName(var->name()); |   707     PrintName(var->name()); | 
|   708     PrintF(";  // "); |   708     PrintF(";  // "); | 
|   709     PrintLocation(var); |   709     PrintLocation(var); | 
|   710     if (var->is_accessed_from_inner_scope()) { |   710     if (var->has_forced_context_allocation()) { | 
|   711       if (!var->IsUnallocated()) PrintF(", "); |   711       if (!var->IsUnallocated()) PrintF(", "); | 
|   712       PrintF("inner scope access"); |   712       PrintF("forced context allocation"); | 
|   713     } |   713     } | 
|   714     PrintF("\n"); |   714     PrintF("\n"); | 
|   715   } |   715   } | 
|   716 } |   716 } | 
|   717  |   717  | 
|   718  |   718  | 
|   719 static void PrintMap(int indent, VariableMap* map) { |   719 static void PrintMap(int indent, VariableMap* map) { | 
|   720   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { |   720   for (VariableMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) { | 
|   721     Variable* var = reinterpret_cast<Variable*>(p->value); |   721     Variable* var = reinterpret_cast<Variable*>(p->value); | 
|   722     PrintVar(indent, var); |   722     PrintVar(indent, var); | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   841   // This lookup corresponds to a lookup in the "intermediate" scope sitting |   841   // This lookup corresponds to a lookup in the "intermediate" scope sitting | 
|   842   // between this scope and the outer scope. (ECMA-262, 3rd., requires that |   842   // between this scope and the outer scope. (ECMA-262, 3rd., requires that | 
|   843   // the name of named function literal is kept in an intermediate scope |   843   // the name of named function literal is kept in an intermediate scope | 
|   844   // in between this scope and the next outer scope.) |   844   // in between this scope and the next outer scope.) | 
|   845   *binding_kind = UNBOUND; |   845   *binding_kind = UNBOUND; | 
|   846   if (function_ != NULL && function_->name().is_identical_to(name)) { |   846   if (function_ != NULL && function_->name().is_identical_to(name)) { | 
|   847     var = function_->var(); |   847     var = function_->var(); | 
|   848     *binding_kind = BOUND; |   848     *binding_kind = BOUND; | 
|   849   } else if (outer_scope_ != NULL) { |   849   } else if (outer_scope_ != NULL) { | 
|   850     var = outer_scope_->LookupRecursive(name, context, binding_kind); |   850     var = outer_scope_->LookupRecursive(name, context, binding_kind); | 
|   851     if (*binding_kind == BOUND) var->MarkAsAccessedFromInnerScope(); |   851     if (*binding_kind == BOUND && (is_function_scope() || is_with_scope())) { | 
 |   852       var->ForceContextAllocation(); | 
 |   853     } | 
|   852   } |   854   } | 
|   853  |   855  | 
|   854   if (is_with_scope()) { |   856   if (is_with_scope()) { | 
|   855     // The current scope is a with scope, so the variable binding can not be |   857     // The current scope is a with scope, so the variable binding can not be | 
|   856     // statically resolved. However, note that it was necessary to do a lookup |   858     // statically resolved. However, note that it was necessary to do a lookup | 
|   857     // in the outer scope anyway, because if a binding exists in an outer scope, |   859     // in the outer scope anyway, because if a binding exists in an outer scope, | 
|   858     // the associated variable has to be marked as potentially being accessed |   860     // the associated variable has to be marked as potentially being accessed | 
|   859     // from inside of an inner with scope (the property may not be in the 'with' |   861     // from inside of an inner with scope (the property may not be in the 'with' | 
|   860     // object). |   862     // object). | 
|   861     *binding_kind = DYNAMIC_LOOKUP; |   863     *binding_kind = DYNAMIC_LOOKUP; | 
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   973  |   975  | 
|   974   return scope_calls_eval_ || inner_scope_calls_eval_; |   976   return scope_calls_eval_ || inner_scope_calls_eval_; | 
|   975 } |   977 } | 
|   976  |   978  | 
|   977  |   979  | 
|   978 bool Scope::MustAllocate(Variable* var) { |   980 bool Scope::MustAllocate(Variable* var) { | 
|   979   // Give var a read/write use if there is a chance it might be accessed |   981   // Give var a read/write use if there is a chance it might be accessed | 
|   980   // via an eval() call.  This is only possible if the variable has a |   982   // via an eval() call.  This is only possible if the variable has a | 
|   981   // visible name. |   983   // visible name. | 
|   982   if ((var->is_this() || var->name()->length() > 0) && |   984   if ((var->is_this() || var->name()->length() > 0) && | 
|   983       (var->is_accessed_from_inner_scope() || |   985       (var->has_forced_context_allocation() || | 
|   984        scope_calls_eval_ || |   986        scope_calls_eval_ || | 
|   985        inner_scope_calls_eval_ || |   987        inner_scope_calls_eval_ || | 
|   986        scope_contains_with_ || |   988        scope_contains_with_ || | 
|   987        is_catch_scope() || |   989        is_catch_scope() || | 
|   988        is_block_scope())) { |   990        is_block_scope())) { | 
|   989     var->set_is_used(true); |   991     var->set_is_used(true); | 
|   990   } |   992   } | 
|   991   // Global variables do not need to be allocated. |   993   // Global variables do not need to be allocated. | 
|   992   return !var->is_global() && var->is_used(); |   994   return !var->is_global() && var->is_used(); | 
|   993 } |   995 } | 
|   994  |   996  | 
|   995  |   997  | 
|   996 bool Scope::MustAllocateInContext(Variable* var) { |   998 bool Scope::MustAllocateInContext(Variable* var) { | 
|   997   // If var is accessed from an inner scope, or if there is a possibility |   999   // If var is accessed from an inner scope, or if there is a possibility | 
|   998   // that it might be accessed from the current or an inner scope (through |  1000   // that it might be accessed from the current or an inner scope (through | 
|   999   // an eval() call or a runtime with lookup), it must be allocated in the |  1001   // an eval() call or a runtime with lookup), it must be allocated in the | 
|  1000   // context. |  1002   // context. | 
|  1001   // |  1003   // | 
|  1002   // Exceptions: temporary variables are never allocated in a context; |  1004   // Exceptions: temporary variables are never allocated in a context; | 
|  1003   // catch-bound variables are always allocated in a context. |  1005   // catch-bound variables are always allocated in a context. | 
|  1004   if (var->mode() == TEMPORARY) return false; |  1006   if (var->mode() == TEMPORARY) return false; | 
|  1005   if (is_catch_scope() || is_block_scope()) return true; |  1007   if (is_catch_scope() || is_block_scope()) return true; | 
|  1006   return var->is_accessed_from_inner_scope() || |  1008   return var->has_forced_context_allocation() || | 
|  1007       scope_calls_eval_ || |  1009       scope_calls_eval_ || | 
|  1008       inner_scope_calls_eval_ || |  1010       inner_scope_calls_eval_ || | 
|  1009       scope_contains_with_ || |  1011       scope_contains_with_ || | 
|  1010       var->is_global(); |  1012       var->is_global(); | 
|  1011 } |  1013 } | 
|  1012  |  1014  | 
|  1013  |  1015  | 
|  1014 bool Scope::HasArgumentsParameter() { |  1016 bool Scope::HasArgumentsParameter() { | 
|  1015   for (int i = 0; i < params_.length(); i++) { |  1017   for (int i = 0; i < params_.length(); i++) { | 
|  1016     if (params_[i]->name().is_identical_to( |  1018     if (params_[i]->name().is_identical_to( | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1060   } |  1062   } | 
|  1061  |  1063  | 
|  1062   // The same parameter may occur multiple times in the parameters_ list. |  1064   // The same parameter may occur multiple times in the parameters_ list. | 
|  1063   // If it does, and if it is not copied into the context object, it must |  1065   // If it does, and if it is not copied into the context object, it must | 
|  1064   // receive the highest parameter index for that parameter; thus iteration |  1066   // receive the highest parameter index for that parameter; thus iteration | 
|  1065   // order is relevant! |  1067   // order is relevant! | 
|  1066   for (int i = params_.length() - 1; i >= 0; --i) { |  1068   for (int i = params_.length() - 1; i >= 0; --i) { | 
|  1067     Variable* var = params_[i]; |  1069     Variable* var = params_[i]; | 
|  1068     ASSERT(var->scope() == this); |  1070     ASSERT(var->scope() == this); | 
|  1069     if (uses_nonstrict_arguments) { |  1071     if (uses_nonstrict_arguments) { | 
|  1070       // Give the parameter a use from an inner scope, to force allocation |  1072       // Force context allocation of the parameter. | 
|  1071       // to the context. |  1073       var->ForceContextAllocation(); | 
|  1072       var->MarkAsAccessedFromInnerScope(); |  | 
|  1073     } |  1074     } | 
|  1074  |  1075  | 
|  1075     if (MustAllocate(var)) { |  1076     if (MustAllocate(var)) { | 
|  1076       if (MustAllocateInContext(var)) { |  1077       if (MustAllocateInContext(var)) { | 
|  1077         ASSERT(var->IsUnallocated() || var->IsContextSlot()); |  1078         ASSERT(var->IsUnallocated() || var->IsContextSlot()); | 
|  1078         if (var->IsUnallocated()) { |  1079         if (var->IsUnallocated()) { | 
|  1079           AllocateHeapSlot(var); |  1080           AllocateHeapSlot(var); | 
|  1080         } |  1081         } | 
|  1081       } else { |  1082       } else { | 
|  1082         ASSERT(var->IsUnallocated() || var->IsParameter()); |  1083         ASSERT(var->IsUnallocated() || var->IsParameter()); | 
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1160   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |  1161   if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 
|  1161       !must_have_local_context) { |  1162       !must_have_local_context) { | 
|  1162     num_heap_slots_ = 0; |  1163     num_heap_slots_ = 0; | 
|  1163   } |  1164   } | 
|  1164  |  1165  | 
|  1165   // Allocation done. |  1166   // Allocation done. | 
|  1166   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |  1167   ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 
|  1167 } |  1168 } | 
|  1168  |  1169  | 
|  1169 } }  // namespace v8::internal |  1170 } }  // namespace v8::internal | 
| OLD | NEW |