Changeset 186996 in webkit
- Timestamp:
- Jul 18, 2015 1:12:14 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r186986 r186996 1 2015-07-18 Saam barati <saambarati1@gmail.com> 2 3 lexical scoping is broken with respect to "break" and "continue" 4 https://bugs.webkit.org/show_bug.cgi?id=147063 5 6 Reviewed by Filip Pizlo. 7 8 Bug #142944 which introduced "let" and lexical scoping 9 didn't properly hook into the bytecode generator's machinery 10 for calculating scope depth deltas for "break" and "continue". This 11 resulted in the bytecode generator popping an incorrect number 12 of scopes when lexical scopes were involved. 13 14 This patch fixes this problem and generalizes this machinery a bit. 15 This patch also renames old functions in a sensible way that is more 16 coherent in a world with lexical scoping. 17 18 * bytecompiler/BytecodeGenerator.cpp: 19 (JSC::BytecodeGenerator::BytecodeGenerator): 20 (JSC::BytecodeGenerator::newLabelScope): 21 (JSC::BytecodeGenerator::emitProfileType): 22 (JSC::BytecodeGenerator::pushLexicalScope): 23 (JSC::BytecodeGenerator::popLexicalScope): 24 (JSC::BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration): 25 (JSC::BytecodeGenerator::resolveType): 26 (JSC::BytecodeGenerator::emitResolveScope): 27 (JSC::BytecodeGenerator::emitGetFromScope): 28 (JSC::BytecodeGenerator::emitPutToScope): 29 (JSC::BytecodeGenerator::emitPushWithScope): 30 (JSC::BytecodeGenerator::emitGetParentScope): 31 (JSC::BytecodeGenerator::emitPopScope): 32 (JSC::BytecodeGenerator::emitPopWithOrCatchScope): 33 (JSC::BytecodeGenerator::emitPopScopes): 34 (JSC::BytecodeGenerator::calculateTargetScopeDepthForExceptionHandler): 35 (JSC::BytecodeGenerator::localScopeDepth): 36 (JSC::BytecodeGenerator::labelScopeDepth): 37 (JSC::BytecodeGenerator::emitThrowReferenceError): 38 (JSC::BytecodeGenerator::emitPushFunctionNameScope): 39 (JSC::BytecodeGenerator::pushScopedControlFlowContext): 40 (JSC::BytecodeGenerator::popScopedControlFlowContext): 41 (JSC::BytecodeGenerator::emitPushCatchScope): 42 (JSC::BytecodeGenerator::currentScopeDepth): Deleted. 43 * bytecompiler/BytecodeGenerator.h: 44 (JSC::BytecodeGenerator::hasFinaliser): 45 (JSC::BytecodeGenerator::scopeDepth): Deleted. 46 * bytecompiler/NodesCodegen.cpp: 47 (JSC::ContinueNode::trivialTarget): 48 (JSC::BreakNode::trivialTarget): 49 (JSC::ReturnNode::emitBytecode): 50 (JSC::WithNode::emitBytecode): 51 (JSC::TryNode::emitBytecode): 52 * tests/stress/lexical-scoping-break-continue.js: Added. 53 (assert): 54 (.): 55 1 56 2015-07-17 Filip Pizlo <fpizlo@apple.com> 2 57 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r186860 r186996 523 523 } 524 524 525 if (m_lexicalEnvironmentRegister) 526 pushScopedControlFlowContext(); 525 527 m_symbolTableStack.append(SymbolTableStackEntry{ Strong<SymbolTable>(*m_vm, m_symbolTable), m_lexicalEnvironmentRegister, false, symbolTableConstantIndex }); 526 528 m_TDZStack.append(std::make_pair(*parentScopeTDZVariables, false)); … … 628 630 629 631 // Allocate new label scope. 630 LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.632 LabelScope scope(type, name, labelScopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets. 631 633 m_labelScopes.append(scope); 632 634 return LabelScopePtr(m_labelScopes, m_labelScopes.size() - 1); … … 1211 1213 emitOpcode(op_profile_type); 1212 1214 instructions().append(registerToProfile->index()); 1213 instructions().append( currentScopeDepth());1215 instructions().append(localScopeDepth()); 1214 1216 instructions().append(flag); 1215 1217 instructions().append(identifier ? addConstant(*identifier) : 0); … … 1319 1321 1320 1322 emitMove(scopeRegister(), newScope); 1323 1324 pushScopedControlFlowContext(); 1321 1325 } 1322 1326 … … 1366 1370 if (hasCapturedVariables) { 1367 1371 RELEASE_ASSERT(stackEntry.m_scope); 1368 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), scopeRegister());1369 emitMove(scopeRegister(), parentScope.get());1372 emitPopScope(scopeRegister(), stackEntry.m_scope); 1373 popScopedControlFlowContext(); 1370 1374 stackEntry.m_scope->deref(); 1371 1375 } … … 1424 1428 // the assumption that the scope's register index is constant even 1425 1429 // though the value in that register will change on each loop iteration. 1426 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), scopeRegister());1430 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), loopScope); 1427 1431 emitMove(scopeRegister(), parentScope.get()); 1428 1432 … … 1573 1577 ResolveType BytecodeGenerator::resolveType() 1574 1578 { 1575 if (m_localScopeDepth) 1576 return Dynamic; 1579 for (unsigned i = m_symbolTableStack.size(); i--; ) { 1580 if (m_symbolTableStack[i].m_isWithOrCatch) 1581 return Dynamic; 1582 } 1583 1577 1584 if (m_symbolTable && m_symbolTable->usesNonStrictEval()) 1578 1585 return GlobalPropertyWithVarInjectionChecks; … … 1633 1640 instructions().append(addConstant(variable.ident())); 1634 1641 instructions().append(resolveType()); 1635 instructions().append( currentScopeDepth());1642 instructions().append(localScopeDepth()); 1636 1643 instructions().append(0); 1637 1644 return dst; … … 1667 1674 instructions().append(addConstant(variable.ident())); 1668 1675 instructions().append(ResolveModeAndType(resolveMode, variable.offset().isScope() ? LocalClosureVar : resolveType()).operand()); 1669 instructions().append( currentScopeDepth());1676 instructions().append(localScopeDepth()); 1670 1677 instructions().append(variable.offset().isScope() ? variable.offset().scopeOffset().offset() : 0); 1671 1678 instructions().append(profile); … … 1707 1714 ASSERT(resolveType() != LocalClosureVar); 1708 1715 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1709 instructions().append( currentScopeDepth());1716 instructions().append(localScopeDepth()); 1710 1717 } 1711 1718 instructions().append(!!offset ? offset.offset() : 0); … … 2475 2482 RegisterID* BytecodeGenerator::emitPushWithScope(RegisterID* dst, RegisterID* scope) 2476 2483 { 2477 ControlFlowContext context; 2478 context.isFinallyBlock = false; 2479 m_scopeContextStack.append(context); 2480 m_localScopeDepth++; 2484 pushScopedControlFlowContext(); 2481 2485 2482 2486 RegisterID* result = emitUnaryOp(op_push_with_scope, dst, scope); … … 2493 2497 } 2494 2498 2495 void BytecodeGenerator::emitPopScope(RegisterID* srcDst)2496 { 2497 ASSERT(m_scopeContextStack.size());2498 ASSERT(!m_scopeContextStack.last().isFinallyBlock);2499 2500 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), srcDst); 2501 emitMove(srcDst, parentScope.get()); 2502 2503 m_scopeContextStack.removeLast();2504 m_localScopeDepth--;2499 void BytecodeGenerator::emitPopScope(RegisterID* dst, RegisterID* scope) 2500 { 2501 RefPtr<RegisterID> parentScope = emitGetParentScope(newTemporary(), scope); 2502 emitMove(dst, parentScope.get()); 2503 } 2504 2505 void BytecodeGenerator::emitPopWithOrCatchScope(RegisterID* srcDst) 2506 { 2507 emitPopScope(srcDst, srcDst); 2508 popScopedControlFlowContext(); 2505 2509 SymbolTableStackEntry stackEntry = m_symbolTableStack.takeLast(); 2506 2510 RELEASE_ASSERT(stackEntry.m_isWithOrCatch); … … 2816 2820 void BytecodeGenerator::emitPopScopes(RegisterID* scope, int targetScopeDepth) 2817 2821 { 2818 ASSERT( scopeDepth() - targetScopeDepth >= 0);2819 2820 size_t scopeDelta = scopeDepth() - targetScopeDepth;2822 ASSERT(labelScopeDepth() - targetScopeDepth >= 0); 2823 2824 size_t scopeDelta = labelScopeDepth() - targetScopeDepth; 2821 2825 ASSERT(scopeDelta <= m_scopeContextStack.size()); 2822 2826 if (!scopeDelta) … … 2877 2881 int BytecodeGenerator::calculateTargetScopeDepthForExceptionHandler() const 2878 2882 { 2879 int depth = m_localScopeDepth; 2880 2881 for (unsigned i = m_symbolTableStack.size(); i--; ) { 2882 RegisterID* scope = m_symbolTableStack[i].m_scope; 2883 if (scope) 2884 depth++; 2885 } 2883 int depth = localScopeDepth(); 2886 2884 2887 2885 // Currently, we're maintaing compatibility with how things are done and letting the exception handling 2888 // code take into consideration the base activation of the function. There is no reason we shouldn't 2886 // code take into consideration the base activation of the function. There is no reason we shouldn't 2889 2887 // be able to calculate the exact depth here and let the exception handler not worry if there is a base 2890 2888 // activation or not. … … 2896 2894 } 2897 2895 2898 int BytecodeGenerator::currentScopeDepth() const 2899 { 2900 // This is the current number of JSScope descendents that would be allocated 2901 // in this function/program if this code were running. 2902 int depth = 0; 2903 for (unsigned i = m_symbolTableStack.size(); i--; ) { 2904 if (m_symbolTableStack[i].m_scope || m_symbolTableStack[i].m_isWithOrCatch) 2905 depth++; 2906 } 2907 return depth; 2896 int BytecodeGenerator::localScopeDepth() const 2897 { 2898 return m_localScopeDepth; 2899 } 2900 2901 int BytecodeGenerator::labelScopeDepth() const 2902 { 2903 return localScopeDepth() + m_finallyDepth; 2908 2904 } 2909 2905 … … 2931 2927 } 2932 2928 2933 void BytecodeGenerator:: emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes)2929 void BytecodeGenerator::pushScopedControlFlowContext() 2934 2930 { 2935 2931 ControlFlowContext context; … … 2937 2933 m_scopeContextStack.append(context); 2938 2934 m_localScopeDepth++; 2935 } 2936 2937 void BytecodeGenerator::popScopedControlFlowContext() 2938 { 2939 ASSERT(m_scopeContextStack.size()); 2940 ASSERT(!m_scopeContextStack.last().isFinallyBlock); 2941 m_scopeContextStack.removeLast(); 2942 m_localScopeDepth--; 2943 } 2944 2945 void BytecodeGenerator::emitPushCatchScope(RegisterID* dst, const Identifier& property, RegisterID* value, unsigned attributes) 2946 { 2947 pushScopedControlFlowContext(); 2939 2948 2940 2949 emitOpcode(op_push_name_scope); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r186860 r186996 586 586 void emitGetScope(); 587 587 RegisterID* emitPushWithScope(RegisterID* dst, RegisterID* scope); 588 void emitPopScope(RegisterID* srcDst); 588 void emitPopScope(RegisterID* dst, RegisterID* scope); 589 void emitPopWithOrCatchScope(RegisterID* srcDst); 589 590 RegisterID* emitGetParentScope(RegisterID* dst, RegisterID* scope); 590 591 591 592 void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart); 592 593 593 int scopeDepth() { return m_localScopeDepth + m_finallyDepth; }594 594 bool hasFinaliser() { return m_finallyDepth != 0; } 595 595 … … 625 625 void popLexicalScope(VariableEnvironmentNode*); 626 626 void prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode*, RegisterID* loopSymbolTable); 627 int labelScopeDepth() const; 627 628 628 629 private: … … 762 763 763 764 int calculateTargetScopeDepthForExceptionHandler() const; 764 int currentScopeDepth() const; 765 int localScopeDepth() const; 766 void pushScopedControlFlowContext(); 767 void popScopedControlFlowContext(); 765 768 766 769 Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r186959 r186996 2628 2628 ASSERT(scope); 2629 2629 2630 if (generator. scopeDepth() != scope->scopeDepth())2630 if (generator.labelScopeDepth() != scope->scopeDepth()) 2631 2631 return 0; 2632 2632 … … 2657 2657 ASSERT(scope); 2658 2658 2659 if (generator. scopeDepth() != scope->scopeDepth())2659 if (generator.labelScopeDepth() != scope->scopeDepth()) 2660 2660 return 0; 2661 2661 … … 2691 2691 generator.emitTypeProfilerExpressionInfo(divotStart(), divotEnd()); 2692 2692 } 2693 if (generator. scopeDepth()) {2693 if (generator.labelScopeDepth()) { 2694 2694 returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get()); 2695 2695 generator.emitPopScopes(generator.scopeRegister(), 0); … … 2715 2715 generator.emitPushWithScope(generator.scopeRegister(), scope.get()); 2716 2716 generator.emitNode(dst, m_statement); 2717 generator.emitPop Scope(generator.scopeRegister());2717 generator.emitPopWithOrCatchScope(generator.scopeRegister()); 2718 2718 } 2719 2719 … … 2968 2968 generator.emitProfileControlFlow(m_tryBlock->endOffset() + 1); 2969 2969 generator.emitNode(dst, m_catchBlock); 2970 generator.emitPop Scope(generator.scopeRegister());2970 generator.emitPopWithOrCatchScope(generator.scopeRegister()); 2971 2971 generator.emitLabel(catchEndLabel.get()); 2972 2972 }
Note: See TracChangeset
for help on using the changeset viewer.