Changeset 209974 in webkit
- Timestamp:
- Dec 18, 2016 11:04:20 AM (7 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r209966 r209974 1 2016-12-18 Mark Lam <mark.lam@apple.com> 2 3 Rename finallyActionRegister to completionTypeRegister and only store int JSValues in it. 4 https://bugs.webkit.org/show_bug.cgi?id=165979 5 6 Reviewed by Saam Barati. 7 8 This patch makes it so that we only store int JSValues in the finallyActionRegister 9 thereby making type prediction on this register more successful for JITs. In so 10 doing, we are able to get some additional benefits: 11 12 1. Renamed the following: 13 FinallyRegistersScope => CompletionRecordScope 14 finallyActionRegister => completionTypeRegister 15 finallyReturnValueRegister => completionValueRegister 16 17 These new names are more in line with the ES spec, which describes these 18 values as the completion record and its type and value properties. 19 https://tc39.github.io/ecma262/#sec-completion-record-specification-type 20 21 2. We now think of the Break and Continue jumpIDs as encodings of CompletionType 22 (in our implementation of completion type). As a result, we only need one of 23 each of the emitter methods for getting, setting, and compare-and-jump on the 24 completion type. The code using these methods also reads much clearer now. 25 26 3. Finally blocks' op_catch should now always pop the caught Exception object into 27 the completionValueRegister instead of the completionTypeRegister (formerly 28 finallyActionRegister). 29 30 Also removed the restoreScopeRegister() call in the IteratorClose catch block 31 because that is an implementation specific synthesized catch block, and we 32 can guarantee that it never needs to resolve any symbols from the scope. Hence, 33 there is no need to restore the scope register. 34 35 * bytecompiler/BytecodeGenerator.cpp: 36 (JSC::BytecodeGenerator::emitEnumeration): 37 (JSC::BytecodeGenerator::emitJumpViaFinallyIfNeeded): 38 (JSC::BytecodeGenerator::emitReturnViaFinallyIfNeeded): 39 (JSC::BytecodeGenerator::emitFinallyCompletion): 40 (JSC::BytecodeGenerator::allocateCompletionRecordRegisters): 41 (JSC::BytecodeGenerator::releaseCompletionRecordRegisters): 42 (JSC::BytecodeGenerator::emitJumpIfCompletionType): 43 (JSC::BytecodeGenerator::allocateFinallyRegisters): Deleted. 44 (JSC::BytecodeGenerator::releaseFinallyRegisters): Deleted. 45 (JSC::BytecodeGenerator::emitCompareFinallyActionAndJumpIf): Deleted. 46 * bytecompiler/BytecodeGenerator.h: 47 (JSC::bytecodeOffsetToJumpID): 48 (JSC::FinallyJump::FinallyJump): 49 (JSC::FinallyContext::registerJump): 50 (JSC::BytecodeGenerator::CompletionRecordScope::CompletionRecordScope): 51 (JSC::BytecodeGenerator::CompletionRecordScope::~CompletionRecordScope): 52 (JSC::BytecodeGenerator::completionTypeRegister): 53 (JSC::BytecodeGenerator::completionValueRegister): 54 (JSC::BytecodeGenerator::emitSetCompletionType): 55 (JSC::BytecodeGenerator::emitSetCompletionValue): 56 (JSC::BytecodeGenerator::FinallyRegistersScope::FinallyRegistersScope): Deleted. 57 (JSC::BytecodeGenerator::FinallyRegistersScope::~FinallyRegistersScope): Deleted. 58 (JSC::BytecodeGenerator::finallyActionRegister): Deleted. 59 (JSC::BytecodeGenerator::finallyReturnValueRegister): Deleted. 60 (JSC::BytecodeGenerator::emitSetFinallyActionToNormalCompletion): Deleted. 61 (JSC::BytecodeGenerator::emitSetFinallyActionToReturnCompletion): Deleted. 62 (JSC::BytecodeGenerator::emitSetFinallyActionToJumpID): Deleted. 63 (JSC::BytecodeGenerator::emitSetFinallyReturnValueRegister): Deleted. 64 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNormalCompletion): Deleted. 65 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotJump): Deleted. 66 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsReturnCompletion): Deleted. 67 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotReturnCompletion): Deleted. 68 (JSC::BytecodeGenerator::emitJumpIfFinallyActionIsNotThrowCompletion): Deleted. 69 (JSC::BytecodeGenerator::emitJumpIfCompletionTypeIsThrow): Deleted. 70 (JSC::BytecodeGenerator::bytecodeOffsetToJumpID): Deleted. 71 * bytecompiler/NodesCodegen.cpp: 72 (JSC::TryNode::emitBytecode): 73 1 74 2016-12-17 Saam Barati <sbarati@apple.com> 2 75 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r209956 r209974 4127 4127 void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack, ForOfNode* forLoopNode, RegisterID* forLoopSymbolTable) 4128 4128 { 4129 FinallyRegistersScope finallyRegistersScope(*this);4129 CompletionRecordScope completionRecordScope(*this); 4130 4130 4131 4131 RefPtr<RegisterID> subject = newTemporary(); … … 4170 4170 popTry(tryData, finallyViaThrowLabel.get()); 4171 4171 4172 RefPtr<Label> finallyBodyLabel = newLabel(); 4173 RefPtr<RegisterID> finallyExceptionRegister = newTemporary(); 4172 4174 RegisterID* unused = newTemporary(); 4173 emitCatch(finallyActionRegister(), unused); 4174 // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw. 4175 4176 emitCatch(completionValueRegister(), unused); 4177 emitSetCompletionType(CompletionType::Throw); 4178 emitMove(finallyExceptionRegister.get(), completionValueRegister()); 4179 emitJump(finallyBodyLabel.get()); 4175 4180 4176 4181 emitLabel(finallyLabel.get()); 4182 emitMoveEmptyValue(finallyExceptionRegister.get()); 4183 4184 emitLabel(finallyBodyLabel.get()); 4177 4185 restoreScopeRegister(); 4178 4186 … … 4181 4189 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword); 4182 4190 emitJumpIfTrue(emitIsUndefined(newTemporary(), returnMethod.get()), finallyDone.get()); 4183 4184 RefPtr<RegisterID> originalFinallyActionRegister = newTemporary();4185 emitMove(originalFinallyActionRegister.get(), finallyActionRegister());4186 4191 4187 4192 RefPtr<Label> returnCallTryStart = newLabel(); … … 4210 4215 RegisterID* unused = newTemporary(); 4211 4216 emitCatch(exceptionRegister.get(), unused); 4212 restoreScopeRegister(); 4217 // Since this is a synthesized catch block and we're guaranteed to never need 4218 // to resolve any symbols from the scope, we can skip restoring the scope 4219 // register here. 4213 4220 4214 4221 RefPtr<Label> throwLabel = newLabel(); 4215 emitJumpIf CompletionTypeIsThrow(originalFinallyActionRegister.get(), throwLabel.get());4216 emitMove( originalFinallyActionRegister.get(), exceptionRegister.get());4222 emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyExceptionRegister.get()), throwLabel.get()); 4223 emitMove(exceptionRegister.get(), finallyExceptionRegister.get()); 4217 4224 4218 4225 emitLabel(throwLabel.get()); 4219 emitThrow( originalFinallyActionRegister.get());4226 emitThrow(exceptionRegister.get()); 4220 4227 4221 4228 emitLabel(endCatchLabel.get()); … … 4820 4827 return false; // No finallys to thread through. 4821 4828 4822 intjumpID = bytecodeOffsetToJumpID(instructions().size());4829 auto jumpID = bytecodeOffsetToJumpID(instructions().size()); 4823 4830 int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth); 4824 4831 outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget); 4825 4832 4826 emitSet FinallyActionToJumpID(jumpID);4833 emitSetCompletionType(jumpID); 4827 4834 emitJump(innermostFinallyContext->finallyLabel()); 4828 4835 return true; // We'll be jumping to a finally block. … … 4850 4857 return false; // No finallys to thread through. 4851 4858 4852 emitSet FinallyActionToReturnCompletion();4853 emitSet FinallyReturnValueRegister(returnRegister);4859 emitSetCompletionType(CompletionType::Return); 4860 emitSetCompletionValue(returnRegister); 4854 4861 emitJump(innermostFinallyContext->finallyLabel()); 4855 4862 return true; // We'll be jumping to a finally block. … … 4858 4865 void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, Label* normalCompletionLabel) 4859 4866 { 4860 // FIXME: switch the finallyActionRegister to only store int values for all CompletionTypes. This is more optimal for JIT type speculation. 4861 // https://bugs.webkit.org/show_bug.cgi?id=165979 4862 emitJumpIfFinallyActionIsNormalCompletion(normalCompletionLabel); 4867 emitJumpIfCompletionType(op_stricteq, CompletionType::Normal, normalCompletionLabel); 4863 4868 4864 4869 if (context.numberOfBreaksOrContinues() || context.handlesReturns()) { … … 4870 4875 RefPtr<Label> nextLabel = newLabel(); 4871 4876 auto& jump = context.jumps(i); 4872 emitJumpIf FinallyActionIsNotJump(jump.jumpID, nextLabel.get());4877 emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get()); 4873 4878 4874 4879 restoreScopeRegister(jump.targetLexicalScopeIndex); 4875 emitSet FinallyActionToNormalCompletion();4880 emitSetCompletionType(CompletionType::Normal); 4876 4881 emitJump(jump.targetLabel.get()); 4877 4882 … … 4881 4886 bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps; 4882 4887 if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns()) 4883 emitJumpIf FinallyActionIsNotThrowCompletion(outerContext->finallyLabel());4888 emitJumpIfCompletionType(op_nstricteq, CompletionType::Throw, outerContext->finallyLabel()); 4884 4889 4885 4890 } else { … … 4891 4896 RefPtr<Label> nextLabel = newLabel(); 4892 4897 auto& jump = context.jumps(i); 4893 emitJumpIf FinallyActionIsNotJump(jump.jumpID, nextLabel.get());4898 emitJumpIfCompletionType(op_nstricteq, jump.jumpID, nextLabel.get()); 4894 4899 4895 4900 restoreScopeRegister(jump.targetLexicalScopeIndex); 4896 emitSet FinallyActionToNormalCompletion();4901 emitSetCompletionType(CompletionType::Normal); 4897 4902 emitJump(jump.targetLabel.get()); 4898 4903 … … 4902 4907 if (context.handlesReturns()) { 4903 4908 RefPtr<Label> notReturnLabel = newLabel(); 4904 emitJumpIf FinallyActionIsNotReturnCompletion(notReturnLabel.get());4909 emitJumpIfCompletionType(op_nstricteq, CompletionType::Return, notReturnLabel.get()); 4905 4910 4906 4911 emitWillLeaveCallFrameDebugHook(); 4907 emitReturn( finallyReturnValueRegister(), ReturnFrom::Finally);4912 emitReturn(completionValueRegister(), ReturnFrom::Finally); 4908 4913 4909 4914 emitLabel(notReturnLabel.get()); … … 4911 4916 } 4912 4917 } 4913 emitThrow( finallyActionRegister());4914 } 4915 4916 bool BytecodeGenerator::allocate FinallyRegisters()4917 { 4918 if (m_ finallyActionRegister)4918 emitThrow(completionValueRegister()); 4919 } 4920 4921 bool BytecodeGenerator::allocateCompletionRecordRegisters() 4922 { 4923 if (m_completionTypeRegister) 4919 4924 return false; 4920 4925 4921 ASSERT(!m_ finallyReturnValueRegister);4922 m_ finallyActionRegister = newTemporary();4923 m_ finallyReturnValueRegister = newTemporary();4924 4925 emitSet FinallyActionToNormalCompletion();4926 emitMoveEmptyValue(m_ finallyReturnValueRegister.get());4926 ASSERT(!m_completionValueRegister); 4927 m_completionTypeRegister = newTemporary(); 4928 m_completionValueRegister = newTemporary(); 4929 4930 emitSetCompletionType(CompletionType::Normal); 4931 emitMoveEmptyValue(m_completionValueRegister.get()); 4927 4932 return true; 4928 4933 } 4929 4934 4930 void BytecodeGenerator::release FinallyRegisters()4931 { 4932 ASSERT(m_ finallyActionRegister && m_finallyReturnValueRegister);4933 m_ finallyActionRegister = nullptr;4934 m_ finallyReturnValueRegister = nullptr;4935 } 4936 4937 void BytecodeGenerator::emit CompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget)4935 void BytecodeGenerator::releaseCompletionRecordRegisters() 4936 { 4937 ASSERT(m_completionTypeRegister && m_completionValueRegister); 4938 m_completionTypeRegister = nullptr; 4939 m_completionValueRegister = nullptr; 4940 } 4941 4942 void BytecodeGenerator::emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType type, Label* jumpTarget) 4938 4943 { 4939 4944 RefPtr<RegisterID> tempRegister = newTemporary(); 4940 RegisterID* valueConstant = addConstantValue(JSValue( value));4945 RegisterID* valueConstant = addConstantValue(JSValue(static_cast<int>(type))); 4941 4946 OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType()); 4942 4947 4943 auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, finallyActionRegister(), operandTypes);4948 auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, completionTypeRegister(), operandTypes); 4944 4949 emitJumpIfTrue(equivalenceResult, jumpTarget); 4945 4950 } -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r209952 r209974 81 81 }; 82 82 83 // https://tc39.github.io/ecma262/#sec-completion-record-specification-type 84 // 85 // For the Break and Continue cases, instead of using the Break and Continue enum values 86 // below, we use the unique jumpID of the break and continue statement as the encoding 87 // for the CompletionType value. emitFinallyCompletion() uses this jumpID value later 88 // to determine the appropriate jump target to jump to after executing the relevant finally 89 // blocks. The jumpID is computed as: 90 // jumpID = bytecodeOffset (of the break/continue node) + CompletionType::NumberOfTypes. 91 // Hence, there won't be any collision between jumpIDs and CompletionType enums. 92 enum class CompletionType : int { 93 Normal, 94 Break, 95 Continue, 96 Return, 97 Throw, 98 99 NumberOfTypes 100 }; 101 102 inline CompletionType bytecodeOffsetToJumpID(unsigned offset) 103 { 104 int jumpIDAsInt = offset + static_cast<int>(CompletionType::NumberOfTypes); 105 ASSERT(jumpIDAsInt >= static_cast<int>(CompletionType::NumberOfTypes)); 106 return static_cast<CompletionType>(jumpIDAsInt); 107 } 108 83 109 struct FinallyJump { 84 FinallyJump( intjumpID, int targetLexicalScopeIndex, Label* targetLabel)110 FinallyJump(CompletionType jumpID, int targetLexicalScopeIndex, Label* targetLabel) 85 111 : jumpID(jumpID) 86 112 , targetLexicalScopeIndex(targetLexicalScopeIndex) … … 88 114 { } 89 115 90 int jumpID { 0 };91 int targetLexicalScopeIndex { 0 };116 CompletionType jumpID; 117 int targetLexicalScopeIndex; 92 118 RefPtr<Label> targetLabel; 93 119 }; … … 117 143 void setHandlesReturns() { m_handlesReturns = true; } 118 144 119 void registerJump( intjumpID, int lexicalScopeIndex, Label* targetLabel)145 void registerJump(CompletionType jumpID, int lexicalScopeIndex, Label* targetLabel) 120 146 { 121 147 if (!m_jumps) … … 776 802 void emitWillLeaveCallFrameDebugHook(); 777 803 778 class FinallyRegistersScope {804 class CompletionRecordScope { 779 805 public: 780 FinallyRegistersScope(BytecodeGenerator& generator, bool needFinallyRegisters = true)806 CompletionRecordScope(BytecodeGenerator& generator, bool needCompletionRecordRegisters = true) 781 807 : m_generator(generator) 782 808 { 783 if (need FinallyRegisters && m_generator.allocateFinallyRegisters())809 if (needCompletionRecordRegisters && m_generator.allocateCompletionRecordRegisters()) 784 810 m_needToReleaseOnDestruction = true; 785 811 } 786 ~ FinallyRegistersScope()812 ~CompletionRecordScope() 787 813 { 788 814 if (m_needToReleaseOnDestruction) 789 m_generator.release FinallyRegisters();815 m_generator.releaseCompletionRecordRegisters(); 790 816 } 791 817 … … 795 821 }; 796 822 797 RegisterID* finallyActionRegister() const 798 { 799 ASSERT(m_finallyActionRegister); 800 return m_finallyActionRegister.get(); 801 } 802 RegisterID* finallyReturnValueRegister() const 803 { 804 ASSERT(m_finallyReturnValueRegister); 805 return m_finallyReturnValueRegister.get(); 806 } 807 808 void emitSetFinallyActionToNormalCompletion() 809 { 810 emitMoveEmptyValue(m_finallyActionRegister.get()); 811 } 812 void emitSetFinallyActionToReturnCompletion() 813 { 814 emitLoad(finallyActionRegister(), JSValue(static_cast<int>(CompletionType::Return))); 815 } 816 void emitSetFinallyActionToJumpID(int jumpID) 817 { 818 emitLoad(finallyActionRegister(), JSValue(jumpID)); 819 } 820 void emitSetFinallyReturnValueRegister(RegisterID* reg) 821 { 822 emitMove(finallyReturnValueRegister(), reg); 823 } 824 825 void emitJumpIfFinallyActionIsNormalCompletion(Label* jumpTarget) 826 { 827 emitJumpIfTrue(emitIsEmpty(newTemporary(), finallyActionRegister()), jumpTarget); 828 } 829 830 void emitJumpIfFinallyActionIsNotJump(int jumpID, Label* jumpTarget) 831 { 832 emitCompareFinallyActionAndJumpIf(op_nstricteq, jumpID, jumpTarget); 833 } 834 835 void emitJumpIfFinallyActionIsReturnCompletion(Label* jumpTarget) 836 { 837 emitCompareFinallyActionAndJumpIf(op_stricteq, static_cast<int>(CompletionType::Return), jumpTarget); 838 } 839 void emitJumpIfFinallyActionIsNotReturnCompletion(Label* jumpTarget) 840 { 841 emitCompareFinallyActionAndJumpIf(op_nstricteq, static_cast<int>(CompletionType::Return), jumpTarget); 842 } 843 844 void emitJumpIfFinallyActionIsNotThrowCompletion(Label* jumpTarget) 845 { 846 emitJumpIfTrue(emitIsNumber(newTemporary(), finallyActionRegister()), jumpTarget); 847 } 848 void emitJumpIfCompletionTypeIsThrow(RegisterID* reg, Label* jumpTarget) 849 { 850 emitJumpIfFalse(emitIsNumber(newTemporary(), reg), jumpTarget); 851 } 823 RegisterID* completionTypeRegister() const 824 { 825 ASSERT(m_completionTypeRegister); 826 return m_completionTypeRegister.get(); 827 } 828 RegisterID* completionValueRegister() const 829 { 830 ASSERT(m_completionValueRegister); 831 return m_completionValueRegister.get(); 832 } 833 834 void emitSetCompletionType(CompletionType type) 835 { 836 emitLoad(completionTypeRegister(), JSValue(static_cast<int>(type))); 837 } 838 void emitSetCompletionValue(RegisterID* reg) 839 { 840 emitMove(completionValueRegister(), reg); 841 } 842 843 void emitJumpIfCompletionType(OpcodeID compareOpcode, CompletionType, Label* jumpTarget); 852 844 853 845 bool emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label* jumpTarget); … … 856 848 857 849 private: 858 void emitCompareFinallyActionAndJumpIf(OpcodeID compareOpcode, int value, Label* jumpTarget); 859 860 int bytecodeOffsetToJumpID(unsigned offset) 861 { 862 int jumpID = offset + static_cast<int>(CompletionType::NumberOfTypes); 863 ASSERT(jumpID >= static_cast<int>(CompletionType::NumberOfTypes)); 864 return jumpID; 865 } 866 867 bool allocateFinallyRegisters(); 868 void releaseFinallyRegisters(); 850 bool allocateCompletionRecordRegisters(); 851 void releaseCompletionRecordRegisters(); 869 852 870 853 public: … … 1101 1084 RegisterID* m_promiseCapabilityRegister { nullptr }; 1102 1085 1103 // The spec at https://tc39.github.io/ecma262/#sec-completion-record-specification-type says 1104 // that there are 5 types of completions. Conceptually, we'll set m_finallyActionRegister 1105 // to one of these completion types. However, to optimize our implementation, we'll encode 1106 // these type info as follows: 1107 // 1108 // CompletionType::Normal - m_finallyActionRegister is empty. 1109 // CompletionType::Break - m_finallyActionRegister is an int JSValue jumpID. 1110 // CompletionType::Continue - m_finallyActionRegister is an int JSValue jumpID. 1111 // CompletionType::Return - m_finallyActionRegister is the Return enum as an int JSValue. 1112 // CompletionType::Throw - m_finallyActionRegister is the Exception object to rethrow. 1113 // 1114 // Hence, of the 5 completion types, only the CompletionType::Return enum value is used in 1115 // our implementation. The rest are just provided for completeness. 1116 1117 enum class CompletionType : int { 1118 Normal, 1119 Break, 1120 Continue, 1121 Return, 1122 Throw, 1123 1124 NumberOfTypes 1125 }; 1126 1127 RefPtr<RegisterID> m_finallyActionRegister; 1128 RefPtr<RegisterID> m_finallyReturnValueRegister; 1086 RefPtr<RegisterID> m_completionTypeRegister; 1087 RefPtr<RegisterID> m_completionValueRegister; 1129 1088 1130 1089 FinallyContext* m_currentFinallyContext { nullptr }; … … 1144 1103 void popLocalControlFlowScope(); 1145 1104 1146 // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 1105 // FIXME: Restore overflow checking with UnsafeVectorOverflow once SegmentVector supports it. 1147 1106 // https://bugs.webkit.org/show_bug.cgi?id=165980 1148 1107 SegmentedVector<ControlFlowScope, 16> m_controlFlowScopeStack; -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r209952 r209974 3288 3288 3289 3289 ASSERT(m_catchBlock || m_finallyBlock); 3290 BytecodeGenerator:: FinallyRegistersScope finallyRegistersScope(generator, m_finallyBlock);3290 BytecodeGenerator::CompletionRecordScope completionRecordScope(generator, m_finallyBlock); 3291 3291 3292 3292 RefPtr<Label> catchLabel; … … 3317 3317 generator.emitNode(dst, m_tryBlock); 3318 3318 3319 // The finallyActionRegister is an empty value by default, which implies CompletionType::Normal.3320 3319 if (m_finallyBlock) 3321 3320 generator.emitJump(finallyLabel.get()); … … 3352 3351 3353 3352 if (m_finallyBlock) { 3354 generator.emitSet FinallyActionToNormalCompletion();3353 generator.emitSetCompletionType(CompletionType::Normal); 3355 3354 generator.emitJump(finallyLabel.get()); 3356 3355 generator.popTry(tryData, finallyViaThrowLabel.get()); … … 3367 3366 generator.emitLabel(finallyViaThrowLabel.get()); 3368 3367 RegisterID* unused = generator.newTemporary(); 3369 generator.emitCatch(generator. finallyActionRegister(), unused);3370 // Setting the finallyActionRegister to the caught exception here implies CompletionType::Throw.3368 generator.emitCatch(generator.completionValueRegister(), unused); 3369 generator.emitSetCompletionType(CompletionType::Throw); 3371 3370 3372 3371 // Entry to the finally block for CompletionTypes other than Throw.
Note: See TracChangeset
for help on using the changeset viewer.