Changeset 198927 in webkit
- Timestamp:
- Mar 31, 2016 4:01:29 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r198926 r198927 1 2016-03-31 Saam barati <sbarati@apple.com> 2 3 parsing arrow function expressions slows down the parser by 8% lets recoup some loss 4 https://bugs.webkit.org/show_bug.cgi?id=155988 5 6 Reviewed by Benjamin Poulain. 7 8 * js/parser-syntax-check-expected.txt: 9 * js/script-tests/parser-syntax-check.js: 10 (catch): 11 1 12 2016-03-31 Per Arne Vollan <peavo@outlook.com> 2 13 -
trunk/LayoutTests/js/parser-syntax-check-expected.txt
r198233 r198927 1041 1041 PASS Invalid: "function foo(...if) { }" 1042 1042 PASS Invalid: "function f() { function foo(...if) { } }" 1043 Arrow function 1044 PASS Valid: "var x = (x) => x;" 1045 PASS Valid: "function f() { var x = (x) => x; }" 1046 PASS Valid: "var x = (x, y, z) => x;" 1047 PASS Valid: "function f() { var x = (x, y, z) => x; }" 1048 PASS Valid: "var x = ({x}, [y], z) => x;" 1049 PASS Valid: "function f() { var x = ({x}, [y], z) => x; }" 1050 PASS Valid: "var x = ({x = 30}, [y], z) => x;" 1051 PASS Valid: "function f() { var x = ({x = 30}, [y], z) => x; }" 1052 PASS Valid: "var x = (x = 20) => x;" 1053 PASS Valid: "function f() { var x = (x = 20) => x; }" 1054 PASS Valid: "var x = ([x] = 20, y) => x;" 1055 PASS Valid: "function f() { var x = ([x] = 20, y) => x; }" 1056 PASS Valid: "var x = ([x = 20] = 20) => x;" 1057 PASS Valid: "function f() { var x = ([x = 20] = 20) => x; }" 1058 PASS Valid: "var x = foo => x;" 1059 PASS Valid: "function f() { var x = foo => x; }" 1060 PASS Valid: "var x = foo => x => x => x => x;" 1061 PASS Valid: "function f() { var x = foo => x => x => x => x; }" 1062 PASS Valid: "var x = foo => x => (x = 20) => (x = 20) => x;" 1063 PASS Valid: "function f() { var x = foo => x => (x = 20) => (x = 20) => x; }" 1064 PASS Valid: "var x = foo => x => x => x => {x};" 1065 PASS Valid: "function f() { var x = foo => x => x => x => {x}; }" 1066 PASS Valid: "var x = ([x = 25]) => x => x => ({x} = {});" 1067 PASS Valid: "function f() { var x = ([x = 25]) => x => x => ({x} = {}); }" 1068 PASS Invalid: "var x = foo => x => x => {x} => x;" 1069 PASS Invalid: "function f() { var x = foo => x => x => {x} => x; }" 1070 PASS Invalid: "var x = {x} = 20 => x;" 1071 PASS Invalid: "function f() { var x = {x} = 20 => x; }" 1072 PASS Invalid: "var x = [x] = 20 => x;" 1073 PASS Invalid: "function f() { var x = [x] = 20 => x; }" 1074 PASS Invalid: "var x = [x = 25] = 20 => x;" 1075 PASS Invalid: "function f() { var x = [x = 25] = 20 => x; }" 1076 PASS Invalid: "var x = ([x = 25]) =>;" 1077 PASS Invalid: "function f() { var x = ([x = 25]) =>; }" 1078 PASS Invalid: "var x = ([x = 25]) => x =>;" 1079 PASS Invalid: "function f() { var x = ([x = 25]) => x =>; }" 1080 PASS Invalid: "var x = ([x = 25]) => x => x =>;" 1081 PASS Invalid: "function f() { var x = ([x = 25]) => x => x =>; }" 1082 PASS Invalid: "var x = ([x = 25]) => x => x => {;" 1083 PASS Invalid: "function f() { var x = ([x = 25]) => x => x => {; }" 1084 PASS Invalid: "var x ==> x;" 1085 PASS Invalid: "function f() { var x ==> x; }" 1086 PASS Invalid: "var x = x ==> x;" 1087 PASS Invalid: "function f() { var x = x ==> x; }" 1088 PASS Valid: "foo((x) => x)" with ReferenceError 1089 PASS Valid: "function f() { foo((x) => x) }" 1090 PASS Valid: "foo((x, y, z) => x)" with ReferenceError 1091 PASS Valid: "function f() { foo((x, y, z) => x) }" 1092 PASS Valid: "foo(({x}, [y], z) => x)" with ReferenceError 1093 PASS Valid: "function f() { foo(({x}, [y], z) => x) }" 1094 PASS Valid: "foo(({x = 30}, [y], z) => x)" with ReferenceError 1095 PASS Valid: "function f() { foo(({x = 30}, [y], z) => x) }" 1096 PASS Valid: "foo((x = 20) => x)" with ReferenceError 1097 PASS Valid: "function f() { foo((x = 20) => x) }" 1098 PASS Valid: "foo(([x] = 20, y) => x)" with ReferenceError 1099 PASS Valid: "function f() { foo(([x] = 20, y) => x) }" 1100 PASS Valid: "foo(([x = 20] = 20) => x)" with ReferenceError 1101 PASS Valid: "function f() { foo(([x = 20] = 20) => x) }" 1102 PASS Valid: "foo(foo => x)" with ReferenceError 1103 PASS Valid: "function f() { foo(foo => x) }" 1104 PASS Valid: "foo(foo => x => x => x => x)" with ReferenceError 1105 PASS Valid: "function f() { foo(foo => x => x => x => x) }" 1106 PASS Valid: "foo(foo => x => (x = 20) => (x = 20) => x)" with ReferenceError 1107 PASS Valid: "function f() { foo(foo => x => (x = 20) => (x = 20) => x) }" 1108 PASS Valid: "foo(foo => x => x => x => {x})" with ReferenceError 1109 PASS Valid: "function f() { foo(foo => x => x => x => {x}) }" 1110 PASS Valid: "foo(([x = 25]) => x => x => ({x} = {}))" with ReferenceError 1111 PASS Valid: "function f() { foo(([x = 25]) => x => x => ({x} = {})) }" 1112 PASS Invalid: "foo(foo => x => x => {x} => x)" 1113 PASS Invalid: "function f() { foo(foo => x => x => {x} => x) }" 1114 PASS Invalid: "foo({x} = 20 => x)" 1115 PASS Invalid: "function f() { foo({x} = 20 => x) }" 1116 PASS Invalid: "foo([x] = 20 => x)" 1117 PASS Invalid: "function f() { foo([x] = 20 => x) }" 1118 PASS Invalid: "foo([x = 25] = 20 => x)" 1119 PASS Invalid: "function f() { foo([x = 25] = 20 => x) }" 1120 PASS Invalid: "foo(([x = 25]) =>)" 1121 PASS Invalid: "function f() { foo(([x = 25]) =>) }" 1122 PASS Invalid: "foo(([x = 25]) => x =>)" 1123 PASS Invalid: "function f() { foo(([x = 25]) => x =>) }" 1124 PASS Invalid: "foo(([x = 25]) => x => x =>)" 1125 PASS Invalid: "function f() { foo(([x = 25]) => x => x =>) }" 1126 PASS Invalid: "foo(([x = 25]) => x => x => {)" 1127 PASS Invalid: "function f() { foo(([x = 25]) => x => x => {) }" 1128 PASS Invalid: "foo(x ==> x)" 1129 PASS Invalid: "function f() { foo(x ==> x) }" 1130 PASS Invalid: "foo(x = x ==> x)" 1131 PASS Invalid: "function f() { foo(x = x ==> x) }" 1043 1132 PASS e.line is 1 1044 1133 PASS foo is 'PASS' -
trunk/LayoutTests/js/script-tests/parser-syntax-check.js
r198233 r198927 619 619 invalid("function foo(...if) { }"); 620 620 621 debug("Arrow function"); 622 valid("var x = (x) => x;"); 623 valid("var x = (x, y, z) => x;"); 624 valid("var x = ({x}, [y], z) => x;"); 625 valid("var x = ({x = 30}, [y], z) => x;"); 626 valid("var x = (x = 20) => x;"); 627 valid("var x = ([x] = 20, y) => x;"); 628 valid("var x = ([x = 20] = 20) => x;"); 629 valid("var x = foo => x;"); 630 valid("var x = foo => x => x => x => x;"); 631 valid("var x = foo => x => (x = 20) => (x = 20) => x;"); 632 valid("var x = foo => x => x => x => {x};"); 633 valid("var x = ([x = 25]) => x => x => ({x} = {});"); 634 invalid("var x = foo => x => x => {x} => x;"); 635 invalid("var x = {x} = 20 => x;"); 636 invalid("var x = [x] = 20 => x;"); 637 invalid("var x = [x = 25] = 20 => x;"); 638 invalid("var x = ([x = 25]) =>;"); 639 invalid("var x = ([x = 25]) => x =>;"); 640 invalid("var x = ([x = 25]) => x => x =>;"); 641 invalid("var x = ([x = 25]) => x => x => {;"); 642 invalid("var x ==> x;"); 643 invalid("var x = x ==> x;"); 644 valid("foo((x) => x)"); 645 valid("foo((x, y, z) => x)"); 646 valid("foo(({x}, [y], z) => x)"); 647 valid("foo(({x = 30}, [y], z) => x)"); 648 valid("foo((x = 20) => x)"); 649 valid("foo(([x] = 20, y) => x)"); 650 valid("foo(([x = 20] = 20) => x)"); 651 valid("foo(foo => x)"); 652 valid("foo(foo => x => x => x => x)"); 653 valid("foo(foo => x => (x = 20) => (x = 20) => x)"); 654 valid("foo(foo => x => x => x => {x})"); 655 valid("foo(([x = 25]) => x => x => ({x} = {}))"); 656 invalid("foo(foo => x => x => {x} => x)"); 657 invalid("foo({x} = 20 => x)"); 658 invalid("foo([x] = 20 => x)"); 659 invalid("foo([x = 25] = 20 => x)"); 660 invalid("foo(([x = 25]) =>)"); 661 invalid("foo(([x = 25]) => x =>)"); 662 invalid("foo(([x = 25]) => x => x =>)"); 663 invalid("foo(([x = 25]) => x => x => {)"); 664 invalid("foo(x ==> x)"); 665 invalid("foo(x = x ==> x)"); 621 666 622 667 -
trunk/Source/JavaScriptCore/ChangeLog
r198919 r198927 1 2016-03-31 Saam barati <sbarati@apple.com> 2 3 parsing arrow function expressions slows down the parser by 8% lets recoup some loss 4 https://bugs.webkit.org/show_bug.cgi?id=155988 5 6 Reviewed by Benjamin Poulain. 7 8 We used to eagerly check if we're parsing an arrow function. 9 We did this inside parseAssignmentExpression(), and it was 10 very costly. The reason it was costly is that arrow functions 11 might start with an identifier. This means anytime we saw an 12 identifier we would have to do a lookahead, and then most likely 13 backtrack because more often than not, we wouldn't see "=>" 14 as the next token. 15 16 In this patch I implement a new approach. We just parse 17 the lhs of an assignment expression eagerly without doing any 18 lookahead. Retroactively, if we see that we might have started 19 with an arrow function, and we don't have a valid lhs or the 20 next token is a "=>", we try to parse as an arrow function. 21 22 Here are a few examples motivating why this is valid: 23 24 `x => x` 25 In this example: 26 - "x" is a valid arrow function starting point. 27 - "x" also happens to be a valid lhs 28 - because we see "=>" as the next token, we parse as an arrow function and succeed. 29 30 `(x) => x` 31 In this example: 32 - "(" is a valid arrow function starting point. 33 - "(x)" also happens to be a valid lhs 34 - because we see "=>" as the next token, we parse as an arrow function and succeed. 35 36 `({x = 30}) => x;` 37 In this example: 38 - "(" is a valid arrow function starting point. 39 - "({x = 30})" is NOT a valid lhs. Because of this, we try to parse it as an arrow function and succeed. 40 41 There is one interesting implementation detail where we might 42 parse something that is both a valid LHS but happens 43 to actually be the arrow function parameters. The valid LHS 44 parsing might declare such variables as "uses" which would cause 45 weird capture analysis. This patch also introduces a mechanism 46 to backtrack on used variable analysis. 47 48 This is a 3.5%-4.5% octane code load speedup. 49 50 * parser/Lexer.h: 51 (JSC::Lexer::sawError): 52 (JSC::Lexer::setSawError): 53 (JSC::Lexer::getErrorMessage): 54 (JSC::Lexer::setErrorMessage): 55 (JSC::Lexer::sourceURL): 56 (JSC::Lexer::sourceMappingURL): 57 * parser/Parser.cpp: 58 (JSC::Parser<LexerType>::isArrowFunctionParameters): 59 (JSC::Parser<LexerType>::parseAssignmentExpression): 60 (JSC::Parser<LexerType>::parsePrimaryExpression): 61 * parser/Parser.h: 62 (JSC::Scope::Scope): 63 (JSC::Scope::startSwitch): 64 (JSC::Scope::declareParameter): 65 (JSC::Scope::usedVariablesContains): 66 (JSC::Scope::useVariable): 67 (JSC::Scope::pushUsedVariableSet): 68 (JSC::Scope::currentUsedVariablesSize): 69 (JSC::Scope::revertToPreviousUsedVariables): 70 (JSC::Scope::setNeedsFullActivation): 71 (JSC::Scope::needsFullActivation): 72 (JSC::Scope::isArrowFunctionBoundary): 73 (JSC::Scope::setInnerArrowFunctionUsesEvalAndUseArgumentsIfNeeded): 74 (JSC::Scope::collectFreeVariables): 75 (JSC::Scope::fillParametersForSourceProviderCache): 76 (JSC::Scope::restoreFromSourceProviderCache): 77 (JSC::Scope::setIsModule): 78 1 79 2016-03-31 Yusuke Suzuki <utatane.tea@gmail.com> 2 80 -
trunk/Source/JavaScriptCore/parser/Lexer.h
r194017 r198927 86 86 // Functions for use after parsing. 87 87 bool sawError() const { return m_error; } 88 void setSawError(bool sawError) { m_error = sawError; } 88 89 String getErrorMessage() const { return m_lexErrorMessage; } 90 void setErrorMessage(const String& errorMessage) { m_lexErrorMessage = errorMessage; } 89 91 String sourceURL() const { return m_sourceURLDirective; } 90 92 String sourceMappingURL() const { return m_sourceMappingURLDirective; } -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r198472 r198927 61 61 #define semanticFailIfFalse(cond, ...) do { if (!(cond)) internalFailWithMessage(false, __VA_ARGS__); } while (0) 62 62 #define regexFail(failure) do { setErrorMessage(failure); return 0; } while (0) 63 #define restoreSavePointAndFail(savePoint, message) do { restoreSavePointWithError(savePoint, message); return 0; } while (0)64 63 #define failDueToUnexpectedToken() do {\ 65 64 logError(true);\ … … 360 359 bool Parser<LexerType>::isArrowFunctionParameters() 361 360 { 362 bool isArrowFunction = false;363 364 if (match(EOFTOK))365 return false;366 367 361 bool isOpenParen = match(OPENPAREN); 368 362 bool isIdent = match(IDENT); … … 371 365 return false; 372 366 367 bool isArrowFunction = false; 373 368 SavePoint saveArrowFunctionPoint = createSavePoint(); 374 369 … … 2991 2986 int initialNonLHSCount = m_parserState.nonLHSCount; 2992 2987 bool maybeAssignmentPattern = match(OPENBRACE) || match(OPENBRACKET); 2988 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX) 2989 bool wasOpenParen = match(OPENPAREN); 2990 bool isValidArrowFunctionStart = match(OPENPAREN) || match(IDENT); 2993 2991 SavePoint savePoint = createSavePoint(); 2992 size_t usedVariablesSize; 2993 if (wasOpenParen) { 2994 usedVariablesSize = currentScope()->currentUsedVariablesSize(); 2995 currentScope()->pushUsedVariableSet(); 2996 } 2997 #endif 2994 2998 2995 2999 #if ENABLE(ES6_GENERATORS) … … 2998 3002 #endif 2999 3003 3004 TreeExpression lhs = parseConditionalExpression(context); 3005 3000 3006 #if ENABLE(ES6_ARROWFUNCTION_SYNTAX) 3001 if (isArrowFunctionParameters()) 3002 return parseArrowFunctionExpression(context); 3007 if (isValidArrowFunctionStart && !match(EOFTOK)) { 3008 bool isArrowFunctionToken = match(ARROWFUNCTION); 3009 if (!lhs || isArrowFunctionToken) { 3010 SavePoint errorRestorationSavePoint = createSavePointForError(); 3011 String oldErrorMessage = m_errorMessage; 3012 String oldLexerErrorMessage = m_lexer->getErrorMessage(); 3013 bool hasLexerError = m_lexer->sawError(); 3014 restoreSavePoint(savePoint); 3015 if (isArrowFunctionParameters()) { 3016 if (wasOpenParen) 3017 currentScope()->revertToPreviousUsedVariables(usedVariablesSize); 3018 return parseArrowFunctionExpression(context); 3019 } 3020 restoreSavePointWithError(errorRestorationSavePoint, oldErrorMessage); 3021 m_lexer->setErrorMessage(oldLexerErrorMessage); 3022 m_lexer->setSawError(hasLexerError); 3023 if (isArrowFunctionToken) 3024 failDueToUnexpectedToken(); 3025 } 3026 } 3027 3003 3028 #endif 3004 3005 TreeExpression lhs = parseConditionalExpression(context);3006 3029 3007 3030 if (!lhs && (!maybeAssignmentPattern || !classifier.indicatesPossiblePattern())) … … 3010 3033 if (maybeAssignmentPattern && (!lhs || (context.isObjectOrArrayLiteral(lhs) && match(EQUAL)))) { 3011 3034 String expressionError = m_errorMessage; 3035 String oldLexerErrorMessage = m_lexer->getErrorMessage(); 3036 bool hasLexerError = m_lexer->sawError(); 3012 3037 SavePoint expressionErrorLocation = createSavePointForError(); 3013 3038 restoreSavePoint(savePoint); 3014 3039 auto pattern = tryParseDestructuringPatternExpression(context, AssignmentContext::AssignmentExpression); 3015 if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) 3016 restoreSavePointAndFail(expressionErrorLocation, expressionError); 3040 if (classifier.indicatesPossiblePattern() && (!pattern || !match(EQUAL))) { 3041 restoreSavePointWithError(expressionErrorLocation, expressionError); 3042 m_lexer->setErrorMessage(oldLexerErrorMessage); 3043 m_lexer->setSawError(hasLexerError); 3044 return 0; 3045 } 3017 3046 failIfFalse(pattern, "Cannot parse assignment pattern"); 3018 3047 consumeOrFail(EQUAL, "Expected '=' following assignment pattern"); … … 3667 3696 JSTokenLocation location(tokenLocation()); 3668 3697 next(); 3698 if (UNLIKELY(match(ARROWFUNCTION))) 3699 return 0; 3669 3700 currentScope()->useVariable(ident, m_vm->propertyNames->eval == *ident); 3670 3701 m_parserState.lastIdentifier = ident; -
trunk/Source/JavaScriptCore/parser/Parser.h
r198375 r198927 42 42 #include <wtf/RefPtr.h> 43 43 #include <wtf/SmallPtrSet.h> 44 45 namespace JSC {46 struct Scope;47 }48 49 namespace WTF {50 template <> struct VectorTraits<JSC::Scope> : VectorTraitsBase</* is pod */ false, void> {51 static const bool canMoveWithMemcpy = true;52 };53 }54 44 55 45 namespace JSC { … … 192 182 , m_innerArrowFunctionFeatures(0) 193 183 { 184 m_usedVariables.append(UniquedStringImplPtrSet()); 185 } 186 187 Scope(Scope&& other) 188 : m_vm(other.m_vm) 189 , m_shadowsArguments(other.m_shadowsArguments) 190 , m_usesEval(other.m_usesEval) 191 , m_needsFullActivation(other.m_needsFullActivation) 192 , m_hasDirectSuper(other.m_hasDirectSuper) 193 , m_needsSuperBinding(other.m_needsSuperBinding) 194 , m_allowsVarDeclarations(other.m_allowsVarDeclarations) 195 , m_allowsLexicalDeclarations(other.m_allowsLexicalDeclarations) 196 , m_strictMode(other.m_strictMode) 197 , m_isFunction(other.m_isFunction) 198 , m_isGenerator(other.m_isGenerator) 199 , m_isGeneratorBoundary(other.m_isGeneratorBoundary) 200 , m_isArrowFunction(other.m_isArrowFunction) 201 , m_isArrowFunctionBoundary(other.m_isArrowFunctionBoundary) 202 , m_isLexicalScope(other.m_isLexicalScope) 203 , m_isFunctionBoundary(other.m_isFunctionBoundary) 204 , m_isValidStrictMode(other.m_isValidStrictMode) 205 , m_hasArguments(other.m_hasArguments) 206 , m_isEvalContext(other.m_isEvalContext) 207 , m_constructorKind(other.m_constructorKind) 208 , m_expectedSuperBinding(other.m_expectedSuperBinding) 209 , m_loopDepth(other.m_loopDepth) 210 , m_switchDepth(other.m_switchDepth) 211 , m_innerArrowFunctionFeatures(other.m_innerArrowFunctionFeatures) 212 , m_labels(WTFMove(other.m_labels)) 213 , m_declaredParameters(WTFMove(other.m_declaredParameters)) 214 , m_declaredVariables(WTFMove(other.m_declaredVariables)) 215 , m_lexicalVariables(WTFMove(other.m_lexicalVariables)) 216 , m_usedVariables(WTFMove(other.m_usedVariables)) 217 , m_closedVariableCandidates(WTFMove(other.m_closedVariableCandidates)) 218 , m_writtenVariables(WTFMove(other.m_writtenVariables)) 219 , m_moduleScopeData(WTFMove(other.m_moduleScopeData)) 220 , m_functionDeclarations(WTFMove(other.m_functionDeclarations)) 221 { 194 222 } 195 223 … … 463 491 } 464 492 465 bool usedVariablesContains(UniquedStringImpl* impl) const { return m_usedVariables.contains(impl); } 493 bool usedVariablesContains(UniquedStringImpl* impl) const 494 { 495 for (const UniquedStringImplPtrSet& set : m_usedVariables) { 496 if (set.contains(impl)) 497 return true; 498 } 499 return false; 500 } 466 501 void useVariable(const Identifier* ident, bool isEval) 467 502 { 503 useVariable(ident->impl(), isEval); 504 } 505 void useVariable(UniquedStringImpl* impl, bool isEval) 506 { 468 507 m_usesEval |= isEval; 469 m_usedVariables.add(ident->impl()); 470 } 508 m_usedVariables.last().add(impl); 509 } 510 511 void pushUsedVariableSet() { m_usedVariables.append(UniquedStringImplPtrSet()); } 512 size_t currentUsedVariablesSize() { return m_usedVariables.size(); } 513 514 void revertToPreviousUsedVariables(size_t size) { m_usedVariables.resize(size); } 471 515 472 516 void setNeedsFullActivation() { m_needsFullActivation = true; } … … 505 549 setInnerArrowFunctionUsesEval(); 506 550 507 if ( m_usedVariables.contains(m_vm->propertyNames->arguments.impl()))551 if (usedVariablesContains(m_vm->propertyNames->arguments.impl())) 508 552 setInnerArrowFunctionUsesArguments(); 509 553 } … … 515 559 516 560 { 517 for (UniquedStringImpl* impl : nestedScope->m_usedVariables) { 518 if (nestedScope->m_declaredVariables.contains(impl) || nestedScope->m_lexicalVariables.contains(impl)) 519 continue; 520 521 // "arguments" reference should be resolved at function boudary. 522 if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunctionBoundary()) 523 continue; 524 525 m_usedVariables.add(impl); 526 // We don't want a declared variable that is used in an inner scope to be thought of as captured if 527 // that inner scope is both a lexical scope and not a function. Only inner functions and "catch" 528 // statements can cause variables to be captured. 529 if (shouldTrackClosedVariables && (nestedScope->m_isFunctionBoundary || !nestedScope->m_isLexicalScope)) 530 m_closedVariableCandidates.add(impl); 561 UniquedStringImplPtrSet& destinationSet = m_usedVariables.last(); 562 for (const UniquedStringImplPtrSet& usedVariablesSet : nestedScope->m_usedVariables) { 563 for (UniquedStringImpl* impl : usedVariablesSet) { 564 if (nestedScope->m_declaredVariables.contains(impl) || nestedScope->m_lexicalVariables.contains(impl)) 565 continue; 566 567 // "arguments" reference should be resolved at function boudary. 568 if (nestedScope->isFunctionBoundary() && nestedScope->hasArguments() && impl == m_vm->propertyNames->arguments.impl() && !nestedScope->isArrowFunctionBoundary()) 569 continue; 570 571 destinationSet.add(impl); 572 // We don't want a declared variable that is used in an inner scope to be thought of as captured if 573 // that inner scope is both a lexical scope and not a function. Only inner functions and "catch" 574 // statements can cause variables to be captured. 575 if (shouldTrackClosedVariables && (nestedScope->m_isFunctionBoundary || !nestedScope->m_isLexicalScope)) 576 m_closedVariableCandidates.add(impl); 577 } 531 578 } 532 579 } … … 603 650 parameters.innerArrowFunctionFeatures = m_innerArrowFunctionFeatures; 604 651 copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables); 605 copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables); 652 for (const UniquedStringImplPtrSet& set : m_usedVariables) 653 copyCapturedVariablesToVector(set, parameters.usedVariables); 606 654 } 607 655 … … 613 661 m_innerArrowFunctionFeatures = info->innerArrowFunctionFeatures; 614 662 m_needsFullActivation = info->needsFullActivation; 663 UniquedStringImplPtrSet& destSet = m_usedVariables.last(); 615 664 for (unsigned i = 0; i < info->usedVariablesCount; ++i) 616 m_usedVariables.add(info->usedVariables()[i]);665 destSet.add(info->usedVariables()[i]); 617 666 for (unsigned i = 0; i < info->writtenVariablesCount; ++i) 618 667 m_writtenVariables.add(info->writtenVariables()[i]); … … 658 707 } 659 708 660 // All the fields in Scope must be able to use memcpy as their661 // move operation. If you add a field that violates this, make sure662 // to remove this comment and update WTF::VectorTraits<JSC::Scope>.663 709 const VM* m_vm; 664 710 bool m_shadowsArguments; … … 691 737 VariableEnvironment m_declaredVariables; 692 738 VariableEnvironment m_lexicalVariables; 693 UniquedStringImplPtrSetm_usedVariables;739 Vector<UniquedStringImplPtrSet, 6> m_usedVariables; 694 740 IdentifierSet m_closedVariableCandidates; 695 741 UniquedStringImplPtrSet m_writtenVariables;
Note: See TracChangeset
for help on using the changeset viewer.