Changeset 186860 in webkit for trunk/Source/JavaScriptCore/parser/Parser.h
- Timestamp:
- Jul 15, 2015, 2:41:08 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/parser/Parser.h
r186379 r186860 37 37 #include "SourceProviderCache.h" 38 38 #include "SourceProviderCacheItem.h" 39 #include "VariableEnvironment.h" 39 40 #include <wtf/Forward.h> 40 41 #include <wtf/Noncopyable.h> … … 98 99 enum DestructuringKind { 99 100 DestructureToVariables, 101 DestructureToLexicalVariables, 100 102 DestructureToParameters, 101 103 DestructureToExpressions … … 118 120 , m_hasDirectSuper(false) 119 121 , m_needsSuperBinding(false) 120 , m_allowsNewDecls(true) 122 , m_allowsVarDeclarations(true) 123 , m_allowsLexicalDeclarations(true) 121 124 , m_strictMode(strictMode) 122 125 , m_isFunction(isFunction) 126 , m_isLexicalScope(false) 123 127 , m_isFunctionBoundary(false) 124 128 , m_isValidStrictMode(true) … … 135 139 , m_hasDirectSuper(rhs.m_hasDirectSuper) 136 140 , m_needsSuperBinding(rhs.m_needsSuperBinding) 137 , m_allowsNewDecls(rhs.m_allowsNewDecls) 141 , m_allowsVarDeclarations(rhs.m_allowsVarDeclarations) 142 , m_allowsLexicalDeclarations(rhs.m_allowsLexicalDeclarations) 138 143 , m_strictMode(rhs.m_strictMode) 139 144 , m_isFunction(rhs.m_isFunction) 145 , m_isLexicalScope(rhs.m_isLexicalScope) 140 146 , m_isFunctionBoundary(rhs.m_isFunctionBoundary) 141 147 , m_isValidStrictMode(rhs.m_isValidStrictMode) … … 190 196 m_isFunction = true; 191 197 m_isFunctionBoundary = true; 192 } 193 bool isFunction() { return m_isFunction; } 194 bool isFunctionBoundary() { return m_isFunctionBoundary; } 198 setIsLexicalScope(); 199 } 200 201 bool isFunction() const { return m_isFunction; } 202 bool isFunctionBoundary() const { return m_isFunctionBoundary; } 203 204 void setIsLexicalScope() 205 { 206 m_isLexicalScope = true; 207 m_allowsLexicalDeclarations = true; 208 } 209 bool isLexicalScope() { return m_isLexicalScope; } 210 211 VariableEnvironment& declaredVariables() { return m_declaredVariables; } 212 VariableEnvironment& finalizeLexicalEnvironment() 213 { 214 if (m_usesEval || m_needsFullActivation) 215 m_lexicalVariables.markAllVariablesAsCaptured(); 216 else 217 computeLexicallyCapturedVariablesAndPurgeCandidates(); 218 219 return m_lexicalVariables; 220 } 221 222 void computeLexicallyCapturedVariablesAndPurgeCandidates() 223 { 224 // Because variables may be defined at any time in the range of a lexical scope, we must 225 // track lexical variables that might be captured. Then, when we're preparing to pop the top 226 // lexical scope off the stack, we should find which variables are truly captured, and which 227 // variable still may be captured in a parent scope. 228 if (m_lexicalVariables.size() && m_closedVariableCandidates.size()) { 229 auto end = m_closedVariableCandidates.end(); 230 for (auto iter = m_closedVariableCandidates.begin(); iter != end; ++iter) 231 m_lexicalVariables.markVariableAsCapturedIfDefined(iter->get()); 232 } 233 234 // We can now purge values from the captured candidates because they're captured in this scope. 235 { 236 for (auto entry : m_lexicalVariables) { 237 if (entry.value.isCaptured()) 238 m_closedVariableCandidates.remove(entry.key); 239 } 240 } 241 } 195 242 196 243 void declareCallee(const Identifier* ident) 197 244 { 198 m_declaredVariables.add(ident->impl()); 199 } 200 201 bool declareVariable(const Identifier* ident) 202 { 245 auto addResult = m_declaredVariables.add(ident->impl()); 246 // We want to track if callee is captured, but we don't want to act like it's a 'var' 247 // because that would cause the BytecodeGenerator to emit bad code. 248 addResult.iterator->value.clearIsVar(); 249 } 250 251 bool declareVariable(const Identifier* ident, bool isConstant = false) 252 { 253 ASSERT(m_allowsVarDeclarations); 203 254 bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; 204 255 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 205 m_declaredVariables.add(ident->impl()); 256 auto addResult = m_declaredVariables.add(ident->impl()); 257 addResult.iterator->value.setIsVar(); 258 if (isConstant) 259 addResult.iterator->value.setIsConstant(); 260 206 261 return isValidStrictMode; 207 262 } 208 263 264 bool declareLexicalVariable(const Identifier* ident) 265 { 266 ASSERT(m_allowsLexicalDeclarations); 267 bool isValidStrictMode = m_vm->propertyNames->eval != *ident && m_vm->propertyNames->arguments != *ident; 268 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 269 auto addResult = m_lexicalVariables.add(ident->impl()); 270 addResult.iterator->value.setIsLet(); 271 bool successfulDeclaration = addResult.isNewEntry && isValidStrictMode; 272 return successfulDeclaration; 273 } 274 209 275 bool hasDeclaredVariable(const Identifier& ident) 210 276 { 211 return m_declaredVariables.contains(ident.impl()); 212 } 213 214 bool hasDeclaredParameter(const Identifier& ident) 215 { 216 return m_declaredParameters.contains(ident.impl()) || m_declaredVariables.contains(ident.impl()); 277 return hasDeclaredVariable(ident.impl()); 278 } 279 280 bool hasDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) 281 { 282 return m_declaredVariables.contains(ident.get()); 283 } 284 285 bool hasLexicallyDeclaredVariable(const RefPtr<UniquedStringImpl>& ident) const 286 { 287 return m_lexicalVariables.contains(ident.get()); 288 } 289 290 ALWAYS_INLINE bool hasDeclaredParameter(const Identifier& ident) 291 { 292 return hasDeclaredParameter(ident.impl()); 293 } 294 295 bool hasDeclaredParameter(const RefPtr<UniquedStringImpl>& ident) 296 { 297 return m_declaredParameters.contains(ident) || m_declaredVariables.contains(ident.get()); 217 298 } 218 299 … … 223 304 } 224 305 225 void preventNewDecls() { m_allowsNewDecls = false; } 226 bool allowsNewDecls() const { return m_allowsNewDecls; } 306 void preventAllVariableDeclarations() 307 { 308 m_allowsVarDeclarations = false; 309 m_allowsLexicalDeclarations = false; 310 } 311 void preventVarDeclarations() { m_allowsVarDeclarations = false; } 312 bool allowsVarDeclarations() const { return m_allowsVarDeclarations; } 313 bool allowsLexicalDeclarations() const { return m_allowsLexicalDeclarations; } 227 314 228 315 bool declareParameter(const Identifier* ident) 229 316 { 317 ASSERT(m_allowsVarDeclarations); 230 318 bool isArguments = m_vm->propertyNames->arguments == *ident; 231 bool isValidStrictMode = m_declaredVariables.add(ident->impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; 319 auto addResult = m_declaredVariables.add(ident->impl()); 320 addResult.iterator->value.clearIsVar(); 321 bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; 232 322 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 233 323 m_declaredParameters.add(ident->impl()); … … 246 336 { 247 337 bool isArguments = m_vm->propertyNames->arguments == *ident; 248 bool newEntry = m_declaredVariables.add(ident->impl()).isNewEntry; 249 bool isValidStrictMode = newEntry && m_vm->propertyNames->eval != *ident && !isArguments; 338 auto addResult = m_declaredVariables.add(ident->impl()); 339 addResult.iterator->value.setIsVar(); // Treat destructuring parameters as "var"s. 340 bool isValidStrictMode = addResult.isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; 250 341 m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; 251 342 252 343 if (isArguments) 253 344 m_shadowsArguments = true; 254 if (! newEntry)345 if (!addResult.isNewEntry) 255 346 return BindingFailed; 256 347 return isValidStrictMode ? BindingSucceeded : StrictBindingFailed; … … 269 360 270 361 void setNeedsFullActivation() { m_needsFullActivation = true; } 362 bool needsFullActivation() const { return m_needsFullActivation; } 271 363 272 364 #if ENABLE(ES6_CLASS_SYNTAX) … … 284 376 void setNeedsSuperBinding() { m_needsSuperBinding = true; } 285 377 286 boolcollectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables)378 void collectFreeVariables(Scope* nestedScope, bool shouldTrackClosedVariables) 287 379 { 288 380 if (nestedScope->m_usesEval) 289 381 m_usesEval = true; 290 IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); 291 for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { 292 if (nestedScope->m_declaredVariables.contains(*ptr)) 293 continue; 294 m_usedVariables.add(*ptr); 295 if (shouldTrackClosedVariables) 296 m_closedVariables.add(*ptr); 297 } 382 383 { 384 IdentifierSet::iterator end = nestedScope->m_usedVariables.end(); 385 for (IdentifierSet::iterator ptr = nestedScope->m_usedVariables.begin(); ptr != end; ++ptr) { 386 if (nestedScope->m_declaredVariables.contains(*ptr) || nestedScope->m_lexicalVariables.contains(*ptr)) 387 continue; 388 m_usedVariables.add(*ptr); 389 // We don't want a declared variable that is used in an inner scope to be thought of as captured if 390 // that inner scope is both a lexical scope and not a function. Only inner functions and "catch" 391 // statements can cause variables to be captured. 392 if (shouldTrackClosedVariables && (nestedScope->m_isFunctionBoundary || !nestedScope->m_isLexicalScope)) 393 m_closedVariableCandidates.add(*ptr); 394 } 395 } 396 // Propagate closed variable candidates downwards within the same function. 397 // Cross function captures will be realized via m_usedVariables propagation. 398 if (shouldTrackClosedVariables && !nestedScope->m_isFunctionBoundary && nestedScope->m_closedVariableCandidates.size()) { 399 IdentifierSet::iterator end = nestedScope->m_closedVariableCandidates.end(); 400 IdentifierSet::iterator begin = nestedScope->m_closedVariableCandidates.begin(); 401 m_closedVariableCandidates.add(begin, end); 402 } 403 298 404 if (nestedScope->m_writtenVariables.size()) { 299 405 IdentifierSet::iterator end = nestedScope->m_writtenVariables.end(); 300 406 for (IdentifierSet::iterator ptr = nestedScope->m_writtenVariables.begin(); ptr != end; ++ptr) { 301 if (nestedScope->m_declaredVariables.contains(*ptr) )407 if (nestedScope->m_declaredVariables.contains(*ptr) || nestedScope->m_lexicalVariables.contains(*ptr)) 302 408 continue; 303 409 m_writtenVariables.add(*ptr); 304 410 } 305 411 } 306 307 return true; 308 } 309 310 void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter, bool& modifiedArguments) 412 } 413 414 void getCapturedVars(IdentifierSet& capturedVariables, bool& modifiedParameter, bool& modifiedArguments) 311 415 { 312 416 if (m_needsFullActivation || m_usesEval) { 313 417 modifiedParameter = true; 314 capturedVariables = m_declaredVariables; 418 for (auto& entry : m_declaredVariables) 419 capturedVariables.add(entry.key); 315 420 return; 316 421 } 317 for (IdentifierSet::iterator ptr = m_closedVariable s.begin(); ptr != m_closedVariables.end(); ++ptr) {422 for (IdentifierSet::iterator ptr = m_closedVariableCandidates.begin(); ptr != m_closedVariableCandidates.end(); ++ptr) { 318 423 if (!m_declaredVariables.contains(*ptr)) 319 424 continue; … … 344 449 IdentifierSet::iterator end = capturedVariables.end(); 345 450 for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) { 346 if (m_declaredVariables.contains(*it) )451 if (m_declaredVariables.contains(*it) || m_lexicalVariables.contains(*it)) 347 452 continue; 348 453 vector.append(*it); … … 379 484 bool m_hasDirectSuper : 1; 380 485 bool m_needsSuperBinding : 1; 381 bool m_allowsNewDecls : 1; 486 bool m_allowsVarDeclarations : 1; 487 bool m_allowsLexicalDeclarations : 1; 382 488 bool m_strictMode : 1; 383 489 bool m_isFunction : 1; 490 bool m_isLexicalScope : 1; 384 491 bool m_isFunctionBoundary : 1; 385 492 bool m_isValidStrictMode : 1; … … 390 497 std::unique_ptr<LabelStack> m_labels; 391 498 IdentifierSet m_declaredParameters; 392 IdentifierSet m_declaredVariables; 499 VariableEnvironment m_declaredVariables; 500 VariableEnvironment m_lexicalVariables; 393 501 IdentifierSet m_usedVariables; 394 IdentifierSet m_closedVariable s;502 IdentifierSet m_closedVariableCandidates; 395 503 IdentifierSet m_writtenVariables; 396 504 }; … … 480 588 }; 481 589 590 struct AutoCleanupLexicalScope { 591 // We can allocate this object on the stack without actually knowing beforehand if we're 592 // going to create a new lexical scope. If we decide to create a new lexical scope, we 593 // can pass the scope into this obejct and it will take care of the cleanup for us if the parse fails. 594 // This is helpful if we may fail from syntax errors after creating a lexical scope conditionally. 595 AutoCleanupLexicalScope() 596 : m_scope(nullptr, UINT_MAX) 597 , m_parser(nullptr) 598 { 599 } 600 601 ~AutoCleanupLexicalScope() 602 { 603 // This should only ever be called if we fail from a syntax error. Otherwise 604 // it's the intention that a user of this class pops this scope manually on a 605 // successful parse. 606 if (isValid()) 607 m_parser->popScope(*this, false); 608 } 609 610 void setIsValid(ScopeRef& scope, Parser* parser) 611 { 612 RELEASE_ASSERT(scope->isLexicalScope()); 613 m_scope = scope; 614 m_parser = parser; 615 } 616 617 bool isValid() const { return !!m_parser; } 618 619 void setPopped() 620 { 621 m_parser = nullptr; 622 } 623 624 ScopeRef& scope() { return m_scope; } 625 626 private: 627 ScopeRef m_scope; 628 Parser* m_parser; 629 }; 630 482 631 ScopeRef currentScope() 483 632 { … … 497 646 } 498 647 499 boolpopScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables)648 void popScopeInternal(ScopeRef& scope, bool shouldTrackClosedVariables) 500 649 { 501 650 ASSERT_UNUSED(scope, scope.index() == m_scopeStack.size() - 1); 502 651 ASSERT(m_scopeStack.size() > 1); 503 bool result = m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); 652 m_scopeStack[m_scopeStack.size() - 2].collectFreeVariables(&m_scopeStack.last(), shouldTrackClosedVariables); 653 if (!m_scopeStack.last().isFunctionBoundary() && m_scopeStack.last().needsFullActivation()) 654 m_scopeStack[m_scopeStack.size() - 2].setNeedsFullActivation(); 504 655 m_scopeStack.removeLast(); 505 return result; 506 } 507 508 bool popScope(ScopeRef& scope, bool shouldTrackClosedVariables) 509 { 510 return popScopeInternal(scope, shouldTrackClosedVariables); 511 } 512 513 bool popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) 656 } 657 658 ALWAYS_INLINE void popScope(ScopeRef& scope, bool shouldTrackClosedVariables) 659 { 660 popScopeInternal(scope, shouldTrackClosedVariables); 661 } 662 663 ALWAYS_INLINE void popScope(AutoPopScopeRef& scope, bool shouldTrackClosedVariables) 514 664 { 515 665 scope.setPopped(); 516 return popScopeInternal(scope, shouldTrackClosedVariables); 517 } 518 519 bool declareVariable(const Identifier* ident) 666 popScopeInternal(scope, shouldTrackClosedVariables); 667 } 668 669 ALWAYS_INLINE void popScope(AutoCleanupLexicalScope& cleanupScope, bool shouldTrackClosedVariables) 670 { 671 RELEASE_ASSERT(cleanupScope.isValid()); 672 ScopeRef& scope = cleanupScope.scope(); 673 cleanupScope.setPopped(); 674 popScopeInternal(scope, shouldTrackClosedVariables); 675 } 676 677 enum class DeclarationType { VarDeclaration, LexicalDeclaration }; 678 bool declareVariable(const Identifier* ident, typename Parser::DeclarationType type = DeclarationType::VarDeclaration, bool isConstant = false) 520 679 { 521 680 unsigned i = m_scopeStack.size() - 1; 522 681 ASSERT(i < m_scopeStack.size()); 523 while (!m_scopeStack[i].allowsNewDecls()) { 682 683 if (type == DeclarationType::VarDeclaration) { 684 while (!m_scopeStack[i].allowsVarDeclarations()) { 685 i--; 686 ASSERT(i < m_scopeStack.size()); 687 } 688 689 return m_scopeStack[i].declareVariable(ident, isConstant); 690 } 691 692 ASSERT(type == DeclarationType::LexicalDeclaration); 693 694 // Lexical variables declared at a top level scope that shadow arguments or vars are not allowed. 695 if (m_statementDepth == 1 && (hasDeclaredParameter(*ident) || hasDeclaredVariable(*ident))) 696 return false; 697 698 while (!m_scopeStack[i].allowsLexicalDeclarations()) { 524 699 i--; 525 700 ASSERT(i < m_scopeStack.size()); 526 701 } 527 return m_scopeStack[i].declareVariable(ident); 702 703 return m_scopeStack[i].declareLexicalVariable(ident); 528 704 } 529 705 … … 532 708 unsigned i = m_scopeStack.size() - 1; 533 709 ASSERT(i < m_scopeStack.size()); 534 while (!m_scopeStack[i].allows NewDecls()) {710 while (!m_scopeStack[i].allowsVarDeclarations()) { 535 711 i--; 536 712 ASSERT(i < m_scopeStack.size()); … … 538 714 return m_scopeStack[i].hasDeclaredVariable(ident); 539 715 } 540 716 541 717 NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident) 542 718 { 543 719 unsigned i = m_scopeStack.size() - 1; 544 720 ASSERT(i < m_scopeStack.size()); 545 while (!m_scopeStack[i].allows NewDecls()) {721 while (!m_scopeStack[i].allowsVarDeclarations()) { 546 722 i--; 547 723 ASSERT(i < m_scopeStack.size()); … … 555 731 m_scopeStack.last().declareWrite(ident); 556 732 } 557 733 558 734 ScopeStack m_scopeStack; 559 735 … … 566 742 String parseInner(); 567 743 568 void didFinishParsing(SourceElements*, DeclarationStacks::VarStack&, 569 DeclarationStacks::FunctionStack&, CodeFeatures, int, IdentifierSet&, const Vector<RefPtr<UniquedStringImpl>>&&); 744 void didFinishParsing(SourceElements*, DeclarationStacks::FunctionStack&, VariableEnvironment&, CodeFeatures, int, const Vector<RefPtr<UniquedStringImpl>>&&); 570 745 571 746 // Used to determine type of error to report. … … 754 929 } 755 930 void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); } 756 void popLabel( ) { currentScope()->popLabel(); }931 void popLabel(ScopeRef scope) { scope->popLabel(); } 757 932 ScopeLabelInfo* getLabel(const Identifier* label) 758 933 { … … 765 940 } 766 941 return result; 942 } 943 944 ALWAYS_INLINE bool isLETMaskedAsIDENT() 945 { 946 return match(LET) && !strictMode(); 767 947 } 768 948 … … 774 954 #endif 775 955 template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&); 776 template <class TreeBuilder> TreeStatement parseVar Declaration(TreeBuilder&);956 template <class TreeBuilder> TreeStatement parseVariableDeclaration(TreeBuilder&, DeclarationType); 777 957 template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&); 778 958 template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&); … … 811 991 template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); 812 992 enum VarDeclarationListContext { ForLoopContext, VarDeclarationContext }; 813 template <class TreeBuilder> TreeExpression parseVar DeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext);993 template <class TreeBuilder> TreeExpression parseVariableDeclarationList(TreeBuilder&, int& declarations, TreeDestructuringPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd, VarDeclarationListContext, DeclarationType); 814 994 template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); 815 995 … … 819 999 #endif 820 1000 821 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, const Identifier&, int depth, JSToken );822 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, int depth = 0);823 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder& );1001 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern createBindingPattern(TreeBuilder&, DestructuringKind, const Identifier&, int depth, JSToken, AssignmentContext); 1002 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern parseDestructuringPattern(TreeBuilder&, DestructuringKind, AssignmentContext = AssignmentContext::DeclarationStatement, int depth = 0); 1003 template <class TreeBuilder> NEVER_INLINE TreeDestructuringPattern tryParseDestructuringPatternExpression(TreeBuilder&, AssignmentContext); 824 1004 template <class TreeBuilder> NEVER_INLINE TreeExpression parseDefaultValueForDestructuringPattern(TreeBuilder&); 825 1005 … … 947 1127 ConstructorKind m_defaultConstructorKind; 948 1128 ThisTDZMode m_thisTDZMode; 949 DeclarationStacks::VarStackm_varDeclarations;1129 VariableEnvironment m_varDeclarations; 950 1130 DeclarationStacks::FunctionStack m_funcDeclarations; 951 IdentifierSet m_capturedVariables;952 1131 Vector<RefPtr<UniquedStringImpl>> m_closedVariables; 953 1132 CodeFeatures m_features; … … 1021 1200 m_varDeclarations, 1022 1201 m_funcDeclarations, 1023 m_capturedVariables,1202 currentScope()->finalizeLexicalEnvironment(), 1024 1203 *m_source, 1025 1204 m_features,
Note:
See TracChangeset
for help on using the changeset viewer.