Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(660)

Side by Side Diff: src/scopes.cc

Issue 1060913005: [strong] Stricter check for referring to other classes inside methods. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: . Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698