Changeset 291815 in webkit
- Timestamp:
- Mar 24, 2022, 2:41:42 PM (4 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
jit/JITOperations.cpp (modified) (1 diff)
-
jit/JITOperations.h (modified) (1 diff)
-
jit/ThunkGenerators.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r291785 r291815 1 2022-03-24 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] JSRemoteFunction thunk should materialize code-pointer 4 https://bugs.webkit.org/show_bug.cgi?id=238313 5 6 Reviewed by Mark Lam. 7 8 When invoking a JSRemoteFunction, we must first wrap the arguments passed to it. 9 The wrapping operation may trigger a GC, and GC can jettison JIT code. As a result, 10 even though we know that the target JSFunction has JIT code that we want to execute, 11 the JIT code may be jettisoned (while wrapping the arguments for it) before we get 12 to the call. This resulted in occasional crashes on the JSTests/stress/shadow-realm-evaluate.js test. 13 14 This patch fixes this by doing a null check on the JIT code just before calling it, 15 and if null (i.e. the JIT code has been jettisoned), re-materializing the JIT code 16 first before making the call. 17 18 * jit/JITOperations.cpp: 19 (JSC::JSC_DEFINE_JIT_OPERATION): 20 * jit/JITOperations.h: 21 * jit/ThunkGenerators.cpp: 22 (JSC::remoteFunctionCallGenerator): 23 1 24 2022-03-23 Geza Lore <glore@igalia.com> 2 25 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r291779 r291815 157 157 158 158 RELEASE_AND_RETURN(scope, JSValue::encode(getWrappedValue(globalObject, globalObject, JSValue::decode(encodedValue)))); 159 } 160 161 JSC_DEFINE_JIT_OPERATION(operationMaterializeRemoteFunctionTargetCode, void*, (JSRemoteFunction* callee)) 162 { 163 JSGlobalObject* globalObject = callee->globalObject(); 164 VM& vm = globalObject->vm(); 165 166 CallFrame* callFrame = DECLARE_CALL_FRAME(vm); 167 JITOperationPrologueCallFrameTracer tracer(vm, callFrame); 168 auto throwScope = DECLARE_THROW_SCOPE(vm); 169 170 ASSERT(isRemoteFunction(vm, callee)); 171 172 auto* targetFunction = jsCast<JSFunction*>(callee->targetFunction()); // We call this function only when JSRemoteFunction's target is JSFunction. 173 ExecutableBase* executable = targetFunction->executable(); 174 175 // Force the executable to cache its arity entrypoint. 176 { 177 DeferTraps deferTraps(vm); // We can't jettison any code until after we link the call. 178 if (!executable->isHostFunction()) { 179 JSScope* scope = targetFunction->scopeUnchecked(); 180 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 181 CodeBlock* codeBlockSlot = nullptr; 182 functionExecutable->prepareForExecution<FunctionExecutable>(vm, targetFunction, scope, CodeForCall, codeBlockSlot); 183 RETURN_IF_EXCEPTION(throwScope, nullptr); 184 } 185 return executable->entrypointFor(CodeForCall, MustCheckArity).executableAddress(); 186 } 159 187 } 160 188 -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r290768 r291815 162 162 JSC_DECLARE_JIT_OPERATION(operationGetWrappedValueForCaller, EncodedJSValue, (JSRemoteFunction*, EncodedJSValue)); 163 163 JSC_DECLARE_JIT_OPERATION(operationGetWrappedValueForTarget, EncodedJSValue, (JSRemoteFunction*, EncodedJSValue)); 164 JSC_DECLARE_JIT_OPERATION(operationMaterializeRemoteFunctionTargetCode, void*, (JSRemoteFunction*)); 164 165 JSC_DECLARE_JIT_OPERATION(operationThrowRemoteFunctionException, EncodedJSValue, (JSRemoteFunction*)); 165 166 -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp
r291785 r291815 1503 1503 jit.storePtr(GPRInfo::regT1, jit.addressFor(loopIndex)); 1504 1504 1505 jit.setupArguments<decltype(operationGetWrappedValueForTarget)>(GPRInfo::regT0, valueRegs); 1505 1506 jit.prepareCallOperation(vm); 1506 jit.setupArguments<decltype(operationGetWrappedValueForTarget)>(GPRInfo::regT0, valueRegs);1507 1507 jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationGetWrappedValueForTarget)), GPRInfo::nonArgGPR0); 1508 1508 emitPointerValidation(jit, GPRInfo::nonArgGPR0, OperationPtrTag); … … 1525 1525 jit.storeCell(GPRInfo::regT2, CCallHelpers::calleeFrameSlot(CallFrameSlot::callee)); 1526 1526 1527 jit.loadPtr(CCallHelpers::Address(GPRInfo::regT2, JSFunction::offsetOfExecutableOrRareData()), GPRInfo::regT 0);1528 auto hasExecutable = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT 0, CCallHelpers::TrustedImm32(JSFunction::rareDataTag));1529 jit.loadPtr(CCallHelpers::Address(GPRInfo::regT 0, FunctionRareData::offsetOfExecutable() - JSFunction::rareDataTag), GPRInfo::regT0);1527 jit.loadPtr(CCallHelpers::Address(GPRInfo::regT2, JSFunction::offsetOfExecutableOrRareData()), GPRInfo::regT1); 1528 auto hasExecutable = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT1, CCallHelpers::TrustedImm32(JSFunction::rareDataTag)); 1529 jit.loadPtr(CCallHelpers::Address(GPRInfo::regT1, FunctionRareData::offsetOfExecutable() - JSFunction::rareDataTag), GPRInfo::regT1); 1530 1530 hasExecutable.link(&jit); 1531 1531 1532 1532 jit.loadPtr( 1533 1533 CCallHelpers::Address( 1534 GPRInfo::regT0, ExecutableBase::offsetOfJITCodeWithArityCheckFor(CodeForCall)), 1535 GPRInfo::regT0); 1536 1534 GPRInfo::regT1, ExecutableBase::offsetOfJITCodeWithArityCheckFor(CodeForCall)), 1535 GPRInfo::regT1); 1536 auto codeExists = jit.branchTestPtr(CCallHelpers::NonZero, GPRInfo::regT1); 1537 1538 // The calls to operationGetWrappedValueForTarget above may GC, and any GC can potentially jettison the JIT code in the target JSFunction. 1539 // If we find that the JIT code is null (i.e. has been jettisoned), then we need to re-materialize it for the call below. Note that we know 1540 // that operationMaterializeRemoteFunctionTargetCode should be able to re-materialize the JIT code (except for any OOME) because we only 1541 // went down this code path after we found a non-null JIT code (in the noCode check) above i.e. it should be possible to materialize the JIT code. 1542 jit.setupArguments<decltype(operationMaterializeRemoteFunctionTargetCode)>(GPRInfo::regT0); 1543 jit.prepareCallOperation(vm); 1544 jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationMaterializeRemoteFunctionTargetCode)), GPRInfo::nonArgGPR0); 1545 emitPointerValidation(jit, GPRInfo::nonArgGPR0, OperationPtrTag); 1546 jit.call(GPRInfo::nonArgGPR0, OperationPtrTag); 1547 exceptionChecks.append(jit.emitJumpIfException(vm)); 1548 jit.move(GPRInfo::returnValueGPR, GPRInfo::regT1); 1549 1550 codeExists.link(&jit); 1537 1551 // Based on the check above, we should be good with this. On ARM64, emitPointerValidation will do this. 1538 1552 #if ASSERT_ENABLED && !CPU(ARM64E) 1539 1553 { 1540 CCallHelpers::Jump checkNotNull = jit.branchTestPtr(CCallHelpers::NonZero, GPRInfo::regT 0);1554 CCallHelpers::Jump checkNotNull = jit.branchTestPtr(CCallHelpers::NonZero, GPRInfo::regT1); 1541 1555 jit.abortWithReason(TGInvalidPointer); 1542 1556 checkNotNull.link(&jit); … … 1544 1558 #endif 1545 1559 1546 emitPointerValidation(jit, GPRInfo::regT 0, JSEntryPtrTag);1547 jit.call(GPRInfo::regT 0, JSEntryPtrTag);1560 emitPointerValidation(jit, GPRInfo::regT1, JSEntryPtrTag); 1561 jit.call(GPRInfo::regT1, JSEntryPtrTag); 1548 1562 1549 1563 // Wrap return value … … 1558 1572 resultIsPrimitive.append(jit.branchIfNotObject(resultRegs.payloadGPR())); 1559 1573 1560 jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationGetWrappedValueForCaller)), GPRInfo::nonArgGPR0);1561 emitPointerValidation(jit, GPRInfo::nonArgGPR0, OperationPtrTag);1562 1563 1574 jit.loadCell(CCallHelpers::addressFor(CallFrameSlot::callee), GPRInfo::regT2); 1564 1575 jit.setupArguments<decltype(operationGetWrappedValueForCaller)>(GPRInfo::regT2, resultRegs); 1565 1576 jit.prepareCallOperation(vm); 1577 jit.move(CCallHelpers::TrustedImmPtr(tagCFunction<OperationPtrTag>(operationGetWrappedValueForCaller)), GPRInfo::nonArgGPR0); 1578 emitPointerValidation(jit, GPRInfo::nonArgGPR0, OperationPtrTag); 1566 1579 jit.call(GPRInfo::nonArgGPR0, OperationPtrTag); 1567 1580 exceptionChecks.append(jit.emitJumpIfException(vm));
Note:
See TracChangeset
for help on using the changeset viewer.