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/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/messages.h" | 9 #include "src/messages.h" |
10 #include "src/parser.h" | 10 #include "src/parser.h" |
(...skipping 14 matching lines...) Expand all Loading... | |
25 | 25 |
26 VariableMap::VariableMap(Zone* zone) | 26 VariableMap::VariableMap(Zone* zone) |
27 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), | 27 : ZoneHashMap(ZoneHashMap::PointersMatch, 8, ZoneAllocationPolicy(zone)), |
28 zone_(zone) {} | 28 zone_(zone) {} |
29 VariableMap::~VariableMap() {} | 29 VariableMap::~VariableMap() {} |
30 | 30 |
31 | 31 |
32 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, | 32 Variable* VariableMap::Declare(Scope* scope, const AstRawString* name, |
33 VariableMode mode, Variable::Kind kind, | 33 VariableMode mode, Variable::Kind kind, |
34 InitializationFlag initialization_flag, | 34 InitializationFlag initialization_flag, |
35 MaybeAssignedFlag maybe_assigned_flag) { | 35 MaybeAssignedFlag maybe_assigned_flag, |
36 int declaration_group_start) { | |
36 // AstRawStrings are unambiguous, i.e., the same string is always represented | 37 // AstRawStrings are unambiguous, i.e., the same string is always represented |
37 // by the same AstRawString*. | 38 // by the same AstRawString*. |
38 // FIXME(marja): fix the type of Lookup. | 39 // FIXME(marja): fix the type of Lookup. |
39 Entry* p = | 40 Entry* p = |
40 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), | 41 ZoneHashMap::LookupOrInsert(const_cast<AstRawString*>(name), name->hash(), |
41 ZoneAllocationPolicy(zone())); | 42 ZoneAllocationPolicy(zone())); |
42 if (p->value == NULL) { | 43 if (p->value == NULL) { |
43 // The variable has not been declared yet -> insert it. | 44 // The variable has not been declared yet -> insert it. |
44 DCHECK(p->key == name); | 45 DCHECK(p->key == name); |
45 p->value = new (zone()) Variable(scope, name, mode, kind, | 46 if (kind == Variable::CLASS) { |
46 initialization_flag, maybe_assigned_flag); | 47 p->value = new (zone()) |
48 ClassVariable(scope, name, mode, kind, initialization_flag, | |
49 maybe_assigned_flag, declaration_group_start); | |
50 } else { | |
51 p->value = new (zone()) Variable( | |
52 scope, name, mode, kind, initialization_flag, maybe_assigned_flag); | |
53 } | |
47 } | 54 } |
48 return reinterpret_cast<Variable*>(p->value); | 55 return reinterpret_cast<Variable*>(p->value); |
49 } | 56 } |
50 | 57 |
51 | 58 |
52 Variable* VariableMap::Lookup(const AstRawString* name) { | 59 Variable* VariableMap::Lookup(const AstRawString* name) { |
53 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); | 60 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); |
54 if (p != NULL) { | 61 if (p != NULL) { |
55 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); | 62 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); |
56 DCHECK(p->value != NULL); | 63 DCHECK(p->value != NULL); |
(...skipping 12 matching lines...) Expand all Loading... | |
69 variables_(zone), | 76 variables_(zone), |
70 internals_(4, zone), | 77 internals_(4, zone), |
71 temps_(4, zone), | 78 temps_(4, zone), |
72 params_(4, zone), | 79 params_(4, zone), |
73 unresolved_(16, zone), | 80 unresolved_(16, zone), |
74 decls_(4, zone), | 81 decls_(4, zone), |
75 module_descriptor_( | 82 module_descriptor_( |
76 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), | 83 scope_type == MODULE_SCOPE ? ModuleDescriptor::New(zone) : NULL), |
77 already_resolved_(false), | 84 already_resolved_(false), |
78 ast_value_factory_(ast_value_factory), | 85 ast_value_factory_(ast_value_factory), |
79 zone_(zone) { | 86 zone_(zone), |
87 class_declaration_group_start_(-1) { | |
80 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), | 88 SetDefaults(scope_type, outer_scope, Handle<ScopeInfo>::null(), |
81 function_kind); | 89 function_kind); |
82 // The outermost scope must be a script scope. | 90 // The outermost scope must be a script scope. |
83 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); | 91 DCHECK(scope_type == SCRIPT_SCOPE || outer_scope != NULL); |
84 DCHECK(!HasIllegalRedeclaration()); | 92 DCHECK(!HasIllegalRedeclaration()); |
85 } | 93 } |
86 | 94 |
87 | 95 |
88 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, | 96 Scope::Scope(Zone* zone, Scope* inner_scope, ScopeType scope_type, |
89 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) | 97 Handle<ScopeInfo> scope_info, AstValueFactory* value_factory) |
90 : inner_scopes_(4, zone), | 98 : inner_scopes_(4, zone), |
91 variables_(zone), | 99 variables_(zone), |
92 internals_(4, zone), | 100 internals_(4, zone), |
93 temps_(4, zone), | 101 temps_(4, zone), |
94 params_(4, zone), | 102 params_(4, zone), |
95 unresolved_(16, zone), | 103 unresolved_(16, zone), |
96 decls_(4, zone), | 104 decls_(4, zone), |
97 module_descriptor_(NULL), | 105 module_descriptor_(NULL), |
98 already_resolved_(true), | 106 already_resolved_(true), |
99 ast_value_factory_(value_factory), | 107 ast_value_factory_(value_factory), |
100 zone_(zone) { | 108 zone_(zone), |
109 class_declaration_group_start_(-1) { | |
101 SetDefaults(scope_type, NULL, scope_info); | 110 SetDefaults(scope_type, NULL, scope_info); |
102 if (!scope_info.is_null()) { | 111 if (!scope_info.is_null()) { |
103 num_heap_slots_ = scope_info_->ContextLength(); | 112 num_heap_slots_ = scope_info_->ContextLength(); |
104 } | 113 } |
105 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. | 114 // Ensure at least MIN_CONTEXT_SLOTS to indicate a materialized context. |
106 num_heap_slots_ = Max(num_heap_slots_, | 115 num_heap_slots_ = Max(num_heap_slots_, |
107 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); | 116 static_cast<int>(Context::MIN_CONTEXT_SLOTS)); |
108 AddInnerScope(inner_scope); | 117 AddInnerScope(inner_scope); |
109 } | 118 } |
110 | 119 |
111 | 120 |
112 Scope::Scope(Zone* zone, Scope* inner_scope, | 121 Scope::Scope(Zone* zone, Scope* inner_scope, |
113 const AstRawString* catch_variable_name, | 122 const AstRawString* catch_variable_name, |
114 AstValueFactory* value_factory) | 123 AstValueFactory* value_factory) |
115 : inner_scopes_(1, zone), | 124 : inner_scopes_(1, zone), |
116 variables_(zone), | 125 variables_(zone), |
117 internals_(0, zone), | 126 internals_(0, zone), |
118 temps_(0, zone), | 127 temps_(0, zone), |
119 params_(0, zone), | 128 params_(0, zone), |
120 unresolved_(0, zone), | 129 unresolved_(0, zone), |
121 decls_(0, zone), | 130 decls_(0, zone), |
122 module_descriptor_(NULL), | 131 module_descriptor_(NULL), |
123 already_resolved_(true), | 132 already_resolved_(true), |
124 ast_value_factory_(value_factory), | 133 ast_value_factory_(value_factory), |
125 zone_(zone) { | 134 zone_(zone), |
135 class_declaration_group_start_(-1) { | |
126 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); | 136 SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
127 AddInnerScope(inner_scope); | 137 AddInnerScope(inner_scope); |
128 ++num_var_or_const_; | 138 ++num_var_or_const_; |
129 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; | 139 num_heap_slots_ = Context::MIN_CONTEXT_SLOTS; |
130 Variable* variable = variables_.Declare(this, | 140 Variable* variable = variables_.Declare(this, |
131 catch_variable_name, | 141 catch_variable_name, |
132 VAR, | 142 VAR, |
133 Variable::NORMAL, | 143 Variable::NORMAL, |
134 kCreatedInitialized); | 144 kCreatedInitialized); |
135 AllocateHeapSlot(variable); | 145 AllocateHeapSlot(variable); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
403 | 413 |
404 mode = DYNAMIC; | 414 mode = DYNAMIC; |
405 location = Variable::LOOKUP; | 415 location = Variable::LOOKUP; |
406 init_flag = kCreatedInitialized; | 416 init_flag = kCreatedInitialized; |
407 // Be conservative and flag parameters as maybe assigned. Better information | 417 // Be conservative and flag parameters as maybe assigned. Better information |
408 // would require ScopeInfo to serialize the maybe_assigned bit also for | 418 // would require ScopeInfo to serialize the maybe_assigned bit also for |
409 // parameters. | 419 // parameters. |
410 maybe_assigned_flag = kMaybeAssigned; | 420 maybe_assigned_flag = kMaybeAssigned; |
411 } | 421 } |
412 | 422 |
423 // TODO(marja, rossberg): Declare variables of the right Kind. | |
413 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, | 424 Variable* var = variables_.Declare(this, name, mode, Variable::NORMAL, |
414 init_flag, maybe_assigned_flag); | 425 init_flag, maybe_assigned_flag); |
415 var->AllocateTo(location, index); | 426 var->AllocateTo(location, index); |
416 return var; | 427 return var; |
417 } | 428 } |
418 | 429 |
419 | 430 |
420 Variable* Scope::LookupFunctionVar(const AstRawString* name, | 431 Variable* Scope::LookupFunctionVar(const AstRawString* name, |
421 AstNodeFactory* factory) { | 432 AstNodeFactory* factory) { |
422 if (function_ != NULL && function_->proxy()->raw_name() == name) { | 433 if (function_ != NULL && function_->proxy()->raw_name() == name) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 } | 475 } |
465 // TODO(wingo): Avoid O(n^2) check. | 476 // TODO(wingo): Avoid O(n^2) check. |
466 *is_duplicate = IsDeclaredParameter(name); | 477 *is_duplicate = IsDeclaredParameter(name); |
467 params_.Add(var, zone()); | 478 params_.Add(var, zone()); |
468 return var; | 479 return var; |
469 } | 480 } |
470 | 481 |
471 | 482 |
472 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 483 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
473 InitializationFlag init_flag, Variable::Kind kind, | 484 InitializationFlag init_flag, Variable::Kind kind, |
474 MaybeAssignedFlag maybe_assigned_flag) { | 485 MaybeAssignedFlag maybe_assigned_flag, |
486 int declaration_group_start) { | |
475 DCHECK(!already_resolved()); | 487 DCHECK(!already_resolved()); |
476 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 488 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
477 // introduces during variable allocation, INTERNAL variables are allocated | 489 // introduces during variable allocation, INTERNAL variables are allocated |
478 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 490 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
479 DCHECK(IsDeclaredVariableMode(mode)); | 491 DCHECK(IsDeclaredVariableMode(mode)); |
480 ++num_var_or_const_; | 492 ++num_var_or_const_; |
481 return variables_.Declare(this, name, mode, kind, init_flag, | 493 return variables_.Declare(this, name, mode, kind, init_flag, |
482 maybe_assigned_flag); | 494 maybe_assigned_flag, declaration_group_start); |
483 } | 495 } |
484 | 496 |
485 | 497 |
486 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 498 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
487 DCHECK(is_script_scope()); | 499 DCHECK(is_script_scope()); |
488 return variables_.Declare(this, | 500 return variables_.Declare(this, |
489 name, | 501 name, |
490 DYNAMIC_GLOBAL, | 502 DYNAMIC_GLOBAL, |
491 Variable::NORMAL, | 503 Variable::NORMAL, |
492 kCreatedInitialized); | 504 kCreatedInitialized); |
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1125 | 1137 |
1126 return true; | 1138 return true; |
1127 } | 1139 } |
1128 | 1140 |
1129 | 1141 |
1130 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { | 1142 bool Scope::CheckStrongModeDeclaration(VariableProxy* proxy, Variable* var) { |
1131 // Check for declaration-after use (for variables) in strong mode. Note that | 1143 // Check for declaration-after use (for variables) in strong mode. Note that |
1132 // we can only do this in the case where we have seen the declaration. And we | 1144 // we can only do this in the case where we have seen the declaration. And we |
1133 // always allow referencing functions (for now). | 1145 // always allow referencing functions (for now). |
1134 | 1146 |
1147 // This might happen during lazy compilation; we don't keep track of | |
1148 // initializer positions for variables stored in ScopeInfo, so we cannot check | |
1149 // bindings against them. TODO(marja, rossberg): remove this hack. | |
1150 if (var->initializer_position() == RelocInfo::kNoPosition) return true; | |
1151 | |
1135 // Allow referencing the class name from methods of that class, even though | 1152 // Allow referencing the class name from methods of that class, even though |
1136 // the initializer position for class names is only after the body. | 1153 // the initializer position for class names is only after the body. |
1137 Scope* scope = this; | 1154 Scope* scope = this; |
1138 while (scope) { | 1155 while (scope) { |
1139 if (scope->ClassVariableForMethod() == var) return true; | 1156 if (scope->ClassVariableForMethod() == var) return true; |
1140 scope = scope->outer_scope(); | 1157 scope = scope->outer_scope(); |
1141 } | 1158 } |
1142 | 1159 |
1143 // Allow references from methods to classes declared later, if we detect no | 1160 // Allow references from methods to classes declared later, if we detect no |
1144 // problematic dependency cycles. | 1161 // problematic dependency cycles. Note that we can be inside multiple methods |
1162 // at the same time, and it's enough if we find one where the reference is | |
1163 // allowed. | |
1164 if (var->is_class() && | |
1165 var->AsClassVariable()->declaration_group_start() >= 0) { | |
1166 for (scope = this; scope && scope != var->scope(); | |
1167 scope = scope->outer_scope()) { | |
1168 ClassVariable* class_var = scope->ClassVariableForMethod(); | |
1169 if (class_var) { | |
1170 // A method is referring to some other class, possibly declared | |
1171 // later. Referring to a class declared earlier is always OK and covered | |
1172 // by the code outside this if. Here we only need to allow special cases | |
1173 // for referring to a class which is declared later. | |
1145 | 1174 |
1146 if (ClassVariableForMethod() && var->is_class()) { | 1175 // Referring to a class C declared later is OK under the following |
1147 // A method is referring to some other class, possibly declared | 1176 // circumstances: |
1148 // later. Referring to a class declared earlier is always OK and covered by | |
1149 // the code outside this if. Here we only need to allow special cases for | |
1150 // referring to a class which is declared later. | |
1151 | 1177 |
1152 // Referring to a class C declared later is OK under the following | 1178 // 1. The class declarations are in a consecutive group with no other |
1153 // circumstances: | 1179 // declarations or statements in between, and |
1154 | 1180 |
1155 // 1. The class declarations are in a consecutive group with no other | 1181 // 2. There is no dependency cycle where the first edge is an |
1156 // declarations or statements in between, and | 1182 // initialization time dependency (computed property name or extends |
1183 // clause) from C to something that depends on this class directly or | |
1184 // transitively. | |
1157 | 1185 |
1158 // 2. There is no dependency cycle where the first edge is an initialization | 1186 // This is needed because a class ("class Name { }") creates two |
1159 // time dependency (computed property name or extends clause) from C to | 1187 // bindings (one in the outer scope, and one in the class scope). The |
1160 // something that depends on this class directly or transitively. | 1188 // method is a function scope inside the inner scope (class scope). The |
1189 // consecutive class declarations are in the outer scope. | |
1190 if (class_var->corresponding_outer_class_variable()) { | |
1191 class_var = class_var->corresponding_outer_class_variable(); | |
rossberg
2015/04/23 13:17:20
Nit: you could switch the two lines and avoid the
marja
2015/04/23 13:40:23
Done.
| |
1192 if (class_var->declaration_group_start() == | |
1193 var->AsClassVariable()->declaration_group_start()) { | |
1194 return true; | |
1195 } | |
1196 } | |
1161 | 1197 |
1162 // TODO(marja,rossberg): implement these checks. Here we undershoot the | 1198 // TODO(marja,rossberg): implement the dependency cycle detection. Here |
1163 // target and allow referring to any class. | 1199 // we undershoot the target and allow referring to any class in the same |
1164 return true; | 1200 // consectuive declaration group. |
1201 | |
1202 // The cycle detection can work roughly like this: 1) detect init-time | |
1203 // references here (they are free variables which are inside the class | |
1204 // scope but not inside a method scope - no parser changes needed to | |
1205 // detect them) 2) if we encounter an init-time reference here, allow | |
1206 // it, but record it for a later dependency cycle check 3) also record | |
1207 // non-init-time references here 4) after scope analysis is done, | |
1208 // analyse the dependency cycles: an illegal cycle is one starting with | |
1209 // an init-time reference and leading back to the starting point with | |
1210 // either non-init-time and init-time references. | |
1211 } | |
1212 } | |
1165 } | 1213 } |
1166 | 1214 |
1167 // If both the use and the declaration are inside an eval scope (possibly | 1215 // If both the use and the declaration are inside an eval scope (possibly |
1168 // indirectly), or one of them is, we need to check whether they are inside | 1216 // indirectly), or one of them is, we need to check whether they are inside |
1169 // the same eval scope or different ones. | 1217 // the same eval scope or different ones. |
1170 | 1218 |
1171 // TODO(marja,rossberg): Detect errors across different evals (depends on the | 1219 // TODO(marja,rossberg): Detect errors across different evals (depends on the |
1172 // future of eval in strong mode). | 1220 // future of eval in strong mode). |
1173 const Scope* eval_for_use = NearestOuterEvalScope(); | 1221 const Scope* eval_for_use = NearestOuterEvalScope(); |
1174 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); | 1222 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); |
1175 | 1223 |
1176 if (proxy->position() != RelocInfo::kNoPosition && | 1224 if (proxy->position() != RelocInfo::kNoPosition && |
1177 proxy->position() < var->initializer_position() && !var->is_function() && | 1225 proxy->position() < var->initializer_position() && !var->is_function() && |
1178 eval_for_use == eval_for_declaration) { | 1226 eval_for_use == eval_for_declaration) { |
1179 DCHECK(proxy->end_position() != RelocInfo::kNoPosition); | 1227 DCHECK(proxy->end_position() != RelocInfo::kNoPosition); |
1180 ReportMessage(proxy->position(), proxy->end_position(), | 1228 ReportMessage(proxy->position(), proxy->end_position(), |
1181 "strong_use_before_declaration", proxy->raw_name()); | 1229 "strong_use_before_declaration", proxy->raw_name()); |
1182 return false; | 1230 return false; |
1183 } | 1231 } |
1184 return true; | 1232 return true; |
1185 } | 1233 } |
1186 | 1234 |
1187 | 1235 |
1188 Variable* Scope::ClassVariableForMethod() const { | 1236 ClassVariable* Scope::ClassVariableForMethod() const { |
1237 // TODO(marja, rossberg): This fails to find a class variable in the following | |
1238 // cases: | |
1239 // let A = class { ... } | |
1240 // It needs to be investigated whether this causes any practical problems. | |
1189 if (!is_function_scope()) return nullptr; | 1241 if (!is_function_scope()) return nullptr; |
1190 if (IsInObjectLiteral(function_kind_)) return nullptr; | 1242 if (IsInObjectLiteral(function_kind_)) return nullptr; |
1191 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) && | 1243 if (!IsConciseMethod(function_kind_) && !IsConstructor(function_kind_) && |
1192 !IsAccessorFunction(function_kind_)) { | 1244 !IsAccessorFunction(function_kind_)) { |
1193 return nullptr; | 1245 return nullptr; |
1194 } | 1246 } |
1195 DCHECK_NOT_NULL(outer_scope_); | 1247 DCHECK_NOT_NULL(outer_scope_); |
1196 DCHECK(outer_scope_->is_class_scope()); | 1248 DCHECK(outer_scope_->is_class_scope()); |
1197 // The class scope contains at most one variable, the class name. | 1249 // The class scope contains at most one variable, the class name. |
1198 DCHECK(outer_scope_->variables_.occupancy() <= 1); | 1250 DCHECK(outer_scope_->variables_.occupancy() <= 1); |
1199 if (outer_scope_->variables_.occupancy() == 0) return nullptr; | 1251 if (outer_scope_->variables_.occupancy() == 0) return nullptr; |
1200 VariableMap::Entry* p = outer_scope_->variables_.Start(); | 1252 VariableMap::Entry* p = outer_scope_->variables_.Start(); |
1201 return reinterpret_cast<Variable*>(p->value); | 1253 Variable* var = reinterpret_cast<Variable*>(p->value); |
1254 if (!var->is_class()) return nullptr; | |
1255 return var->AsClassVariable(); | |
1202 } | 1256 } |
1203 | 1257 |
1204 | 1258 |
1205 bool Scope::ResolveVariablesRecursively(ParseInfo* info, | 1259 bool Scope::ResolveVariablesRecursively(ParseInfo* info, |
1206 AstNodeFactory* factory) { | 1260 AstNodeFactory* factory) { |
1207 DCHECK(info->script_scope()->is_script_scope()); | 1261 DCHECK(info->script_scope()->is_script_scope()); |
1208 | 1262 |
1209 // Resolve unresolved variables for this scope. | 1263 // Resolve unresolved variables for this scope. |
1210 for (int i = 0; i < unresolved_.length(); i++) { | 1264 for (int i = 0; i < unresolved_.length(); i++) { |
1211 if (!ResolveVariable(info, unresolved_[i], factory)) return false; | 1265 if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1490 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1544 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1491 } | 1545 } |
1492 | 1546 |
1493 | 1547 |
1494 int Scope::ContextLocalCount() const { | 1548 int Scope::ContextLocalCount() const { |
1495 if (num_heap_slots() == 0) return 0; | 1549 if (num_heap_slots() == 0) return 0; |
1496 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1550 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1497 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1551 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1498 } | 1552 } |
1499 } } // namespace v8::internal | 1553 } } // namespace v8::internal |
OLD | NEW |