| 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 LocalsMap::LocalsMap(bool gotta_love_static_overloading) : HashMap() {} | 74 LocalsMap::LocalsMap(bool gotta_love_static_overloading) : HashMap() {} |
| 75 | 75 |
| 76 LocalsMap::LocalsMap() : HashMap(Match, &LocalsMapAllocator, 8) {} | 76 LocalsMap::LocalsMap() : HashMap(Match, &LocalsMapAllocator, 8) {} |
| 77 LocalsMap::~LocalsMap() {} | 77 LocalsMap::~LocalsMap() {} |
| 78 | 78 |
| 79 | 79 |
| 80 Variable* LocalsMap::Declare(Scope* scope, | 80 Variable* LocalsMap::Declare(Scope* scope, |
| 81 Handle<String> name, | 81 Handle<String> name, |
| 82 Variable::Mode mode, | 82 Variable::Mode mode, |
| 83 bool is_valid_LHS, | 83 bool is_valid_LHS, |
| 84 bool is_this) { | 84 Variable::Kind kind) { |
| 85 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); | 85 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), true); |
| 86 if (p->value == NULL) { | 86 if (p->value == NULL) { |
| 87 // The variable has not been declared yet -> insert it. | 87 // The variable has not been declared yet -> insert it. |
| 88 ASSERT(p->key == name.location()); | 88 ASSERT(p->key == name.location()); |
| 89 p->value = new Variable(scope, name, mode, is_valid_LHS, is_this); | 89 p->value = new Variable(scope, name, mode, is_valid_LHS, kind); |
| 90 } | 90 } |
| 91 return reinterpret_cast<Variable*>(p->value); | 91 return reinterpret_cast<Variable*>(p->value); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 Variable* LocalsMap::Lookup(Handle<String> name) { | 95 Variable* LocalsMap::Lookup(Handle<String> name) { |
| 96 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); | 96 HashMap::Entry* p = HashMap::Lookup(name.location(), name->Hash(), false); |
| 97 if (p != NULL) { | 97 if (p != NULL) { |
| 98 ASSERT(*reinterpret_cast<String**>(p->key) == *name); | 98 ASSERT(*reinterpret_cast<String**>(p->key) == *name); |
| 99 ASSERT(p->value != NULL); | 99 ASSERT(p->value != NULL); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 | 162 |
| 163 // Declare convenience variables. | 163 // Declare convenience variables. |
| 164 // Declare and allocate receiver (even for the global scope, and even | 164 // Declare and allocate receiver (even for the global scope, and even |
| 165 // if naccesses_ == 0). | 165 // if naccesses_ == 0). |
| 166 // NOTE: When loading parameters in the global scope, we must take | 166 // NOTE: When loading parameters in the global scope, we must take |
| 167 // care not to access them as properties of the global object, but | 167 // care not to access them as properties of the global object, but |
| 168 // instead load them directly from the stack. Currently, the only | 168 // instead load them directly from the stack. Currently, the only |
| 169 // such parameter is 'this' which is passed on the stack when | 169 // such parameter is 'this' which is passed on the stack when |
| 170 // invoking scripts | 170 // invoking scripts |
| 171 { Variable* var = | 171 { Variable* var = |
| 172 locals_.Declare(this, Factory::this_symbol(), Variable::VAR, false, true); | 172 locals_.Declare(this, Factory::this_symbol(), Variable::VAR, |
| 173 false, Variable::THIS); |
| 173 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); | 174 var->rewrite_ = new Slot(var, Slot::PARAMETER, -1); |
| 174 receiver_ = new VariableProxy(Factory::this_symbol(), true, false); | 175 receiver_ = new VariableProxy(Factory::this_symbol(), true, false); |
| 175 receiver_->BindTo(var); | 176 receiver_->BindTo(var); |
| 176 } | 177 } |
| 177 | 178 |
| 178 if (is_function_scope()) { | 179 if (is_function_scope()) { |
| 179 // Declare 'arguments' variable which exists in all functions. | 180 // Declare 'arguments' variable which exists in all functions. |
| 180 // Note that it may never be accessed, in which case it won't | 181 // Note that it may never be accessed, in which case it won't |
| 181 // be allocated during variable allocation. | 182 // be allocated during variable allocation. |
| 182 Declare(Factory::arguments_symbol(), Variable::VAR); | 183 locals_.Declare(this, Factory::arguments_symbol(), Variable::VAR, |
| 184 true, Variable::ARGUMENTS); |
| 183 } | 185 } |
| 184 } | 186 } |
| 185 | 187 |
| 186 | 188 |
| 187 | 189 |
| 188 Variable* Scope::LookupLocal(Handle<String> name) { | 190 Variable* Scope::LookupLocal(Handle<String> name) { |
| 189 return locals_.Lookup(name); | 191 return locals_.Lookup(name); |
| 190 } | 192 } |
| 191 | 193 |
| 192 | 194 |
| 193 Variable* Scope::Lookup(Handle<String> name) { | 195 Variable* Scope::Lookup(Handle<String> name) { |
| 194 for (Scope* scope = this; | 196 for (Scope* scope = this; |
| 195 scope != NULL; | 197 scope != NULL; |
| 196 scope = scope->outer_scope()) { | 198 scope = scope->outer_scope()) { |
| 197 Variable* var = scope->LookupLocal(name); | 199 Variable* var = scope->LookupLocal(name); |
| 198 if (var != NULL) return var; | 200 if (var != NULL) return var; |
| 199 } | 201 } |
| 200 return NULL; | 202 return NULL; |
| 201 } | 203 } |
| 202 | 204 |
| 203 | 205 |
| 204 Variable* Scope::DeclareFunctionVar(Handle<String> name) { | 206 Variable* Scope::DeclareFunctionVar(Handle<String> name) { |
| 205 ASSERT(is_function_scope() && function_ == NULL); | 207 ASSERT(is_function_scope() && function_ == NULL); |
| 206 function_ = new Variable(this, name, Variable::CONST, true, false); | 208 function_ = new Variable(this, name, Variable::CONST, true, Variable::NORMAL); |
| 207 return function_; | 209 return function_; |
| 208 } | 210 } |
| 209 | 211 |
| 210 | 212 |
| 211 Variable* Scope::Declare(Handle<String> name, Variable::Mode mode) { | 213 Variable* Scope::Declare(Handle<String> name, Variable::Mode mode) { |
| 212 // DYNAMIC variables are introduces during variable allocation, | 214 // DYNAMIC variables are introduces during variable allocation, |
| 213 // INTERNAL variables are allocated explicitly, and TEMPORARY | 215 // INTERNAL variables are allocated explicitly, and TEMPORARY |
| 214 // variables are allocated via NewTemporary(). | 216 // variables are allocated via NewTemporary(). |
| 215 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 217 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 216 return locals_.Declare(this, name, mode, true, false); | 218 return locals_.Declare(this, name, mode, true, Variable::NORMAL); |
| 217 } | 219 } |
| 218 | 220 |
| 219 | 221 |
| 220 void Scope::AddParameter(Variable* var) { | 222 void Scope::AddParameter(Variable* var) { |
| 221 ASSERT(is_function_scope()); | 223 ASSERT(is_function_scope()); |
| 222 ASSERT(LookupLocal(var->name()) == var); | 224 ASSERT(LookupLocal(var->name()) == var); |
| 223 params_.Add(var); | 225 params_.Add(var); |
| 224 } | 226 } |
| 225 | 227 |
| 226 | 228 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 240 for (int i = unresolved_.length(); i-- > 0;) { | 242 for (int i = unresolved_.length(); i-- > 0;) { |
| 241 if (unresolved_[i] == var) { | 243 if (unresolved_[i] == var) { |
| 242 unresolved_.Remove(i); | 244 unresolved_.Remove(i); |
| 243 return; | 245 return; |
| 244 } | 246 } |
| 245 } | 247 } |
| 246 } | 248 } |
| 247 | 249 |
| 248 | 250 |
| 249 VariableProxy* Scope::NewTemporary(Handle<String> name) { | 251 VariableProxy* Scope::NewTemporary(Handle<String> name) { |
| 250 Variable* var = new Variable(this, name, Variable::TEMPORARY, true, false); | 252 Variable* var = new Variable(this, name, Variable::TEMPORARY, true, |
| 253 Variable::NORMAL); |
| 251 VariableProxy* tmp = new VariableProxy(name, false, false); | 254 VariableProxy* tmp = new VariableProxy(name, false, false); |
| 252 tmp->BindTo(var); | 255 tmp->BindTo(var); |
| 253 temps_.Add(var); | 256 temps_.Add(var); |
| 254 return tmp; | 257 return tmp; |
| 255 } | 258 } |
| 256 | 259 |
| 257 | 260 |
| 258 void Scope::AddDeclaration(Declaration* declaration) { | 261 void Scope::AddDeclaration(Declaration* declaration) { |
| 259 decls_.Add(declaration); | 262 decls_.Add(declaration); |
| 260 } | 263 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 } | 499 } |
| 497 #endif // DEBUG | 500 #endif // DEBUG |
| 498 | 501 |
| 499 | 502 |
| 500 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { | 503 Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) { |
| 501 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); | 504 if (dynamics_ == NULL) dynamics_ = new DynamicScopePart(); |
| 502 LocalsMap* map = dynamics_->GetMap(mode); | 505 LocalsMap* map = dynamics_->GetMap(mode); |
| 503 Variable* var = map->Lookup(name); | 506 Variable* var = map->Lookup(name); |
| 504 if (var == NULL) { | 507 if (var == NULL) { |
| 505 // Declare a new non-local. | 508 // Declare a new non-local. |
| 506 var = map->Declare(NULL, name, mode, true, false); | 509 var = map->Declare(NULL, name, mode, true, Variable::NORMAL); |
| 507 // Allocate it by giving it a dynamic lookup. | 510 // Allocate it by giving it a dynamic lookup. |
| 508 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); | 511 var->rewrite_ = new Slot(var, Slot::LOOKUP, -1); |
| 509 } | 512 } |
| 510 return var; | 513 return var; |
| 511 } | 514 } |
| 512 | 515 |
| 513 | 516 |
| 514 // Lookup a variable starting with this scope. The result is either | 517 // Lookup a variable starting with this scope. The result is either |
| 515 // the statically resolved (local!) variable belonging to an outer scope, | 518 // the statically resolved (local!) variable belonging to an outer scope, |
| 516 // or NULL. It may be NULL because a) we couldn't find a variable, or b) | 519 // or NULL. It may be NULL because a) we couldn't find a variable, or b) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 // that the variable might be introduced dynamically (through | 615 // that the variable might be introduced dynamically (through |
| 613 // a local or outer eval() call, or an outer 'with' statement), | 616 // a local or outer eval() call, or an outer 'with' statement), |
| 614 // or we don't know about the outer scope (because we are | 617 // or we don't know about the outer scope (because we are |
| 615 // in an eval scope). | 618 // in an eval scope). |
| 616 if (is_global_scope() || | 619 if (is_global_scope() || |
| 617 !(scope_inside_with_ || outer_scope_is_eval_scope_ || | 620 !(scope_inside_with_ || outer_scope_is_eval_scope_ || |
| 618 scope_calls_eval_ || outer_scope_calls_eval_)) { | 621 scope_calls_eval_ || outer_scope_calls_eval_)) { |
| 619 // We must have a global variable. | 622 // We must have a global variable. |
| 620 ASSERT(global_scope != NULL); | 623 ASSERT(global_scope != NULL); |
| 621 var = new Variable(global_scope, proxy->name(), | 624 var = new Variable(global_scope, proxy->name(), |
| 622 Variable::DYNAMIC, true, false); | 625 Variable::DYNAMIC, true, Variable::NORMAL); |
| 623 | 626 |
| 624 } else if (scope_inside_with_) { | 627 } else if (scope_inside_with_) { |
| 625 // If we are inside a with statement we give up and look up | 628 // If we are inside a with statement we give up and look up |
| 626 // the variable at runtime. | 629 // the variable at runtime. |
| 627 var = NonLocal(proxy->name(), Variable::DYNAMIC); | 630 var = NonLocal(proxy->name(), Variable::DYNAMIC); |
| 628 | 631 |
| 629 } else if (invalidated_local != NULL) { | 632 } else if (invalidated_local != NULL) { |
| 630 // No with statements are involved and we found a local | 633 // No with statements are involved and we found a local |
| 631 // variable that might be shadowed by eval introduced | 634 // variable that might be shadowed by eval introduced |
| 632 // variables. | 635 // variables. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 790 // and bind the corresponding proxy. It's ok to declare it only now | 793 // and bind the corresponding proxy. It's ok to declare it only now |
| 791 // because it's a local variable that is allocated after the parameters | 794 // because it's a local variable that is allocated after the parameters |
| 792 // have been allocated. | 795 // have been allocated. |
| 793 // | 796 // |
| 794 // Note: This is "almost" at temporary variable but we cannot use | 797 // Note: This is "almost" at temporary variable but we cannot use |
| 795 // NewTemporary() because the mode needs to be INTERNAL since this | 798 // NewTemporary() because the mode needs to be INTERNAL since this |
| 796 // variable may be allocated in the heap-allocated context (temporaries | 799 // variable may be allocated in the heap-allocated context (temporaries |
| 797 // are never allocated in the context). | 800 // are never allocated in the context). |
| 798 Variable* arguments_shadow = | 801 Variable* arguments_shadow = |
| 799 new Variable(this, Factory::arguments_shadow_symbol(), | 802 new Variable(this, Factory::arguments_shadow_symbol(), |
| 800 Variable::INTERNAL, true, false); | 803 Variable::INTERNAL, true, Variable::ARGUMENTS); |
| 801 arguments_shadow_ = | 804 arguments_shadow_ = |
| 802 new VariableProxy(Factory::arguments_shadow_symbol(), false, false); | 805 new VariableProxy(Factory::arguments_shadow_symbol(), false, false); |
| 803 arguments_shadow_->BindTo(arguments_shadow); | 806 arguments_shadow_->BindTo(arguments_shadow); |
| 804 temps_.Add(arguments_shadow); | 807 temps_.Add(arguments_shadow); |
| 805 | 808 |
| 806 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. | 809 // Allocate the parameters by rewriting them into '.arguments[i]' accesses. |
| 807 for (int i = 0; i < params_.length(); i++) { | 810 for (int i = 0; i < params_.length(); i++) { |
| 808 Variable* var = params_[i]; | 811 Variable* var = params_[i]; |
| 809 ASSERT(var->scope() == this); | 812 ASSERT(var->scope() == this); |
| 810 if (MustAllocate(var)) { | 813 if (MustAllocate(var)) { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && | 935 if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS && |
| 933 !must_have_local_context) { | 936 !must_have_local_context) { |
| 934 num_heap_slots_ = 0; | 937 num_heap_slots_ = 0; |
| 935 } | 938 } |
| 936 | 939 |
| 937 // Allocation done. | 940 // Allocation done. |
| 938 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); | 941 ASSERT(num_heap_slots_ == 0 || num_heap_slots_ >= Context::MIN_CONTEXT_SLOTS); |
| 939 } | 942 } |
| 940 | 943 |
| 941 } } // namespace v8::internal | 944 } } // namespace v8::internal |
| OLD | NEW |