Changeset 238989 in webkit
- Timestamp:
- Dec 7, 2018 4:25:46 PM (5 years ago)
- Location:
- releases/WebKitGTK/webkit-2.22
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
releases/WebKitGTK/webkit-2.22/JSTests/ChangeLog
r238986 r238989 1 2018-09-17 Mark Lam <mark.lam@apple.com> 2 3 Ensure that ForInContexts are invalidated if their loop local is over-written. 4 https://bugs.webkit.org/show_bug.cgi?id=189571 5 <rdar://problem/44402277> 6 7 Reviewed by Saam Barati. 8 9 * stress/regress-189571.js: Added. 10 1 11 2018-08-24 Yusuke Suzuki <yusukesuzuki@slowstart.org> 2 12 -
releases/WebKitGTK/webkit-2.22/Source/JavaScriptCore/ChangeLog
r238988 r238989 1 2018-09-18 Mark Lam <mark.lam@apple.com> 2 3 Ensure that ForInContexts are invalidated if their loop local is over-written. 4 https://bugs.webkit.org/show_bug.cgi?id=189571 5 <rdar://problem/44402277> 6 7 Reviewed by Saam Barati. 8 9 Instead of hunting down every place in the BytecodeGenerator that potentially 10 needs to invalidate an enclosing ForInContext (if one exists), we simply iterate 11 the bytecode range of the loop body when the ForInContext is popped, and 12 invalidate the context if we ever find the loop temp variable over-written. 13 14 This has 2 benefits: 15 1. It ensures that every type of opcode that can write to the loop temp will be 16 handled appropriately, not just the op_mov that we've hunted down. 17 2. It avoids us having to check the BytecodeGenerator's m_forInContextStack 18 every time we emit an op_mov (or other opcodes that can write to a local) 19 even when we're not inside a for-in loop. 20 21 JSC benchmarks show that that this change is performance neutral. 22 23 * bytecompiler/BytecodeGenerator.cpp: 24 (JSC::BytecodeGenerator::pushIndexedForInScope): 25 (JSC::BytecodeGenerator::popIndexedForInScope): 26 (JSC::BytecodeGenerator::pushStructureForInScope): 27 (JSC::BytecodeGenerator::popStructureForInScope): 28 (JSC::ForInContext::finalize): 29 (JSC::StructureForInContext::finalize): 30 (JSC::IndexedForInContext::finalize): 31 (JSC::BytecodeGenerator::invalidateForInContextForLocal): Deleted. 32 * bytecompiler/BytecodeGenerator.h: 33 (JSC::ForInContext::ForInContext): 34 (JSC::ForInContext::bodyBytecodeStartOffset const): 35 (JSC::StructureForInContext::StructureForInContext): 36 (JSC::IndexedForInContext::IndexedForInContext): 37 * bytecompiler/NodesCodegen.cpp: 38 (JSC::PostfixNode::emitResolve): 39 (JSC::PrefixNode::emitResolve): 40 (JSC::ReadModifyResolveNode::emitBytecode): 41 (JSC::AssignResolveNode::emitBytecode): 42 (JSC::EmptyLetExpression::emitBytecode): 43 (JSC::ForInNode::emitLoopHeader): 44 (JSC::ForOfNode::emitBytecode): 45 (JSC::BindingNode::bindValue const): 46 (JSC::AssignmentElementNode::bindValue const): 47 * runtime/CommonSlowPaths.cpp: 48 (JSC::SLOW_PATH_DECL): 49 1 50 2018-09-14 Mark Lam <mark.lam@apple.com> 2 51 -
releases/WebKitGTK/webkit-2.22/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r238988 r238989 37 37 #include "BytecodeGeneratorification.h" 38 38 #include "BytecodeLivenessAnalysis.h" 39 #include "BytecodeUseDef.h" 39 40 #include "CatchScope.h" 40 41 #include "DefinePropertyAttributes.h" … … 4625 4626 if (!localRegister) 4626 4627 return; 4627 m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister))); 4628 unsigned bodyBytecodeStartOffset = instructions().size(); 4629 m_forInContextStack.append(adoptRef(*new IndexedForInContext(localRegister, indexRegister, bodyBytecodeStartOffset))); 4628 4630 } 4629 4631 … … 4632 4634 if (!localRegister) 4633 4635 return; 4634 m_forInContextStack.last()->asIndexedForInContext().finalize(*this); 4636 unsigned bodyBytecodeEndOffset = instructions().size(); 4637 m_forInContextStack.last()->asIndexedForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset); 4635 4638 m_forInContextStack.removeLast(); 4636 4639 } … … 4735 4738 if (!localRegister) 4736 4739 return; 4737 m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister))); 4740 unsigned bodyBytecodeStartOffset = instructions().size(); 4741 m_forInContextStack.append(adoptRef(*new StructureForInContext(localRegister, indexRegister, propertyRegister, enumeratorRegister, bodyBytecodeStartOffset))); 4738 4742 } 4739 4743 … … 4742 4746 if (!localRegister) 4743 4747 return; 4744 m_forInContextStack.last()->asStructureForInContext().finalize(*this); 4748 unsigned bodyBytecodeEndOffset = instructions().size(); 4749 m_forInContextStack.last()->asStructureForInContext().finalize(*this, m_codeBlock.get(), bodyBytecodeEndOffset); 4745 4750 m_forInContextStack.removeLast(); 4746 4751 } 4747 4752 4748 void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister) 4753 RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip) 4754 { 4755 RefPtr<RegisterID> restArrayLength = newTemporary(); 4756 emitOpcode(op_get_rest_length); 4757 instructions().append(restArrayLength->index()); 4758 instructions().append(numParametersToSkip); 4759 4760 emitOpcode(op_create_rest); 4761 instructions().append(result->index()); 4762 instructions().append(restArrayLength->index()); 4763 instructions().append(numParametersToSkip); 4764 4765 return result; 4766 } 4767 4768 void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const String& error) 4769 { 4770 // FIXME: op_jneq_null treats "undetectable" objects as null/undefined. RequireObjectCoercible 4771 // thus incorrectly throws a TypeError for interfaces like HTMLAllCollection. 4772 Ref<Label> target = newLabel(); 4773 size_t begin = instructions().size(); 4774 emitOpcode(op_jneq_null); 4775 instructions().append(value->index()); 4776 instructions().append(target->bind(begin, instructions().size())); 4777 emitThrowTypeError(error); 4778 emitLabel(target.get()); 4779 } 4780 4781 void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result) 4782 { 4783 Ref<Label> mergePoint = newLabel(); 4784 unsigned yieldPointIndex = m_yieldPoints++; 4785 emitGeneratorStateChange(yieldPointIndex + 1); 4786 4787 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) { 4788 int suspendReason = static_cast<int32_t>(result); 4789 emitPutById(generatorRegister(), propertyNames().builtinNames().asyncGeneratorSuspendReasonPrivateName(), emitLoad(nullptr, jsNumber(suspendReason))); 4790 } 4791 4792 // Split the try range here. 4793 Ref<Label> savePoint = newEmittedLabel(); 4794 for (unsigned i = m_tryContextStack.size(); i--;) { 4795 TryContext& context = m_tryContextStack[i]; 4796 m_tryRanges.append(TryRange { 4797 context.start.copyRef(), 4798 savePoint.copyRef(), 4799 context.tryData 4800 }); 4801 // Try range will be restared at the merge point. 4802 context.start = mergePoint.get(); 4803 } 4804 Vector<TryContext> savedTryContextStack; 4805 m_tryContextStack.swap(savedTryContextStack); 4806 4807 emitOpcode(op_yield); 4808 instructions().append(generatorFrameRegister()->index()); 4809 instructions().append(yieldPointIndex); 4810 instructions().append(argument->index()); 4811 4812 // Restore the try contexts, which start offset is updated to the merge point. 4813 m_tryContextStack.swap(savedTryContextStack); 4814 emitLabel(mergePoint.get()); 4815 } 4816 4817 RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result) 4818 { 4819 emitYieldPoint(argument, result); 4820 4821 Ref<Label> normalLabel = newLabel(); 4822 RefPtr<RegisterID> condition = newTemporary(); 4823 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)))); 4824 emitJumpIfTrue(condition.get(), normalLabel.get()); 4825 4826 Ref<Label> throwLabel = newLabel(); 4827 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode)))); 4828 emitJumpIfTrue(condition.get(), throwLabel.get()); 4829 // Return. 4830 { 4831 RefPtr<RegisterID> returnRegister = generatorValueRegister(); 4832 bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get()); 4833 if (!hasFinally) 4834 emitReturn(returnRegister.get()); 4835 } 4836 4837 // Throw. 4838 emitLabel(throwLabel.get()); 4839 emitThrow(generatorValueRegister()); 4840 4841 // Normal. 4842 emitLabel(normalLabel.get()); 4843 return generatorValueRegister(); 4844 } 4845 4846 RegisterID* BytecodeGenerator::emitCallIterator(RegisterID* iterator, RegisterID* argument, ThrowableExpressionData* node) 4847 { 4848 CallArguments args(*this, nullptr); 4849 move(args.thisRegister(), argument); 4850 emitCall(iterator, iterator, NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4851 4852 return iterator; 4853 } 4854 4855 void BytecodeGenerator::emitAwait(RegisterID* value) 4856 { 4857 emitYield(value, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await); 4858 move(value, generatorValueRegister()); 4859 } 4860 4861 RegisterID* BytecodeGenerator::emitGetIterator(RegisterID* argument, ThrowableExpressionData* node) 4862 { 4863 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().iteratorSymbol); 4864 emitCallIterator(iterator.get(), argument, node); 4865 4866 return iterator.get(); 4867 } 4868 4869 RegisterID* BytecodeGenerator::emitGetAsyncIterator(RegisterID* argument, ThrowableExpressionData* node) 4870 { 4871 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().asyncIteratorSymbol); 4872 Ref<Label> asyncIteratorNotFound = newLabel(); 4873 Ref<Label> asyncIteratorFound = newLabel(); 4874 Ref<Label> iteratorReceived = newLabel(); 4875 4876 emitJumpIfTrue(emitUnaryOp(op_eq_null, newTemporary(), iterator.get()), asyncIteratorNotFound.get()); 4877 4878 emitJump(asyncIteratorFound.get()); 4879 emitLabel(asyncIteratorNotFound.get()); 4880 4881 RefPtr<RegisterID> commonIterator = emitGetIterator(argument, node); 4882 move(iterator.get(), commonIterator.get()); 4883 4884 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4885 4886 auto varCreateAsyncFromSyncIterator = variable(propertyNames().builtinNames().createAsyncFromSyncIteratorPrivateName()); 4887 RefPtr<RegisterID> scope = newTemporary(); 4888 move(scope.get(), emitResolveScope(scope.get(), varCreateAsyncFromSyncIterator)); 4889 RefPtr<RegisterID> createAsyncFromSyncIterator = emitGetFromScope(newTemporary(), scope.get(), varCreateAsyncFromSyncIterator, ThrowIfNotFound); 4890 4891 CallArguments args(*this, nullptr, 2); 4892 emitLoad(args.thisRegister(), jsUndefined()); 4893 4894 move(args.argumentRegister(0), iterator.get()); 4895 move(args.argumentRegister(1), nextMethod.get()); 4896 4897 JSTextPosition divot(m_scopeNode->firstLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset()); 4898 emitCall(iterator.get(), createAsyncFromSyncIterator.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No); 4899 4900 emitJump(iteratorReceived.get()); 4901 4902 emitLabel(asyncIteratorFound.get()); 4903 emitCallIterator(iterator.get(), argument, node); 4904 emitLabel(iteratorReceived.get()); 4905 4906 return iterator.get(); 4907 } 4908 4909 RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, ThrowableExpressionData* node) 4910 { 4911 RefPtr<RegisterID> value = newTemporary(); 4912 { 4913 RefPtr<RegisterID> iterator = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? emitGetAsyncIterator(argument, node) : emitGetIterator(argument, node); 4914 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4915 4916 Ref<Label> loopDone = newLabel(); 4917 { 4918 Ref<Label> nextElement = newLabel(); 4919 emitLoad(value.get(), jsUndefined()); 4920 4921 emitJump(nextElement.get()); 4922 4923 Ref<Label> loopStart = newLabel(); 4924 emitLabel(loopStart.get()); 4925 emitLoopHint(); 4926 4927 Ref<Label> branchOnResult = newLabel(); 4928 { 4929 emitYieldPoint(value.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield); 4930 4931 Ref<Label> normalLabel = newLabel(); 4932 Ref<Label> returnLabel = newLabel(); 4933 { 4934 RefPtr<RegisterID> condition = newTemporary(); 4935 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)))); 4936 emitJumpIfTrue(condition.get(), normalLabel.get()); 4937 4938 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ReturnMode)))); 4939 emitJumpIfTrue(condition.get(), returnLabel.get()); 4940 4941 // Fallthrough to ThrowMode. 4942 } 4943 4944 // Throw. 4945 { 4946 Ref<Label> throwMethodFound = newLabel(); 4947 RefPtr<RegisterID> throwMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().throwKeyword); 4948 emitJumpIfFalse(emitIsUndefined(newTemporary(), throwMethod.get()), throwMethodFound.get()); 4949 4950 EmitAwait emitAwaitInIteratorClose = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? EmitAwait::Yes : EmitAwait::No; 4951 emitIteratorClose(iterator.get(), node, emitAwaitInIteratorClose); 4952 4953 emitThrowTypeError("Delegated generator does not have a 'throw' method."_s); 4954 4955 emitLabel(throwMethodFound.get()); 4956 CallArguments throwArguments(*this, nullptr, 1); 4957 move(throwArguments.thisRegister(), iterator.get()); 4958 move(throwArguments.argumentRegister(0), generatorValueRegister()); 4959 emitCall(value.get(), throwMethod.get(), NoExpectedFunction, throwArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4960 4961 emitJump(branchOnResult.get()); 4962 } 4963 4964 // Return. 4965 emitLabel(returnLabel.get()); 4966 { 4967 Ref<Label> returnMethodFound = newLabel(); 4968 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword); 4969 emitJumpIfFalse(emitIsUndefined(newTemporary(), returnMethod.get()), returnMethodFound.get()); 4970 4971 move(value.get(), generatorValueRegister()); 4972 4973 Ref<Label> returnSequence = newLabel(); 4974 emitJump(returnSequence.get()); 4975 4976 emitLabel(returnMethodFound.get()); 4977 CallArguments returnArguments(*this, nullptr, 1); 4978 move(returnArguments.thisRegister(), iterator.get()); 4979 move(returnArguments.argumentRegister(0), generatorValueRegister()); 4980 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4981 4982 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) 4983 emitAwait(value.get()); 4984 4985 Ref<Label> returnIteratorResultIsObject = newLabel(); 4986 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), returnIteratorResultIsObject.get()); 4987 emitThrowTypeError("Iterator result interface is not an object."_s); 4988 4989 emitLabel(returnIteratorResultIsObject.get()); 4990 4991 Ref<Label> returnFromGenerator = newLabel(); 4992 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), returnFromGenerator.get()); 4993 4994 emitGetById(value.get(), value.get(), propertyNames().value); 4995 emitJump(loopStart.get()); 4996 4997 emitLabel(returnFromGenerator.get()); 4998 emitGetById(value.get(), value.get(), propertyNames().value); 4999 5000 emitLabel(returnSequence.get()); 5001 bool hasFinally = emitReturnViaFinallyIfNeeded(value.get()); 5002 if (!hasFinally) 5003 emitReturn(value.get()); 5004 } 5005 5006 // Normal. 5007 emitLabel(normalLabel.get()); 5008 move(value.get(), generatorValueRegister()); 5009 } 5010 5011 emitLabel(nextElement.get()); 5012 emitIteratorNextWithValue(value.get(), nextMethod.get(), iterator.get(), value.get(), node); 5013 5014 emitLabel(branchOnResult.get()); 5015 5016 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) 5017 emitAwait(value.get()); 5018 5019 Ref<Label> iteratorValueIsObject = newLabel(); 5020 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), iteratorValueIsObject.get()); 5021 emitThrowTypeError("Iterator result interface is not an object."_s); 5022 emitLabel(iteratorValueIsObject.get()); 5023 5024 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get()); 5025 emitGetById(value.get(), value.get(), propertyNames().value); 5026 5027 emitJump(loopStart.get()); 5028 } 5029 emitLabel(loopDone.get()); 5030 } 5031 5032 emitGetById(value.get(), value.get(), propertyNames().value); 5033 return value.get(); 5034 } 5035 5036 5037 void BytecodeGenerator::emitGeneratorStateChange(int32_t state) 5038 { 5039 RegisterID* completedState = emitLoad(nullptr, jsNumber(state)); 5040 emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState); 5041 } 5042 5043 bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget) 5044 { 5045 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0); 5046 size_t numberOfScopesToCheckForFinally = labelScopeDepth() - targetLabelScopeDepth; 5047 ASSERT(numberOfScopesToCheckForFinally <= m_controlFlowScopeStack.size()); 5048 if (!numberOfScopesToCheckForFinally) 5049 return false; 5050 5051 FinallyContext* innermostFinallyContext = nullptr; 5052 FinallyContext* outermostFinallyContext = nullptr; 5053 size_t scopeIndex = m_controlFlowScopeStack.size() - 1; 5054 while (numberOfScopesToCheckForFinally--) { 5055 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex--]; 5056 if (scope->isFinallyScope()) { 5057 FinallyContext* finallyContext = &scope->finallyContext; 5058 if (!innermostFinallyContext) 5059 innermostFinallyContext = finallyContext; 5060 outermostFinallyContext = finallyContext; 5061 finallyContext->incNumberOfBreaksOrContinues(); 5062 } 5063 } 5064 if (!outermostFinallyContext) 5065 return false; // No finallys to thread through. 5066 5067 auto jumpID = bytecodeOffsetToJumpID(instructions().size()); 5068 int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth); 5069 outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget); 5070 5071 emitSetCompletionType(jumpID); 5072 emitJump(*innermostFinallyContext->finallyLabel()); 5073 return true; // We'll be jumping to a finally block. 5074 } 5075 5076 bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister) 5077 { 5078 size_t numberOfScopesToCheckForFinally = m_controlFlowScopeStack.size(); 5079 if (!numberOfScopesToCheckForFinally) 5080 return false; 5081 5082 FinallyContext* innermostFinallyContext = nullptr; 5083 while (numberOfScopesToCheckForFinally) { 5084 size_t scopeIndex = --numberOfScopesToCheckForFinally; 5085 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex]; 5086 if (scope->isFinallyScope()) { 5087 FinallyContext* finallyContext = &scope->finallyContext; 5088 if (!innermostFinallyContext) 5089 innermostFinallyContext = finallyContext; 5090 finallyContext->setHandlesReturns(); 5091 } 5092 } 5093 if (!innermostFinallyContext) 5094 return false; // No finallys to thread through. 5095 5096 emitSetCompletionType(CompletionType::Return); 5097 emitSetCompletionValue(returnRegister); 5098 emitJump(*innermostFinallyContext->finallyLabel()); 5099 return true; // We'll be jumping to a finally block. 5100 } 5101 5102 void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, RegisterID* completionTypeRegister, Label& normalCompletionLabel) 5103 { 5104 if (context.numberOfBreaksOrContinues() || context.handlesReturns()) { 5105 emitJumpIf(op_stricteq, completionTypeRegister, CompletionType::Normal, normalCompletionLabel); 5106 5107 FinallyContext* outerContext = context.outerContext(); 5108 5109 size_t numberOfJumps = context.numberOfJumps(); 5110 ASSERT(outerContext || numberOfJumps == context.numberOfBreaksOrContinues()); 5111 5112 for (size_t i = 0; i < numberOfJumps; i++) { 5113 Ref<Label> nextLabel = newLabel(); 5114 auto& jump = context.jumps(i); 5115 emitJumpIf(op_nstricteq, completionTypeRegister, jump.jumpID, nextLabel.get()); 5116 5117 restoreScopeRegister(jump.targetLexicalScopeIndex); 5118 emitSetCompletionType(CompletionType::Normal); 5119 emitJump(jump.targetLabel.get()); 5120 5121 emitLabel(nextLabel.get()); 5122 } 5123 5124 if (outerContext) { 5125 // We are not the outermost finally. 5126 bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps; 5127 if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns()) 5128 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Throw, *outerContext->finallyLabel()); 5129 5130 } else { 5131 // We are the outermost finally. 5132 if (context.handlesReturns()) { 5133 Ref<Label> notReturnLabel = newLabel(); 5134 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Return, notReturnLabel.get()); 5135 5136 emitWillLeaveCallFrameDebugHook(); 5137 emitReturn(completionValueRegister(), ReturnFrom::Finally); 5138 5139 emitLabel(notReturnLabel.get()); 5140 } 5141 } 5142 } 5143 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Throw, normalCompletionLabel); 5144 emitThrow(completionValueRegister()); 5145 } 5146 5147 bool BytecodeGenerator::allocateCompletionRecordRegisters() 5148 { 5149 if (m_completionTypeRegister) 5150 return false; 5151 5152 ASSERT(!m_completionValueRegister); 5153 m_completionTypeRegister = newTemporary(); 5154 m_completionValueRegister = newTemporary(); 5155 5156 emitSetCompletionType(CompletionType::Normal); 5157 moveEmptyValue(m_completionValueRegister.get()); 5158 return true; 5159 } 5160 5161 void BytecodeGenerator::releaseCompletionRecordRegisters() 5162 { 5163 ASSERT(m_completionTypeRegister && m_completionValueRegister); 5164 m_completionTypeRegister = nullptr; 5165 m_completionValueRegister = nullptr; 5166 } 5167 5168 void BytecodeGenerator::emitJumpIf(OpcodeID compareOpcode, RegisterID* completionTypeRegister, CompletionType type, Label& jumpTarget) 5169 { 5170 RefPtr<RegisterID> tempRegister = newTemporary(); 5171 RegisterID* valueConstant = addConstantValue(jsNumber(static_cast<int>(type))); 5172 OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType()); 5173 5174 auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, completionTypeRegister, operandTypes); 5175 emitJumpIfTrue(equivalenceResult, jumpTarget); 5176 } 5177 5178 void ForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset) 4749 5179 { 4750 5180 // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if … … 4759 5189 // reassigned, or we'd have to resort to runtime checks to see if the variable had been 4760 5190 // reassigned from its original value. 4761 for (size_t i = m_forInContextStack.size(); i--; ) { 4762 ForInContext& context = m_forInContextStack[i].get(); 4763 if (context.local() == localRegister) 4764 context.invalidate(); 4765 } 4766 } 4767 4768 RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip) 4769 { 4770 RefPtr<RegisterID> restArrayLength = newTemporary(); 4771 emitOpcode(op_get_rest_length); 4772 instructions().append(restArrayLength->index()); 4773 instructions().append(numParametersToSkip); 4774 4775 emitOpcode(op_create_rest); 4776 instructions().append(result->index()); 4777 instructions().append(restArrayLength->index()); 4778 instructions().append(numParametersToSkip); 4779 4780 return result; 4781 } 4782 4783 void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const String& error) 4784 { 4785 // FIXME: op_jneq_null treats "undetectable" objects as null/undefined. RequireObjectCoercible 4786 // thus incorrectly throws a TypeError for interfaces like HTMLAllCollection. 4787 Ref<Label> target = newLabel(); 4788 size_t begin = instructions().size(); 4789 emitOpcode(op_jneq_null); 4790 instructions().append(value->index()); 4791 instructions().append(target->bind(begin, instructions().size())); 4792 emitThrowTypeError(error); 4793 emitLabel(target.get()); 4794 } 4795 4796 void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result) 4797 { 4798 Ref<Label> mergePoint = newLabel(); 4799 unsigned yieldPointIndex = m_yieldPoints++; 4800 emitGeneratorStateChange(yieldPointIndex + 1); 4801 4802 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) { 4803 int suspendReason = static_cast<int32_t>(result); 4804 emitPutById(generatorRegister(), propertyNames().builtinNames().asyncGeneratorSuspendReasonPrivateName(), emitLoad(nullptr, jsNumber(suspendReason))); 4805 } 4806 4807 // Split the try range here. 4808 Ref<Label> savePoint = newEmittedLabel(); 4809 for (unsigned i = m_tryContextStack.size(); i--;) { 4810 TryContext& context = m_tryContextStack[i]; 4811 m_tryRanges.append(TryRange { 4812 context.start.copyRef(), 4813 savePoint.copyRef(), 4814 context.tryData 5191 5192 for (unsigned offset = bodyBytecodeStartOffset(); isValid() && offset < bodyBytecodeEndOffset;) { 5193 UnlinkedInstruction* instruction = &generator.instructions()[offset]; 5194 OpcodeID opcodeID = instruction->u.opcode; 5195 unsigned opcodeLength = opcodeLengths[opcodeID]; 5196 5197 ASSERT(opcodeID != op_enter); 5198 computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, [&] (UnlinkedCodeBlock*, UnlinkedInstruction*, OpcodeID, int operand) { 5199 if (local()->index() == operand) 5200 invalidate(); 4815 5201 }); 4816 // Try range will be restared at the merge point. 4817 context.start = mergePoint.get(); 4818 } 4819 Vector<TryContext> savedTryContextStack; 4820 m_tryContextStack.swap(savedTryContextStack); 4821 4822 emitOpcode(op_yield); 4823 instructions().append(generatorFrameRegister()->index()); 4824 instructions().append(yieldPointIndex); 4825 instructions().append(argument->index()); 4826 4827 // Restore the try contexts, which start offset is updated to the merge point. 4828 m_tryContextStack.swap(savedTryContextStack); 4829 emitLabel(mergePoint.get()); 4830 } 4831 4832 RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result) 4833 { 4834 emitYieldPoint(argument, result); 4835 4836 Ref<Label> normalLabel = newLabel(); 4837 RefPtr<RegisterID> condition = newTemporary(); 4838 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)))); 4839 emitJumpIfTrue(condition.get(), normalLabel.get()); 4840 4841 Ref<Label> throwLabel = newLabel(); 4842 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode)))); 4843 emitJumpIfTrue(condition.get(), throwLabel.get()); 4844 // Return. 4845 { 4846 RefPtr<RegisterID> returnRegister = generatorValueRegister(); 4847 bool hasFinally = emitReturnViaFinallyIfNeeded(returnRegister.get()); 4848 if (!hasFinally) 4849 emitReturn(returnRegister.get()); 4850 } 4851 4852 // Throw. 4853 emitLabel(throwLabel.get()); 4854 emitThrow(generatorValueRegister()); 4855 4856 // Normal. 4857 emitLabel(normalLabel.get()); 4858 return generatorValueRegister(); 4859 } 4860 4861 RegisterID* BytecodeGenerator::emitCallIterator(RegisterID* iterator, RegisterID* argument, ThrowableExpressionData* node) 4862 { 4863 CallArguments args(*this, nullptr); 4864 move(args.thisRegister(), argument); 4865 emitCall(iterator, iterator, NoExpectedFunction, args, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4866 4867 return iterator; 4868 } 4869 4870 void BytecodeGenerator::emitAwait(RegisterID* value) 4871 { 4872 emitYield(value, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await); 4873 move(value, generatorValueRegister()); 4874 } 4875 4876 RegisterID* BytecodeGenerator::emitGetIterator(RegisterID* argument, ThrowableExpressionData* node) 4877 { 4878 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().iteratorSymbol); 4879 emitCallIterator(iterator.get(), argument, node); 4880 4881 return iterator.get(); 4882 } 4883 4884 RegisterID* BytecodeGenerator::emitGetAsyncIterator(RegisterID* argument, ThrowableExpressionData* node) 4885 { 4886 RefPtr<RegisterID> iterator = emitGetById(newTemporary(), argument, propertyNames().asyncIteratorSymbol); 4887 Ref<Label> asyncIteratorNotFound = newLabel(); 4888 Ref<Label> asyncIteratorFound = newLabel(); 4889 Ref<Label> iteratorReceived = newLabel(); 4890 4891 emitJumpIfTrue(emitUnaryOp(op_eq_null, newTemporary(), iterator.get()), asyncIteratorNotFound.get()); 4892 4893 emitJump(asyncIteratorFound.get()); 4894 emitLabel(asyncIteratorNotFound.get()); 4895 4896 RefPtr<RegisterID> commonIterator = emitGetIterator(argument, node); 4897 move(iterator.get(), commonIterator.get()); 4898 4899 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4900 4901 auto varCreateAsyncFromSyncIterator = variable(propertyNames().builtinNames().createAsyncFromSyncIteratorPrivateName()); 4902 RefPtr<RegisterID> scope = newTemporary(); 4903 move(scope.get(), emitResolveScope(scope.get(), varCreateAsyncFromSyncIterator)); 4904 RefPtr<RegisterID> createAsyncFromSyncIterator = emitGetFromScope(newTemporary(), scope.get(), varCreateAsyncFromSyncIterator, ThrowIfNotFound); 4905 4906 CallArguments args(*this, nullptr, 2); 4907 emitLoad(args.thisRegister(), jsUndefined()); 4908 4909 move(args.argumentRegister(0), iterator.get()); 4910 move(args.argumentRegister(1), nextMethod.get()); 4911 4912 JSTextPosition divot(m_scopeNode->firstLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset()); 4913 emitCall(iterator.get(), createAsyncFromSyncIterator.get(), NoExpectedFunction, args, divot, divot, divot, DebuggableCall::No); 4914 4915 emitJump(iteratorReceived.get()); 4916 4917 emitLabel(asyncIteratorFound.get()); 4918 emitCallIterator(iterator.get(), argument, node); 4919 emitLabel(iteratorReceived.get()); 4920 4921 return iterator.get(); 4922 } 4923 4924 RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, ThrowableExpressionData* node) 4925 { 4926 RefPtr<RegisterID> value = newTemporary(); 4927 { 4928 RefPtr<RegisterID> iterator = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? emitGetAsyncIterator(argument, node) : emitGetIterator(argument, node); 4929 RefPtr<RegisterID> nextMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().next); 4930 4931 Ref<Label> loopDone = newLabel(); 4932 { 4933 Ref<Label> nextElement = newLabel(); 4934 emitLoad(value.get(), jsUndefined()); 4935 4936 emitJump(nextElement.get()); 4937 4938 Ref<Label> loopStart = newLabel(); 4939 emitLabel(loopStart.get()); 4940 emitLoopHint(); 4941 4942 Ref<Label> branchOnResult = newLabel(); 4943 { 4944 emitYieldPoint(value.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield); 4945 4946 Ref<Label> normalLabel = newLabel(); 4947 Ref<Label> returnLabel = newLabel(); 4948 { 4949 RefPtr<RegisterID> condition = newTemporary(); 4950 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)))); 4951 emitJumpIfTrue(condition.get(), normalLabel.get()); 4952 4953 emitEqualityOp(op_stricteq, condition.get(), generatorResumeModeRegister(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ReturnMode)))); 4954 emitJumpIfTrue(condition.get(), returnLabel.get()); 4955 4956 // Fallthrough to ThrowMode. 4957 } 4958 4959 // Throw. 4960 { 4961 Ref<Label> throwMethodFound = newLabel(); 4962 RefPtr<RegisterID> throwMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().throwKeyword); 4963 emitJumpIfFalse(emitIsUndefined(newTemporary(), throwMethod.get()), throwMethodFound.get()); 4964 4965 EmitAwait emitAwaitInIteratorClose = parseMode() == SourceParseMode::AsyncGeneratorBodyMode ? EmitAwait::Yes : EmitAwait::No; 4966 emitIteratorClose(iterator.get(), node, emitAwaitInIteratorClose); 4967 4968 emitThrowTypeError("Delegated generator does not have a 'throw' method."_s); 4969 4970 emitLabel(throwMethodFound.get()); 4971 CallArguments throwArguments(*this, nullptr, 1); 4972 move(throwArguments.thisRegister(), iterator.get()); 4973 move(throwArguments.argumentRegister(0), generatorValueRegister()); 4974 emitCall(value.get(), throwMethod.get(), NoExpectedFunction, throwArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4975 4976 emitJump(branchOnResult.get()); 4977 } 4978 4979 // Return. 4980 emitLabel(returnLabel.get()); 4981 { 4982 Ref<Label> returnMethodFound = newLabel(); 4983 RefPtr<RegisterID> returnMethod = emitGetById(newTemporary(), iterator.get(), propertyNames().returnKeyword); 4984 emitJumpIfFalse(emitIsUndefined(newTemporary(), returnMethod.get()), returnMethodFound.get()); 4985 4986 move(value.get(), generatorValueRegister()); 4987 4988 Ref<Label> returnSequence = newLabel(); 4989 emitJump(returnSequence.get()); 4990 4991 emitLabel(returnMethodFound.get()); 4992 CallArguments returnArguments(*this, nullptr, 1); 4993 move(returnArguments.thisRegister(), iterator.get()); 4994 move(returnArguments.argumentRegister(0), generatorValueRegister()); 4995 emitCall(value.get(), returnMethod.get(), NoExpectedFunction, returnArguments, node->divot(), node->divotStart(), node->divotEnd(), DebuggableCall::No); 4996 4997 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) 4998 emitAwait(value.get()); 4999 5000 Ref<Label> returnIteratorResultIsObject = newLabel(); 5001 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), returnIteratorResultIsObject.get()); 5002 emitThrowTypeError("Iterator result interface is not an object."_s); 5003 5004 emitLabel(returnIteratorResultIsObject.get()); 5005 5006 Ref<Label> returnFromGenerator = newLabel(); 5007 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), returnFromGenerator.get()); 5008 5009 emitGetById(value.get(), value.get(), propertyNames().value); 5010 emitJump(loopStart.get()); 5011 5012 emitLabel(returnFromGenerator.get()); 5013 emitGetById(value.get(), value.get(), propertyNames().value); 5014 5015 emitLabel(returnSequence.get()); 5016 bool hasFinally = emitReturnViaFinallyIfNeeded(value.get()); 5017 if (!hasFinally) 5018 emitReturn(value.get()); 5019 } 5020 5021 // Normal. 5022 emitLabel(normalLabel.get()); 5023 move(value.get(), generatorValueRegister()); 5024 } 5025 5026 emitLabel(nextElement.get()); 5027 emitIteratorNextWithValue(value.get(), nextMethod.get(), iterator.get(), value.get(), node); 5028 5029 emitLabel(branchOnResult.get()); 5030 5031 if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) 5032 emitAwait(value.get()); 5033 5034 Ref<Label> iteratorValueIsObject = newLabel(); 5035 emitJumpIfTrue(emitIsObject(newTemporary(), value.get()), iteratorValueIsObject.get()); 5036 emitThrowTypeError("Iterator result interface is not an object."_s); 5037 emitLabel(iteratorValueIsObject.get()); 5038 5039 emitJumpIfTrue(emitGetById(newTemporary(), value.get(), propertyNames().done), loopDone.get()); 5040 emitGetById(value.get(), value.get(), propertyNames().value); 5041 5042 emitJump(loopStart.get()); 5043 } 5044 emitLabel(loopDone.get()); 5045 } 5046 5047 emitGetById(value.get(), value.get(), propertyNames().value); 5048 return value.get(); 5049 } 5050 5051 5052 void BytecodeGenerator::emitGeneratorStateChange(int32_t state) 5053 { 5054 RegisterID* completedState = emitLoad(nullptr, jsNumber(state)); 5055 emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState); 5056 } 5057 5058 bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget) 5059 { 5060 ASSERT(labelScopeDepth() - targetLabelScopeDepth >= 0); 5061 size_t numberOfScopesToCheckForFinally = labelScopeDepth() - targetLabelScopeDepth; 5062 ASSERT(numberOfScopesToCheckForFinally <= m_controlFlowScopeStack.size()); 5063 if (!numberOfScopesToCheckForFinally) 5064 return false; 5065 5066 FinallyContext* innermostFinallyContext = nullptr; 5067 FinallyContext* outermostFinallyContext = nullptr; 5068 size_t scopeIndex = m_controlFlowScopeStack.size() - 1; 5069 while (numberOfScopesToCheckForFinally--) { 5070 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex--]; 5071 if (scope->isFinallyScope()) { 5072 FinallyContext* finallyContext = &scope->finallyContext; 5073 if (!innermostFinallyContext) 5074 innermostFinallyContext = finallyContext; 5075 outermostFinallyContext = finallyContext; 5076 finallyContext->incNumberOfBreaksOrContinues(); 5077 } 5078 } 5079 if (!outermostFinallyContext) 5080 return false; // No finallys to thread through. 5081 5082 auto jumpID = bytecodeOffsetToJumpID(instructions().size()); 5083 int lexicalScopeIndex = labelScopeDepthToLexicalScopeIndex(targetLabelScopeDepth); 5084 outermostFinallyContext->registerJump(jumpID, lexicalScopeIndex, jumpTarget); 5085 5086 emitSetCompletionType(jumpID); 5087 emitJump(*innermostFinallyContext->finallyLabel()); 5088 return true; // We'll be jumping to a finally block. 5089 } 5090 5091 bool BytecodeGenerator::emitReturnViaFinallyIfNeeded(RegisterID* returnRegister) 5092 { 5093 size_t numberOfScopesToCheckForFinally = m_controlFlowScopeStack.size(); 5094 if (!numberOfScopesToCheckForFinally) 5095 return false; 5096 5097 FinallyContext* innermostFinallyContext = nullptr; 5098 while (numberOfScopesToCheckForFinally) { 5099 size_t scopeIndex = --numberOfScopesToCheckForFinally; 5100 ControlFlowScope* scope = &m_controlFlowScopeStack[scopeIndex]; 5101 if (scope->isFinallyScope()) { 5102 FinallyContext* finallyContext = &scope->finallyContext; 5103 if (!innermostFinallyContext) 5104 innermostFinallyContext = finallyContext; 5105 finallyContext->setHandlesReturns(); 5106 } 5107 } 5108 if (!innermostFinallyContext) 5109 return false; // No finallys to thread through. 5110 5111 emitSetCompletionType(CompletionType::Return); 5112 emitSetCompletionValue(returnRegister); 5113 emitJump(*innermostFinallyContext->finallyLabel()); 5114 return true; // We'll be jumping to a finally block. 5115 } 5116 5117 void BytecodeGenerator::emitFinallyCompletion(FinallyContext& context, RegisterID* completionTypeRegister, Label& normalCompletionLabel) 5118 { 5119 if (context.numberOfBreaksOrContinues() || context.handlesReturns()) { 5120 emitJumpIf(op_stricteq, completionTypeRegister, CompletionType::Normal, normalCompletionLabel); 5121 5122 FinallyContext* outerContext = context.outerContext(); 5123 5124 size_t numberOfJumps = context.numberOfJumps(); 5125 ASSERT(outerContext || numberOfJumps == context.numberOfBreaksOrContinues()); 5126 5127 for (size_t i = 0; i < numberOfJumps; i++) { 5128 Ref<Label> nextLabel = newLabel(); 5129 auto& jump = context.jumps(i); 5130 emitJumpIf(op_nstricteq, completionTypeRegister, jump.jumpID, nextLabel.get()); 5131 5132 restoreScopeRegister(jump.targetLexicalScopeIndex); 5133 emitSetCompletionType(CompletionType::Normal); 5134 emitJump(jump.targetLabel.get()); 5135 5136 emitLabel(nextLabel.get()); 5137 } 5138 5139 if (outerContext) { 5140 // We are not the outermost finally. 5141 bool hasBreaksOrContinuesNotCoveredByJumps = context.numberOfBreaksOrContinues() > numberOfJumps; 5142 if (hasBreaksOrContinuesNotCoveredByJumps || context.handlesReturns()) 5143 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Throw, *outerContext->finallyLabel()); 5144 5145 } else { 5146 // We are the outermost finally. 5147 if (context.handlesReturns()) { 5148 Ref<Label> notReturnLabel = newLabel(); 5149 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Return, notReturnLabel.get()); 5150 5151 emitWillLeaveCallFrameDebugHook(); 5152 emitReturn(completionValueRegister(), ReturnFrom::Finally); 5153 5154 emitLabel(notReturnLabel.get()); 5155 } 5156 } 5157 } 5158 emitJumpIf(op_nstricteq, completionTypeRegister, CompletionType::Throw, normalCompletionLabel); 5159 emitThrow(completionValueRegister()); 5160 } 5161 5162 bool BytecodeGenerator::allocateCompletionRecordRegisters() 5163 { 5164 if (m_completionTypeRegister) 5165 return false; 5166 5167 ASSERT(!m_completionValueRegister); 5168 m_completionTypeRegister = newTemporary(); 5169 m_completionValueRegister = newTemporary(); 5170 5171 emitSetCompletionType(CompletionType::Normal); 5172 moveEmptyValue(m_completionValueRegister.get()); 5173 return true; 5174 } 5175 5176 void BytecodeGenerator::releaseCompletionRecordRegisters() 5177 { 5178 ASSERT(m_completionTypeRegister && m_completionValueRegister); 5179 m_completionTypeRegister = nullptr; 5180 m_completionValueRegister = nullptr; 5181 } 5182 5183 void BytecodeGenerator::emitJumpIf(OpcodeID compareOpcode, RegisterID* completionTypeRegister, CompletionType type, Label& jumpTarget) 5184 { 5185 RefPtr<RegisterID> tempRegister = newTemporary(); 5186 RegisterID* valueConstant = addConstantValue(jsNumber(static_cast<int>(type))); 5187 OperandTypes operandTypes = OperandTypes(ResultType::numberTypeIsInt32(), ResultType::unknownType()); 5188 5189 auto equivalenceResult = emitBinaryOp(compareOpcode, tempRegister.get(), valueConstant, completionTypeRegister, operandTypes); 5190 emitJumpIfTrue(equivalenceResult, jumpTarget); 5191 } 5192 5193 void StructureForInContext::finalize(BytecodeGenerator& generator) 5194 { 5202 offset += opcodeLength; 5203 } 5204 } 5205 5206 void StructureForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset) 5207 { 5208 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset); 5195 5209 if (isValid()) 5196 5210 return; … … 5220 5234 } 5221 5235 5222 void IndexedForInContext::finalize(BytecodeGenerator& generator) 5223 { 5236 void IndexedForInContext::finalize(BytecodeGenerator& generator, UnlinkedCodeBlock* codeBlock, unsigned bodyBytecodeEndOffset) 5237 { 5238 Base::finalize(generator, codeBlock, bodyBytecodeEndOffset); 5224 5239 if (isValid()) 5225 5240 return; -
releases/WebKitGTK/webkit-2.22/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r238988 r238989 212 212 213 213 protected: 214 ForInContext(RegisterID* localRegister, Type type )214 ForInContext(RegisterID* localRegister, Type type, unsigned bodyBytecodeStartOffset) 215 215 : m_localRegister(localRegister) 216 216 , m_type(type) 217 , m_bodyBytecodeStartOffset(bodyBytecodeStartOffset) 217 218 { } 219 220 unsigned bodyBytecodeStartOffset() const { return m_bodyBytecodeStartOffset; } 221 222 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset); 218 223 219 224 private: … … 221 226 bool m_isValid { true }; 222 227 Type m_type; 228 unsigned m_bodyBytecodeStartOffset; 223 229 }; 224 230 225 231 class StructureForInContext : public ForInContext { 232 using Base = ForInContext; 226 233 public: 227 234 using GetInst = std::tuple<unsigned, int, UnlinkedValueProfile>; 228 235 229 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister )230 : ForInContext(localRegister, Type::StructureForIn )236 StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister, unsigned bodyBytecodeStartOffset) 237 : ForInContext(localRegister, Type::StructureForIn, bodyBytecodeStartOffset) 231 238 , m_indexRegister(indexRegister) 232 239 , m_propertyRegister(propertyRegister) … … 244 251 } 245 252 246 void finalize(BytecodeGenerator& );253 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset); 247 254 248 255 private: … … 254 261 255 262 class IndexedForInContext : public ForInContext { 263 using Base = ForInContext; 256 264 public: 257 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister )258 : ForInContext(localRegister, Type::IndexedForIn )265 IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister, unsigned bodyBytecodeStartOffset) 266 : ForInContext(localRegister, Type::IndexedForIn, bodyBytecodeStartOffset) 259 267 , m_indexRegister(indexRegister) 260 268 { … … 263 271 RegisterID* index() const { return m_indexRegister.get(); } 264 272 265 void finalize(BytecodeGenerator& );273 void finalize(BytecodeGenerator&, UnlinkedCodeBlock*, unsigned bodyBytecodeEndOffset); 266 274 void addGetInst(unsigned instIndex, int propertyIndex) { m_getInsts.append({ instIndex, propertyIndex }); } 267 275 … … 939 947 void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator); 940 948 void popStructureForInScope(RegisterID* local); 941 void invalidateForInContextForLocal(RegisterID* local);942 949 943 950 LabelScope* breakTarget(const Identifier&); -
releases/WebKitGTK/webkit-2.22/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r238986 r238989 1557 1557 localReg = generator.move(generator.tempDestination(dst), local); 1558 1558 } 1559 generator.invalidateForInContextForLocal(local);1560 1559 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), localReg.get(), m_operator); 1561 1560 generator.emitProfileType(localReg.get(), var, divotStart(), divotEnd()); … … 1770 1769 localReg = generator.move(generator.tempDestination(dst), localReg.get()); 1771 1770 } else if (generator.vm()->typeProfiler()) { 1772 generator.invalidateForInContextForLocal(local);1773 1771 RefPtr<RegisterID> tempDst = generator.tempDestination(dst); 1774 1772 generator.move(tempDst.get(), localReg.get()); … … 1778 1776 return generator.move(dst, tempDst.get()); 1779 1777 } 1780 generator.invalidateForInContextForLocal(local);1781 1778 emitIncOrDec(generator, localReg.get(), m_operator); 1782 1779 return generator.move(dst, localReg.get()); … … 2442 2439 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 2443 2440 generator.move(local, result.get()); 2444 generator.invalidateForInContextForLocal(local);2445 2441 generator.emitProfileType(local, divotStart(), divotEnd()); 2446 2442 return generator.move(dst, result.get()); … … 2448 2444 2449 2445 RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 2450 generator.invalidateForInContextForLocal(local);2451 2446 generator.emitProfileType(result, divotStart(), divotEnd()); 2452 2447 return generator.move(dst, result); … … 2506 2501 generator.move(local, tempDst.get()); 2507 2502 generator.emitProfileType(local, var, divotStart(), divotEnd()); 2508 generator.invalidateForInContextForLocal(local);2509 2503 result = generator.move(dst, tempDst.get()); 2510 2504 } else { 2511 2505 RegisterID* right = generator.emitNode(local, m_right); 2512 2506 generator.emitProfileType(right, var, divotStart(), divotEnd()); 2513 generator.invalidateForInContextForLocal(local);2514 2507 result = generator.move(dst, right); 2515 2508 } … … 2753 2746 if (RegisterID* local = var.local()) { 2754 2747 generator.emitLoad(local, jsUndefined()); 2755 generator.invalidateForInContextForLocal(local);2756 2748 generator.emitProfileType(local, var, position(), JSTextPosition(-1, position().offset + m_ident.length(), -1)); 2757 2749 } else { … … 2967 2959 generator.emitReadOnlyExceptionIfNeeded(var); 2968 2960 generator.move(local, propertyName); 2969 generator.invalidateForInContextForLocal(local);2970 2961 } else { 2971 2962 if (generator.isStrictMode()) … … 3035 3026 } 3036 3027 generator.move(var.local(), propertyName); 3037 generator.invalidateForInContextForLocal(var.local());3038 3028 generator.emitProfileType(propertyName, var, simpleBinding->divotStart(), simpleBinding->divotEnd()); 3039 3029 return; … … 3226 3216 generator.emitReadOnlyExceptionIfNeeded(var); 3227 3217 generator.move(local, value); 3228 generator.invalidateForInContextForLocal(local);3229 3218 } else { 3230 3219 if (generator.isStrictMode()) … … 4400 4389 } 4401 4390 generator.move(local, value); 4402 generator.invalidateForInContextForLocal(local);4403 4391 generator.emitProfileType(local, var, divotStart(), divotEnd()); 4404 4392 if (m_bindingContext == AssignmentContext::DeclarationStatement || m_bindingContext == AssignmentContext::ConstDeclarationStatement) … … 4449 4437 generator.emitReadOnlyExceptionIfNeeded(var); 4450 4438 else { 4451 generator.invalidateForInContextForLocal(local);4452 4439 generator.move(local, value); 4453 4440 generator.emitProfileType(local, divotStart(), divotEnd()); -
releases/WebKitGTK/webkit-2.22/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r238986 r238989 811 811 CHECK_EXCEPTION(); 812 812 JSValue property = OP(3).jsValue(); 813 ASSERT(property.isString()); 813 814 JSString* string = asString(property); 814 815 auto propertyName = string->toIdentifier(exec); … … 822 823 JSValue baseValue = OP_C(2).jsValue(); 823 824 JSValue property = OP(3).jsValue(); 825 ASSERT(property.isString()); 824 826 JSString* string = asString(property); 825 827 auto propertyName = string->toIdentifier(exec);
Note: See TracChangeset
for help on using the changeset viewer.