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 consecutive_declaration_batch_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 p->value = new (zone()) |
46 initialization_flag, maybe_assigned_flag); | 47 Variable(scope, name, mode, kind, initialization_flag, |
48 maybe_assigned_flag, consecutive_declaration_batch_start); | |
47 } | 49 } |
48 return reinterpret_cast<Variable*>(p->value); | 50 return reinterpret_cast<Variable*>(p->value); |
49 } | 51 } |
50 | 52 |
51 | 53 |
52 Variable* VariableMap::Lookup(const AstRawString* name) { | 54 Variable* VariableMap::Lookup(const AstRawString* name) { |
53 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); | 55 Entry* p = ZoneHashMap::Lookup(const_cast<AstRawString*>(name), name->hash()); |
54 if (p != NULL) { | 56 if (p != NULL) { |
55 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); | 57 DCHECK(reinterpret_cast<const AstRawString*>(p->key) == name); |
56 DCHECK(p->value != NULL); | 58 DCHECK(p->value != NULL); |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 rest_parameter_ = var; | 464 rest_parameter_ = var; |
463 rest_index_ = num_parameters(); | 465 rest_index_ = num_parameters(); |
464 } | 466 } |
465 params_.Add(var, zone()); | 467 params_.Add(var, zone()); |
466 return var; | 468 return var; |
467 } | 469 } |
468 | 470 |
469 | 471 |
470 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, | 472 Variable* Scope::DeclareLocal(const AstRawString* name, VariableMode mode, |
471 InitializationFlag init_flag, Variable::Kind kind, | 473 InitializationFlag init_flag, Variable::Kind kind, |
472 MaybeAssignedFlag maybe_assigned_flag) { | 474 MaybeAssignedFlag maybe_assigned_flag, |
475 int consecutive_declaration_batch_start) { | |
473 DCHECK(!already_resolved()); | 476 DCHECK(!already_resolved()); |
474 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are | 477 // This function handles VAR, LET, and CONST modes. DYNAMIC variables are |
475 // introduces during variable allocation, INTERNAL variables are allocated | 478 // introduces during variable allocation, INTERNAL variables are allocated |
476 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). | 479 // explicitly, and TEMPORARY variables are allocated via NewTemporary(). |
477 DCHECK(IsDeclaredVariableMode(mode)); | 480 DCHECK(IsDeclaredVariableMode(mode)); |
478 ++num_var_or_const_; | 481 ++num_var_or_const_; |
479 return variables_.Declare(this, name, mode, kind, init_flag, | 482 return variables_.Declare(this, name, mode, kind, init_flag, |
480 maybe_assigned_flag); | 483 maybe_assigned_flag, |
484 consecutive_declaration_batch_start); | |
481 } | 485 } |
482 | 486 |
483 | 487 |
484 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { | 488 Variable* Scope::DeclareDynamicGlobal(const AstRawString* name) { |
485 DCHECK(is_script_scope()); | 489 DCHECK(is_script_scope()); |
486 return variables_.Declare(this, | 490 return variables_.Declare(this, |
487 name, | 491 name, |
488 DYNAMIC_GLOBAL, | 492 DYNAMIC_GLOBAL, |
489 Variable::NORMAL, | 493 Variable::NORMAL, |
490 kCreatedInitialized); | 494 kCreatedInitialized); |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 // Allow referencing the class name from methods of that class, even though | 1137 // Allow referencing the class name from methods of that class, even though |
1134 // the initializer position for class names is only after the body. | 1138 // the initializer position for class names is only after the body. |
1135 Scope* scope = this; | 1139 Scope* scope = this; |
1136 while (scope) { | 1140 while (scope) { |
1137 if (scope->ClassVariableForMethod() == var) return true; | 1141 if (scope->ClassVariableForMethod() == var) return true; |
1138 scope = scope->outer_scope(); | 1142 scope = scope->outer_scope(); |
1139 } | 1143 } |
1140 | 1144 |
1141 // Allow references from methods to classes declared later, if we detect no | 1145 // Allow references from methods to classes declared later, if we detect no |
1142 // problematic dependency cycles. | 1146 // problematic dependency cycles. |
1143 | 1147 Variable* class_var = ClassVariableForMethod(); |
1144 if (ClassVariableForMethod() && var->is_class()) { | 1148 if (class_var && var->is_class()) { |
1145 // A method is referring to some other class, possibly declared | 1149 // A method is referring to some other class, possibly declared |
1146 // later. Referring to a class declared earlier is always OK and covered by | 1150 // later. Referring to a class declared earlier is always OK and covered by |
1147 // the code outside this if. Here we only need to allow special cases for | 1151 // the code outside this if. Here we only need to allow special cases for |
1148 // referring to a class which is declared later. | 1152 // referring to a class which is declared later. |
1149 | 1153 |
1150 // Referring to a class C declared later is OK under the following | 1154 // Referring to a class C declared later is OK under the following |
1151 // circumstances: | 1155 // circumstances: |
1152 | 1156 |
1153 // 1. The class declarations are in a consecutive group with no other | 1157 // 1. The class declarations are in a consecutive group with no other |
1154 // declarations or statements in between, and | 1158 // declarations or statements in between, and |
1155 | 1159 |
1156 // 2. There is no dependency cycle where the first edge is an initialization | 1160 // 2. There is no dependency cycle where the first edge is an initialization |
1157 // time dependency (computed property name or extends clause) from C to | 1161 // time dependency (computed property name or extends clause) from C to |
1158 // something that depends on this class directly or transitively. | 1162 // something that depends on this class directly or transitively. |
1159 | 1163 |
1160 // TODO(marja,rossberg): implement these checks. Here we undershoot the | 1164 // This is needed because a class normally creates two scopes (outer and |
rossberg
2015/04/20 11:15:25
Hm, a class only introduces a single scope. Do you
marja
2015/04/20 15:58:22
Yes, s/two scopes/two bindings/ was what I meant;
| |
1161 // target and allow referring to any class. | 1165 // inner); the reference is coming from the inner one, but classes in the |
1162 return true; | 1166 // same consectutive class declaration batch are declared in the outer |
rossberg
2015/04/20 11:15:25
Nit: "consectutive class declaration batch" -> "de
marja
2015/04/20 15:58:22
Done.
| |
1167 // one. We also need to compare the scopes to distinguish between two | |
1168 // consecutive classes from a class which has another class inside its | |
1169 // computed property name. This is pretty complicated. | |
1170 if (class_var->scope()->outer_scope()) { | |
1171 Variable* maybe_outer_class_var = | |
1172 class_var->scope()->outer_scope()->LookupLocal(class_var->raw_name()); | |
1173 if (maybe_outer_class_var) { | |
rossberg
2015/04/20 11:15:25
This may be too liberal. I suppose you somehow nee
marja
2015/04/20 15:58:22
Ahh, true. The breaking case is this:
let A = cla
| |
1174 class_var = maybe_outer_class_var; | |
1175 } | |
1176 } | |
1177 | |
1178 // TODO(marja,rossberg): implement the dependency cycle detection. Here we | |
1179 // undershoot the target and allow referring to any class in the same | |
1180 // consectuive declaration batch. | |
1181 if (class_var->scope() == var->scope() && | |
1182 class_var->consecutive_declaration_batch_start() == | |
1183 var->consecutive_declaration_batch_start() && | |
1184 class_var->consecutive_declaration_batch_start() >= 0) { | |
1185 return true; | |
1186 } | |
1163 } | 1187 } |
1164 | 1188 |
1165 // If both the use and the declaration are inside an eval scope (possibly | 1189 // If both the use and the declaration are inside an eval scope (possibly |
1166 // indirectly), or one of them is, we need to check whether they are inside | 1190 // indirectly), or one of them is, we need to check whether they are inside |
1167 // the same eval scope or different ones. | 1191 // the same eval scope or different ones. |
1168 | 1192 |
1169 // TODO(marja,rossberg): Detect errors across different evals (depends on the | 1193 // TODO(marja,rossberg): Detect errors across different evals (depends on the |
1170 // future of eval in strong mode). | 1194 // future of eval in strong mode). |
1171 const Scope* eval_for_use = NearestOuterEvalScope(); | 1195 const Scope* eval_for_use = NearestOuterEvalScope(); |
1172 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); | 1196 const Scope* eval_for_declaration = var->scope()->NearestOuterEvalScope(); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1488 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); | 1512 (function_ != NULL && function_->proxy()->var()->IsStackLocal() ? 1 : 0); |
1489 } | 1513 } |
1490 | 1514 |
1491 | 1515 |
1492 int Scope::ContextLocalCount() const { | 1516 int Scope::ContextLocalCount() const { |
1493 if (num_heap_slots() == 0) return 0; | 1517 if (num_heap_slots() == 0) return 0; |
1494 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - | 1518 return num_heap_slots() - Context::MIN_CONTEXT_SLOTS - |
1495 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); | 1519 (function_ != NULL && function_->proxy()->var()->IsContextSlot() ? 1 : 0); |
1496 } | 1520 } |
1497 } } // namespace v8::internal | 1521 } } // namespace v8::internal |
OLD | NEW |