Ignore:
Timestamp:
Dec 9, 2016, 5:22:15 PM (9 years ago)
Author:
[email protected]
Message:

GC might be forced to look at a nuked object due to ordering of AllocatePropertyStorage, MaterializeNewObject, and PutStructure
https://bugs.webkit.org/show_bug.cgi?id=165672

Reviewed by Geoffrey Garen.

We need to make sure that the shady stuff in a property put happens after the
PutByOffset, since the PutByOffset is the place where we materialize. More generally, we
should strive to not have any fenceposts between Nodes where a GC would be illegal.

This gets us most of the way there by separating NukeStructureAndSetButterfly from
[Re]AllocatePropertyStorage. A transitioning put will now look something like:

GetButterfly
ReallocatePropertyStorage
PutByOffset
NukeStructureAndSetButterfly
PutStructure


Previously the structure would get nuked by ReallocatePropertyStorage, so if we placed
an object materialization just after it (before the PutByOffset) then any GC that
completed at that safepoint would encounter an unresolved visit race due to seeing a
nuked structure. We cannot have nuked structures at safepoints, and this change makes
sure that we don't - at least until someone tries to sink to the PutStructure. We will
eventually have to create a combined SetStructureAndButterfly node, but we don't need it
yet.

This also fixes a goof where the DFG's AllocatePropertyStorage was nulling the structure
instead of nuking it. This could easily have caused many crashes in GC.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handlePutById):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGClobbersExitState.cpp:

(JSC::DFG::clobbersExitState):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGMayExit.cpp:
  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileReallocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::compileNukeStructureAndSetButterfly):

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGStoreBarrierInsertionPhase.cpp:
  • dfg/DFGTypeCheckHoistingPhase.cpp:

(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNukeStructureAndSetButterfly):
(JSC::FTL::DFG::LowerDFGToB3::storageForTransition):
(JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::reallocatePropertyStorage):
(JSC::FTL::DFG::LowerDFGToB3::allocatePropertyStorageWithSizeImpl):

  • runtime/Options.cpp:

(JSC::recomputeDependentOptions):

  • runtime/Options.h: Fix a bug - make it possible to turn on concurrent GC optionally again.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r209594 r209638  
    73907390
    73917391        GPRFlushedCallResult result(this);
    7392         callOperation(operationReallocateButterflyToHavePropertyStorageWithInitialCapacity, result.gpr(), baseGPR);
     7392        callOperation(operationAllocateComplexPropertyStorageWithInitialCapacity, result.gpr(), baseGPR);
    73937393        m_jit.exceptionCheck();
    73947394       
     
    73977397    }
    73987398   
    7399     SpeculateCellOperand base(this, node->child1());
    74007399    GPRTemporary scratch1(this);
    74017400    GPRTemporary scratch2(this);
    74027401    GPRTemporary scratch3(this);
    74037402       
    7404     GPRReg baseGPR = base.gpr();
    74057403    GPRReg scratchGPR1 = scratch1.gpr();
    74067404    GPRReg scratchGPR2 = scratch2.gpr();
     
    74167414       
    74177415    addSlowPathGenerator(
    7418         slowPathCall(slowPath, this, operationAllocatePropertyStorageWithInitialCapacity, scratchGPR1));
    7419 
    7420     m_jit.store32(TrustedImm32(0), JITCompiler::Address(baseGPR, JSCell::structureIDOffset()));
    7421     m_jit.storeButterfly(scratchGPR1, baseGPR);
     7416        slowPathCall(slowPath, this, operationAllocateSimplePropertyStorageWithInitialCapacity, scratchGPR1));
    74227417
    74237418    storageResult(scratchGPR1, node);
     
    74407435
    74417436        GPRFlushedCallResult result(this);
    7442         callOperation(operationReallocateButterflyToGrowPropertyStorage, result.gpr(), baseGPR, newSize / sizeof(JSValue));
     7437        callOperation(operationAllocateComplexPropertyStorage, result.gpr(), baseGPR, newSize / sizeof(JSValue));
    74437438        m_jit.exceptionCheck();
    74447439
     
    74477442    }
    74487443   
    7449     SpeculateCellOperand base(this, node->child1());
    74507444    StorageOperand oldStorage(this, node->child2());
    74517445    GPRTemporary scratch1(this);
     
    74537447    GPRTemporary scratch3(this);
    74547448       
    7455     GPRReg baseGPR = base.gpr();
    74567449    GPRReg oldStorageGPR = oldStorage.gpr();
    74577450    GPRReg scratchGPR1 = scratch1.gpr();
     
    74697462
    74707463    addSlowPathGenerator(
    7471         slowPathCall(slowPath, this, operationAllocatePropertyStorage, scratchGPR1, newSize / sizeof(JSValue)));
     7464        slowPathCall(slowPath, this, operationAllocateSimplePropertyStorage, scratchGPR1, newSize / sizeof(JSValue)));
    74727465
    74737466    // We have scratchGPR1 = new storage, scratchGPR2 = scratch
     
    74777470    }
    74787471       
    7479     m_jit.nukeStructureAndStoreButterfly(scratchGPR1, baseGPR);
    7480 
    74817472    storageResult(scratchGPR1, node);
     7473}
     7474
     7475void SpeculativeJIT::compileNukeStructureAndSetButterfly(Node* node)
     7476{
     7477    SpeculateCellOperand base(this, node->child1());
     7478    StorageOperand storage(this, node->child2());
     7479   
     7480    GPRReg baseGPR = base.gpr();
     7481    GPRReg storageGPR = storage.gpr();
     7482   
     7483    m_jit.nukeStructureAndStoreButterfly(storageGPR, baseGPR);
     7484   
     7485    noResult(node);
    74827486}
    74837487
Note: See TracChangeset for help on using the changeset viewer.