Ignore:
Timestamp:
Mar 25, 2015, 6:26:56 PM (10 years ago)
Author:
[email protected]
Message:

Use JITCompilationCanFail in more places, and make the fail path of JITCompilationMustSucceed a crash instead of attempting GC
https://bugs.webkit.org/show_bug.cgi?id=142993

Source/JavaScriptCore:

Reviewed by Geoffrey Garen and Mark Lam.

This changes the most commonly invoked paths that relied on JITCompilationMustSucceed
into using JITCompilationCanFail and having a legit fallback path. This mostly involves
having the FTL JIT do the same trick as the DFG JIT in case of any memory allocation
failure, but also involves adding the same kind of thing to the stub generators in
Repatch.

Because of that change, there are relatively few uses of JITCompilationMustSucceed. Most
of those uses cannot handle a GC, and so cannot do releaseExecutableMemory(). Only a few,
like host call stub generation, could handle a GC, but those get invoked very rarely. So,
this patch changes the releaseExecutableMemory() call into a crash with some diagnostic
printout.

Also add a way of inducing executable allocation failure, so that we can test this.

(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::link): Deleted.
(JSC::DFG::JITCompiler::linkFunction): Deleted.

  • dfg/DFGJITCompiler.h:
  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::compileInThreadImpl):

  • ftl/FTLCompile.cpp:

(JSC::FTL::mmAllocateCodeSection):
(JSC::FTL::mmAllocateDataSection):

  • ftl/FTLLink.cpp:

(JSC::FTL::link):

  • ftl/FTLState.h:
  • jit/ArityCheckFailReturnThunks.cpp:

(JSC::ArityCheckFailReturnThunks::returnPCsFor):

  • jit/ExecutableAllocationFuzz.cpp: Added.

(JSC::numberOfExecutableAllocationFuzzChecks):
(JSC::doExecutableAllocationFuzzing):

  • jit/ExecutableAllocationFuzz.h: Added.

(JSC::doExecutableAllocationFuzzingIfEnabled):

  • jit/ExecutableAllocatorFixedVMPool.cpp:

(JSC::ExecutableAllocator::allocate):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JITCompilationEffort.h:
  • jit/Repatch.cpp:

(JSC::generateByIdStub):
(JSC::tryCacheGetByID):
(JSC::tryBuildGetByIDList):
(JSC::emitPutReplaceStub):
(JSC::emitPutTransitionStubAndGetOldStructure):
(JSC::tryCachePutByID):
(JSC::tryBuildPutByIdList):
(JSC::tryRepatchIn):
(JSC::linkPolymorphicCall):

  • jsc.cpp:

(jscmain):

  • runtime/Options.h:
  • runtime/TestRunnerUtils.h:
  • runtime/VM.cpp:
  • tests/executableAllocationFuzz: Added.
  • tests/executableAllocationFuzz.yaml: Added.
  • tests/executableAllocationFuzz/v8-raytrace.js: Added.

Tools:

Reviewed by Mark Lam.

Bunch of support for testing executable allocation failure.

  • Scripts/jsc-stress-test-helpers/js-executable-allocation-fuzz: Added.

(fail):

  • Scripts/run-javascriptcore-tests:

(runJSCStressTests):

  • Scripts/run-jsc-stress-tests:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r179831 r181990  
    294294}
    295295
    296 static void generateByIdStub(
     296static bool generateByIdStub(
    297297    ExecState* exec, ByIdStubKind kind, const Identifier& propertyName,
    298298    FunctionPtr custom, StructureStubInfo& stubInfo, StructureChain* chain, size_t count,
     
    575575    emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
    576576   
    577     LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock());
     577    LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock(), JITCompilationCanFail);
     578    if (patchBuffer.didFailToAllocate())
     579        return false;
    578580   
    579581    linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
     
    602604    else
    603605        stubRoutine = createJITStubRoutine(code, *vm, codeBlock->ownerExecutable(), true);
     606   
     607    return true;
    604608}
    605609
     
    688692            emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
    689693           
    690             LinkBuffer patchBuffer(*vm, stubJit, codeBlock);
     694            LinkBuffer patchBuffer(*vm, stubJit, codeBlock, JITCompilationCanFail);
     695            if (patchBuffer.didFailToAllocate())
     696                return GiveUpOnCache;
    691697
    692698            linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCases);
     
    718724        MacroAssembler::Jump success = stubJit.jump();
    719725
    720         LinkBuffer patchBuffer(*vm, stubJit, codeBlock);
    721 
     726        LinkBuffer patchBuffer(*vm, stubJit, codeBlock, JITCompilationCanFail);
     727        if (patchBuffer.didFailToAllocate())
     728            return GiveUpOnCache;
     729       
    722730        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
    723731        patchBuffer.link(failure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase));
     
    845853   
    846854    RefPtr<JITStubRoutine> stubRoutine;
    847     generateByIdStub(
     855    bool result = generateByIdStub(
    848856        exec, kindFor(slot), ident, customFor(slot), stubInfo, prototypeChain, count, offset,
    849857        structure, loadTargetFromProxy, slot.watchpointSet(),
    850858        stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone),
    851859        CodeLocationLabel(list->currentSlowPathTarget(stubInfo)), stubRoutine);
     860    if (!result)
     861        return GiveUpOnCache;
    852862   
    853863    GetByIdAccess::AccessType accessType;
     
    902912}
    903913
    904 static void emitPutReplaceStub(
     914static bool emitPutReplaceStub(
    905915    ExecState* exec,
    906916    const Identifier&,
     
    969979    }
    970980   
    971     LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock());
     981    LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock(), JITCompilationCanFail);
     982    if (patchBuffer.didFailToAllocate())
     983        return false;
     984   
    972985    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
    973986    patchBuffer.link(failure, failureLabel);
     
    978991            toCString(*exec->codeBlock()).data(), stubInfo.callReturnLocation.labelAtOffset(
    979992                stubInfo.patch.deltaCallToDone).executableAddress()));
     993   
     994    return true;
    980995}
    981996
     
    12141229    }
    12151230   
    1216     LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock());
     1231    LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock(), JITCompilationCanFail);
     1232    if (patchBuffer.didFailToAllocate())
     1233        return nullptr;
     1234   
    12171235    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
    12181236    if (allocator.didReuseRegisters())
     
    13091327        list = PolymorphicPutByIdList::from(putKind, stubInfo);
    13101328
    1311         generateByIdStub(
     1329        bool result = generateByIdStub(
    13121330            exec, kindFor(slot), ident, customFor(slot), stubInfo, prototypeChain, count,
    13131331            offset, structure, false, nullptr,
     
    13151333            stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase),
    13161334            stubRoutine);
    1317 
     1335        if (!result)
     1336            return GiveUpOnCache;
     1337       
    13181338        list->addAccess(PutByIdAccess::setter(
    13191339            *vm, codeBlock->ownerExecutable(),
     
    13841404           
    13851405            // We're now committed to creating the stub. Mogrify the meta-data accordingly.
    1386             emitPutReplaceStub(
     1406            bool result = emitPutReplaceStub(
    13871407                exec, propertyName, slot, stubInfo,
    13881408                structure, CodeLocationLabel(list->currentSlowPathTarget()), stubRoutine);
    1389 
     1409            if (!result)
     1410                return GiveUpOnCache;
     1411           
    13901412            list->addAccess(
    13911413                PutByIdAccess::replace(
     
    14171439        list = PolymorphicPutByIdList::from(putKind, stubInfo);
    14181440
    1419         generateByIdStub(
     1441        bool result = generateByIdStub(
    14201442            exec, kindFor(slot), propertyName, customFor(slot), stubInfo, prototypeChain, count,
    14211443            offset, structure, false, nullptr,
     
    14231445            CodeLocationLabel(list->currentSlowPathTarget()),
    14241446            stubRoutine);
    1425 
     1447        if (!result)
     1448            return GiveUpOnCache;
     1449       
    14261450        list->addAccess(PutByIdAccess::setter(
    14271451            *vm, codeBlock->ownerExecutable(),
     
    15491573        emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCases);
    15501574       
    1551         LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock());
    1552 
     1575        LinkBuffer patchBuffer(*vm, stubJit, exec->codeBlock(), JITCompilationCanFail);
     1576        if (patchBuffer.didFailToAllocate())
     1577            return GiveUpOnCache;
     1578       
    15531579        linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, successLabel, slowCaseLabel);
    15541580       
     
    18521878    AssemblyHelpers::Jump slow = stubJit.jump();
    18531879       
    1854     LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock);
     1880    LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock, JITCompilationCanFail);
     1881    if (patchBuffer.didFailToAllocate()) {
     1882        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
     1883        return;
     1884    }
    18551885   
    18561886    RELEASE_ASSERT(callCases.size() == calls.size());
Note: See TracChangeset for help on using the changeset viewer.