Ignore:
Timestamp:
Sep 15, 2021, 3:18:52 PM (4 years ago)
Author:
[email protected]
Message:

Move some profiling to UnlinkedCodeBlock
https://bugs.webkit.org/show_bug.cgi?id=230078
<rdar://problem/82947571>

Reviewed by Yusuke Suzuki.

This patch moves ValueProfiles and ArrayProfiles for non-call opcodes into
UnlinkedCodeBlock. This way, the data is shared between the linked CodeBlocks
of the same UnlinkedCodeBlock. The profiling bet here is that when the same code
runs in a different global object, it largely runs in the same way. We've made
this same bet in other ways with our profiling, and it largely makes sense
to do for ValueProfile and ArrayProfile since they both hold global object
independent data.

Because ArrayProfiles are now shared between CodeBlocks, the existing m_usesOriginalArrayStructures
bit is slightly harder to track now, since the ArrayProfile may see inputs from a different
global object, an array may be an original array in one lexical global object,
but not another. So we now track when an ArrayProfile sees a different global
object than the lexical global object, and when we observe exits in the DFG,
we propagate that bit to the m_usesOriginalArrayStructures bit.

This patch also makes it so we no longer hold the CodeBlock lock when
processing ValueProfiles and ArrayProfiles. We now allow multiple compiler
threads to race against each other when updating these profiles. This is fine.
It may end up with incomplete data in the profiles, but it won't corrupt them.

This patch also makes it so we finalized visited UnlinkedCodeBlocks to finalize
their value profiles. We no longer do that work inside CodeBlock for the
ValueProfiles that UnlinkedCodeBlock owns. This also means that we have to
WriteBarrier UnlinkedCodeBlock when executing in the LLInt, Baseline, and
other areas, such as OSR exit, and in the GC when a CodeBlock was executing.
That way we're guaranteed to visit the UnlinkedCodeBlock, add it to the
visited set, and then finalize it at the end of GC.

This patch also makes it so that inside CodeBlock::finishCreation, we finish
linking before we do anything that can throw an exception. It's not valid to
finalize a CodeBlock that isn't linked.

This was measured as a 0.5-1% speedup on Speedometer2.

  • bytecode/ArrayProfile.cpp:

(JSC::ArrayProfile::computeUpdatedPrediction):
(JSC::ArrayProfile::briefDescription):
(JSC::ArrayProfile::briefDescriptionWithoutUpdating):

  • bytecode/ArrayProfile.h:

(JSC::ArrayProfile::ArrayProfile):
(JSC::ArrayProfile::observedArrayModes const):
(JSC::ArrayProfile::mayInterceptIndexedAccesses const):
(JSC::ArrayProfile::mayStoreToHole const):
(JSC::ArrayProfile::outOfBounds const):
(JSC::ArrayProfile::usesOriginalArrayStructures const):
(JSC::ArrayProfile::setDoesNotUseOriginalArrayStructures):
(JSC::ArrayProfile::observedDifferentGlobalObject const):

  • bytecode/BytecodeList.rb:
  • bytecode/BytecodeOperandsForCheckpoint.h:

(JSC::valueProfileForImpl):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::setConstantRegisters):
(JSC::CodeBlock::initializeTemplateObjects):
(JSC::CodeBlock::setNumParameters):
(JSC::CodeBlock::visitChildren):
(JSC::CodeBlock::finalizeUnconditionally):
(JSC::CodeBlock::getArrayProfile):
(JSC::CodeBlock::updateAllValueProfilePredictionsAndCountLiveness):
(JSC::CodeBlock::updateAllArrayPredictions):
(JSC::CodeBlock::tryGetValueProfileForBytecodeIndex):
(JSC::CodeBlock::valueProfilePredictionForBytecodeIndex):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::offsetOfUnlinkedCodeBlock):
(JSC::CodeBlock::numberOfArgumentValueProfiles):
(JSC::CodeBlock::valueProfileForArgument):
(JSC::CodeBlock::metadata):

  • bytecode/CodeBlockInlines.h:

(JSC::CodeBlock::forEachValueProfile):
(JSC::CodeBlock::forEachArrayProfile):

  • bytecode/DFGExitProfile.cpp:

(JSC::DFG::ExitProfile::hasAnyExitsAt const):

  • bytecode/DFGExitProfile.h:
  • bytecode/GetByIdMetadata.h:

(JSC::GetByIdModeMetadata::setArrayLengthMode):

  • bytecode/LazyOperandValueProfile.cpp:

(JSC::CompressedLazyOperandValueProfileHolder::computeUpdatedPredictions):
(JSC::LazyOperandValueProfileParser::prediction const):

  • bytecode/MetadataTable.cpp:

(JSC::DeallocTable::withOpcodeType):

  • bytecode/MetadataTable.h:

(JSC::MetadataTable::get):
(JSC::MetadataTable::forEach):
(JSC::MetadataTable::getWithoutAligning):
(JSC::MetadataTable::getImpl): Deleted.

  • bytecode/Opcode.h:
  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedCodeBlock::visitChildrenImpl):
(JSC::UnlinkedCodeBlock::allocateSharedProfiles):
(JSC::UnlinkedCodeBlock::finalizeUnconditionally):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::hasAnyExitsAt const):
(JSC::UnlinkedCodeBlock::hasAnyExitsAt):
(JSC::UnlinkedCodeBlock::valueProfile):
(JSC::UnlinkedCodeBlock::arrayProfile):
(JSC::UnlinkedCodeBlock::numValueProfiles const):
(JSC::UnlinkedCodeBlock::numArrayProfiles const):

  • bytecode/UnlinkedCodeBlockGenerator.cpp:

(JSC::UnlinkedCodeBlockGenerator::finalize):

  • bytecode/UnlinkedMetadataTable.cpp:

(JSC::UnlinkedMetadataTable::finalize):

  • bytecode/UnlinkedMetadataTable.h:

(JSC::UnlinkedMetadataTable::isFinalized):
(JSC::UnlinkedMetadataTable::hasMetadata):

  • bytecode/UnlinkedMetadataTableInlines.h:

(JSC::UnlinkedMetadataTable::numEntries):

  • bytecode/ValueProfile.h:

(JSC::ValueProfileBase::ValueProfileBase):
(JSC::ValueProfileBase::clearBuckets):
(JSC::ValueProfileBase::briefDescription):
(JSC::ValueProfileBase::computeUpdatedPrediction):
(JSC::ValueProfile::offsetOfFirstBucket):
(JSC::ValueProfileBase::classInfo const): Deleted.

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::fromObserved):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::withSpeculationFromProfile const):
(JSC::DFG::ArrayMode::withProfile const):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::getPredictionWithoutOSRExit):
(JSC::DFG::ByteCodeParser::getArrayMode):
(JSC::DFG::ByteCodeParser::handleVarargsInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::handlePutByVal):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::attemptToMakeGetArrayLength):

  • dfg/DFGGraph.h:
  • dfg/DFGOSRExitCompilerCommon.cpp:

(JSC::DFG::osrWriteBarrier):
(JSC::DFG::adjustAndJumpToTarget):

  • dfg/DFGPredictionInjectionPhase.cpp:

(JSC::DFG::PredictionInjectionPhase::run):

  • heap/CodeBlockSetInlines.h:

(JSC::CodeBlockSet::iterateViaSubspaces):

  • heap/Heap.cpp:

(JSC::Heap::finalizeMarkedUnconditionalFinalizers):
(JSC::Heap::finalizeUnconditionalFinalizers):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::runEndPhase):
(JSC::Heap::addCoreConstraints):

  • jit/JIT.h:
  • jit/JITInlines.h:

(JSC::JIT::emitValueProfilingSiteIfProfiledOpcode):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_enter):
(JSC::JIT::op_enter_handlerGenerator):

  • jit/JITOperations.cpp:

(JSC::putByValOptimize):
(JSC::directPutByValOptimize):
(JSC::JSC_DEFINE_JIT_OPERATION):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::generateGetByValSlowCase):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emit_op_in_by_val):
(JSC::JIT::emitSlow_op_in_by_val):
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::slow_op_get_from_scopeGenerator):
(JSC::JIT::emit_op_enumerator_get_by_val):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emit_op_get_by_id):
(JSC::JIT::emit_op_in_by_val):
(JSC::JIT::emitSlow_op_in_by_val):

  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::performLLIntGetByID):
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::getByVal):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • profiler/ProfilerBytecodeSequence.cpp:

(JSC::Profiler::BytecodeSequence::BytecodeSequence):

  • runtime/CachedTypes.cpp:

(JSC::CachedCodeBlock::numValueProfiles const):
(JSC::CachedCodeBlock::numArrayProfiles const):
(JSC::UnlinkedCodeBlock::UnlinkedCodeBlock):
(JSC::CachedCodeBlock<CodeBlockType>::encode):

  • runtime/CommonSlowPaths.cpp:

(JSC::iteratorNextTryFastImpl):
(JSC::JSC_DEFINE_COMMON_SLOW_PATH):

  • runtime/JSScope.cpp:

(JSC::abstractAccess):
(JSC::JSScope::abstractResolve):

  • runtime/VM.cpp:
  • runtime/VM.h:

(JSC::VM::forEachUnlinkedCodeBlockSpace):
(JSC::VM::forEachCodeBlockSpace): Deleted.

File:
1 edited

Legend:

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

    r272170 r282478  
    3737namespace JSC { namespace DFG {
    3838
    39 ArrayMode ArrayMode::fromObserved(const ConcurrentJSLocker& locker, ArrayProfile* profile, Array::Action action, bool makeSafe)
    40 {
     39ArrayMode ArrayMode::fromObserved(Graph& graph, const CodeOrigin& origin, ArrayProfile* profile, Array::Action action, bool makeSafe)
     40{
     41    if (profile->observedDifferentGlobalObject() && graph.hasAnyExitsAt(origin)) {
     42        // This could be an original array structure, but from a different
     43        // global object than the lexical global object. So we conservatively
     44        // say it is not an original array structure.
     45        profile->setDoesNotUseOriginalArrayStructures();
     46    }
     47
    4148    Array::Class nonArray;
    42     if (profile->usesOriginalArrayStructures(locker))
     49    if (profile->usesOriginalArrayStructures())
    4350        nonArray = Array::OriginalNonArray;
    4451    else
     
    6471            converts = Array::AsIs;
    6572
    66         return ArrayMode(type, isArray, converts, action).withProfile(locker, profile, makeSafe);
     73        return ArrayMode(type, isArray, converts, action).withProfile(profile, makeSafe);
    6774    };
    6875
    69     ArrayModes observed = profile->observedArrayModes(locker);
     76    ArrayModes observed = profile->observedArrayModes();
    7077    switch (observed) {
    7178    case 0:
    7279        return ArrayMode(Array::Unprofiled);
    7380    case asArrayModesIgnoringTypedArrays(NonArray):
    74         if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
     81        if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
    7582            return ArrayMode(Array::SelectUsingArguments, nonArray, Array::OutOfBounds, Array::Convert, action);
    76         return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(locker, profile, makeSafe);
     83        return ArrayMode(Array::SelectUsingPredictions, nonArray, action).withSpeculationFromProfile(profile, makeSafe);
    7784
    7885    case asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
    7986        if (action == Array::Write)
    8087            return ArrayMode(Array::SelectUsingArguments, Array::Array, Array::OutOfBounds, Array::Convert, action);
    81         return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     88        return ArrayMode(Array::Undecided, Array::Array, Array::OutOfBounds, Array::AsIs, action).withProfile(profile, makeSafe);
    8289       
    8390    case asArrayModesIgnoringTypedArrays(NonArray) | asArrayModesIgnoringTypedArrays(ArrayWithUndecided):
    84         if (action == Array::Write && !profile->mayInterceptIndexedAccesses(locker))
     91        if (action == Array::Write && !profile->mayInterceptIndexedAccesses())
    8592            return ArrayMode(Array::SelectUsingArguments, Array::PossiblyArray, Array::OutOfBounds, Array::Convert, action);
    86         return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(locker, profile, makeSafe);
     93        return ArrayMode(Array::SelectUsingPredictions, action).withSpeculationFromProfile(profile, makeSafe);
    8794
    8895    case asArrayModesIgnoringTypedArrays(NonArrayWithInt32):
     
    114121
    115122    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage):
    116         return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     123        return ArrayMode(Array::ArrayStorage, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    117124    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
    118125    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage):
    119         return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     126        return ArrayMode(Array::SlowPutArrayStorage, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    120127    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
    121         return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     128        return ArrayMode(Array::ArrayStorage, Array::Array, Array::AsIs, action).withProfile(profile, makeSafe);
    122129    case asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    123130    case asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    124         return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     131        return ArrayMode(Array::SlowPutArrayStorage, Array::Array, Array::AsIs, action).withProfile(profile, makeSafe);
    125132    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage):
    126         return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     133        return ArrayMode(Array::ArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(profile, makeSafe);
    127134    case asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    128135    case asArrayModesIgnoringTypedArrays(NonArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithArrayStorage) | asArrayModesIgnoringTypedArrays(NonArrayWithSlowPutArrayStorage) | asArrayModesIgnoringTypedArrays(ArrayWithSlowPutArrayStorage):
    129         return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     136        return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs, action).withProfile(profile, makeSafe);
    130137    case Int8ArrayMode:
    131         return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     138        return ArrayMode(Array::Int8Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    132139    case Int16ArrayMode:
    133         return ArrayMode(Array::Int16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     140        return ArrayMode(Array::Int16Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    134141    case Int32ArrayMode:
    135         return ArrayMode(Array::Int32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     142        return ArrayMode(Array::Int32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    136143    case Uint8ArrayMode:
    137         return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     144        return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    138145    case Uint8ClampedArrayMode:
    139         return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     146        return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    140147    case Uint16ArrayMode:
    141         return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     148        return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    142149    case Uint32ArrayMode:
    143         return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     150        return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    144151    case Float32ArrayMode:
    145         return ArrayMode(Array::Float32Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     152        return ArrayMode(Array::Float32Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    146153    case Float64ArrayMode:
    147         return ArrayMode(Array::Float64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     154        return ArrayMode(Array::Float64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    148155    case BigInt64ArrayMode:
    149         return ArrayMode(Array::BigInt64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     156        return ArrayMode(Array::BigInt64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    150157    case BigUint64ArrayMode:
    151         return ArrayMode(Array::BigUint64Array, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
     158        return ArrayMode(Array::BigUint64Array, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
    152159
    153160    default:
    154161        // If we have seen multiple TypedArray types, or a TypedArray and non-typed array, it doesn't make sense to try to convert the object since you can't convert typed arrays.
    155162        if (observed & ALL_TYPED_ARRAY_MODES)
    156             return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(locker, profile, makeSafe);
    157 
    158         if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
    159             return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(locker, profile, makeSafe);
     163            return ArrayMode(Array::Generic, nonArray, Array::AsIs, action).withProfile(profile, makeSafe);
     164
     165        if ((observed & asArrayModesIgnoringTypedArrays(NonArray)) && profile->mayInterceptIndexedAccesses())
     166            return ArrayMode(Array::SelectUsingPredictions).withSpeculationFromProfile(profile, makeSafe);
    160167       
    161168        Array::Type type;
     
    184191            arrayClass = Array::PossiblyArray;
    185192       
    186         return ArrayMode(type, arrayClass, Array::Convert, action).withProfile(locker, profile, makeSafe);
     193        return ArrayMode(type, arrayClass, Array::Convert, action).withProfile(profile, makeSafe);
    187194    }
    188195}
Note: See TracChangeset for help on using the changeset viewer.