Changeset 281615 in webkit


Ignore:
Timestamp:
Aug 26, 2021 12:39:01 AM (11 months ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Polymorphic PutByVal
https://bugs.webkit.org/show_bug.cgi?id=229229

Reviewed by Saam Barati.

This patch changes PutByVal IC to modern style. This polymorphic PutByVal can handle multiple array types and multiple identifiers.
Also, this removes adhoc IC code in Baseline so that it paves the way to unlinked Baseline JIT by cleaning up IC.

Several interesting points of the design.

  1. We need to pass ArrayProfile* via GPRReg to IC since we need to profile mayStoreToHole, which is still important to avoid the slow path.
  2. Transition / Replace IC need to record propertyRegs if it exists not to clobber these registers. This is important in DFG / FTL since IC should not clobber these registers unless it is flushed. It also makes Baseline code smaller since we do not reload them in the slow path call.
  3. Added a path folding String/Symbol when emitting PutByVal in DFG / FTL. This edge-case is found via a microbenchmark. Let's consider the case: one put_by_val site has one identifier "foo", but it has so many different Structures. Previously, we emit JITPutByIdGenerator adhocly, and still we cache this "foo" identifier in cachedId. In DFG / FTL, while we cannot make it PutByOffset, we can emit PutById since we know that identifier is always "foo". But after this patch's change, such a site becomes slow-path. And then this identifier information is missed, and we were emitting PutByVal for that. For now, we attempt to fold to one identifier in DFGByteCodeParser so that we can still attempt to make it PutById, which can be PutByOffset in constant folding phase. We would like to handle this one identifier slow-path case in PutByStatus / GetByStatus in the future patch.
  4. Now, DFG OSR exit does not query to ByValInfo for setter calls since JITPutByValGenerator use StructureStubInfo in Baseline.

Results of Microbenchmarks look good.

ToT Patched

put-by-val-direct-large-index 94.6265+-0.9076 93.4550+-0.7121 might be 1.0125x faster
inlined-put-by-val-with-string-transition

23.7131+-0.3282 22.7679+-0.1137 definitely 1.0415x faster

put-by-val-with-string-slightly-polymorphic

1.9852+-0.0284 1.9580+-0.0224 might be 1.0139x faster

get-and-put-by-val-double-index-dont-fall-off-a-cliff

185.4762+-0.5737 ? 185.6325+-0.5819 ?

polymorphic-put-by-val-with-string 30.9903+-0.1207 30.8097+-0.1285
put-by-val-machine-int 1.8803+-0.0384 1.8707+-0.0440
fold-put-by-val-with-symbol-to-multi-put-by-offset

4.8463+-0.1148 4.7839+-0.0547 might be 1.0130x faster

put-by-val-with-string-replace-and-transition

8.8730+-1.5934 6.2276+-0.0585 definitely 1.4248x faster

fold-put-by-val-with-string-to-multi-put-by-offset

4.8183+-0.0841 ? 4.8233+-0.0892 ?

put-by-val-direct 0.2845+-0.0091 ? 0.2901+-0.0088 ? might be 1.0196x slower
put-by-val-with-symbol-replace-and-transition

6.3527+-0.0686 ? 6.3933+-0.0961 ?

put-by-val-with-symbol 9.3556+-3.1421 7.1509+-0.1019 might be 1.3083x faster
put-by-val-with-symbol-slightly-polymorphic

2.0052+-0.0309 1.9781+-0.0397 might be 1.0137x faster

put-by-val-negative-array-index 14.9572+-0.1221 14.5636+-0.1044 definitely 1.0270x faster
put-by-val-with-string 11.6345+-4.3048 7.0919+-0.0918 definitely 1.6405x faster
put-by-val-large-index-blank-indexing-type

3.1425+-0.1165 3.1236+-0.0378

inlined-put-by-val-with-symbol-transition

23.4932+-0.3186 22.8469+-0.0873 definitely 1.0283x faster

polymorphic-put-by-val-with-symbol 36.6046+-1.6519 30.8597+-0.1474 definitely 1.1862x faster

Speedometer2 showed roughly 0.2-0.3% progression.


| subtest | ms | ms | b / a | pValue (significance using False Discovery Rate) |


| Elm-TodoMVC |121.916667 |121.958333 |1.000342 | 0.876802 |
| VueJS-TodoMVC |26.263333 |26.006667 |0.990227 | 0.263868 |
| EmberJS-TodoMVC |127.080000 |127.866667 |1.006190 | 0.011497 (significant) |
| BackboneJS-TodoMVC |48.920000 |49.318333 |1.008143 | 0.003395 (significant) |
| Preact-TodoMVC |19.828333 |19.828333 |1.000000 | 1.000000 |
| AngularJS-TodoMVC |134.011667 |132.080000 |0.985586 | 0.000000 (significant) |
| Vanilla-ES2015-TodoMVC |63.726667 |63.838333 |1.001752 | 0.408404 |
| Inferno-TodoMVC |65.153333 |63.753333 |0.978512 | 0.000000 (significant) |
| Flight-TodoMVC |78.133333 |78.780000 |1.008276 | 0.097794 |
| Angular2-TypeScript-TodoMVC |40.415000 |40.100000 |0.992206 | 0.287630 |
| VanillaJS-TodoMVC |51.931667 |52.500000 |1.010944 | 0.004149 (significant) |
| jQuery-TodoMVC |226.056667 |225.073333 |0.995650 | 0.007796 (significant) |
| EmberJS-Debug-TodoMVC |341.210000 |340.978333 |0.999321 | 0.623386 |
| React-TodoMVC |87.198333 |86.893333 |0.996502 | 0.042189 |
| React-Redux-TodoMVC |146.506667 |145.958333 |0.996257 | 0.018801 (significant) |
| Vanilla-ES2015-Babel-Webpack-TodoMVC |61.450000 |61.870000 |1.006835 | 0.000049 (significant) |


a mean = 254.85111
b mean = 255.25735
pValue = 0.1856561656
(Bigger means are better.)
1.002 times better
Results ARE NOT significant

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Sources.txt:
  • bytecode/AccessCase.cpp:

(JSC::AccessCase::create):
(JSC::AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck const):
(JSC::AccessCase::requiresIdentifierNameMatch const):
(JSC::AccessCase::requiresInt32PropertyCheck const):
(JSC::AccessCase::needsScratchFPR const):
(JSC::AccessCase::forEachDependentCell const):
(JSC::AccessCase::doesCalls const):
(JSC::AccessCase::canReplace const):
(JSC::AccessCase::generateWithGuard):
(JSC::AccessCase::generateImpl):
(JSC::AccessCase::toTypedArrayType):
(JSC::AccessCase::canBeShared):

  • bytecode/AccessCase.h:

(JSC::SharedJITStubSet::Hash::Key::Key):
(JSC::SharedJITStubSet::Hash::Key::operator==):
(JSC::SharedJITStubSet::Searcher::Translator::equal):

  • bytecode/ArrayProfile.h:

(JSC::ArrayProfile::offsetOfMayStoreToHole):
(JSC::ArrayProfile::offsetOfLastSeenStructureID):

  • bytecode/GetterSetterAccessCase.cpp:

(JSC::GetterSetterAccessCase::emitDOMJITGetter):

  • bytecode/ICStatusMap.h:
  • bytecode/InlineAccess.cpp:

(JSC::getScratchRegister):

  • bytecode/PolymorphicAccess.cpp:

(JSC::PolymorphicAccess::regenerate):
(WTF::printInternal):

  • bytecode/PutByStatus.cpp: Renamed from Source/JavaScriptCore/bytecode/PutByIdStatus.cpp.

(JSC::PutByStatus::appendVariant):
(JSC::PutByStatus::shrinkToFit):
(JSC::PutByStatus::computeFromLLInt):
(JSC::PutByStatus::PutByStatus):
(JSC::PutByStatus::computeFor):
(JSC::PutByStatus::computeForStubInfo):
(JSC::PutByStatus::makesCalls const):
(JSC::PutByStatus::slowVersion const):
(JSC::PutByStatus::singleIdentifier const):
(JSC::PutByStatus::visitAggregateImpl):
(JSC::PutByStatus::markIfCheap):
(JSC::PutByStatus::finalize):
(JSC::PutByStatus::merge):
(JSC::PutByStatus::filter):
(JSC::PutByStatus::dump const):

  • bytecode/PutByStatus.h: Renamed from Source/JavaScriptCore/bytecode/PutByIdStatus.h.
  • bytecode/PutByVariant.cpp: Renamed from Source/JavaScriptCore/bytecode/PutByIdVariant.cpp.

(JSC::PutByVariant::PutByVariant):
(JSC::PutByVariant::operator=):
(JSC::PutByVariant::replace):
(JSC::PutByVariant::transition):
(JSC::PutByVariant::setter):
(JSC::PutByVariant::oldStructureForTransition const):
(JSC::PutByVariant::fixTransitionToReplaceIfNecessary):
(JSC::PutByVariant::writesStructures const):
(JSC::PutByVariant::reallocatesStorage const):
(JSC::PutByVariant::makesCalls const):
(JSC::PutByVariant::attemptToMerge):
(JSC::PutByVariant::attemptToMergeTransitionWithReplace):
(JSC::PutByVariant::visitAggregateImpl):
(JSC::PutByVariant::markIfCheap):
(JSC::PutByVariant::finalize):
(JSC::PutByVariant::dump const):
(JSC::PutByVariant::dumpInContext const):

  • bytecode/PutByVariant.h: Renamed from Source/JavaScriptCore/bytecode/PutByIdVariant.h.

(JSC::PutByVariant::PutByVariant):
(JSC::PutByVariant::identifier const):
(JSC::PutByVariant::overlaps):

  • bytecode/RecordedStatuses.cpp:

(JSC::RecordedStatuses::addPutByStatus):
(JSC::RecordedStatuses::visitAggregateImpl):
(JSC::RecordedStatuses::addPutByIdStatus): Deleted.

  • bytecode/RecordedStatuses.h:
  • bytecode/StructureStubInfo.cpp:

(JSC::StructureStubInfo::reset):

  • bytecode/StructureStubInfo.h:
  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGArgumentsEliminationPhase.cpp:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::load):
(JSC::DFG::ByteCodeParser::store):
(JSC::DFG::ByteCodeParser::emitPutById):
(JSC::DFG::ByteCodeParser::handlePutById):
(JSC::DFG::ByteCodeParser::handlePutPrivateNameById):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::handlePutByVal):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGClobbersExitState.cpp:

(JSC::DFG::clobbersExitState):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
(JSC::DFG::ConstantFoldingPhase::tryFoldAsPutByOffset):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

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

(JSC::DFG::JITCompiler::link):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::addPutByVal):

  • dfg/DFGMayExit.cpp:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasPutByStatus):
(JSC::DFG::Node::putByStatus):
(JSC::DFG::Node::hasPutByIdStatus): Deleted.
(JSC::DFG::Node::putByIdStatus): Deleted.

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

(JSC::DFG::callerReturnPC):

  • dfg/DFGObjectAllocationSinkingPhase.cpp:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGStoreBarrierInsertionPhase.cpp:
  • dfg/DFGValidate.cpp:
  • dfg/DFGVarargsForwardingPhase.cpp:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileMultiPutByOffset):

  • generator/DSL.rb:
  • jit/ICStats.h:
  • jit/JIT.cpp:

(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::link):

  • jit/JIT.h:
  • jit/JITInlineCacheGenerator.cpp:

(JSC::JITPutByIdGenerator::JITPutByIdGenerator):
(JSC::JITPutByValGenerator::JITPutByValGenerator):
(JSC::JITPutByValGenerator::generateFastPath):
(JSC::JITPutByValGenerator::finalize):

  • jit/JITInlineCacheGenerator.h:
  • jit/JITInlines.h:

(JSC::JIT::emitArrayProfilingSiteWithCell):
(JSC::JIT::chooseArrayMode): Deleted.

  • jit/JITOperations.cpp:

(JSC::JSC_DEFINE_JIT_OPERATION):
(JSC::putByVal):
(JSC::directPutByVal):
(JSC::putByValOptimize):
(JSC::directPutByValOptimize):
(JSC::tryPutByValOptimize): Deleted.
(JSC::tryDirectPutByValOptimize): Deleted.

  • jit/JITOperations.h:
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::slow_op_put_by_val_prepareCallGenerator):
(JSC::JIT::emitSlow_op_put_private_name):
(JSC::JIT::slow_op_put_private_name_prepareCallGenerator):
(JSC::JIT::emitGenericContiguousPutByVal): Deleted.
(JSC::JIT::emitArrayStoragePutByVal): Deleted.
(JSC::JIT::privateCompilePutByVal): Deleted.
(JSC::JIT::privateCompilePutByValWithCachedId): Deleted.
(JSC::JIT::emitIntTypedArrayPutByVal): Deleted.
(JSC::JIT::emitFloatTypedArrayPutByVal): Deleted.

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::emitGenericContiguousPutByVal): Deleted.
(JSC::JIT::emitArrayStoragePutByVal): Deleted.

  • jit/Repatch.cpp:

(JSC::appropriateGenericPutByFunction):
(JSC::appropriateOptimizingPutByFunction):
(JSC::tryCachePutBy):
(JSC::repatchPutBy):
(JSC::tryCacheArrayPutByVal):
(JSC::repatchArrayPutByVal):
(JSC::tryCacheInBy):
(JSC::resetPutBy):
(JSC::appropriateGenericPutByIdFunction): Deleted.
(JSC::appropriateOptimizingPutByIdFunction): Deleted.
(JSC::tryCachePutByID): Deleted.
(JSC::repatchPutByID): Deleted.
(JSC::resetPutByID): Deleted.

  • jit/Repatch.h:
  • llint/LowLevelInterpreter.h:
Location:
trunk/Source/JavaScriptCore
Files:
54 edited
4 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r281607 r281615  
     12021-08-25  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Polymorphic PutByVal
     4        https://bugs.webkit.org/show_bug.cgi?id=229229
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch changes PutByVal IC to modern style. This polymorphic PutByVal can handle multiple array types and multiple identifiers.
     9        Also, this removes adhoc IC code in Baseline so that it paves the way to unlinked Baseline JIT by cleaning up IC.
     10
     11        Several interesting points of the design.
     12
     13        1. We need to pass ArrayProfile* via GPRReg to IC since we need to profile mayStoreToHole, which is still important to avoid the slow path.
     14        2. Transition / Replace IC need to record propertyRegs if it exists not to clobber these registers. This is important in DFG / FTL since
     15           IC should not clobber these registers unless it is flushed. It also makes Baseline code smaller since we do not reload them in the slow path call.
     16        3. Added a path folding String/Symbol when emitting PutByVal in DFG / FTL. This edge-case is found via a microbenchmark. Let's consider the case: one
     17           put_by_val site has one identifier "foo", but it has so many different Structures. Previously, we emit JITPutByIdGenerator adhocly, and still we
     18           cache this "foo" identifier in cachedId. In DFG / FTL, while we cannot make it PutByOffset, we can emit PutById since we know that identifier is
     19           always "foo". But after this patch's change, such a site becomes slow-path. And then this identifier information is missed, and we were emitting
     20           PutByVal for that. For now, we attempt to fold to one identifier in DFGByteCodeParser so that we can still attempt to make it PutById, which
     21           can be PutByOffset in constant folding phase. We would like to handle this one identifier slow-path case in PutByStatus / GetByStatus in the future
     22           patch.
     23        4. Now, DFG OSR exit does not query to ByValInfo for setter calls since JITPutByValGenerator use StructureStubInfo in Baseline.
     24
     25        Results of Microbenchmarks look good.
     26
     27                                                             ToT                     Patched
     28
     29        put-by-val-direct-large-index                  94.6265+-0.9076           93.4550+-0.7121          might be 1.0125x faster
     30        inlined-put-by-val-with-string-transition
     31                                                       23.7131+-0.3282     ^     22.7679+-0.1137        ^ definitely 1.0415x faster
     32        put-by-val-with-string-slightly-polymorphic
     33                                                        1.9852+-0.0284            1.9580+-0.0224          might be 1.0139x faster
     34        get-and-put-by-val-double-index-dont-fall-off-a-cliff
     35                                                      185.4762+-0.5737     ?    185.6325+-0.5819        ?
     36        polymorphic-put-by-val-with-string             30.9903+-0.1207           30.8097+-0.1285
     37        put-by-val-machine-int                          1.8803+-0.0384            1.8707+-0.0440
     38        fold-put-by-val-with-symbol-to-multi-put-by-offset
     39                                                        4.8463+-0.1148            4.7839+-0.0547          might be 1.0130x faster
     40        put-by-val-with-string-replace-and-transition
     41                                                        8.8730+-1.5934     ^      6.2276+-0.0585        ^ definitely 1.4248x faster
     42        fold-put-by-val-with-string-to-multi-put-by-offset
     43                                                        4.8183+-0.0841     ?      4.8233+-0.0892        ?
     44        put-by-val-direct                               0.2845+-0.0091     ?      0.2901+-0.0088        ? might be 1.0196x slower
     45        put-by-val-with-symbol-replace-and-transition
     46                                                        6.3527+-0.0686     ?      6.3933+-0.0961        ?
     47        put-by-val-with-symbol                          9.3556+-3.1421            7.1509+-0.1019          might be 1.3083x faster
     48        put-by-val-with-symbol-slightly-polymorphic
     49                                                        2.0052+-0.0309            1.9781+-0.0397          might be 1.0137x faster
     50        put-by-val-negative-array-index                14.9572+-0.1221     ^     14.5636+-0.1044        ^ definitely 1.0270x faster
     51        put-by-val-with-string                         11.6345+-4.3048     ^      7.0919+-0.0918        ^ definitely 1.6405x faster
     52        put-by-val-large-index-blank-indexing-type
     53                                                        3.1425+-0.1165            3.1236+-0.0378
     54        inlined-put-by-val-with-symbol-transition
     55                                                       23.4932+-0.3186     ^     22.8469+-0.0873        ^ definitely 1.0283x faster
     56        polymorphic-put-by-val-with-symbol             36.6046+-1.6519     ^     30.8597+-0.1474        ^ definitely 1.1862x faster
     57
     58        Speedometer2 showed roughly 0.2-0.3% progression.
     59
     60        ----------------------------------------------------------------------------------------------------------------------------------
     61        |               subtest                |     ms      |     ms      |  b / a   | pValue (significance using False Discovery Rate) |
     62        ----------------------------------------------------------------------------------------------------------------------------------
     63        | Elm-TodoMVC                          |121.916667   |121.958333   |1.000342  | 0.876802                                         |
     64        | VueJS-TodoMVC                        |26.263333    |26.006667    |0.990227  | 0.263868                                         |
     65        | EmberJS-TodoMVC                      |127.080000   |127.866667   |1.006190  | 0.011497 (significant)                           |
     66        | BackboneJS-TodoMVC                   |48.920000    |49.318333    |1.008143  | 0.003395 (significant)                           |
     67        | Preact-TodoMVC                       |19.828333    |19.828333    |1.000000  | 1.000000                                         |
     68        | AngularJS-TodoMVC                    |134.011667   |132.080000   |0.985586  | 0.000000 (significant)                           |
     69        | Vanilla-ES2015-TodoMVC               |63.726667    |63.838333    |1.001752  | 0.408404                                         |
     70        | Inferno-TodoMVC                      |65.153333    |63.753333    |0.978512  | 0.000000 (significant)                           |
     71        | Flight-TodoMVC                       |78.133333    |78.780000    |1.008276  | 0.097794                                         |
     72        | Angular2-TypeScript-TodoMVC          |40.415000    |40.100000    |0.992206  | 0.287630                                         |
     73        | VanillaJS-TodoMVC                    |51.931667    |52.500000    |1.010944  | 0.004149 (significant)                           |
     74        | jQuery-TodoMVC                       |226.056667   |225.073333   |0.995650  | 0.007796 (significant)                           |
     75        | EmberJS-Debug-TodoMVC                |341.210000   |340.978333   |0.999321  | 0.623386                                         |
     76        | React-TodoMVC                        |87.198333    |86.893333    |0.996502  | 0.042189                                         |
     77        | React-Redux-TodoMVC                  |146.506667   |145.958333   |0.996257  | 0.018801 (significant)                           |
     78        | Vanilla-ES2015-Babel-Webpack-TodoMVC |61.450000    |61.870000    |1.006835  | 0.000049 (significant)                           |
     79        ----------------------------------------------------------------------------------------------------------------------------------
     80        a mean = 254.85111
     81        b mean = 255.25735
     82        pValue = 0.1856561656
     83        (Bigger means are better.)
     84        1.002 times better
     85        Results ARE NOT significant
     86
     87        * JavaScriptCore.xcodeproj/project.pbxproj:
     88        * Sources.txt:
     89        * bytecode/AccessCase.cpp:
     90        (JSC::AccessCase::create):
     91        (JSC::AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck const):
     92        (JSC::AccessCase::requiresIdentifierNameMatch const):
     93        (JSC::AccessCase::requiresInt32PropertyCheck const):
     94        (JSC::AccessCase::needsScratchFPR const):
     95        (JSC::AccessCase::forEachDependentCell const):
     96        (JSC::AccessCase::doesCalls const):
     97        (JSC::AccessCase::canReplace const):
     98        (JSC::AccessCase::generateWithGuard):
     99        (JSC::AccessCase::generateImpl):
     100        (JSC::AccessCase::toTypedArrayType):
     101        (JSC::AccessCase::canBeShared):
     102        * bytecode/AccessCase.h:
     103        (JSC::SharedJITStubSet::Hash::Key::Key):
     104        (JSC::SharedJITStubSet::Hash::Key::operator==):
     105        (JSC::SharedJITStubSet::Searcher::Translator::equal):
     106        * bytecode/ArrayProfile.h:
     107        (JSC::ArrayProfile::offsetOfMayStoreToHole):
     108        (JSC::ArrayProfile::offsetOfLastSeenStructureID):
     109        * bytecode/GetterSetterAccessCase.cpp:
     110        (JSC::GetterSetterAccessCase::emitDOMJITGetter):
     111        * bytecode/ICStatusMap.h:
     112        * bytecode/InlineAccess.cpp:
     113        (JSC::getScratchRegister):
     114        * bytecode/PolymorphicAccess.cpp:
     115        (JSC::PolymorphicAccess::regenerate):
     116        (WTF::printInternal):
     117        * bytecode/PutByStatus.cpp: Renamed from Source/JavaScriptCore/bytecode/PutByIdStatus.cpp.
     118        (JSC::PutByStatus::appendVariant):
     119        (JSC::PutByStatus::shrinkToFit):
     120        (JSC::PutByStatus::computeFromLLInt):
     121        (JSC::PutByStatus::PutByStatus):
     122        (JSC::PutByStatus::computeFor):
     123        (JSC::PutByStatus::computeForStubInfo):
     124        (JSC::PutByStatus::makesCalls const):
     125        (JSC::PutByStatus::slowVersion const):
     126        (JSC::PutByStatus::singleIdentifier const):
     127        (JSC::PutByStatus::visitAggregateImpl):
     128        (JSC::PutByStatus::markIfCheap):
     129        (JSC::PutByStatus::finalize):
     130        (JSC::PutByStatus::merge):
     131        (JSC::PutByStatus::filter):
     132        (JSC::PutByStatus::dump const):
     133        * bytecode/PutByStatus.h: Renamed from Source/JavaScriptCore/bytecode/PutByIdStatus.h.
     134        * bytecode/PutByVariant.cpp: Renamed from Source/JavaScriptCore/bytecode/PutByIdVariant.cpp.
     135        (JSC::PutByVariant::PutByVariant):
     136        (JSC::PutByVariant::operator=):
     137        (JSC::PutByVariant::replace):
     138        (JSC::PutByVariant::transition):
     139        (JSC::PutByVariant::setter):
     140        (JSC::PutByVariant::oldStructureForTransition const):
     141        (JSC::PutByVariant::fixTransitionToReplaceIfNecessary):
     142        (JSC::PutByVariant::writesStructures const):
     143        (JSC::PutByVariant::reallocatesStorage const):
     144        (JSC::PutByVariant::makesCalls const):
     145        (JSC::PutByVariant::attemptToMerge):
     146        (JSC::PutByVariant::attemptToMergeTransitionWithReplace):
     147        (JSC::PutByVariant::visitAggregateImpl):
     148        (JSC::PutByVariant::markIfCheap):
     149        (JSC::PutByVariant::finalize):
     150        (JSC::PutByVariant::dump const):
     151        (JSC::PutByVariant::dumpInContext const):
     152        * bytecode/PutByVariant.h: Renamed from Source/JavaScriptCore/bytecode/PutByIdVariant.h.
     153        (JSC::PutByVariant::PutByVariant):
     154        (JSC::PutByVariant::identifier const):
     155        (JSC::PutByVariant::overlaps):
     156        * bytecode/RecordedStatuses.cpp:
     157        (JSC::RecordedStatuses::addPutByStatus):
     158        (JSC::RecordedStatuses::visitAggregateImpl):
     159        (JSC::RecordedStatuses::addPutByIdStatus): Deleted.
     160        * bytecode/RecordedStatuses.h:
     161        * bytecode/StructureStubInfo.cpp:
     162        (JSC::StructureStubInfo::reset):
     163        * bytecode/StructureStubInfo.h:
     164        * dfg/DFGAbstractInterpreterInlines.h:
     165        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     166        (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterICStatus):
     167        * dfg/DFGArgumentsEliminationPhase.cpp:
     168        * dfg/DFGByteCodeParser.cpp:
     169        (JSC::DFG::ByteCodeParser::load):
     170        (JSC::DFG::ByteCodeParser::store):
     171        (JSC::DFG::ByteCodeParser::emitPutById):
     172        (JSC::DFG::ByteCodeParser::handlePutById):
     173        (JSC::DFG::ByteCodeParser::handlePutPrivateNameById):
     174        (JSC::DFG::ByteCodeParser::parseBlock):
     175        (JSC::DFG::ByteCodeParser::handlePutByVal):
     176        * dfg/DFGClobberize.h:
     177        (JSC::DFG::clobberize):
     178        * dfg/DFGClobbersExitState.cpp:
     179        (JSC::DFG::clobbersExitState):
     180        * dfg/DFGConstantFoldingPhase.cpp:
     181        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     182        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
     183        (JSC::DFG::ConstantFoldingPhase::tryFoldAsPutByOffset):
     184        * dfg/DFGDoesGC.cpp:
     185        (JSC::DFG::doesGC):
     186        * dfg/DFGFixupPhase.cpp:
     187        (JSC::DFG::FixupPhase::fixupNode):
     188        * dfg/DFGGraph.cpp:
     189        (JSC::DFG::Graph::dump):
     190        * dfg/DFGGraph.h:
     191        * dfg/DFGJITCompiler.cpp:
     192        (JSC::DFG::JITCompiler::link):
     193        * dfg/DFGJITCompiler.h:
     194        (JSC::DFG::JITCompiler::addPutByVal):
     195        * dfg/DFGMayExit.cpp:
     196        * dfg/DFGNode.h:
     197        (JSC::DFG::Node::hasPutByStatus):
     198        (JSC::DFG::Node::putByStatus):
     199        (JSC::DFG::Node::hasPutByIdStatus): Deleted.
     200        (JSC::DFG::Node::putByIdStatus): Deleted.
     201        * dfg/DFGNodeType.h:
     202        * dfg/DFGOSRExitCompilerCommon.cpp:
     203        (JSC::DFG::callerReturnPC):
     204        * dfg/DFGObjectAllocationSinkingPhase.cpp:
     205        * dfg/DFGPredictionPropagationPhase.cpp:
     206        * dfg/DFGSafeToExecute.h:
     207        (JSC::DFG::safeToExecute):
     208        * dfg/DFGSpeculativeJIT32_64.cpp:
     209        (JSC::DFG::SpeculativeJIT::compile):
     210        * dfg/DFGSpeculativeJIT64.cpp:
     211        (JSC::DFG::SpeculativeJIT::compile):
     212        * dfg/DFGStoreBarrierInsertionPhase.cpp:
     213        * dfg/DFGValidate.cpp:
     214        * dfg/DFGVarargsForwardingPhase.cpp:
     215        * ftl/FTLCapabilities.cpp:
     216        (JSC::FTL::canCompile):
     217        * ftl/FTLLowerDFGToB3.cpp:
     218        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     219        (JSC::FTL::DFG::LowerDFGToB3::compilePutByVal):
     220        (JSC::FTL::DFG::LowerDFGToB3::compileMultiPutByOffset):
     221        * generator/DSL.rb:
     222        * jit/ICStats.h:
     223        * jit/JIT.cpp:
     224        (JSC::JIT::privateCompileSlowCases):
     225        (JSC::JIT::link):
     226        * jit/JIT.h:
     227        * jit/JITInlineCacheGenerator.cpp:
     228        (JSC::JITPutByIdGenerator::JITPutByIdGenerator):
     229        (JSC::JITPutByValGenerator::JITPutByValGenerator):
     230        (JSC::JITPutByValGenerator::generateFastPath):
     231        (JSC::JITPutByValGenerator::finalize):
     232        * jit/JITInlineCacheGenerator.h:
     233        * jit/JITInlines.h:
     234        (JSC::JIT::emitArrayProfilingSiteWithCell):
     235        (JSC::JIT::chooseArrayMode): Deleted.
     236        * jit/JITOperations.cpp:
     237        (JSC::JSC_DEFINE_JIT_OPERATION):
     238        (JSC::putByVal):
     239        (JSC::directPutByVal):
     240        (JSC::putByValOptimize):
     241        (JSC::directPutByValOptimize):
     242        (JSC::tryPutByValOptimize): Deleted.
     243        (JSC::tryDirectPutByValOptimize): Deleted.
     244        * jit/JITOperations.h:
     245        * jit/JITPropertyAccess.cpp:
     246        (JSC::JIT::emit_op_put_by_val):
     247        (JSC::JIT::emitSlow_op_put_by_val):
     248        (JSC::JIT::slow_op_put_by_val_prepareCallGenerator):
     249        (JSC::JIT::emitSlow_op_put_private_name):
     250        (JSC::JIT::slow_op_put_private_name_prepareCallGenerator):
     251        (JSC::JIT::emitGenericContiguousPutByVal): Deleted.
     252        (JSC::JIT::emitArrayStoragePutByVal): Deleted.
     253        (JSC::JIT::privateCompilePutByVal): Deleted.
     254        (JSC::JIT::privateCompilePutByValWithCachedId): Deleted.
     255        (JSC::JIT::emitIntTypedArrayPutByVal): Deleted.
     256        (JSC::JIT::emitFloatTypedArrayPutByVal): Deleted.
     257        * jit/JITPropertyAccess32_64.cpp:
     258        (JSC::JIT::emit_op_put_by_val):
     259        (JSC::JIT::emitSlow_op_put_by_val):
     260        (JSC::JIT::emitGenericContiguousPutByVal): Deleted.
     261        (JSC::JIT::emitArrayStoragePutByVal): Deleted.
     262        * jit/Repatch.cpp:
     263        (JSC::appropriateGenericPutByFunction):
     264        (JSC::appropriateOptimizingPutByFunction):
     265        (JSC::tryCachePutBy):
     266        (JSC::repatchPutBy):
     267        (JSC::tryCacheArrayPutByVal):
     268        (JSC::repatchArrayPutByVal):
     269        (JSC::tryCacheInBy):
     270        (JSC::resetPutBy):
     271        (JSC::appropriateGenericPutByIdFunction): Deleted.
     272        (JSC::appropriateOptimizingPutByIdFunction): Deleted.
     273        (JSC::tryCachePutByID): Deleted.
     274        (JSC::repatchPutByID): Deleted.
     275        (JSC::resetPutByID): Deleted.
     276        * jit/Repatch.h:
     277        * llint/LowLevelInterpreter.h:
     278
    12792021-08-25  Yusuke Suzuki  <ysuzuki@apple.com>
    2280
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r281325 r281615  
    465465                0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329414CA7DC10085F3C6 /* CallLinkStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
    466466                0F9332A014CA7DCD0085F3C6 /* GetByStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329614CA7DC10085F3C6 /* GetByStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
    467                 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
     467                0F9332A414CA7DD90085F3C6 /* PutByStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
    468468                0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    469                 0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
     469                0F93B4AA18B92C4D00178A3F /* PutByVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93B4A818B92C4D00178A3F /* PutByVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
    470470                0F952AA11DF7860900E06FBD /* VisitRaceKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952AA01DF7860700E06FBD /* VisitRaceKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
    471471                0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F952ABB1B487A7700C367C5 /* TrackedReferences.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    28672867                0F93329514CA7DC10085F3C6 /* GetByStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByStatus.cpp; sourceTree = "<group>"; };
    28682868                0F93329614CA7DC10085F3C6 /* GetByStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByStatus.h; sourceTree = "<group>"; };
    2869                 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; };
    2870                 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; };
     2869                0F93329914CA7DC10085F3C6 /* PutByStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByStatus.cpp; sourceTree = "<group>"; };
     2870                0F93329A14CA7DC10085F3C6 /* PutByStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByStatus.h; sourceTree = "<group>"; };
    28712871                0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; };
    2872                 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdVariant.cpp; sourceTree = "<group>"; };
    2873                 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdVariant.h; sourceTree = "<group>"; };
     2872                0F93B4A718B92C4D00178A3F /* PutByVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByVariant.cpp; sourceTree = "<group>"; };
     2873                0F93B4A818B92C4D00178A3F /* PutByVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByVariant.h; sourceTree = "<group>"; };
    28742874                0F952A9F1DF7860700E06FBD /* VisitRaceKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VisitRaceKey.cpp; sourceTree = "<group>"; };
    28752875                0F952AA01DF7860700E06FBD /* VisitRaceKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitRaceKey.h; sourceTree = "<group>"; };
     
    86968696                                0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */,
    86978697                                0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */,
    8698                                 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
    8699                                 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
    8700                                 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
    8701                                 0F93B4A818B92C4D00178A3F /* PutByIdVariant.h */,
     8698                                0F93329914CA7DC10085F3C6 /* PutByStatus.cpp */,
     8699                                0F93329A14CA7DC10085F3C6 /* PutByStatus.h */,
     8700                                0F93B4A718B92C4D00178A3F /* PutByVariant.cpp */,
     8701                                0F93B4A818B92C4D00178A3F /* PutByVariant.h */,
    87028702                                0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */,
    87038703                                0F44A7AD20BF685F0022B171 /* RecordedStatuses.cpp */,
     
    1050710507                                0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */,
    1050810508                                0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
    10509                                 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */,
    10510                                 0F93B4AA18B92C4D00178A3F /* PutByIdVariant.h in Headers */,
     10509                                0F9332A414CA7DD90085F3C6 /* PutByStatus.h in Headers */,
     10510                                0F93B4AA18B92C4D00178A3F /* PutByVariant.h in Headers */,
    1051110511                                0F0CD4C215F1A6070032F1C0 /* PutDirectIndexMode.h in Headers */,
    1051210512                                0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */,
  • trunk/Source/JavaScriptCore/Sources.txt

    r280493 r281615  
    270270bytecode/ProxyableAccessCase.cpp
    271271bytecode/PutByIdFlags.cpp
    272 bytecode/PutByIdStatus.cpp
    273 bytecode/PutByIdVariant.cpp
     272bytecode/PutByStatus.cpp
     273bytecode/PutByVariant.cpp
    274274bytecode/RecordedStatuses.cpp
    275275bytecode/ReduceWhitespace.cpp
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp

    r280460 r281615  
    100100    case IndexedTypedArrayFloat64Load:
    101101    case IndexedStringLoad:
     102    case IndexedInt32Store:
     103    case IndexedDoubleStore:
     104    case IndexedContiguousStore:
     105    case IndexedArrayStorageStore:
     106    case IndexedTypedArrayInt8Store:
     107    case IndexedTypedArrayUint8Store:
     108    case IndexedTypedArrayUint8ClampedStore:
     109    case IndexedTypedArrayInt16Store:
     110    case IndexedTypedArrayUint16Store:
     111    case IndexedTypedArrayInt32Store:
     112    case IndexedTypedArrayUint32Store:
     113    case IndexedTypedArrayFloat32Store:
     114    case IndexedTypedArrayFloat64Store:
    102115        RELEASE_ASSERT(!prototypeAccessChain);
    103116        break;
     
    273286    case IndexedTypedArrayFloat64Load:
    274287    case IndexedStringLoad:
     288    case IndexedInt32Store:
     289    case IndexedDoubleStore:
     290    case IndexedContiguousStore:
     291    case IndexedArrayStorageStore:
     292    case IndexedTypedArrayInt8Store:
     293    case IndexedTypedArrayUint8Store:
     294    case IndexedTypedArrayUint8ClampedStore:
     295    case IndexedTypedArrayInt16Store:
     296    case IndexedTypedArrayUint16Store:
     297    case IndexedTypedArrayInt32Store:
     298    case IndexedTypedArrayUint32Store:
     299    case IndexedTypedArrayFloat32Store:
     300    case IndexedTypedArrayFloat64Store:
    275301        return false;
    276302    default:
     
    327353    case IndexedTypedArrayFloat64Load:
    328354    case IndexedStringLoad:
     355    case IndexedInt32Store:
     356    case IndexedDoubleStore:
     357    case IndexedContiguousStore:
     358    case IndexedArrayStorageStore:
     359    case IndexedTypedArrayInt8Store:
     360    case IndexedTypedArrayUint8Store:
     361    case IndexedTypedArrayUint8ClampedStore:
     362    case IndexedTypedArrayInt16Store:
     363    case IndexedTypedArrayUint16Store:
     364    case IndexedTypedArrayInt32Store:
     365    case IndexedTypedArrayUint32Store:
     366    case IndexedTypedArrayFloat32Store:
     367    case IndexedTypedArrayFloat64Store:
    329368        return false;
    330369    }
     
    379418    case IndexedTypedArrayFloat64Load:
    380419    case IndexedStringLoad:
     420    case IndexedInt32Store:
     421    case IndexedDoubleStore:
     422    case IndexedContiguousStore:
     423    case IndexedArrayStorageStore:
     424    case IndexedTypedArrayInt8Store:
     425    case IndexedTypedArrayUint8Store:
     426    case IndexedTypedArrayUint8ClampedStore:
     427    case IndexedTypedArrayInt16Store:
     428    case IndexedTypedArrayUint16Store:
     429    case IndexedTypedArrayInt32Store:
     430    case IndexedTypedArrayUint32Store:
     431    case IndexedTypedArrayFloat32Store:
     432    case IndexedTypedArrayFloat64Store:
    381433        return true;
    382434    }
     
    426478    case IndexedTypedArrayInt32Load:
    427479    case IndexedStringLoad:
     480    case IndexedInt32Store:
     481    case IndexedContiguousStore:
     482    case IndexedArrayStorageStore:
     483    case IndexedTypedArrayInt8Store:
     484    case IndexedTypedArrayUint8Store:
     485    case IndexedTypedArrayUint8ClampedStore:
     486    case IndexedTypedArrayInt16Store:
     487    case IndexedTypedArrayUint16Store:
     488    case IndexedTypedArrayInt32Store:
    428489        return false;
    429490    case IndexedDoubleLoad:
     
    431492    case IndexedTypedArrayFloat64Load:
    432493    case IndexedTypedArrayUint32Load:
     494    case IndexedDoubleStore:
     495    case IndexedTypedArrayUint32Store:
     496    case IndexedTypedArrayFloat32Store:
     497    case IndexedTypedArrayFloat64Store:
    433498        return true;
    434499    }
     
    516581    case IndexedTypedArrayFloat64Load:
    517582    case IndexedStringLoad:
     583    case IndexedInt32Store:
     584    case IndexedDoubleStore:
     585    case IndexedContiguousStore:
     586    case IndexedArrayStorageStore:
     587    case IndexedTypedArrayInt8Store:
     588    case IndexedTypedArrayUint8Store:
     589    case IndexedTypedArrayUint8ClampedStore:
     590    case IndexedTypedArrayInt16Store:
     591    case IndexedTypedArrayUint16Store:
     592    case IndexedTypedArrayInt32Store:
     593    case IndexedTypedArrayUint32Store:
     594    case IndexedTypedArrayFloat32Store:
     595    case IndexedTypedArrayFloat64Store:
    518596        break;
    519597    }
     
    570648    case IndexedTypedArrayFloat64Load:
    571649    case IndexedStringLoad:
     650    case IndexedInt32Store:
     651    case IndexedDoubleStore:
     652    case IndexedContiguousStore:
     653    case IndexedArrayStorageStore:
     654    case IndexedTypedArrayInt8Store:
     655    case IndexedTypedArrayUint8Store:
     656    case IndexedTypedArrayUint8ClampedStore:
     657    case IndexedTypedArrayInt16Store:
     658    case IndexedTypedArrayUint16Store:
     659    case IndexedTypedArrayInt32Store:
     660    case IndexedTypedArrayUint32Store:
     661    case IndexedTypedArrayFloat32Store:
     662    case IndexedTypedArrayFloat64Store:
    572663        doesCalls = false;
    573664        break;
     
    651742    case IndexedTypedArrayFloat64Load:
    652743    case IndexedStringLoad:
     744    case IndexedInt32Store:
     745    case IndexedDoubleStore:
     746    case IndexedContiguousStore:
     747    case IndexedArrayStorageStore:
     748    case IndexedTypedArrayInt8Store:
     749    case IndexedTypedArrayUint8Store:
     750    case IndexedTypedArrayUint8ClampedStore:
     751    case IndexedTypedArrayInt16Store:
     752    case IndexedTypedArrayUint16Store:
     753    case IndexedTypedArrayInt32Store:
     754    case IndexedTypedArrayUint32Store:
     755    case IndexedTypedArrayFloat32Store:
     756    case IndexedTypedArrayFloat64Store:
    653757        return other.type() == type();
    654758
     
    9621066        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    9631067            allocator.lock(stubInfo.m_stubInfoGPR);
     1068        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    9641069        allocator.lock(scratchGPR);
    9651070       
     
    10611166        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    10621167            allocator.lock(stubInfo.m_stubInfoGPR);
     1168        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    10631169        allocator.lock(scratchGPR);
    10641170        GPRReg scratch2GPR = allocator.allocateScratchGPR();
     
    11461252        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    11471253            allocator.lock(stubInfo.m_stubInfoGPR);
     1254        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    11481255        allocator.lock(scratchGPR);
    11491256        GPRReg scratch2GPR = allocator.allocateScratchGPR();
     
    12001307        jit.and32(CCallHelpers::TrustedImm32(IndexingShapeMask), scratchGPR);
    12011308
    1202         CCallHelpers::Jump isOutOfBounds;
    1203         CCallHelpers::Jump isEmpty;
    1204 
    12051309        ScratchRegisterAllocator allocator(stubInfo.usedRegisters);
    12061310        allocator.lock(stubInfo.baseRegs());
     
    12091313        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    12101314            allocator.lock(stubInfo.m_stubInfoGPR);
     1315        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    12111316        allocator.lock(scratchGPR);
    12121317        GPRReg scratch2GPR = allocator.allocateScratchGPR();
     
    12281333
    12291334            jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
    1230             isOutOfBounds = jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, ArrayStorage::vectorLengthOffset()));
     1335            failAndIgnore.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, ArrayStorage::vectorLengthOffset())));
    12311336
    12321337            jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
    12331338#if USE(JSVALUE64)
    12341339            jit.loadValue(CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight, ArrayStorage::vectorOffset()), JSValueRegs(scratchGPR));
    1235             isEmpty = jit.branchIfEmpty(scratchGPR);
     1340            failAndIgnore.append(jit.branchIfEmpty(scratchGPR));
    12361341            jit.move(scratchGPR, valueRegs.payloadGPR());
    12371342#else
    12381343            jit.loadValue(CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight, ArrayStorage::vectorOffset()), JSValueRegs(scratch3GPR, scratchGPR));
    1239             isEmpty = jit.branchIfEmpty(scratch3GPR);
     1344            failAndIgnore.append(jit.branchIfEmpty(scratch3GPR));
    12401345            jit.move(scratchGPR, valueRegs.payloadGPR());
    12411346            jit.move(scratch3GPR, valueRegs.tagGPR());
     
    12631368
    12641369            jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
    1265             isOutOfBounds = jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, Butterfly::offsetOfPublicLength()));
     1370            failAndIgnore.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, Butterfly::offsetOfPublicLength())));
    12661371            jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
    12671372            if (m_type == IndexedDoubleLoad) {
    12681373                RELEASE_ASSERT(state.scratchFPR != InvalidFPRReg);
    12691374                jit.loadDouble(CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight), state.scratchFPR);
    1270                 isEmpty = jit.branchIfNaN(state.scratchFPR);
     1375                failAndIgnore.append(jit.branchIfNaN(state.scratchFPR));
    12711376                jit.boxDouble(state.scratchFPR, valueRegs);
    12721377            } else {
    12731378#if USE(JSVALUE64)
    12741379                jit.loadValue(CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight), JSValueRegs(scratchGPR));
    1275                 isEmpty = jit.branchIfEmpty(scratchGPR);
     1380                failAndIgnore.append(jit.branchIfEmpty(scratchGPR));
    12761381                jit.move(scratchGPR, valueRegs.payloadGPR());
    12771382#else
    12781383                jit.loadValue(CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight), JSValueRegs(scratch3GPR, scratchGPR));
    1279                 isEmpty = jit.branchIfEmpty(scratch3GPR);
     1384                failAndIgnore.append(jit.branchIfEmpty(scratch3GPR));
    12801385                jit.move(scratchGPR, valueRegs.payloadGPR());
    12811386                jit.move(scratch3GPR, valueRegs.tagGPR());
     
    12871392        state.succeed();
    12881393
    1289         if (allocator.didReuseRegisters()) {
    1290             isOutOfBounds.link(&jit);
    1291             isEmpty.link(&jit);
     1394        if (allocator.didReuseRegisters() && !failAndIgnore.empty()) {
     1395            failAndIgnore.link(&jit);
    12921396            allocator.restoreReusedRegistersByPopping(jit, preservedState);
    12931397            state.failAndIgnore.append(jit.jump());
    1294         } else {
    1295             state.failAndIgnore.append(isOutOfBounds);
    1296             state.failAndIgnore.append(isEmpty);
    1297         }
    1298 
     1398        } else
     1399            state.failAndIgnore.append(failAndIgnore);
    12991400        return;
    13001401    }
    13011402
    1302     case InstanceOfHit:
    1303     case InstanceOfMiss:
    1304         emitDefaultGuard();
    1305        
    1306         fallThrough.append(
    1307             jit.branchPtr(
    1308                 CCallHelpers::NotEqual, state.u.prototypeGPR,
    1309                 CCallHelpers::TrustedImmPtr(as<InstanceOfAccessCase>().prototype())));
    1310         break;
    1311        
    1312     case InstanceOfGeneric: {
     1403    case IndexedInt32Store:
     1404    case IndexedDoubleStore:
     1405    case IndexedContiguousStore:
     1406    case IndexedArrayStorageStore: {
    13131407        ASSERT(!viaProxy());
    1314         GPRReg prototypeGPR = state.u.prototypeGPR;
    1315         // Legend: value = `base instanceof prototypeGPR`.
    1316        
    1317         GPRReg valueGPR = valueRegs.payloadGPR();
    1318        
     1408        GPRReg propertyGPR = state.u.propertyGPR;
     1409
     1410        // int32 check done in polymorphic access.
     1411        jit.load8(CCallHelpers::Address(baseGPR, JSCell::indexingTypeAndMiscOffset()), scratchGPR);
     1412        fallThrough.append(jit.branchTest32(CCallHelpers::NonZero, scratchGPR, CCallHelpers::TrustedImm32(CopyOnWrite)));
     1413        jit.and32(CCallHelpers::TrustedImm32(IndexingShapeMask), scratchGPR);
     1414
     1415        CCallHelpers::JumpList isOutOfBounds;
     1416
    13191417        ScratchRegisterAllocator allocator(stubInfo.usedRegisters);
    13201418        allocator.lock(stubInfo.baseRegs());
     
    13231421        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    13241422            allocator.lock(stubInfo.m_stubInfoGPR);
     1423        if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     1424            allocator.lock(stubInfo.m_arrayProfileGPR);
     1425        allocator.lock(scratchGPR);
     1426        GPRReg scratch2GPR = allocator.allocateScratchGPR();
     1427        ScratchRegisterAllocator::PreservedState preservedState;
     1428
     1429        CCallHelpers::JumpList failAndIgnore;
     1430        CCallHelpers::JumpList failAndRepatch;
     1431        auto preserveReusedRegisters = [&] {
     1432            preservedState = allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     1433        };
     1434
     1435        CCallHelpers::Label storeResult;
     1436        if (m_type == IndexedArrayStorageStore) {
     1437            fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(ArrayStorageShape)));
     1438
     1439            preserveReusedRegisters();
     1440
     1441            jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
     1442            failAndIgnore.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, ArrayStorage::vectorLengthOffset())));
     1443
     1444            jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
     1445
     1446#if USE(JSVALUE64)
     1447            isOutOfBounds.append(jit.branchTest64(CCallHelpers::Zero, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight, ArrayStorage::vectorOffset())));
     1448#else
     1449            isOutOfBounds.append(jit.branch32(CCallHelpers::Equal, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight, ArrayStorage::vectorOffset() + JSValue::offsetOfTag()), CCallHelpers::TrustedImm32(JSValue::EmptyValueTag)));
     1450#endif
     1451
     1452            storeResult = jit.label();
     1453            jit.storeValue(valueRegs, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight, ArrayStorage::vectorOffset()));
     1454        } else {
     1455            IndexingType expectedShape;
     1456            switch (m_type) {
     1457            case IndexedInt32Store:
     1458                expectedShape = Int32Shape;
     1459                break;
     1460            case IndexedDoubleStore:
     1461                expectedShape = DoubleShape;
     1462                break;
     1463            case IndexedContiguousStore:
     1464                expectedShape = ContiguousShape;
     1465                break;
     1466            default:
     1467                RELEASE_ASSERT_NOT_REACHED();
     1468                break;
     1469            }
     1470
     1471            fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(expectedShape)));
     1472
     1473            preserveReusedRegisters();
     1474
     1475            jit.loadPtr(CCallHelpers::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
     1476            isOutOfBounds.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, Butterfly::offsetOfPublicLength())));
     1477            storeResult = jit.label();
     1478            switch (m_type) {
     1479            case IndexedDoubleStore: {
     1480                RELEASE_ASSERT(state.scratchFPR != InvalidFPRReg);
     1481                auto notInt = jit.branchIfNotInt32(valueRegs);
     1482                jit.convertInt32ToDouble(valueRegs.payloadGPR(), state.scratchFPR);
     1483                auto ready = jit.jump();
     1484                notInt.link(&jit);
     1485#if USE(JSVALUE64)
     1486                jit.unboxDoubleWithoutAssertions(valueRegs.payloadGPR(), scratch2GPR, state.scratchFPR);
     1487                failAndRepatch.append(jit.branchIfNaN(state.scratchFPR));
     1488#else
     1489                failAndRepatch.append(jit.branch32(CCallHelpers::Above, valueRegs.tagGPR(), CCallHelpers::TrustedImm32(JSValue::LowestTag)));
     1490                jit.unboxDouble(valueRegs, state.scratchFPR);
     1491#endif
     1492                ready.link(&jit);
     1493
     1494                jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
     1495                jit.storeDouble(state.scratchFPR, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight));
     1496                break;
     1497            }
     1498            case IndexedInt32Store:
     1499                jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
     1500                failAndRepatch.append(jit.branchIfNotInt32(valueRegs));
     1501                jit.storeValue(valueRegs, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight));
     1502                break;
     1503            case IndexedContiguousStore:
     1504                jit.zeroExtend32ToWord(propertyGPR, scratch2GPR);
     1505                jit.storeValue(valueRegs, CCallHelpers::BaseIndex(scratchGPR, scratch2GPR, CCallHelpers::TimesEight));
     1506                // WriteBarrier must be emitted in the embedder side.
     1507                break;
     1508            default:
     1509                RELEASE_ASSERT_NOT_REACHED();
     1510                break;
     1511            }
     1512        }
     1513
     1514        allocator.restoreReusedRegistersByPopping(jit, preservedState);
     1515        state.succeed();
     1516
     1517        if (m_type == IndexedArrayStorageStore) {
     1518            isOutOfBounds.link(&jit);
     1519            if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     1520                jit.store8(CCallHelpers::TrustedImm32(1), CCallHelpers::Address(stubInfo.m_arrayProfileGPR, ArrayProfile::offsetOfMayStoreToHole()));
     1521            jit.add32(CCallHelpers::TrustedImm32(1), CCallHelpers::Address(scratchGPR, ArrayStorage::numValuesInVectorOffset()));
     1522            jit.branch32(CCallHelpers::Below, scratch2GPR, CCallHelpers::Address(scratchGPR, ArrayStorage::lengthOffset())).linkTo(storeResult, &jit);
     1523
     1524            jit.add32(CCallHelpers::TrustedImm32(1), scratch2GPR);
     1525            jit.store32(scratch2GPR, CCallHelpers::Address(scratchGPR, ArrayStorage::lengthOffset()));
     1526            jit.sub32(CCallHelpers::TrustedImm32(1), scratch2GPR);
     1527            jit.jump().linkTo(storeResult, &jit);
     1528        } else {
     1529            isOutOfBounds.link(&jit);
     1530            failAndIgnore.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, CCallHelpers::Address(scratchGPR, Butterfly::offsetOfVectorLength())));
     1531            if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     1532                jit.store8(CCallHelpers::TrustedImm32(1), CCallHelpers::Address(stubInfo.m_arrayProfileGPR, ArrayProfile::offsetOfMayStoreToHole()));
     1533            jit.add32(CCallHelpers::TrustedImm32(1), propertyGPR, scratch2GPR);
     1534            jit.store32(scratch2GPR, CCallHelpers::Address(scratchGPR, Butterfly::offsetOfPublicLength()));
     1535            jit.jump().linkTo(storeResult, &jit);
     1536
     1537        }
     1538
     1539        if (allocator.didReuseRegisters()) {
     1540            if (!failAndIgnore.empty()) {
     1541                failAndIgnore.link(&jit);
     1542                allocator.restoreReusedRegistersByPopping(jit, preservedState);
     1543                state.failAndIgnore.append(jit.jump());
     1544            }
     1545            if (!failAndRepatch.empty()) {
     1546                failAndRepatch.link(&jit);
     1547                allocator.restoreReusedRegistersByPopping(jit, preservedState);
     1548                state.failAndRepatch.append(jit.jump());
     1549            }
     1550        } else {
     1551            state.failAndIgnore.append(failAndIgnore);
     1552            state.failAndRepatch.append(failAndRepatch);
     1553        }
     1554        return;
     1555    }
     1556
     1557    case IndexedTypedArrayInt8Store:
     1558    case IndexedTypedArrayUint8Store:
     1559    case IndexedTypedArrayUint8ClampedStore:
     1560    case IndexedTypedArrayInt16Store:
     1561    case IndexedTypedArrayUint16Store:
     1562    case IndexedTypedArrayInt32Store:
     1563    case IndexedTypedArrayUint32Store:
     1564    case IndexedTypedArrayFloat32Store:
     1565    case IndexedTypedArrayFloat64Store: {
     1566        ASSERT(!viaProxy());
     1567        // This code is written such that the result could alias with the base or the property.
     1568
     1569        TypedArrayType type = toTypedArrayType(m_type);
     1570
     1571        GPRReg propertyGPR = state.u.propertyGPR;
     1572
     1573        jit.load8(CCallHelpers::Address(baseGPR, JSCell::typeInfoTypeOffset()), scratchGPR);
     1574        fallThrough.append(jit.branch32(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImm32(typeForTypedArrayType(type))));
     1575
     1576        if (isInt(type))
     1577            state.failAndRepatch.append(jit.branchIfNotInt32(valueRegs));
     1578        else {
     1579            ASSERT(isFloat(type));
     1580            RELEASE_ASSERT(state.scratchFPR != InvalidFPRReg);
     1581            auto doubleCase = jit.branchIfNotInt32(valueRegs);
     1582            jit.convertInt32ToDouble(valueRegs.payloadGPR(), state.scratchFPR);
     1583            auto ready = jit.jump();
     1584            doubleCase.link(&jit);
     1585#if USE(JSVALUE64)
     1586            state.failAndRepatch.append(jit.branchIfNotNumber(valueRegs.payloadGPR()));
     1587            jit.unboxDoubleWithoutAssertions(valueRegs.payloadGPR(), scratchGPR, state.scratchFPR);
     1588#else
     1589            state.failAndRepatch.append(jit.branch32(CCallHelpers::Above, valueRegs.tagGPR(), CCallHelpers::TrustedImm32(JSValue::LowestTag)));
     1590            jit.unboxDouble(valueRegs, state.scratchFPR);
     1591#endif
     1592            ready.link(&jit);
     1593        }
     1594
     1595        jit.load32(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfLength()), scratchGPR);
     1596        // OutOfBounds bit of ArrayProfile will be set in the operation function.
     1597        state.failAndRepatch.append(jit.branch32(CCallHelpers::AboveOrEqual, propertyGPR, scratchGPR));
     1598
     1599        ScratchRegisterAllocator allocator(stubInfo.usedRegisters);
     1600        allocator.lock(stubInfo.baseRegs());
     1601        allocator.lock(valueRegs);
     1602        allocator.lock(stubInfo.propertyRegs());
     1603        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
     1604            allocator.lock(stubInfo.m_stubInfoGPR);
     1605        if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     1606            allocator.lock(stubInfo.m_arrayProfileGPR);
     1607        allocator.lock(scratchGPR);
     1608        GPRReg scratch2GPR = allocator.allocateScratchGPR();
     1609        GPRReg scratch3GPR = InvalidGPRReg;
     1610        if (isClamped(type))
     1611            scratch3GPR = allocator.allocateScratchGPR();
     1612
     1613        ScratchRegisterAllocator::PreservedState preservedState = allocator.preserveReusedRegistersByPushing(
     1614            jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     1615
     1616        jit.loadPtr(CCallHelpers::Address(baseGPR, JSArrayBufferView::offsetOfVector()), scratch2GPR);
     1617        jit.cageConditionallyAndUntag(Gigacage::Primitive, scratch2GPR, scratchGPR, scratchGPR, false);
     1618
     1619        jit.signExtend32ToPtr(propertyGPR, scratchGPR);
     1620        if (isInt(type)) {
     1621            if (isClamped(type)) {
     1622                ASSERT(elementSize(type) == 1);
     1623                ASSERT(!JSC::isSigned(type));
     1624                jit.move(valueRegs.payloadGPR(), scratch3GPR);
     1625                auto inBounds = jit.branch32(CCallHelpers::BelowOrEqual, scratch3GPR, CCallHelpers::TrustedImm32(0xff));
     1626                auto tooBig = jit.branch32(CCallHelpers::GreaterThan, scratch3GPR, CCallHelpers::TrustedImm32(0xff));
     1627                jit.xor32(scratch3GPR, scratch3GPR);
     1628                auto clamped = jit.jump();
     1629                tooBig.link(&jit);
     1630                jit.move(CCallHelpers::TrustedImm32(0xff), scratch3GPR);
     1631                clamped.link(&jit);
     1632                inBounds.link(&jit);
     1633                jit.store8(scratch3GPR, CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesOne));
     1634            } else {
     1635                switch (elementSize(type)) {
     1636                case 1:
     1637                    jit.store8(valueRegs.payloadGPR(), CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesOne));
     1638                    break;
     1639                case 2:
     1640                    jit.store16(valueRegs.payloadGPR(), CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesTwo));
     1641                    break;
     1642                case 4:
     1643                    jit.store32(valueRegs.payloadGPR(), CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesFour));
     1644                    break;
     1645                default:
     1646                    CRASH();
     1647                }
     1648            }
     1649        } else {
     1650            ASSERT(isFloat(type));
     1651            RELEASE_ASSERT(state.scratchFPR != InvalidFPRReg);
     1652            switch (elementSize(type)) {
     1653            case 4:
     1654                jit.convertDoubleToFloat(state.scratchFPR, state.scratchFPR);
     1655                jit.storeFloat(state.scratchFPR, CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesFour));
     1656                break;
     1657            case 8: {
     1658                jit.storeDouble(state.scratchFPR, CCallHelpers::BaseIndex(scratch2GPR, scratchGPR, CCallHelpers::TimesEight));
     1659                break;
     1660            }
     1661            default:
     1662                CRASH();
     1663            }
     1664        }
     1665
     1666        allocator.restoreReusedRegistersByPopping(jit, preservedState);
     1667        state.succeed();
     1668        return;
     1669    }
     1670
     1671    case InstanceOfHit:
     1672    case InstanceOfMiss:
     1673        emitDefaultGuard();
     1674       
     1675        fallThrough.append(
     1676            jit.branchPtr(
     1677                CCallHelpers::NotEqual, state.u.prototypeGPR,
     1678                CCallHelpers::TrustedImmPtr(as<InstanceOfAccessCase>().prototype())));
     1679        break;
     1680       
     1681    case InstanceOfGeneric: {
     1682        ASSERT(!viaProxy());
     1683        GPRReg prototypeGPR = state.u.prototypeGPR;
     1684        // Legend: value = `base instanceof prototypeGPR`.
     1685       
     1686        GPRReg valueGPR = valueRegs.payloadGPR();
     1687       
     1688        ScratchRegisterAllocator allocator(stubInfo.usedRegisters);
     1689        allocator.lock(stubInfo.baseRegs());
     1690        allocator.lock(valueRegs);
     1691        allocator.lock(stubInfo.propertyRegs());
     1692        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
     1693            allocator.lock(stubInfo.m_stubInfoGPR);
     1694        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    13251695        allocator.lock(scratchGPR);
    13261696       
     
    18952265        allocator.lock(stubInfo.baseRegs());
    18962266        allocator.lock(valueRegs);
     2267        if (stubInfo.propertyRegs())
     2268            allocator.lock(stubInfo.propertyRegs());
    18972269        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    18982270            allocator.lock(stubInfo.m_stubInfoGPR);
     2271        if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     2272            allocator.lock(stubInfo.m_arrayProfileGPR);
    18992273        allocator.lock(scratchGPR);
    19002274
     
    20592433        if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    20602434            allocator.lock(stubInfo.m_stubInfoGPR);
     2435        ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    20612436        allocator.lock(scratchGPR);
    20622437        ASSERT(structure()->transitionWatchpointSetHasBeenInvalidated());
     
    21842559    case IndexedStringLoad:
    21852560    case CheckPrivateBrand:
     2561    case IndexedInt32Store:
     2562    case IndexedDoubleStore:
     2563    case IndexedContiguousStore:
     2564    case IndexedArrayStorageStore:
     2565    case IndexedTypedArrayInt8Store:
     2566    case IndexedTypedArrayUint8Store:
     2567    case IndexedTypedArrayUint8ClampedStore:
     2568    case IndexedTypedArrayInt16Store:
     2569    case IndexedTypedArrayUint16Store:
     2570    case IndexedTypedArrayInt32Store:
     2571    case IndexedTypedArrayUint32Store:
     2572    case IndexedTypedArrayFloat32Store:
     2573    case IndexedTypedArrayFloat64Store:
    21862574        // These need to be handled by generateWithGuard(), since the guard is part of the
    21872575        // algorithm. We can be sure that nobody will call generate() directly for these since they
     
    21972585    switch (accessType) {
    21982586    case IndexedTypedArrayInt8Load:
     2587    case IndexedTypedArrayInt8Store:
    21992588        return TypeInt8;
    22002589    case IndexedTypedArrayUint8Load:
     2590    case IndexedTypedArrayUint8Store:
    22012591        return TypeUint8;
    22022592    case IndexedTypedArrayUint8ClampedLoad:
     2593    case IndexedTypedArrayUint8ClampedStore:
    22032594        return TypeUint8Clamped;
    22042595    case IndexedTypedArrayInt16Load:
     2596    case IndexedTypedArrayInt16Store:
    22052597        return TypeInt16;
    22062598    case IndexedTypedArrayUint16Load:
     2599    case IndexedTypedArrayUint16Store:
    22072600        return TypeUint16;
    22082601    case IndexedTypedArrayInt32Load:
     2602    case IndexedTypedArrayInt32Store:
    22092603        return TypeInt32;
    22102604    case IndexedTypedArrayUint32Load:
     2605    case IndexedTypedArrayUint32Store:
    22112606        return TypeUint32;
    22122607    case IndexedTypedArrayFloat32Load:
     2608    case IndexedTypedArrayFloat32Store:
    22132609        return TypeFloat32;
    22142610    case IndexedTypedArrayFloat64Load:
     2611    case IndexedTypedArrayFloat64Store:
    22152612        return TypeFloat64;
    22162613    default:
     
    22852682    case IndexedTypedArrayFloat32Load:
    22862683    case IndexedTypedArrayFloat64Load:
     2684    case IndexedInt32Store:
     2685    case IndexedDoubleStore:
     2686    case IndexedContiguousStore:
     2687    case IndexedArrayStorageStore:
     2688    case IndexedTypedArrayInt8Store:
     2689    case IndexedTypedArrayUint8Store:
     2690    case IndexedTypedArrayUint8ClampedStore:
     2691    case IndexedTypedArrayInt16Store:
     2692    case IndexedTypedArrayUint16Store:
     2693    case IndexedTypedArrayInt32Store:
     2694    case IndexedTypedArrayUint32Store:
     2695    case IndexedTypedArrayFloat32Store:
     2696    case IndexedTypedArrayFloat64Store:
    22872697    case IndexedStringLoad:
    22882698    case InstanceOfGeneric:
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.h

    r279813 r281615  
    129129        IndexedTypedArrayFloat32Load,
    130130        IndexedTypedArrayFloat64Load,
    131         IndexedStringLoad
     131        IndexedStringLoad,
     132        IndexedInt32Store,
     133        IndexedDoubleStore,
     134        IndexedContiguousStore,
     135        IndexedArrayStorageStore,
     136        IndexedTypedArrayInt8Store,
     137        IndexedTypedArrayUint8Store,
     138        IndexedTypedArrayUint8ClampedStore,
     139        IndexedTypedArrayInt16Store,
     140        IndexedTypedArrayUint16Store,
     141        IndexedTypedArrayInt32Store,
     142        IndexedTypedArrayUint32Store,
     143        IndexedTypedArrayFloat32Store,
     144        IndexedTypedArrayFloat64Store,
    132145    };
    133146
     
    354367            Key() = default;
    355368
    356             Key(GPRReg baseGPR, GPRReg valueGPR, GPRReg extraGPR, GPRReg stubInfoGPR, RegisterSet usedRegisters, PolymorphicAccessJITStubRoutine* wrapped)
     369            Key(GPRReg baseGPR, GPRReg valueGPR, GPRReg extraGPR, GPRReg stubInfoGPR, GPRReg arrayProfileGPR, RegisterSet usedRegisters, PolymorphicAccessJITStubRoutine* wrapped)
    357370                : m_wrapped(wrapped)
    358371                , m_baseGPR(baseGPR)
     
    360373                , m_extraGPR(extraGPR)
    361374                , m_stubInfoGPR(stubInfoGPR)
     375                , m_arrayProfileGPR(arrayProfileGPR)
    362376                , m_usedRegisters(usedRegisters)
    363377            { }
     
    376390                    && a.m_extraGPR == b.m_extraGPR
    377391                    && a.m_stubInfoGPR == b.m_stubInfoGPR
     392                    && a.m_arrayProfileGPR == b.m_arrayProfileGPR
    378393                    && a.m_usedRegisters == b.m_usedRegisters;
    379394            }
     
    384399            GPRReg m_extraGPR;
    385400            GPRReg m_stubInfoGPR;
     401            GPRReg m_arrayProfileGPR;
    386402            RegisterSet m_usedRegisters;
    387403        };
     
    417433                    && a.m_extraGPR == b.m_extraGPR
    418434                    && a.m_stubInfoGPR == b.m_stubInfoGPR
     435                    && a.m_arrayProfileGPR == b.m_arrayProfileGPR
    419436                    && a.m_usedRegisters == b.m_usedRegisters) {
    420437                    // FIXME: The ordering of cases does not matter for sharing capabilities.
     
    446463        GPRReg m_extraGPR;
    447464        GPRReg m_stubInfoGPR;
     465        GPRReg m_arrayProfileGPR;
    448466        RegisterSet m_usedRegisters;
    449467        const FixedVector<RefPtr<AccessCase>>& m_cases;
  • trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h

    r272170 r281615  
    209209    bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
    210210
     211    static ptrdiff_t offsetOfMayStoreToHole() { return OBJECT_OFFSETOF(ArrayProfile, m_mayStoreToHole); }
     212    static ptrdiff_t offsetOfLastSeenStructureID() { return OBJECT_OFFSETOF(ArrayProfile, m_lastSeenStructureID); }
     213
    211214    void setOutOfBounds() { m_outOfBounds = true; }
    212215    bool* addressOfOutOfBounds() { return &m_outOfBounds; }
  • trunk/Source/JavaScriptCore/bytecode/GetterSetterAccessCase.cpp

    r278656 r281615  
    142142    if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    143143        allocator.lock(stubInfo.m_stubInfoGPR);
     144    ASSERT(stubInfo.m_arrayProfileGPR == InvalidGPRReg);
    144145    allocator.lock(scratchGPR);
    145146
  • trunk/Source/JavaScriptCore/bytecode/ICStatusMap.h

    r278445 r281615  
    3737class GetByStatus;
    3838class InByStatus;
    39 class PutByIdStatus;
     39class PutByStatus;
    4040class DeleteByStatus;
    4141class StructureStubInfo;
     
    4949    GetByStatus* getStatus { nullptr };
    5050    InByStatus* inStatus { nullptr };
    51     PutByIdStatus* putStatus { nullptr };
     51    PutByStatus* putStatus { nullptr };
    5252    DeleteByStatus* deleteStatus { nullptr };
    5353};
  • trunk/Source/JavaScriptCore/bytecode/InlineAccess.cpp

    r278656 r281615  
    217217    allocator.lock(stubInfo.valueTagGPR);
    218218#endif
     219    if (stubInfo.propertyRegs())
     220        allocator.lock(stubInfo.propertyRegs());
    219221    if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    220222        allocator.lock(stubInfo.m_stubInfoGPR);
     223    if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     224        allocator.lock(stubInfo.m_arrayProfileGPR);
    221225    GPRReg scratch = allocator.allocateScratchGPR();
    222226    if (allocator.didReuseRegisters())
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp

    r279813 r281615  
    495495    if (stubInfo.m_stubInfoGPR != InvalidGPRReg)
    496496        allocator.lock(stubInfo.m_stubInfoGPR);
     497    if (stubInfo.m_arrayProfileGPR != InvalidGPRReg)
     498        allocator.lock(stubInfo.m_arrayProfileGPR);
    497499
    498500    state.scratchGPR = allocator.allocateScratchGPR();
     
    811813            stubInfo.regs.thisGPR,
    812814            stubInfo.m_stubInfoGPR,
     815            stubInfo.m_arrayProfileGPR,
    813816            stubInfo.usedRegisters,
    814817            keys,
     
    847850    if (codeBlock->useDataIC()) {
    848851        if (canBeShared)
    849             vm.m_sharedJITStubs->add(SharedJITStubSet::Hash::Key(stubInfo.baseGPR, stubInfo.valueGPR, stubInfo.regs.thisGPR, stubInfo.m_stubInfoGPR, stubInfo.usedRegisters, stub.get()));
     852            vm.m_sharedJITStubs->add(SharedJITStubSet::Hash::Key(stubInfo.baseGPR, stubInfo.valueGPR, stubInfo.regs.thisGPR, stubInfo.m_stubInfoGPR, stubInfo.m_arrayProfileGPR, stubInfo.usedRegisters, stub.get()));
    850853    }
    851854
     
    10231026        out.print("IndexedStringLoad");
    10241027        return;
     1028    case AccessCase::IndexedInt32Store:
     1029        out.print("IndexedInt32Store");
     1030        return;
     1031    case AccessCase::IndexedDoubleStore:
     1032        out.print("IndexedDoubleStore");
     1033        return;
     1034    case AccessCase::IndexedContiguousStore:
     1035        out.print("IndexedContiguousStore");
     1036        return;
     1037    case AccessCase::IndexedArrayStorageStore:
     1038        out.print("IndexedArrayStorageStore");
     1039        return;
     1040    case AccessCase::IndexedTypedArrayInt8Store:
     1041        out.print("IndexedTypedArrayInt8Store");
     1042        return;
     1043    case AccessCase::IndexedTypedArrayUint8Store:
     1044        out.print("IndexedTypedArrayUint8Store");
     1045        return;
     1046    case AccessCase::IndexedTypedArrayUint8ClampedStore:
     1047        out.print("IndexedTypedArrayUint8ClampedStore");
     1048        return;
     1049    case AccessCase::IndexedTypedArrayInt16Store:
     1050        out.print("IndexedTypedArrayInt16Store");
     1051        return;
     1052    case AccessCase::IndexedTypedArrayUint16Store:
     1053        out.print("IndexedTypedArrayUint16Store");
     1054        return;
     1055    case AccessCase::IndexedTypedArrayInt32Store:
     1056        out.print("IndexedTypedArrayInt32Store");
     1057        return;
     1058    case AccessCase::IndexedTypedArrayUint32Store:
     1059        out.print("IndexedTypedArrayUint32Store");
     1060        return;
     1061    case AccessCase::IndexedTypedArrayFloat32Store:
     1062        out.print("IndexedTypedArrayFloat32Store");
     1063        return;
     1064    case AccessCase::IndexedTypedArrayFloat64Store:
     1065        out.print("IndexedTypedArrayFloat64Store");
     1066        return;
    10251067    }
    10261068
  • trunk/Source/JavaScriptCore/bytecode/PutByStatus.cpp

    r281614 r281615  
    2525
    2626#include "config.h"
    27 #include "PutByIdStatus.h"
     27#include "PutByStatus.h"
    2828
    2929#include "BytecodeStructs.h"
     
    3939namespace JSC {
    4040
    41 bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
     41bool PutByStatus::appendVariant(const PutByVariant& variant)
    4242{
    4343    return appendICStatusVariant(m_variants, variant);
    4444}
    4545
    46 void PutByIdStatus::shrinkToFit()
     46void PutByStatus::shrinkToFit()
    4747{
    4848    m_variants.shrinkToFit();
    4949}
    5050
    51 PutByIdStatus PutByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid)
     51PutByStatus PutByStatus::computeFromLLInt(CodeBlock* profiledBlock, BytecodeIndex bytecodeIndex)
    5252{
    5353    VM& vm = profiledBlock->vm();
     
    5555    auto instruction = profiledBlock->instructions().at(bytecodeIndex.offset());
    5656
    57     // We are not yet using `computeFromLLInt` in any place for `put_private_name`.
    58     // We can add support for it if this is required in future changes, since we have
    59     // IC implemented for this operation on LLInt.
    60     ASSERT(!instruction->is<OpPutPrivateName>());
     57    switch (instruction->opcodeID()) {
     58    case op_put_by_id:
     59        break;
     60    case op_put_by_val:
     61    case op_put_by_val_direct:
     62        return PutByStatus(NoInformation);
     63    case op_put_private_name:
     64        // We do no have a code retrieving LLInt information for `op_put_private_name`.
     65        // We can add support for it if this is required in future changes, since we have
     66        // IC implemented for this operation on LLInt.
     67        return PutByStatus(NoInformation);
     68    default: {
     69        RELEASE_ASSERT_NOT_REACHED();
     70        break;
     71    }
     72    }
    6173
    6274    auto bytecode = instruction->as<OpPutById>();
    6375    auto& metadata = bytecode.metadata(profiledBlock);
     76    const Identifier* identifier = &(profiledBlock->identifier(bytecode.m_property));
     77    UniquedStringImpl* uid = identifier->impl();
    6478
    6579    StructureID structureID = metadata.m_oldStructureID;
    6680    if (!structureID)
    67         return PutByIdStatus(NoInformation);
     81        return PutByStatus(NoInformation);
    6882   
    6983    Structure* structure = vm.heap.structureIDTable().get(structureID);
     
    7387        PropertyOffset offset = structure->getConcurrently(uid);
    7488        if (!isValidOffset(offset))
    75             return PutByIdStatus(NoInformation);
    76        
    77         return PutByIdVariant::replace(structure, offset);
     89            return PutByStatus(NoInformation);
     90       
     91        return PutByVariant::replace(nullptr, structure, offset);
    7892    }
    7993
     
    8498    PropertyOffset offset = newStructure->getConcurrently(uid);
    8599    if (!isValidOffset(offset))
    86         return PutByIdStatus(NoInformation);
     100        return PutByStatus(NoInformation);
    87101   
    88102    ObjectPropertyConditionSet conditionSet;
     
    92106                vm, profiledBlock->globalObject(), structure, uid);
    93107        if (!conditionSet.isValid())
    94             return PutByIdStatus(NoInformation);
    95     }
    96    
    97     return PutByIdVariant::transition(
    98         structure, newStructure, conditionSet, offset);
     108            return PutByStatus(NoInformation);
     109    }
     110   
     111    return PutByVariant::transition(nullptr, structure, newStructure, conditionSet, offset);
    99112}
    100113
    101114#if ENABLE(JIT)
    102 PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, UniquedStringImpl* uid, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData)
     115PutByStatus::PutByStatus(StubInfoSummary summary, StructureStubInfo& stubInfo)
     116{
     117    switch (summary) {
     118    case StubInfoSummary::NoInformation:
     119        m_state = NoInformation;
     120        return;
     121    case StubInfoSummary::Simple:
     122    case StubInfoSummary::MakesCalls:
     123        RELEASE_ASSERT_NOT_REACHED();
     124        return;
     125    case StubInfoSummary::TakesSlowPath:
     126        m_state = stubInfo.tookSlowPath ? ObservedTakesSlowPath : LikelyTakesSlowPath;
     127        return;
     128    case StubInfoSummary::TakesSlowPathAndMakesCalls:
     129        m_state = stubInfo.tookSlowPath ? ObservedSlowPathAndMakesCalls : MakesCalls;
     130        return;
     131    }
     132    RELEASE_ASSERT_NOT_REACHED();
     133}
     134
     135PutByStatus PutByStatus::computeFor(CodeBlock* profiledBlock, ICStatusMap& map, BytecodeIndex bytecodeIndex, ExitFlag didExit, CallLinkStatus::ExitSiteData callExitSiteData)
    103136{
    104137    ConcurrentJSLocker locker(profiledBlock->m_lock);
     
    106139    UNUSED_PARAM(profiledBlock);
    107140    UNUSED_PARAM(bytecodeIndex);
    108     UNUSED_PARAM(uid);
    109141#if ENABLE(DFG_JIT)
    110142    if (didExit)
    111         return PutByIdStatus(TakesSlowPath);
     143        return PutByStatus(LikelyTakesSlowPath);
    112144   
    113145    StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex)).stubInfo;
    114     PutByIdStatus result = computeForStubInfo(
    115         locker, profiledBlock, stubInfo, uid, callExitSiteData);
     146    PutByStatus result = computeForStubInfo(
     147        locker, profiledBlock, stubInfo, callExitSiteData);
    116148    if (!result)
    117         return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
     149        return computeFromLLInt(profiledBlock, bytecodeIndex);
    118150   
    119151    return result;
     
    122154    UNUSED_PARAM(didExit);
    123155    UNUSED_PARAM(callExitSiteData);
    124     return PutByIdStatus(NoInformation);
     156    return PutByStatus(NoInformation);
    125157#endif // ENABLE(JIT)
    126158}
    127159
    128 PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* baselineBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid)
     160PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* baselineBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin)
    129161{
    130162    return computeForStubInfo(
    131         locker, baselineBlock, stubInfo, uid,
     163        locker, baselineBlock, stubInfo,
    132164        CallLinkStatus::computeExitSiteData(baselineBlock, codeOrigin.bytecodeIndex()));
    133165}
    134166
    135 PutByIdStatus PutByIdStatus::computeForStubInfo(
    136     const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
    137     UniquedStringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
     167PutByStatus PutByStatus::computeForStubInfo(const ConcurrentJSLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CallLinkStatus::ExitSiteData callExitSiteData)
    138168{
    139169    StubInfoSummary summary = StructureStubInfo::summary(profiledBlock->vm(), stubInfo);
    140170    if (!isInlineable(summary))
    141         return PutByIdStatus(summary);
     171        return PutByStatus(summary, *stubInfo);
    142172   
    143173    switch (stubInfo->cacheType()) {
    144174    case CacheType::Unset:
    145175        // This means that we attempted to cache but failed for some reason.
    146         return PutByIdStatus(JSC::slowVersion(summary));
     176        return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    147177       
    148178    case CacheType::PutByIdReplace: {
     179        CacheableIdentifier identifier = stubInfo->identifier();
     180        UniquedStringImpl* uid = identifier.uid();
     181        RELEASE_ASSERT(uid);
    149182        PropertyOffset offset =
    150183            stubInfo->m_inlineAccessBaseStructure->getConcurrently(uid);
    151         if (isValidOffset(offset)) {
    152             return PutByIdVariant::replace(
    153                 stubInfo->m_inlineAccessBaseStructure.get(), offset);
    154         }
    155         return PutByIdStatus(JSC::slowVersion(summary));
     184        if (isValidOffset(offset))
     185            return PutByVariant::replace(WTFMove(identifier), stubInfo->m_inlineAccessBaseStructure.get(), offset);
     186        return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    156187    }
    157188       
     
    159190        PolymorphicAccess* list = stubInfo->u.stub;
    160191       
    161         PutByIdStatus result;
     192        PutByStatus result;
    162193        result.m_state = Simple;
    163194       
     
    165196            const AccessCase& access = list->at(i);
    166197            if (access.viaProxy())
    167                 return PutByIdStatus(JSC::slowVersion(summary));
     198                return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    168199            if (access.usesPolyProto())
    169                 return PutByIdStatus(JSC::slowVersion(summary));
    170            
    171             PutByIdVariant variant;
     200                return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    172201           
    173202            switch (access.type()) {
    174203            case AccessCase::Replace: {
    175204                Structure* structure = access.structure();
    176                 PropertyOffset offset = structure->getConcurrently(uid);
     205                PropertyOffset offset = structure->getConcurrently(access.uid());
    177206                if (!isValidOffset(offset))
    178                     return PutByIdStatus(JSC::slowVersion(summary));
    179                 variant = PutByIdVariant::replace(
    180                     structure, offset);
     207                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
     208                auto variant = PutByVariant::replace(access.identifier(), structure, offset);
     209                if (!result.appendVariant(variant))
     210                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    181211                break;
    182212            }
    183213               
    184214            case AccessCase::Transition: {
    185                 PropertyOffset offset =
    186                     access.newStructure()->getConcurrently(uid);
     215                PropertyOffset offset = access.newStructure()->getConcurrently(access.uid());
    187216                if (!isValidOffset(offset))
    188                     return PutByIdStatus(JSC::slowVersion(summary));
     217                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    189218                ObjectPropertyConditionSet conditionSet = access.conditionSet();
    190219                if (!conditionSet.structuresEnsureValidity())
    191                     return PutByIdStatus(JSC::slowVersion(summary));
    192                 variant = PutByIdVariant::transition(
    193                     access.structure(), access.newStructure(), conditionSet, offset);
     220                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
     221                auto variant = PutByVariant::transition(access.identifier(), access.structure(), access.newStructure(), conditionSet, offset);
     222                if (!result.appendVariant(variant))
     223                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    194224                break;
    195225            }
     
    198228                Structure* structure = access.structure();
    199229               
    200                 ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
    201                     structure, access.conditionSet(), uid);
     230                ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(structure, access.conditionSet(), access.uid());
    202231               
    203232                switch (complexGetStatus.kind()) {
     
    206235                   
    207236                case ComplexGetStatus::TakesSlowPath:
    208                     return PutByIdStatus(JSC::slowVersion(summary));
     237                    return PutByStatus(JSC::slowVersion(summary), *stubInfo);
    209238                   
    210239                case ComplexGetStatus::Inlineable: {
     
    216245                    }
    217246                   
    218                     variant = PutByIdVariant::setter(
    219                         structure, complexGetStatus.offset(), complexGetStatus.conditionSet(),
    220                         WTFMove(callLinkStatus));
    221                 } }
     247                    auto variant = PutByVariant::setter(access.identifier(), structure, complexGetStatus.offset(), complexGetStatus.conditionSet(), WTFMove(callLinkStatus));
     248                    if (!result.appendVariant(variant))
     249                        return PutByStatus(JSC::slowVersion(summary), *stubInfo);
     250                }
     251                }
    222252                break;
    223253            }
     
    225255            case AccessCase::CustomValueSetter:
    226256            case AccessCase::CustomAccessorSetter:
    227                 return PutByIdStatus(MakesCalls);
     257                return PutByStatus(MakesCalls);
    228258
    229259            default:
    230                 return PutByIdStatus(JSC::slowVersion(summary));
    231             }
    232            
    233             if (!result.appendVariant(variant))
    234                 return PutByIdStatus(JSC::slowVersion(summary));
     260                return PutByStatus(JSC::slowVersion(summary), *stubInfo);
     261            }
    235262        }
    236263       
     
    240267       
    241268    default:
    242         return PutByIdStatus(JSC::slowVersion(summary));
    243     }
    244 }
    245 
    246 PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& contextStack, CodeOrigin codeOrigin, UniquedStringImpl* uid)
     269        return PutByStatus(JSC::slowVersion(summary), *stubInfo);
     270    }
     271}
     272
     273PutByStatus PutByStatus::computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& contextStack, CodeOrigin codeOrigin)
    247274{
    248275    BytecodeIndex bytecodeIndex = codeOrigin.bytecodeIndex();
     
    253280        ICStatus status = context->get(codeOrigin);
    254281       
    255         auto bless = [&] (const PutByIdStatus& result) -> PutByIdStatus {
     282        auto bless = [&] (const PutByStatus& result) -> PutByStatus {
    256283            if (!context->isInlined(codeOrigin)) {
    257                 PutByIdStatus baselineResult = computeFor(
    258                     baselineBlock, baselineMap, bytecodeIndex, uid, didExit,
     284                PutByStatus baselineResult = computeFor(
     285                    baselineBlock, baselineMap, bytecodeIndex, didExit,
    259286                    callExitSiteData);
    260287                baselineResult.merge(result);
     
    267294       
    268295        if (status.stubInfo) {
    269             PutByIdStatus result;
     296            PutByStatus result;
    270297            {
    271298                ConcurrentJSLocker locker(context->optimizedCodeBlock->m_lock);
    272299                result = computeForStubInfo(
    273                     locker, context->optimizedCodeBlock, status.stubInfo, uid, callExitSiteData);
     300                    locker, context->optimizedCodeBlock, status.stubInfo, callExitSiteData);
    274301            }
    275302            if (result.isSet())
     
    281308    }
    282309   
    283     return computeFor(baselineBlock, baselineMap, bytecodeIndex, uid, didExit, callExitSiteData);
    284 }
    285 
    286 PutByIdStatus PutByIdStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, UniquedStringImpl* uid, bool isDirect, PrivateFieldPutKind privateFieldPutKind)
    287 {
     310    return computeFor(baselineBlock, baselineMap, bytecodeIndex, didExit, callExitSiteData);
     311}
     312
     313PutByStatus PutByStatus::computeFor(JSGlobalObject* globalObject, const StructureSet& set, CacheableIdentifier identifier, bool isDirect, PrivateFieldPutKind privateFieldPutKind)
     314{
     315    UniquedStringImpl* uid = identifier.uid();
    288316    if (parseIndex(*uid))
    289         return PutByIdStatus(TakesSlowPath);
     317        return PutByStatus(LikelyTakesSlowPath);
    290318
    291319    if (set.isEmpty())
    292         return PutByIdStatus();
     320        return PutByStatus();
    293321   
    294322    VM& vm = globalObject->vm();
    295     PutByIdStatus result;
     323    PutByStatus result;
    296324    result.m_state = Simple;
    297325    for (unsigned i = 0; i < set.size(); ++i) {
     
    299327       
    300328        if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
    301             return PutByIdStatus(TakesSlowPath);
     329            return PutByStatus(LikelyTakesSlowPath);
    302330
    303331        if (!structure->propertyAccessesAreCacheable())
    304             return PutByIdStatus(TakesSlowPath);
     332            return PutByStatus(LikelyTakesSlowPath);
    305333   
    306334        unsigned attributes;
     
    311339            // slow path to throw exception.
    312340            if (privateFieldPutKind.isDefine())
    313                 return PutByIdStatus(TakesSlowPath);
     341                return PutByStatus(LikelyTakesSlowPath);
    314342
    315343            if (attributes & PropertyAttribute::CustomAccessorOrValue)
    316                 return PutByIdStatus(MakesCalls);
     344                return PutByStatus(MakesCalls);
    317345
    318346            if (attributes & (PropertyAttribute::Accessor | PropertyAttribute::ReadOnly))
    319                 return PutByIdStatus(TakesSlowPath);
     347                return PutByStatus(LikelyTakesSlowPath);
    320348           
    321349            WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset);
     
    326354                // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy.
    327355                // So, better leave this alone and take slow path.
    328                 return PutByIdStatus(TakesSlowPath);
    329             }
    330 
    331             PutByIdVariant variant =
    332                 PutByIdVariant::replace(structure, offset);
     356                return PutByStatus(LikelyTakesSlowPath);
     357            }
     358
     359            PutByVariant variant = PutByVariant::replace(identifier, structure, offset);
    333360            if (!result.appendVariant(variant))
    334                 return PutByIdStatus(TakesSlowPath);
     361                return PutByStatus(LikelyTakesSlowPath);
    335362            continue;
    336363        }
     
    341368        // slow path to throw excpetion if it ever gets executed.
    342369        if (privateFieldPutKind.isSet())
    343             return PutByIdStatus(TakesSlowPath);
     370            return PutByStatus(LikelyTakesSlowPath);
    344371
    345372        // Our hypothesis is that we're doing a transition. Before we prove that this is really
     
    348375        // Don't cache put transitions on dictionaries.
    349376        if (structure->isDictionary())
    350             return PutByIdStatus(TakesSlowPath);
     377            return PutByStatus(LikelyTakesSlowPath);
    351378
    352379        // If the structure corresponds to something that isn't an object, then give up, since
    353380        // we don't want to be adding properties to strings.
    354381        if (!structure->typeInfo().isObject())
    355             return PutByIdStatus(TakesSlowPath);
     382            return PutByStatus(LikelyTakesSlowPath);
    356383   
    357384        ObjectPropertyConditionSet conditionSet;
     
    361388                vm, globalObject, structure, uid);
    362389            if (!conditionSet.isValid())
    363                 return PutByIdStatus(TakesSlowPath);
     390                return PutByStatus(LikelyTakesSlowPath);
    364391        }
    365392   
     
    368395            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
    369396        if (!transition)
    370             return PutByIdStatus(TakesSlowPath);
     397            return PutByStatus(LikelyTakesSlowPath);
    371398        ASSERT(isValidOffset(offset));
    372399   
    373         bool didAppend = result.appendVariant(
    374             PutByIdVariant::transition(
    375                 structure, transition, conditionSet, offset));
     400        bool didAppend = result.appendVariant(PutByVariant::transition(identifier, structure, transition, conditionSet, offset));
    376401        if (!didAppend)
    377             return PutByIdStatus(TakesSlowPath);
     402            return PutByStatus(LikelyTakesSlowPath);
    378403    }
    379404   
     
    383408#endif
    384409
    385 bool PutByIdStatus::makesCalls() const
    386 {
    387     if (m_state == MakesCalls)
     410bool PutByStatus::makesCalls() const
     411{
     412    switch (m_state) {
     413    case NoInformation:
     414    case LikelyTakesSlowPath:
     415    case ObservedTakesSlowPath:
     416        return false;
     417    case MakesCalls:
     418    case ObservedSlowPathAndMakesCalls:
    388419        return true;
    389    
    390     if (m_state != Simple)
     420    case Simple: {
     421        for (unsigned i = m_variants.size(); i--;) {
     422            if (m_variants[i].makesCalls())
     423                return true;
     424        }
    391425        return false;
    392    
    393     for (unsigned i = m_variants.size(); i--;) {
    394         if (m_variants[i].makesCalls())
    395             return true;
    396     }
    397    
    398     return false;
    399 }
    400 
    401 PutByIdStatus PutByIdStatus::slowVersion() const
    402 {
    403     return PutByIdStatus(makesCalls() ? MakesCalls : TakesSlowPath);
     426    }
     427    }
     428}
     429
     430PutByStatus PutByStatus::slowVersion() const
     431{
     432    if (observedStructureStubInfoSlowPath())
     433        return PutByStatus(makesCalls() ? ObservedSlowPathAndMakesCalls : ObservedTakesSlowPath);
     434    return PutByStatus(makesCalls() ? MakesCalls : LikelyTakesSlowPath);
     435}
     436
     437CacheableIdentifier PutByStatus::singleIdentifier() const
     438{
     439    return singleIdentifierForICStatus(m_variants);
    404440}
    405441
    406442template<typename Visitor>
    407 void PutByIdStatus::markIfCheap(Visitor& visitor)
    408 {
    409     for (PutByIdVariant& variant : m_variants)
     443void PutByStatus::visitAggregateImpl(Visitor& visitor)
     444{
     445    for (PutByVariant& variant : m_variants)
     446        variant.visitAggregate(visitor);
     447}
     448
     449DEFINE_VISIT_AGGREGATE(PutByStatus);
     450
     451template<typename Visitor>
     452void PutByStatus::markIfCheap(Visitor& visitor)
     453{
     454    for (PutByVariant& variant : m_variants)
    410455        variant.markIfCheap(visitor);
    411456}
    412457
    413 template void PutByIdStatus::markIfCheap(AbstractSlotVisitor&);
    414 template void PutByIdStatus::markIfCheap(SlotVisitor&);
    415 
    416 bool PutByIdStatus::finalize(VM& vm)
    417 {
    418     for (PutByIdVariant& variant : m_variants) {
     458template void PutByStatus::markIfCheap(AbstractSlotVisitor&);
     459template void PutByStatus::markIfCheap(SlotVisitor&);
     460
     461bool PutByStatus::finalize(VM& vm)
     462{
     463    for (PutByVariant& variant : m_variants) {
    419464        if (!variant.finalize(vm))
    420465            return false;
     
    423468}
    424469
    425 void PutByIdStatus::merge(const PutByIdStatus& other)
     470void PutByStatus::merge(const PutByStatus& other)
    426471{
    427472    if (other.m_state == NoInformation)
    428473        return;
    429    
     474
    430475    auto mergeSlow = [&] () {
    431         *this = PutByIdStatus((makesCalls() || other.makesCalls()) ? MakesCalls : TakesSlowPath);
     476        if (observedStructureStubInfoSlowPath() || other.observedStructureStubInfoSlowPath())
     477            *this = PutByStatus((makesCalls() || other.makesCalls()) ? ObservedSlowPathAndMakesCalls : ObservedTakesSlowPath);
     478        else
     479            *this = PutByStatus((makesCalls() || other.makesCalls()) ? MakesCalls : LikelyTakesSlowPath);
    432480    };
    433    
     481
    434482    switch (m_state) {
    435483    case NoInformation:
     
    441489            return mergeSlow();
    442490       
    443         for (const PutByIdVariant& other : other.m_variants) {
     491        for (const PutByVariant& other : other.m_variants) {
    444492            if (!appendVariant(other))
    445493                return mergeSlow();
     
    448496        return;
    449497       
    450     case TakesSlowPath:
     498    case LikelyTakesSlowPath:
     499    case ObservedTakesSlowPath:
    451500    case MakesCalls:
     501    case ObservedSlowPathAndMakesCalls:
    452502        return mergeSlow();
    453503    }
     
    456506}
    457507
    458 void PutByIdStatus::filter(const StructureSet& set)
     508void PutByStatus::filter(const StructureSet& set)
    459509{
    460510    if (m_state != Simple)
    461511        return;
    462512    filterICStatusVariants(m_variants, set);
    463     for (PutByIdVariant& variant : m_variants)
     513    for (PutByVariant& variant : m_variants)
    464514        variant.fixTransitionToReplaceIfNecessary();
    465515    if (m_variants.isEmpty())
     
    467517}
    468518
    469 void PutByIdStatus::dump(PrintStream& out) const
     519void PutByStatus::dump(PrintStream& out) const
    470520{
    471521    switch (m_state) {
     
    473523        out.print("(NoInformation)");
    474524        return;
    475        
    476525    case Simple:
    477526        out.print("(", listDump(m_variants), ")");
    478527        return;
    479        
    480     case TakesSlowPath:
    481         out.print("(TakesSlowPath)");
     528    case LikelyTakesSlowPath:
     529        out.print("LikelyTakesSlowPath");
     530        return;
     531    case ObservedTakesSlowPath:
     532        out.print("ObservedTakesSlowPath");
    482533        return;
    483534    case MakesCalls:
    484         out.print("(MakesCalls)");
     535        out.print("MakesCalls");
     536        return;
     537    case ObservedSlowPathAndMakesCalls:
     538        out.print("ObservedSlowPathAndMakesCalls");
    485539        return;
    486540    }
  • trunk/Source/JavaScriptCore/bytecode/PutByStatus.h

    r281614 r281615  
    3030#include "ICStatusMap.h"
    3131#include "PrivateFieldPutKind.h"
    32 #include "PutByIdVariant.h"
     32#include "PutByVariant.h"
    3333#include "StubInfoSummary.h"
    3434
     
    4444typedef HashMap<CodeOrigin, StructureStubInfo*, CodeOriginApproximateHash> StubInfoMap;
    4545
    46 class PutByIdStatus final {
     46class PutByStatus final {
    4747    WTF_MAKE_FAST_ALLOCATED;
    4848public:
     
    5252        // It's cached as a simple store of some kind.
    5353        Simple,
    54         // It's known to often take slow path.
    55         TakesSlowPath,
    56         // It's known to take paths that make calls.
    57         MakesCalls
     54        // It will likely take the slow path.
     55        LikelyTakesSlowPath,
     56        // It's known to take slow path. We also observed that the slow path was taken on StructureStubInfo.
     57        ObservedTakesSlowPath,
     58        // It will likely take the slow path and will make calls.
     59        MakesCalls,
     60        // It known to take paths that make calls. We also observed that the slow path was taken on StructureStubInfo.
     61        ObservedSlowPathAndMakesCalls,
    5862    };
    5963   
    60     PutByIdStatus()
     64    PutByStatus()
    6165        : m_state(NoInformation)
    6266    {
    6367    }
    6468   
    65     explicit PutByIdStatus(State state)
     69    explicit PutByStatus(State state)
    6670        : m_state(state)
    6771    {
    68         ASSERT(m_state == NoInformation || m_state == TakesSlowPath || m_state == MakesCalls);
     72#if ASSERT_ENABLED
     73        switch (m_state) {
     74        case NoInformation:
     75        case LikelyTakesSlowPath:
     76        case ObservedTakesSlowPath:
     77        case MakesCalls:
     78        case ObservedSlowPathAndMakesCalls:
     79            break;
     80        default:
     81            RELEASE_ASSERT_NOT_REACHED();
     82            break;
     83        }
     84#endif
    6985    }
    7086   
    71     explicit PutByIdStatus(StubInfoSummary summary)
    72     {
    73         switch (summary) {
    74         case StubInfoSummary::NoInformation:
    75             m_state = NoInformation;
    76             return;
    77         case StubInfoSummary::Simple:
    78         case StubInfoSummary::MakesCalls:
    79             RELEASE_ASSERT_NOT_REACHED();
    80             return;
    81         case StubInfoSummary::TakesSlowPath:
    82             m_state = TakesSlowPath;
    83             return;
    84         case StubInfoSummary::TakesSlowPathAndMakesCalls:
    85             m_state = MakesCalls;
    86             return;
    87         }
    88         RELEASE_ASSERT_NOT_REACHED();
    89     }
     87    explicit PutByStatus(StubInfoSummary, StructureStubInfo&);
    9088   
    91     PutByIdStatus(const PutByIdVariant& variant)
     89    PutByStatus(const PutByVariant& variant)
    9290        : m_state(Simple)
    9391    {
     
    9593    }
    9694   
    97     static PutByIdStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, UniquedStringImpl* uid, ExitFlag, CallLinkStatus::ExitSiteData);
    98     static PutByIdStatus computeFor(JSGlobalObject*, const StructureSet&, UniquedStringImpl* uid, bool isDirect, PrivateFieldPutKind);
     95    static PutByStatus computeFor(CodeBlock*, ICStatusMap&, BytecodeIndex, ExitFlag, CallLinkStatus::ExitSiteData);
     96    static PutByStatus computeFor(JSGlobalObject*, const StructureSet&, CacheableIdentifier, bool isDirect, PrivateFieldPutKind);
    9997   
    100     static PutByIdStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack& contextStack, CodeOrigin, UniquedStringImpl* uid);
     98    static PutByStatus computeFor(CodeBlock* baselineBlock, ICStatusMap& baselineMap, ICStatusContextStack&, CodeOrigin);
    10199
    102100#if ENABLE(JIT)
    103     static PutByIdStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid);
     101    static PutByStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin);
    104102#endif
    105103   
     
    109107    bool operator!() const { return m_state == NoInformation; }
    110108    bool isSimple() const { return m_state == Simple; }
    111     bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
     109    bool takesSlowPath() const
     110    {
     111        switch (m_state) {
     112        case LikelyTakesSlowPath:
     113        case ObservedTakesSlowPath:
     114            return true;
     115        default:
     116            return false;
     117        }
     118    }
    112119    bool makesCalls() const;
    113     PutByIdStatus slowVersion() const;
     120    PutByStatus slowVersion() const;
     121    bool observedStructureStubInfoSlowPath() const { return m_state == ObservedTakesSlowPath || m_state == ObservedSlowPathAndMakesCalls; }
    114122   
    115123    size_t numVariants() const { return m_variants.size(); }
    116     const Vector<PutByIdVariant, 1>& variants() const { return m_variants; }
    117     const PutByIdVariant& at(size_t index) const { return m_variants[index]; }
    118     const PutByIdVariant& operator[](size_t index) const { return at(index); }
     124    const Vector<PutByVariant, 1>& variants() const { return m_variants; }
     125    const PutByVariant& at(size_t index) const { return m_variants[index]; }
     126    const PutByVariant& operator[](size_t index) const { return at(index); }
     127    CacheableIdentifier singleIdentifier() const;
    119128   
     129    DECLARE_VISIT_AGGREGATE;
    120130    template<typename Visitor> void markIfCheap(Visitor&);
    121131    bool finalize(VM&);
    122132   
    123     void merge(const PutByIdStatus&);
     133    void merge(const PutByStatus&);
    124134   
    125135    void filter(const StructureSet&);
     
    129139private:
    130140#if ENABLE(JIT)
    131     static PutByIdStatus computeForStubInfo(
    132         const ConcurrentJSLocker&, CodeBlock*, StructureStubInfo*, UniquedStringImpl* uid,
    133         CallLinkStatus::ExitSiteData);
     141    static PutByStatus computeForStubInfo(const ConcurrentJSLocker&, CodeBlock*, StructureStubInfo*, CallLinkStatus::ExitSiteData);
    134142#endif
    135     static PutByIdStatus computeFromLLInt(CodeBlock*, BytecodeIndex, UniquedStringImpl* uid);
     143    static PutByStatus computeFromLLInt(CodeBlock*, BytecodeIndex);
    136144   
    137     bool appendVariant(const PutByIdVariant&);
     145    bool appendVariant(const PutByVariant&);
    138146    void shrinkToFit();
    139147   
    140148    State m_state;
    141     Vector<PutByIdVariant, 1> m_variants;
     149    Vector<PutByVariant, 1> m_variants;
    142150};
    143151
  • trunk/Source/JavaScriptCore/bytecode/PutByVariant.cpp

    r281614 r281615  
    2525
    2626#include "config.h"
    27 #include "PutByIdVariant.h"
    28 
     27#include "PutByVariant.h"
     28
     29#include "CacheableIdentifierInlines.h"
    2930#include "CallLinkStatus.h"
    3031#include "HeapInlines.h"
     
    3233namespace JSC {
    3334
    34 PutByIdVariant::PutByIdVariant(const PutByIdVariant& other)
    35     : PutByIdVariant()
     35PutByVariant::PutByVariant(const PutByVariant& other)
     36    : PutByVariant(other.m_identifier)
    3637{
    3738    *this = other;
    3839}
    3940
    40 PutByIdVariant& PutByIdVariant::operator=(const PutByIdVariant& other)
     41PutByVariant& PutByVariant::operator=(const PutByVariant& other)
    4142{
    4243    m_kind = other.m_kind;
     
    4950    else
    5051        m_callLinkStatus = nullptr;
     52    m_identifier = other.m_identifier;
    5153    return *this;
    5254}
    5355
    54 PutByIdVariant PutByIdVariant::replace(
    55     const StructureSet& structure, PropertyOffset offset)
    56 {
    57     PutByIdVariant result;
     56PutByVariant PutByVariant::replace(CacheableIdentifier identifier, const StructureSet& structure, PropertyOffset offset)
     57{
     58    PutByVariant result(WTFMove(identifier));
    5859    result.m_kind = Replace;
    5960    result.m_oldStructure = structure;
     
    6263}
    6364
    64 PutByIdVariant PutByIdVariant::transition(
    65     const StructureSet& oldStructure, Structure* newStructure,
    66     const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset)
    67 {
    68     PutByIdVariant result;
     65PutByVariant PutByVariant::transition(CacheableIdentifier identifier, const StructureSet& oldStructure, Structure* newStructure, const ObjectPropertyConditionSet& conditionSet, PropertyOffset offset)
     66{
     67    PutByVariant result(WTFMove(identifier));
    6968    result.m_kind = Transition;
    7069    result.m_oldStructure = oldStructure;
     
    7574}
    7675
    77 PutByIdVariant PutByIdVariant::setter(
    78     const StructureSet& structure, PropertyOffset offset,
    79     const ObjectPropertyConditionSet& conditionSet,
    80     std::unique_ptr<CallLinkStatus> callLinkStatus)
    81 {
    82     PutByIdVariant result;
     76PutByVariant PutByVariant::setter(CacheableIdentifier identifier, const StructureSet& structure, PropertyOffset offset, const ObjectPropertyConditionSet& conditionSet, std::unique_ptr<CallLinkStatus> callLinkStatus)
     77{
     78    PutByVariant result(WTFMove(identifier));
    8379    result.m_kind = Setter;
    8480    result.m_oldStructure = structure;
     
    8985}
    9086
    91 Structure* PutByIdVariant::oldStructureForTransition() const
     87Structure* PutByVariant::oldStructureForTransition() const
    9288{
    9389    RELEASE_ASSERT(kind() == Transition);
     
    10399}
    104100
    105 void PutByIdVariant::fixTransitionToReplaceIfNecessary()
     101void PutByVariant::fixTransitionToReplaceIfNecessary()
    106102{
    107103    if (kind() != Transition)
     
    121117}
    122118
    123 bool PutByIdVariant::writesStructures() const
     119bool PutByVariant::writesStructures() const
    124120{
    125121    switch (kind()) {
     
    132128}
    133129
    134 bool PutByIdVariant::reallocatesStorage() const
     130bool PutByVariant::reallocatesStorage() const
    135131{
    136132    switch (kind()) {
     
    144140}
    145141
    146 bool PutByIdVariant::makesCalls() const
     142bool PutByVariant::makesCalls() const
    147143{
    148144    return kind() == Setter;
    149145}
    150146
    151 bool PutByIdVariant::attemptToMerge(const PutByIdVariant& other)
    152 {
     147bool PutByVariant::attemptToMerge(const PutByVariant& other)
     148{
     149    if (!!m_identifier != !!other.m_identifier)
     150        return false;
     151
     152    if (m_identifier && (m_identifier != other.m_identifier))
     153        return false;
     154
    153155    if (m_offset != other.m_offset)
    154156        return false;
     
    170172           
    171173        case Transition: {
    172             PutByIdVariant newVariant = other;
     174            PutByVariant newVariant = other;
    173175            if (newVariant.attemptToMergeTransitionWithReplace(*this)) {
    174176                *this = newVariant;
     
    240242}
    241243
    242 bool PutByIdVariant::attemptToMergeTransitionWithReplace(const PutByIdVariant& replace)
     244bool PutByVariant::attemptToMergeTransitionWithReplace(const PutByVariant& replace)
    243245{
    244246    ASSERT(m_kind == Transition);
     
    264266
    265267template<typename Visitor>
    266 void PutByIdVariant::markIfCheap(Visitor& visitor)
     268void PutByVariant::visitAggregateImpl(Visitor& visitor)
     269{
     270    m_identifier.visitAggregate(visitor);
     271}
     272
     273DEFINE_VISIT_AGGREGATE(PutByVariant);
     274
     275template<typename Visitor>
     276void PutByVariant::markIfCheap(Visitor& visitor)
    267277{
    268278    m_oldStructure.markIfCheap(visitor);
     
    271281}
    272282
    273 template void PutByIdVariant::markIfCheap(AbstractSlotVisitor&);
    274 template void PutByIdVariant::markIfCheap(SlotVisitor&);
    275 
    276 bool PutByIdVariant::finalize(VM& vm)
     283template void PutByVariant::markIfCheap(AbstractSlotVisitor&);
     284template void PutByVariant::markIfCheap(SlotVisitor&);
     285
     286bool PutByVariant::finalize(VM& vm)
    277287{
    278288    if (!m_oldStructure.isStillAlive(vm))
     
    287297}
    288298
    289 void PutByIdVariant::dump(PrintStream& out) const
     299void PutByVariant::dump(PrintStream& out) const
    290300{
    291301    dumpInContext(out, nullptr);
    292302}
    293303
    294 void PutByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
    295 {
     304void PutByVariant::dumpInContext(PrintStream& out, DumpContext* context) const
     305{
     306    out.print("<");
     307    out.print("id='", m_identifier, "', ");
    296308    switch (kind()) {
    297309    case NotSet:
    298         out.print("<empty>");
     310        out.print("empty>");
    299311        return;
    300312       
    301313    case Replace:
    302314        out.print(
    303             "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ", ", ">");
     315            "Replace: ", inContext(structure(), context), ", offset = ", offset(), ", ", ">");
    304316        return;
    305317       
    306318    case Transition:
    307319        out.print(
    308             "<Transition: ", inContext(oldStructure(), context), " to ",
     320            "Transition: ", inContext(oldStructure(), context), " to ",
    309321            pointerDumpInContext(newStructure(), context), ", [",
    310322            inContext(m_conditionSet, context), "], offset = ", offset(), ", ", ">");
     
    313325    case Setter:
    314326        out.print(
    315             "<Setter: ", inContext(structure(), context), ", [",
     327            "Setter: ", inContext(structure(), context), ", [",
    316328            inContext(m_conditionSet, context), "]");
    317329        out.print(", offset = ", m_offset);
  • trunk/Source/JavaScriptCore/bytecode/PutByVariant.h

    r281614 r281615  
    3434class CallLinkStatus;
    3535
    36 class PutByIdVariant {
     36class PutByVariant {
    3737    WTF_MAKE_FAST_ALLOCATED;
    3838public:
     
    4444    };
    4545   
    46     PutByIdVariant()
     46    PutByVariant(CacheableIdentifier identifier)
    4747        : m_kind(NotSet)
    4848        , m_offset(invalidOffset)
    4949        , m_newStructure(nullptr)
     50        , m_identifier(WTFMove(identifier))
    5051    {
    5152    }
    5253   
    53     PutByIdVariant(const PutByIdVariant&);
    54     PutByIdVariant& operator=(const PutByIdVariant&);
     54    PutByVariant(const PutByVariant&);
     55    PutByVariant& operator=(const PutByVariant&);
    5556
    56     static PutByIdVariant replace(const StructureSet&, PropertyOffset);
     57    static PutByVariant replace(CacheableIdentifier, const StructureSet&, PropertyOffset);
    5758   
    58     static PutByIdVariant transition(
    59         const StructureSet& oldStructure, Structure* newStructure,
    60         const ObjectPropertyConditionSet&, PropertyOffset);
     59    static PutByVariant transition(CacheableIdentifier, const StructureSet& oldStructure, Structure* newStructure, const ObjectPropertyConditionSet&, PropertyOffset);
    6160   
    62     static PutByIdVariant setter(
    63         const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&,
    64         std::unique_ptr<CallLinkStatus>);
     61    static PutByVariant setter(CacheableIdentifier, const StructureSet&, PropertyOffset, const ObjectPropertyConditionSet&, std::unique_ptr<CallLinkStatus>);
    6562   
    6663    Kind kind() const { return m_kind; }
     
    131128    }
    132129
    133     bool attemptToMerge(const PutByIdVariant& other);
     130    bool attemptToMerge(const PutByVariant& other);
    134131   
     132    DECLARE_VISIT_AGGREGATE;
    135133    template<typename Visitor> void markIfCheap(Visitor&);
    136134    bool finalize(VM&);
     
    139137    void dumpInContext(PrintStream&, DumpContext*) const;
    140138
    141     bool overlaps(const PutByIdVariant& other)
     139    CacheableIdentifier identifier() const { return m_identifier; }
     140
     141    bool overlaps(const PutByVariant& other)
    142142    {
     143        if (!!m_identifier != !!other.m_identifier)
     144            return true;
     145        if (m_identifier) {
     146            if (m_identifier != other.m_identifier)
     147                return false;
     148        }
    143149        return structureSet().overlaps(other.structureSet());
    144150    }
    145151
    146152private:
    147     bool attemptToMergeTransitionWithReplace(const PutByIdVariant& replace);
     153    bool attemptToMergeTransitionWithReplace(const PutByVariant& replace);
    148154   
    149155    Kind m_kind;
     
    153159    ObjectPropertyConditionSet m_conditionSet;
    154160    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
     161    CacheableIdentifier m_identifier;
    155162};
    156163
  • trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.cpp

    r280050 r281615  
    6363}
    6464   
    65 PutByIdStatus* RecordedStatuses::addPutByIdStatus(const CodeOrigin& codeOrigin, const PutByIdStatus& status)
     65PutByStatus* RecordedStatuses::addPutByStatus(const CodeOrigin& codeOrigin, const PutByStatus& status)
    6666{
    67     auto statusPtr = makeUnique<PutByIdStatus>(status);
    68     PutByIdStatus* result = statusPtr.get();
     67    auto statusPtr = makeUnique<PutByStatus>(status);
     68    PutByStatus* result = statusPtr.get();
    6969    puts.append(std::make_pair(codeOrigin, WTFMove(statusPtr)));
    7070    return result;
     
    107107{
    108108    for (auto& pair : gets)
     109        pair.second->visitAggregate(visitor);
     110    for (auto& pair : puts)
    109111        pair.second->visitAggregate(visitor);
    110112    for (auto& pair : ins)
  • trunk/Source/JavaScriptCore/bytecode/RecordedStatuses.h

    r278445 r281615  
    3131#include "GetByStatus.h"
    3232#include "InByStatus.h"
    33 #include "PutByIdStatus.h"
     33#include "PutByStatus.h"
    3434#include "SetPrivateBrandStatus.h"
    3535
     
    4949    CallLinkStatus* addCallLinkStatus(const CodeOrigin&, const CallLinkStatus&);
    5050    GetByStatus* addGetByStatus(const CodeOrigin&, const GetByStatus&);
    51     PutByIdStatus* addPutByIdStatus(const CodeOrigin&, const PutByIdStatus&);
     51    PutByStatus* addPutByStatus(const CodeOrigin&, const PutByStatus&);
    5252    InByStatus* addInByStatus(const CodeOrigin&, const InByStatus&);
    5353    DeleteByStatus* addDeleteByStatus(const CodeOrigin&, const DeleteByStatus&);
     
    7777    Vector<std::pair<CodeOrigin, std::unique_ptr<CallLinkStatus>>> calls;
    7878    Vector<std::pair<CodeOrigin, std::unique_ptr<GetByStatus>>> gets;
    79     Vector<std::pair<CodeOrigin, std::unique_ptr<PutByIdStatus>>> puts;
     79    Vector<std::pair<CodeOrigin, std::unique_ptr<PutByStatus>>> puts;
    8080    Vector<std::pair<CodeOrigin, std::unique_ptr<InByStatus>>> ins;
    8181    Vector<std::pair<CodeOrigin, std::unique_ptr<DeleteByStatus>>> deletes;
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp

    r280066 r281615  
    282282        resetGetBy(codeBlock, *this, GetByKind::PrivateName);
    283283        break;
    284     case AccessType::Put:
    285         resetPutByID(codeBlock, *this);
     284    case AccessType::PutById:
     285        resetPutBy(codeBlock, *this, PutByKind::ById);
     286        break;
     287    case AccessType::PutByVal:
     288        resetPutBy(codeBlock, *this, PutByKind::ByVal);
    286289        break;
    287290    case AccessType::InById:
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h

    r280066 r281615  
    5555    TryGetById,
    5656    GetByVal,
    57     Put,
     57    PutById,
     58    PutByVal,
    5859    InById,
    5960    InByVal,
     
    366367    } regs;
    367368    GPRReg m_stubInfoGPR { InvalidGPRReg };
     369    GPRReg m_arrayProfileGPR { InvalidGPRReg };
    368370#if USE(JSVALUE32_64)
    369371    GPRReg valueTagGPR;
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r280760 r281615  
    4848#include "MathCommon.h"
    4949#include "NumberConstructor.h"
    50 #include "PutByIdStatus.h"
     50#include "PutByStatus.h"
    5151#include "RegExpObject.h"
    5252#include "SetPrivateBrandStatus.h"
     
    39743974           
    39753975        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    3976             const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
     3976            const PutByVariant& variant = node->multiPutByOffsetData().variants[i];
    39773977            RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
    39783978            thisSet.filter(base);
     
    39833983            resultingValue.merge(thisValue);
    39843984           
    3985             if (variant.kind() == PutByIdVariant::Transition) {
     3985            if (variant.kind() == PutByVariant::Transition) {
    39863986                RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
    39873987                if (thisSet.onlyStructure() != newStructure) {
     
    39913991                newSet.add(newStructure);
    39923992            } else {
    3993                 ASSERT(variant.kind() == PutByIdVariant::Replace);
     3993                ASSERT(variant.kind() == PutByVariant::Replace);
    39943994                newSet.merge(thisSet);
    39953995            }
     
    41414141            bool isDirect = node->op() == PutByIdDirect || node->op() == PutPrivateNameById;
    41424142            auto privateFieldPutKind = node->op() == PutPrivateNameById ? node->privateFieldPutKind() : PrivateFieldPutKind::none();
    4143             PutByIdStatus status = PutByIdStatus::computeFor(
     4143            PutByStatus status = PutByStatus::computeFor(
    41444144                m_graph.globalObjectFor(node->origin.semantic),
    41454145                value.m_structure.toStructureSet(),
    4146                 node->cacheableIdentifier().uid(),
     4146                node->cacheableIdentifier(),
    41474147                isDirect, privateFieldPutKind);
    41484148
     
    41524152                TransitionVector transitions;
    41534153               
    4154                 for (const PutByIdVariant& variant : status.variants()) {
     4154                for (const PutByVariant& variant : status.variants()) {
    41554155                    for (const ObjectPropertyCondition& condition : variant.conditionSet()) {
    41564156                        if (!m_graph.watchCondition(condition)) {
     
    41634163                        break;
    41644164
    4165                     if (variant.kind() == PutByIdVariant::Transition) {
     4165                    if (variant.kind() == PutByVariant::Transition) {
    41664166                        RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
    41674167                        transitions.append(
     
    41704170                        newSet.add(newStructure);
    41714171                    } else {
    4172                         ASSERT(variant.kind() == PutByIdVariant::Replace);
     4172                        ASSERT(variant.kind() == PutByVariant::Replace);
    41734173                        newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
    41744174                    }
     
    44744474    case FilterCallLinkStatus:
    44754475    case FilterGetByStatus:
    4476     case FilterPutByIdStatus:
     4476    case FilterPutByStatus:
    44774477    case FilterInByStatus:
    44784478    case FilterDeleteByStatus:
     
    46534653    }
    46544654       
    4655     case FilterPutByIdStatus: {
     4655    case FilterPutByStatus: {
    46564656        AbstractValue& value = forNode(node->child1());
    46574657        if (value.m_structure.isFinite())
    4658             node->putByIdStatus()->filter(value.m_structure.toStructureSet());
     4658            node->putByStatus()->filter(value.m_structure.toStructureSet());
    46594659        break;
    46604660    }
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp

    r278445 r281615  
    403403                   
    404404                case FilterGetByStatus:
    405                 case FilterPutByIdStatus:
     405                case FilterPutByStatus:
    406406                case FilterCallLinkStatus:
    407407                case FilterInByStatus:
     
    12661266                case GetButterfly:
    12671267                case FilterGetByStatus:
    1268                 case FilterPutByIdStatus:
     1268                case FilterPutByStatus:
    12691269                case FilterCallLinkStatus:
    12701270                case FilterInByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r280760 r281615  
    3434#include "BooleanConstructor.h"
    3535#include "BuiltinNames.h"
    36 #include "ByValInfo.h"
    3736#include "BytecodeGenerator.h"
    3837#include "BytecodeOperandsForCheckpoint.h"
     
    7574#include "PrivateFieldPutKind.h"
    7675#include "PutByIdFlags.h"
    77 #include "PutByIdStatus.h"
     76#include "PutByStatus.h"
    7877#include "RegExpPrototype.h"
    7978#include "SetPrivateBrandStatus.h"
     
    240239    void checkPresenceForReplace(Node* base, UniquedStringImpl*, PropertyOffset, const StructureSet&);
    241240   
    242     // Works with both GetByVariant and the setter form of PutByIdVariant.
     241    // Works with both GetByVariant and the setter form of PutByVariant.
    243242    template<typename VariantType>
    244243    Node* load(SpeculatedType, Node* base, unsigned identifierNumber, const VariantType&);
    245244
    246     Node* store(Node* base, unsigned identifier, const PutByIdVariant&, Node* value);
     245    Node* store(Node* base, unsigned identifier, const PutByVariant&, Node* value);
    247246
    248247    template<typename Op>
     
    254253        VirtualRegister destination, SpeculatedType prediction, Node* base, CacheableIdentifier, unsigned identifierNumber, GetByStatus);
    255254    void emitPutById(
    256         Node* base, CacheableIdentifier, Node* value,  const PutByIdStatus&, bool isDirect, ECMAMode);
     255        Node* base, CacheableIdentifier, Node* value,  const PutByStatus&, bool isDirect, ECMAMode);
    257256    void handlePutById(
    258         Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByIdStatus&,
     257        Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByStatus&,
    259258        bool isDirect, BytecodeIndex osrExitIndex, ECMAMode);
    260259
    261260    void handlePutPrivateNameById(
    262         Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByIdStatus&, PrivateFieldPutKind);
     261        Node* base, CacheableIdentifier, unsigned identifierNumber, Node* value, const PutByStatus&, PrivateFieldPutKind);
    263262
    264263    void handleDeleteById(
     
    45154514                // the structures in the variant.structureSet() agree on the prototype (it would be
    45164515                // hilariously rare if they didn't). Note that we are relying on structureSet() having
    4517                 // at least one element. That will always be true here because of how GetByStatus/PutByIdStatus work.
     4516                // at least one element. That will always be true here because of how GetByStatus/PutByStatus work.
    45184517
    45194518                // FIXME: right now, if we have an OPCS, we have mono proto. However, this will
     
    45944593}
    45954594
    4596 Node* ByteCodeParser::store(Node* base, unsigned identifier, const PutByIdVariant& variant, Node* value)
     4595Node* ByteCodeParser::store(Node* base, unsigned identifier, const PutByVariant& variant, Node* value)
    45974596{
    4598     RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
     4597    RELEASE_ASSERT(variant.kind() == PutByVariant::Replace);
    45994598
    46004599    checkPresenceForReplace(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
     
    49994998
    50004999void ByteCodeParser::emitPutById(
    5001     Node* base, CacheableIdentifier identifier, Node* value, const PutByIdStatus& putByIdStatus, bool isDirect, ECMAMode ecmaMode)
     5000    Node* base, CacheableIdentifier identifier, Node* value, const PutByStatus& putByStatus, bool isDirect, ECMAMode ecmaMode)
    50025001{
    50035002    if (isDirect)
    50045003        addToGraph(PutByIdDirect, OpInfo(identifier), OpInfo(ecmaMode), base, value);
    50055004    else
    5006         addToGraph(putByIdStatus.makesCalls() ? PutByIdFlush : PutById, OpInfo(identifier), OpInfo(ecmaMode), base, value);
     5005        addToGraph(putByStatus.makesCalls() ? PutByIdFlush : PutById, OpInfo(identifier), OpInfo(ecmaMode), base, value);
    50075006}
    50085007
    50095008void ByteCodeParser::handlePutById(
    50105009    Node* base, CacheableIdentifier identifier, unsigned identifierNumber, Node* value,
    5011     const PutByIdStatus& putByIdStatus, bool isDirect, BytecodeIndex osrExitIndex, ECMAMode ecmaMode)
     5010    const PutByStatus& putByStatus, bool isDirect, BytecodeIndex osrExitIndex, ECMAMode ecmaMode)
    50125011{
    5013     if (!putByIdStatus.isSimple() || !putByIdStatus.numVariants() || !Options::useAccessInlining()) {
    5014         if (!putByIdStatus.isSet())
     5012    if (!putByStatus.isSimple() || !putByStatus.numVariants() || !Options::useAccessInlining()) {
     5013        if (!putByStatus.isSet())
    50155014            addToGraph(ForceOSRExit);
    5016         emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5015        emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    50175016        return;
    50185017    }
    50195018   
    5020     if (putByIdStatus.numVariants() > 1) {
    5021         if (!m_graph.m_plan.isFTL() || putByIdStatus.makesCalls()
     5019    if (putByStatus.numVariants() > 1) {
     5020        if (!m_graph.m_plan.isFTL() || putByStatus.makesCalls()
    50225021            || !Options::usePolymorphicAccessInlining()
    5023             || putByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) {
    5024             emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5022            || putByStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) {
     5023            emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    50255024            return;
    50265025        }
    50275026       
    50285027        if (!isDirect) {
    5029             for (unsigned variantIndex = putByIdStatus.numVariants(); variantIndex--;) {
    5030                 if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition)
     5028            for (unsigned variantIndex = putByStatus.numVariants(); variantIndex--;) {
     5029                if (putByStatus[variantIndex].kind() != PutByVariant::Transition)
    50315030                    continue;
    5032                 if (!check(putByIdStatus[variantIndex].conditionSet())) {
    5033                     emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5031                if (!check(putByStatus[variantIndex].conditionSet())) {
     5032                    emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    50345033                    return;
    50355034                }
     
    50405039            m_graph.compilation()->noticeInlinedPutById();
    50415040
    5042         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
    5043 
    5044         for (const PutByIdVariant& variant : putByIdStatus.variants()) {
     5041        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
     5042
     5043        for (const PutByVariant& variant : putByStatus.variants()) {
    50455044            for (Structure* structure : variant.oldStructure())
    50465045                m_graph.registerStructure(structure);
    5047             if (variant.kind() == PutByIdVariant::Transition)
     5046            if (variant.kind() == PutByVariant::Transition)
    50485047                m_graph.registerStructure(variant.newStructure());
    50495048        }
    50505049       
    50515050        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
    5052         data->variants = putByIdStatus.variants();
     5051        data->variants = putByStatus.variants();
    50535052        data->identifierNumber = identifierNumber;
    50545053        addToGraph(MultiPutByOffset, OpInfo(data), base, value);
     
    50565055    }
    50575056   
    5058     ASSERT(putByIdStatus.numVariants() == 1);
    5059     const PutByIdVariant& variant = putByIdStatus[0];
     5057    ASSERT(putByStatus.numVariants() == 1);
     5058    const PutByVariant& variant = putByStatus[0];
    50605059   
    50615060    switch (variant.kind()) {
    5062     case PutByIdVariant::Replace: {
    5063         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
     5061    case PutByVariant::Replace: {
     5062        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
    50645063
    50655064        store(base, identifierNumber, variant, value);
     
    50695068    }
    50705069   
    5071     case PutByIdVariant::Transition: {
    5072         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
     5070    case PutByVariant::Transition: {
     5071        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
    50735072
    50745073        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
    50755074        if (!check(variant.conditionSet())) {
    5076             emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5075            emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    50775076            return;
    50785077        }
     
    51365135    }
    51375136       
    5138     case PutByIdVariant::Setter: {
    5139         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
     5137    case PutByVariant::Setter: {
     5138        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
    51405139
    51415140        Node* loadedValue = load(SpecCellOther, base, identifierNumber, variant);
    51425141        if (!loadedValue) {
    5143             emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5142            emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    51445143            return;
    51455144        }
     
    51855184   
    51865185    default: {
    5187         emitPutById(base, identifier, value, putByIdStatus, isDirect, ecmaMode);
     5186        emitPutById(base, identifier, value, putByStatus, isDirect, ecmaMode);
    51885187        return;
    51895188    } }
     
    51925191void ByteCodeParser::handlePutPrivateNameById(
    51935192    Node* base, CacheableIdentifier identifier, unsigned identifierNumber, Node* value,
    5194     const PutByIdStatus& putByIdStatus, PrivateFieldPutKind privateFieldPutKind)
     5193    const PutByStatus& putByStatus, PrivateFieldPutKind privateFieldPutKind)
    51955194{
    5196     if (!putByIdStatus.isSimple() || !putByIdStatus.numVariants() || !Options::useAccessInlining()) {
    5197         if (!putByIdStatus.isSet())
     5195    if (!putByStatus.isSimple() || !putByStatus.numVariants() || !Options::useAccessInlining()) {
     5196        if (!putByStatus.isSet())
    51985197            addToGraph(ForceOSRExit);
    51995198        addToGraph(PutPrivateNameById, OpInfo(identifier), OpInfo(privateFieldPutKind), base, value);
     
    52015200    }
    52025201   
    5203     if (putByIdStatus.numVariants() > 1) {
    5204         if (!m_graph.m_plan.isFTL() || putByIdStatus.makesCalls()
     5202    if (putByStatus.numVariants() > 1) {
     5203        if (!m_graph.m_plan.isFTL() || putByStatus.makesCalls()
    52055204            || !Options::usePolymorphicAccessInlining()
    5206             || putByIdStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) {
     5205            || putByStatus.numVariants() > Options::maxPolymorphicAccessInliningListSize()) {
    52075206            addToGraph(PutPrivateNameById, OpInfo(identifier), OpInfo(privateFieldPutKind), base, value);
    52085207            return;
     
    52125211            m_graph.compilation()->noticeInlinedPutById();
    52135212   
    5214         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
    5215    
    5216         for (const PutByIdVariant& variant : putByIdStatus.variants()) {
     5213        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
     5214   
     5215        for (const PutByVariant& variant : putByStatus.variants()) {
    52175216            for (Structure* structure : variant.oldStructure())
    52185217                m_graph.registerStructure(structure);
    5219             if (variant.kind() == PutByIdVariant::Transition)
     5218            if (variant.kind() == PutByVariant::Transition)
    52205219                m_graph.registerStructure(variant.newStructure());
    52215220        }
    52225221       
    52235222        MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
    5224         data->variants = putByIdStatus.variants();
     5223        data->variants = putByStatus.variants();
    52255224        data->identifierNumber = identifierNumber;
    52265225        addToGraph(MultiPutByOffset, OpInfo(data), base, value);
     
    52285227    }
    52295228   
    5230     ASSERT(putByIdStatus.numVariants() == 1);
    5231     const PutByIdVariant& variant = putByIdStatus[0];
     5229    ASSERT(putByStatus.numVariants() == 1);
     5230    const PutByVariant& variant = putByStatus[0];
    52325231   
    52335232    switch (variant.kind()) {
    5234     case PutByIdVariant::Replace: {
     5233    case PutByVariant::Replace: {
    52355234        ASSERT(privateFieldPutKind.isSet());
    5236         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
     5235        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
    52375236   
    52385237        store(base, identifierNumber, variant, value);
     
    52425241    }
    52435242   
    5244     case PutByIdVariant::Transition: {
     5243    case PutByVariant::Transition: {
    52455244        ASSERT(privateFieldPutKind.isDefine());
    5246         addToGraph(FilterPutByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(currentCodeOrigin(), putByIdStatus)), base);
     5245        addToGraph(FilterPutByStatus, OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(currentCodeOrigin(), putByStatus)), base);
    52475246   
    52485247        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
     
    64536452            Node* property = get(bytecode.m_property);
    64546453            Node* value = get(bytecode.m_value);
    6455             bool tryCompileAsPutByOffset = false;
    6456 
    6457             CacheableIdentifier identifier;
    6458             unsigned identifierNumber = std::numeric_limits<unsigned>::max();
    6459             PutByIdStatus putByIdStatus;
    6460             {
    6461                 ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
    6462                 ByValInfo* byValInfo = m_inlineStackTop->m_baselineMap.get(CodeOrigin(currentCodeOrigin().bytecodeIndex())).byValInfo;
    6463                 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
    6464                 // At that time, there is no information. For `put_private_name`, we might have some info from
    6465                 // LLInt IC, including cached cell that we could use if ByVal is not available.
    6466                 // https://bugs.webkit.org/show_bug.cgi?id=216779
    6467                 if (byValInfo
    6468                     && byValInfo->stubInfo
    6469                     && !byValInfo->tookSlowPath
    6470                     && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
    6471                     && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
    6472                     && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
    6473                     tryCompileAsPutByOffset = true;
    6474                     identifier = byValInfo->cachedId;
    6475                     ASSERT(identifier.isSymbolCell());
    6476                     identifierNumber = m_graph.identifiers().ensure(identifier.uid());
    6477                     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
    6478                     FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
    6479 
    6480                     addToGraph(CheckIsConstant, OpInfo(frozen), property);
    6481 
    6482                     putByIdStatus = PutByIdStatus::computeForStubInfo(
    6483                         locker, m_inlineStackTop->m_profiledBlock,
    6484                         byValInfo->stubInfo, currentCodeOrigin(), uid);
     6454            bool compiledAsPutPrivateNameById = false;
     6455
     6456            if (!m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
     6457                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
     6458                && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
     6459
     6460                PutByStatus status = PutByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin());
     6461
     6462                if (CacheableIdentifier identifier = status.singleIdentifier()) {
     6463                    UniquedStringImpl* uid = identifier.uid();
     6464                    unsigned identifierNumber = m_graph.identifiers().ensure(uid);
     6465                    if (identifier.isCell()) {
     6466                        FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
     6467                        if (identifier.isSymbolCell())
     6468                            addToGraph(CheckIsConstant, OpInfo(frozen), property);
     6469                        else
     6470                            addToGraph(CheckIdent, OpInfo(uid), property);
     6471                    } else
     6472                        addToGraph(CheckIdent, OpInfo(uid), property);
     6473
     6474                    handlePutPrivateNameById(base, identifier, identifierNumber, value, status, bytecode.m_putKind);
     6475                    compiledAsPutPrivateNameById = true;
    64856476                }
    64866477            }
    64876478
    6488             if (tryCompileAsPutByOffset)
    6489                 handlePutPrivateNameById(base, identifier, identifierNumber, value, putByIdStatus, bytecode.m_putKind);
    6490             else
     6479            if (!compiledAsPutPrivateNameById)
    64916480                addToGraph(PutPrivateName, OpInfo(), OpInfo(bytecode.m_putKind), base, property, value);
    64926481
     
    65686557            bool direct = bytecode.m_flags.isDirect();
    65696558
    6570             PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
     6559            PutByStatus putByStatus = PutByStatus::computeFor(
    65716560                m_inlineStackTop->m_profiledBlock,
    65726561                m_inlineStackTop->m_baselineMap, m_icContextStack,
    6573                 currentCodeOrigin(), m_graph.identifiers()[identifierNumber]);
     6562                currentCodeOrigin());
    65746563           
    6575             handlePutById(base, CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid), identifierNumber, value, putByIdStatus, direct, nextOpcodeIndex(), bytecode.m_flags.ecmaMode());
     6564            handlePutById(base, CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid), identifierNumber, value, putByStatus, direct, nextOpcodeIndex(), bytecode.m_flags.ecmaMode());
    65766565            NEXT_OPCODE(op_put_by_id);
    65776566        }
     
    79807969                    addToGraph(ForceOSRExit);
    79817970
    7982                 PutByIdStatus status;
     7971                PutByStatus status;
    79837972                if (uid)
    7984                     status = PutByIdStatus::computeFor(globalObject, structure, uid, false, PrivateFieldPutKind::none());
     7973                    status = PutByStatus::computeFor(globalObject, structure, CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid), false, PrivateFieldPutKind::none());
    79857974                else
    7986                     status = PutByIdStatus(PutByIdStatus::TakesSlowPath);
     7975                    status = PutByStatus(PutByStatus::LikelyTakesSlowPath);
    79877976                if (status.numVariants() != 1
    7988                     || status[0].kind() != PutByIdVariant::Replace
     7977                    || status[0].kind() != PutByVariant::Replace
    79897978                    || status[0].structure().size() != 1) {
    79907979                    addToGraph(PutById, OpInfo(CacheableIdentifier::createFromIdentifierOwnedByCodeBlock(m_inlineStackTop->m_profiledBlock, uid)), OpInfo(bytecode.m_getPutInfo.ecmaMode()), get(bytecode.m_scope), get(bytecode.m_value));
     
    88158804void ByteCodeParser::handlePutByVal(Bytecode bytecode, BytecodeIndex osrExitIndex)
    88168805{
     8806    CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
    88178807    Node* base = get(bytecode.m_base);
    88188808    Node* property = get(bytecode.m_property);
     
    88208810    bool isDirect = Bytecode::opcodeID == op_put_by_val_direct;
    88218811    bool compiledAsPutById = false;
    8822     {
    8823         CacheableIdentifier identifier;
    8824         unsigned identifierNumber = std::numeric_limits<unsigned>::max();
    8825         PutByIdStatus putByIdStatus;
    8826         {
    8827             ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
    8828             ByValInfo* byValInfo = m_inlineStackTop->m_baselineMap.get(CodeOrigin(currentCodeOrigin().bytecodeIndex())).byValInfo;
    8829             // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
    8830             // At that time, there is no information.
    8831             if (byValInfo
    8832                 && byValInfo->stubInfo
    8833                 && !byValInfo->tookSlowPath
    8834                 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
    8835                 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
    8836                 && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
    8837                 compiledAsPutById = true;
    8838                 identifier = byValInfo->cachedId;
    8839                 identifierNumber = m_graph.identifiers().ensure(identifier.uid());
    8840                 UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
    8841                 FrozenValue* frozen = nullptr;
    8842                 if (identifier.isCell())
    8843                     frozen = m_graph.freezeStrong(identifier.cell());
    8844 
     8812
     8813    PutByStatus status = PutByStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_inlineStackTop->m_baselineMap, m_icContextStack, currentCodeOrigin());
     8814
     8815    if (!m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)
     8816        && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)
     8817        && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantValue)) {
     8818        if (CacheableIdentifier identifier = status.singleIdentifier()) {
     8819            UniquedStringImpl* uid = identifier.uid();
     8820            unsigned identifierNumber = m_graph.identifiers().ensure(uid);
     8821            if (identifier.isCell()) {
     8822                FrozenValue* frozen = m_graph.freezeStrong(identifier.cell());
    88458823                if (identifier.isSymbolCell())
    88468824                    addToGraph(CheckIsConstant, OpInfo(frozen), property);
    8847                 else {
    8848                     ASSERT(!uid->isSymbol());
     8825                else
     8826                    addToGraph(CheckIdent, OpInfo(uid), property);
     8827            } else
     8828                addToGraph(CheckIdent, OpInfo(uid), property);
     8829
     8830            handlePutById(base, identifier, identifierNumber, value, status, isDirect, osrExitIndex, bytecode.m_ecmaMode);
     8831            compiledAsPutById = true;
     8832        } else if (status.takesSlowPath()) {
     8833            // Even though status is taking a slow path, it is possible that this node still has constant identifier and using PutById is always better in that case.
     8834            UniquedStringImpl* uid = nullptr;
     8835            JSCell* propertyCell = nullptr;
     8836            if (auto* symbol = property->dynamicCastConstant<Symbol*>(*m_vm)) {
     8837                uid = &symbol->uid();
     8838                propertyCell = symbol;
     8839                FrozenValue* frozen = m_graph.freezeStrong(symbol);
     8840                addToGraph(CheckIsConstant, OpInfo(frozen), property);
     8841            } else if (auto* string = property->dynamicCastConstant<JSString*>(*m_vm)) {
     8842                if (auto* impl = string->tryGetValueImpl(); impl->isAtom() && !parseIndex(*const_cast<StringImpl*>(impl))) {
     8843                    uid = bitwise_cast<UniquedStringImpl*>(impl);
     8844                    propertyCell = string;
     8845                    m_graph.freezeStrong(string);
    88498846                    addToGraph(CheckIdent, OpInfo(uid), property);
    88508847                }
    8851 
    8852                 putByIdStatus = PutByIdStatus::computeForStubInfo(
    8853                     locker, m_inlineStackTop->m_profiledBlock,
    8854                     byValInfo->stubInfo, currentCodeOrigin(), uid);
    8855 
    8856             }
    8857         }
    8858 
    8859         if (compiledAsPutById)
    8860             handlePutById(base, identifier, identifierNumber, value, putByIdStatus, isDirect, osrExitIndex, bytecode.m_ecmaMode);
     8848            }
     8849
     8850            if (uid) {
     8851                unsigned identifierNumber = m_graph.identifiers().ensure(uid);
     8852                handlePutById(base, CacheableIdentifier::createFromCell(propertyCell), identifierNumber, value, status, isDirect, osrExitIndex, bytecode.m_ecmaMode);
     8853                compiledAsPutById = true;
     8854            }
     8855        }
    88618856    }
    88628857
    88638858    if (!compiledAsPutById) {
    8864         ArrayMode arrayMode = getArrayMode(bytecode.metadata(m_inlineStackTop->m_codeBlock).m_arrayProfile, Array::Write);
     8859        ArrayMode arrayMode = getArrayMode(bytecode.metadata(codeBlock).m_arrayProfile, Array::Write);
    88658860
    88668861        addVarArgChild(base);
     
    88698864        addVarArgChild(nullptr); // Leave room for property storage.
    88708865        addVarArgChild(nullptr); // Leave room for length.
    8871         addToGraph(Node::VarArg, isDirect ? PutByValDirect : PutByVal, OpInfo(arrayMode.asWord()), OpInfo(bytecode.m_ecmaMode));
     8866        Node* putByVal = addToGraph(Node::VarArg, isDirect ? PutByValDirect : PutByVal, OpInfo(arrayMode.asWord()), OpInfo(bytecode.m_ecmaMode));
    88728867        m_exitOK = false; // PutByVal and PutByValDirect must be treated as if they clobber exit state, since FixupPhase may make them generic.
     8868        if (status.observedStructureStubInfoSlowPath())
     8869            m_graph.m_slowPutByVal.add(putByVal);
    88738870    }
    88748871}
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r280760 r281615  
    570570    case FilterCallLinkStatus:
    571571    case FilterGetByStatus:
    572     case FilterPutByIdStatus:
     572    case FilterPutByStatus:
    573573    case FilterInByStatus:
    574574    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp

    r278445 r281615  
    8282    case FilterCallLinkStatus:
    8383    case FilterGetByStatus:
    84     case FilterPutByIdStatus:
     84    case FilterPutByStatus:
    8585    case FilterInByStatus:
    8686    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r278696 r281615  
    3939#include "GetByStatus.h"
    4040#include "JSCInlines.h"
    41 #include "PutByIdStatus.h"
     41#include "PutByStatus.h"
    4242#include "StructureCache.h"
    4343
     
    502502
    503503                for (unsigned i = 0; i < data.variants.size(); ++i) {
    504                     PutByIdVariant& variant = data.variants[i];
     504                    PutByVariant& variant = data.variants[i];
    505505                    variant.oldStructure().genericFilter([&] (Structure* structure) -> bool {
    506506                        return baseValue.contains(m_graph.registerStructure(structure));
     
    514514                    }
    515515                   
    516                     if (variant.kind() == PutByIdVariant::Transition
     516                    if (variant.kind() == PutByVariant::Transition
    517517                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
    518                         variant = PutByIdVariant::replace(
    519                             variant.oldStructure(),
    520                             variant.offset());
     518                        variant = PutByVariant::replace(variant.identifier(), variant.oldStructure(), variant.offset());
    521519                        changed = true;
    522520                    }
     
    12141212    }
    12151213
    1216     void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)
     1214    void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByVariant& variant, unsigned identifierNumber)
    12171215    {
    12181216        NodeOrigin origin = node->origin;
     
    12251223
    12261224        Transition* transition = nullptr;
    1227         if (variant.kind() == PutByIdVariant::Transition) {
     1225        if (variant.kind() == PutByVariant::Transition) {
    12281226            transition = m_graph.m_transitions.add(
    12291227                m_graph.registerStructure(variant.oldStructureForTransition()), m_graph.registerStructure(variant.newStructure()));
     
    12701268        node->origin.exitOK = canExit;
    12711269
    1272         if (variant.kind() == PutByIdVariant::Transition) {
     1270        if (variant.kind() == PutByVariant::Transition) {
    12731271            if (didAllocateStorage) {
    12741272                m_insertionSet.insertNode(
     
    14071405            return;
    14081406
    1409         PutByIdStatus status = PutByIdStatus::computeFor(
     1407        PutByStatus status = PutByStatus::computeFor(
    14101408            m_graph.globalObjectFor(origin.semantic),
    14111409            baseValue.m_structure.toStructureSet(),
    1412             node->cacheableIdentifier().uid(),
     1410            node->cacheableIdentifier(),
    14131411            isDirect, privateFieldPutKind);
    14141412
     
    14251423        RegisteredStructureSet newSet;
    14261424        TransitionVector transitions;
    1427         for (const PutByIdVariant& variant : status.variants()) {
    1428             if (variant.kind() == PutByIdVariant::Transition) {
     1425        for (const PutByVariant& variant : status.variants()) {
     1426            if (variant.kind() == PutByVariant::Transition) {
    14291427                for (const ObjectPropertyCondition& condition : variant.conditionSet()) {
    14301428                    if (m_graph.watchCondition(condition))
     
    14491447                newSet.add(newStructure);
    14501448            } else {
    1451                 ASSERT(variant.kind() == PutByIdVariant::Replace);
     1449                ASSERT(variant.kind() == PutByVariant::Replace);
    14521450                ASSERT(privateFieldPutKind.isNone() || privateFieldPutKind.isSet());
    14531451                DFG_ASSERT(m_graph, node, variant.conditionSet().isEmpty());
     
    14651463
    14661464        m_insertionSet.insertNode(
    1467             indexInBlock, SpecNone, FilterPutByIdStatus, node->origin,
    1468             OpInfo(m_graph.m_plan.recordedStatuses().addPutByIdStatus(node->origin.semantic, status)),
     1465            indexInBlock, SpecNone, FilterPutByStatus, node->origin,
     1466            OpInfo(m_graph.m_plan.recordedStatuses().addPutByStatus(node->origin.semantic, status)),
    14691467            Edge(baseNode));
    14701468
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r280760 r281615  
    248248    case FilterCallLinkStatus:
    249249    case FilterGetByStatus:
    250     case FilterPutByIdStatus:
     250    case FilterPutByStatus:
    251251    case FilterInByStatus:
    252252    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r280760 r281615  
    12351235                        fixEdge<CellUse>(child1);
    12361236                        fixEdge<SymbolUse>(child2);
     1237                        break;
     1238                    }
     1239                    if (!m_graph.m_slowPutByVal.contains(node)) {
     1240                        fixEdge<CellUse>(child1);
    12371241                        break;
    12381242                    }
     
    28662870        case FilterCallLinkStatus:
    28672871        case FilterGetByStatus:
    2868         case FilterPutByIdStatus:
     2872        case FilterPutByStatus:
    28692873        case FilterInByStatus:
    28702874        case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r280760 r281615  
    386386    if (node->hasInByStatus())
    387387        out.print(comma, *node->inByStatus());
    388     if (node->hasPutByIdStatus())
    389         out.print(comma, *node->putByIdStatus());
     388    if (node->hasPutByStatus())
     389        out.print(comma, *node->putByStatus());
    390390    if (node->hasEnumeratorMetadata())
    391391        out.print(comma, "enumeratorModes = ", node->enumeratorMetadata().toRaw());
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r278945 r281615  
    12031203
    12041204    HashSet<Node*> m_slowGetByVal;
     1205    HashSet<Node*> m_slowPutByVal;
    12051206
    12061207private:
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r278445 r281615  
    253253    finalizeInlineCaches(m_getByVals, linkBuffer);
    254254    finalizeInlineCaches(m_putByIds, linkBuffer);
     255    finalizeInlineCaches(m_putByVals, linkBuffer);
    255256    finalizeInlineCaches(m_delByIds, linkBuffer);
    256257    finalizeInlineCaches(m_delByVals, linkBuffer);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r278656 r281615  
    200200    }
    201201
     202    void addPutByVal(const JITPutByValGenerator& gen, SlowPathGenerator* slowPath)
     203    {
     204        m_putByVals.append(InlineCacheWrapper<JITPutByValGenerator>(gen, slowPath));
     205    }
     206
    202207    void addDelById(const JITDelByIdGenerator& gen, SlowPathGenerator* slowPath)
    203208    {
     
    361366    Vector<InlineCacheWrapper<JITGetByValGenerator>, 4> m_getByVals;
    362367    Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds;
     368    Vector<InlineCacheWrapper<JITPutByValGenerator>, 4> m_putByVals;
    363369    Vector<InlineCacheWrapper<JITDelByIdGenerator>, 4> m_delByIds;
    364370    Vector<InlineCacheWrapper<JITDelByValGenerator>, 4> m_delByVals;
  • trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp

    r280760 r281615  
    107107    case FilterCallLinkStatus:
    108108    case FilterGetByStatus:
    109     case FilterPutByIdStatus:
     109    case FilterPutByStatus:
    110110    case FilterInByStatus:
    111111    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r280760 r281615  
    5656#include "Operands.h"
    5757#include "PrivateFieldPutKind.h"
    58 #include "PutByIdVariant.h"
     58#include "PutByVariant.h"
    5959#include "SetPrivateBrandVariant.h"
    6060#include "SpeculatedType.h"
     
    9393struct MultiPutByOffsetData {
    9494    unsigned identifierNumber;
    95     Vector<PutByIdVariant, 2> variants;
     95    Vector<PutByVariant, 2> variants;
    9696   
    9797    bool writesStructures() const;
     
    32113211    }
    32123212   
    3213     bool hasPutByIdStatus()
    3214     {
    3215         return op() == FilterPutByIdStatus;
    3216     }
    3217    
    3218     PutByIdStatus* putByIdStatus()
    3219     {
    3220         ASSERT(hasPutByIdStatus());
    3221         return m_opInfo.as<PutByIdStatus*>();
     3213    bool hasPutByStatus()
     3214    {
     3215        return op() == FilterPutByStatus;
     3216    }
     3217   
     3218    PutByStatus* putByStatus()
     3219    {
     3220        ASSERT(hasPutByStatus());
     3221        return m_opInfo.as<PutByStatus*>();
    32223222    }
    32233223
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r280760 r281615  
    547547    macro(FilterGetByStatus, NodeMustGenerate) \
    548548    macro(FilterInByStatus, NodeMustGenerate) \
    549     macro(FilterPutByIdStatus, NodeMustGenerate) \
     549    macro(FilterPutByStatus, NodeMustGenerate) \
    550550    macro(FilterDeleteByStatus, NodeMustGenerate) \
    551551    macro(FilterCheckPrivateBrandStatus, NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp

    r279256 r281615  
    216216        case InlineCallFrame::GetterCall:
    217217        case InlineCallFrame::SetterCall: {
    218             if (callInstruction.opcodeID() == op_put_by_val) {
    219                 // We compile op_put_by_val as PutById and inlines SetterCall only when we found StructureStubInfo for this op_put_by_val.
    220                 // But still it is possible that we cannot find StructureStubInfo here. Let's consider the following scenario.
    221                 // 1. Baseline CodeBlock (A) is compiled.
    222                 // 2. (A) gets DFG (B).
    223                 // 3. Since (A) collects enough information for put_by_val, (B) can get StructureStubInfo from (A) and copmile it as inlined Setter call.
    224                 // 4. (A)'s JITData is destroyed since it is not executed. Then, (A) becomes LLInt.
    225                 // 5. The CodeBlock inlining (A) gets OSR exit. So (A) is executed and (A) eventually gets Baseline CodeBlock again.
    226                 // 6. (B) gets OSR exit. (B) attempts to search for StructureStubInfo in (A) for PutById (originally, put_by_val). But it does not exist since (A)'s JITData is cleared once.
    227                 ByValInfo* byValInfo = baselineCodeBlockForCaller->findByValInfo(CodeOrigin(callBytecodeIndex));
    228                 RELEASE_ASSERT(byValInfo);
    229                 jumpTarget = byValInfo->doneTarget.retagged<JSEntryPtrTag>();
    230                 break;
    231             }
    232 
    233218            StructureStubInfo* stubInfo = baselineCodeBlockForCaller->findStubInfo(CodeOrigin(callBytecodeIndex));
    234219            RELEASE_ASSERT(stubInfo);
  • trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp

    r278445 r281615  
    12591259        case FilterCallLinkStatus:
    12601260        case FilterGetByStatus:
    1261         case FilterPutByIdStatus:
     1261        case FilterPutByStatus:
    12621262        case FilterInByStatus:
    12631263        case FilterDeleteByStatus:
     
    25552555                        // at this point, we can simply trust that the incoming value has the right type
    25562556                        // for whatever structure we are using.
    2557                         data->variants.append(
    2558                             PutByIdVariant::replace(currentSet, currentOffset));
     2557                        data->variants.append(PutByVariant::replace(nullptr, currentSet, currentOffset));
    25592558                        currentOffset = offset;
    25602559                        currentSet.clear();
     
    25622561                    currentSet.add(structure.get());
    25632562                }
    2564                 data->variants.append(
    2565                     PutByIdVariant::replace(currentSet, currentOffset));
     2563                data->variants.append(PutByVariant::replace(nullptr, currentSet, currentOffset));
    25662564            }
    25672565
     
    26162614                case FilterCallLinkStatus:
    26172615                case FilterGetByStatus:
    2618                 case FilterPutByIdStatus:
     2616                case FilterPutByStatus:
    26192617                case FilterInByStatus:
    26202618                case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r280760 r281615  
    14501450        case FilterCallLinkStatus:
    14511451        case FilterGetByStatus:
    1452         case FilterPutByIdStatus:
     1452        case FilterPutByStatus:
    14531453        case FilterInByStatus:
    14541454        case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r280760 r281615  
    360360    case FilterCallLinkStatus:
    361361    case FilterGetByStatus:
    362     case FilterPutByIdStatus:
     362    case FilterPutByStatus:
    363363    case FilterInByStatus:
    364364    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r281324 r281615  
    26912691        case Array::Generic: {
    26922692            ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
    2693 
    2694             if (child1.useKind() == CellUse) {
    2695                 if (child2.useKind() == StringUse) {
    2696                     compilePutByValForCellWithString(node, child1, child2, child3);
    2697                     alreadyHandled = true;
    2698                     break;
     2693            if (m_graph.m_slowPutByVal.contains(node)) {
     2694                if (child1.useKind() == CellUse) {
     2695                    if (child2.useKind() == StringUse) {
     2696                        compilePutByValForCellWithString(node, child1, child2, child3);
     2697                        alreadyHandled = true;
     2698                        break;
     2699                    }
     2700
     2701                    if (child2.useKind() == SymbolUse) {
     2702                        compilePutByValForCellWithSymbol(node, child1, child2, child3);
     2703                        alreadyHandled = true;
     2704                        break;
     2705                    }
    26992706                }
    27002707
    2701                 if (child2.useKind() == SymbolUse) {
    2702                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
    2703                     alreadyHandled = true;
    2704                     break;
    2705                 }
     2708                SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
     2709                JSValueOperand property(this, child2);
     2710                JSValueOperand value(this, child3);
     2711                GPRReg baseGPR = base.gpr();
     2712                JSValueRegs propertyRegs = property.jsValueRegs();
     2713                JSValueRegs valueRegs = value.jsValueRegs();
     2714
     2715                flushRegisters();
     2716                if (node->op() == PutByValDirect)
     2717                    callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs, valueRegs);
     2718                else
     2719                    callOperation(node->ecmaMode().isStrict() ? operationPutByValCellStrict : operationPutByValCellNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs, valueRegs);
     2720                m_jit.exceptionCheck();
     2721
     2722                noResult(node);
     2723                alreadyHandled = true;
     2724                break;
    27062725            }
    2707            
    2708             SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
    2709             JSValueOperand property(this, child2);
    2710             JSValueOperand value(this, child3);
    2711             GPRReg baseGPR = base.gpr();
     2726
     2727            JSValueOperand base(this, child1, ManualOperandSpeculation);
     2728            JSValueOperand property(this, child2, ManualOperandSpeculation);
     2729            JSValueOperand value(this, child3, ManualOperandSpeculation);
     2730            JSValueRegs baseRegs = base.jsValueRegs();
    27122731            JSValueRegs propertyRegs = property.jsValueRegs();
    27132732            JSValueRegs valueRegs = value.jsValueRegs();
    2714            
    2715             flushRegisters();
    2716             if (node->op() == PutByValDirect)
    2717                 callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs, valueRegs);
    2718             else
    2719                 callOperation(node->ecmaMode().isStrict() ? operationPutByValCellStrict : operationPutByValCellNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, propertyRegs, valueRegs);
    2720             m_jit.exceptionCheck();
    2721            
     2733
     2734            speculate(node, child1);
     2735            speculate(node, child2);
     2736            speculate(node, child3);
     2737
     2738            CodeOrigin codeOrigin = node->origin.semantic;
     2739            CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     2740            RegisterSet usedRegisters = this->usedRegisters();
     2741            bool isDirect = node->op() == PutByValDirect;
     2742            ECMAMode ecmaMode = node->ecmaMode();
     2743
     2744            JITPutByValGenerator gen(
     2745                m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::PutByVal, usedRegisters,
     2746                baseRegs, propertyRegs, valueRegs, InvalidGPRReg, InvalidGPRReg);
     2747
     2748            if (m_state.forNode(child2).isType(SpecString))
     2749                gen.stubInfo()->propertyIsString = true;
     2750            else if (m_state.forNode(child2).isType(SpecInt32Only))
     2751                gen.stubInfo()->propertyIsInt32 = true;
     2752            else if (m_state.forNode(child2).isType(SpecSymbol))
     2753                gen.stubInfo()->propertyIsSymbol = true;
     2754
     2755            gen.generateFastPath(m_jit);
     2756
     2757            JITCompiler::JumpList slowCases;
     2758            slowCases.append(gen.slowPathJump());
     2759
     2760            std::unique_ptr<SlowPathGenerator> slowPath;
     2761            auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize);
     2762            slowPath = slowPathCall(
     2763                slowCases, this, operation,
     2764                NoResult, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), baseRegs, propertyRegs, valueRegs, gen.stubInfo(), nullptr);
     2765
     2766            m_jit.addPutByVal(gen, slowPath.get());
     2767            addSlowPathGenerator(WTFMove(slowPath));
     2768
    27222769            noResult(node);
    27232770            alreadyHandled = true;
     
    43234370    case FilterCallLinkStatus:
    43244371    case FilterGetByStatus:
    4325     case FilterPutByIdStatus:
     4372    case FilterPutByStatus:
    43264373    case FilterInByStatus:
    43274374    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r280760 r281615  
    31783178        case Array::Generic: {
    31793179            DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect, node->op());
    3180 
    3181             if (child1.useKind() == CellUse) {
    3182                 if (child2.useKind() == StringUse) {
    3183                     compilePutByValForCellWithString(node, child1, child2, child3);
    3184                     alreadyHandled = true;
    3185                     break;
     3180            if (m_graph.m_slowPutByVal.contains(node) || (child1.useKind() != CellUse && child1.useKind() != KnownCellUse)) {
     3181                if (child1.useKind() == CellUse) {
     3182                    if (child2.useKind() == StringUse) {
     3183                        compilePutByValForCellWithString(node, child1, child2, child3);
     3184                        alreadyHandled = true;
     3185                        break;
     3186                    }
     3187
     3188                    if (child2.useKind() == SymbolUse) {
     3189                        compilePutByValForCellWithSymbol(node, child1, child2, child3);
     3190                        alreadyHandled = true;
     3191                        break;
     3192                    }
    31863193                }
    31873194
    3188                 if (child2.useKind() == SymbolUse) {
    3189                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
    3190                     alreadyHandled = true;
    3191                     break;
    3192                 }
     3195                JSValueOperand arg1(this, child1);
     3196                JSValueOperand arg2(this, child2);
     3197                JSValueOperand arg3(this, child3);
     3198                GPRReg arg1GPR = arg1.gpr();
     3199                GPRReg arg2GPR = arg2.gpr();
     3200                GPRReg arg3GPR = arg3.gpr();
     3201                flushRegisters();
     3202                if (node->op() == PutByValDirect)
     3203                    callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR, arg3GPR);
     3204                else
     3205                    callOperation(node->ecmaMode().isStrict() ? operationPutByValStrict : operationPutByValNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR, arg3GPR);
     3206                m_jit.exceptionCheck();
     3207
     3208                noResult(node);
     3209                alreadyHandled = true;
     3210                break;
    31933211            }
    3194            
    3195             JSValueOperand arg1(this, child1);
    3196             JSValueOperand arg2(this, child2);
    3197             JSValueOperand arg3(this, child3);
    3198             GPRReg arg1GPR = arg1.gpr();
    3199             GPRReg arg2GPR = arg2.gpr();
    3200             GPRReg arg3GPR = arg3.gpr();
    3201             flushRegisters();
    3202             if (node->op() == PutByValDirect)
    3203                 callOperation(node->ecmaMode().isStrict() ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR, arg3GPR);
    3204             else
    3205                 callOperation(node->ecmaMode().isStrict() ? operationPutByValStrict : operationPutByValNonStrict, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), arg1GPR, arg2GPR, arg3GPR);
    3206             m_jit.exceptionCheck();
    3207            
     3212
     3213            SpeculateCellOperand base(this, child1);
     3214            JSValueOperand property(this, child2, ManualOperandSpeculation);
     3215            JSValueOperand value(this, child3, ManualOperandSpeculation);
     3216            GPRReg baseGPR = base.gpr();
     3217            GPRReg propertyGPR = property.gpr();
     3218            GPRReg valueGPR = value.gpr();
     3219
     3220            GPRTemporary stubInfo;
     3221            GPRReg stubInfoGPR = InvalidGPRReg;
     3222            if (JITCode::useDataIC(JITType::DFGJIT)) {
     3223                stubInfo = GPRTemporary(this);
     3224                stubInfoGPR = stubInfo.gpr();
     3225            }
     3226
     3227            speculate(node, child2);
     3228            speculate(node, child3);
     3229
     3230            CodeOrigin codeOrigin = node->origin.semantic;
     3231            CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     3232            RegisterSet usedRegisters = this->usedRegisters();
     3233            bool isDirect = node->op() == PutByValDirect;
     3234            ECMAMode ecmaMode = node->ecmaMode();
     3235
     3236            JITPutByValGenerator gen(
     3237                m_jit.codeBlock(), JITType::DFGJIT, codeOrigin, callSite, AccessType::PutByVal, usedRegisters,
     3238                JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR);
     3239
     3240            if (m_state.forNode(child2).isType(SpecString))
     3241                gen.stubInfo()->propertyIsString = true;
     3242            else if (m_state.forNode(child2).isType(SpecInt32Only))
     3243                gen.stubInfo()->propertyIsInt32 = true;
     3244            else if (m_state.forNode(child2).isType(SpecSymbol))
     3245                gen.stubInfo()->propertyIsSymbol = true;
     3246
     3247            gen.generateFastPath(m_jit);
     3248
     3249            JITCompiler::JumpList slowCases;
     3250            if (!JITCode::useDataIC(JITType::DFGJIT))
     3251                slowCases.append(gen.slowPathJump());
     3252
     3253            std::unique_ptr<SlowPathGenerator> slowPath;
     3254            auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize);
     3255            if (JITCode::useDataIC(JITType::DFGJIT)) {
     3256                slowPath = slowPathICCall(
     3257                    slowCases, this, gen.stubInfo(), stubInfoGPR, CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), operation,
     3258                    NoResult, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), baseGPR, propertyGPR, valueGPR, stubInfoGPR, nullptr);
     3259            } else {
     3260                slowPath = slowPathCall(
     3261                    slowCases, this, operation,
     3262                    NoResult, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(codeOrigin)), baseGPR, propertyGPR, valueGPR, gen.stubInfo(), nullptr);
     3263            }
     3264
     3265            m_jit.addPutByVal(gen, slowPath.get());
     3266            addSlowPathGenerator(WTFMove(slowPath));
     3267
    32083268            noResult(node);
    32093269            alreadyHandled = true;
     
    58725932    case FilterCallLinkStatus:
    58735933    case FilterGetByStatus:
    5874     case FilterPutByIdStatus:
     5934    case FilterPutByStatus:
    58755935    case FilterInByStatus:
    58765936    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp

    r272580 r281615  
    234234            case PutByValAlias: {
    235235                switch (m_node->arrayMode().modeForPut().type()) {
     236                case Array::Generic:
     237                case Array::BigInt64Array:
     238                case Array::BigUint64Array: {
     239                    Edge child1 = m_graph.varArgChild(m_node, 0);
     240                    Edge child3 = m_graph.varArgChild(m_node, 2);
     241                    if (!m_graph.m_slowPutByVal.contains(m_node) && (child1.useKind() == CellUse || child1.useKind() == KnownCellUse))
     242                        considerBarrier(child1, child3);
     243                    break;
     244                }
    236245                case Array::Contiguous:
    237246                case Array::ArrayStorage:
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r278696 r281615  
    313313                case MultiPutByOffset:
    314314                    for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    315                         const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
    316                         if (variant.kind() != PutByIdVariant::Transition)
     315                        const PutByVariant& variant = node->multiPutByOffsetData().variants[i];
     316                        if (variant.kind() != PutByVariant::Transition)
    317317                            continue;
    318318                        VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
  • trunk/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp

    r278445 r281615  
    197197               
    198198            case FilterGetByStatus:
    199             case FilterPutByIdStatus:
     199            case FilterPutByStatus:
    200200            case FilterCallLinkStatus:
    201201            case FilterInByStatus:
     
    422422
    423423            case FilterGetByStatus:
    424             case FilterPutByIdStatus:
     424            case FilterPutByStatus:
    425425            case FilterCallLinkStatus:
    426426            case FilterInByStatus:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r280760 r281615  
    408408    case FilterCallLinkStatus:
    409409    case FilterGetByStatus:
    410     case FilterPutByIdStatus:
     410    case FilterPutByStatus:
    411411    case FilterInByStatus:
    412412    case FilterDeleteByStatus:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r281565 r281615  
    16501650        case FilterCallLinkStatus:
    16511651        case FilterGetByStatus:
    1652         case FilterPutByIdStatus:
     1652        case FilterPutByStatus:
    16531653        case FilterInByStatus:
    16541654        case FilterDeleteByStatus:
     
    55575557        case Array::BigUint64Array:
    55585558        case Array::Generic: {
    5559             if (child1.useKind() == CellUse) {
    5560                 V_JITOperation_GCCJ operation = nullptr;
    5561                 if (child2.useKind() == StringUse) {
    5562                     if (m_node->op() == PutByValDirect) {
    5563                         if (m_node->ecmaMode().isStrict())
    5564                             operation = operationPutByValDirectCellStringStrict;
    5565                         else
    5566                             operation = operationPutByValDirectCellStringNonStrict;
     5559            if (m_graph.m_slowPutByVal.contains(m_node) || (child1.useKind() != CellUse && child1.useKind() != KnownCellUse)) {
     5560                if (child1.useKind() == CellUse) {
     5561                    V_JITOperation_GCCJ operation = nullptr;
     5562                    if (child2.useKind() == StringUse) {
     5563                        if (m_node->op() == PutByValDirect) {
     5564                            if (m_node->ecmaMode().isStrict())
     5565                                operation = operationPutByValDirectCellStringStrict;
     5566                            else
     5567                                operation = operationPutByValDirectCellStringNonStrict;
     5568                        } else {
     5569                            if (m_node->ecmaMode().isStrict())
     5570                                operation = operationPutByValCellStringStrict;
     5571                            else
     5572                                operation = operationPutByValCellStringNonStrict;
     5573                        }
     5574                        vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowString(child2), lowJSValue(child3));
     5575                        return;
     5576                    }
     5577
     5578                    if (child2.useKind() == SymbolUse) {
     5579                        if (m_node->op() == PutByValDirect) {
     5580                            if (m_node->ecmaMode().isStrict())
     5581                                operation = operationPutByValDirectCellSymbolStrict;
     5582                            else
     5583                                operation = operationPutByValDirectCellSymbolNonStrict;
     5584                        } else {
     5585                            if (m_node->ecmaMode().isStrict())
     5586                                operation = operationPutByValCellSymbolStrict;
     5587                            else
     5588                                operation = operationPutByValCellSymbolNonStrict;
     5589                        }
     5590                        vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowSymbol(child2), lowJSValue(child3));
     5591                        return;
     5592                    }
     5593                }
     5594
     5595                V_JITOperation_GJJJ operation;
     5596                if (m_node->op() == PutByValDirect) {
     5597                    if (m_node->ecmaMode().isStrict())
     5598                        operation = operationPutByValDirectStrict;
     5599                    else
     5600                        operation = operationPutByValDirectNonStrict;
     5601                } else {
     5602                    if (m_node->ecmaMode().isStrict())
     5603                        operation = operationPutByValStrict;
     5604                    else
     5605                        operation = operationPutByValNonStrict;
     5606                }
     5607
     5608                vmCall(
     5609                    Void, operation, weakPointer(globalObject),
     5610                    lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
     5611                return;
     5612            }
     5613
     5614            Node* node = m_node;
     5615
     5616            LValue base = lowCell(child1);
     5617            LValue property = lowJSValue(child2, ManualOperandSpeculation);
     5618            LValue value = lowJSValue(child3, ManualOperandSpeculation);
     5619
     5620            speculate(child2);
     5621            speculate(child3);
     5622            bool propertyIsString = false;
     5623            bool propertyIsInt32 = false;
     5624            bool propertyIsSymbol = false;
     5625            if (abstractValue(child2).isType(SpecString))
     5626                propertyIsString = true;
     5627            else if (abstractValue(child2).isType(SpecInt32Only))
     5628                propertyIsInt32 = true;
     5629            else if (abstractValue(child2).isType(SpecSymbol))
     5630                propertyIsSymbol = true;
     5631
     5632            PatchpointValue* patchpoint = m_out.patchpoint(Void);
     5633            patchpoint->appendSomeRegister(base);
     5634            patchpoint->appendSomeRegister(property);
     5635            patchpoint->appendSomeRegister(value);
     5636            patchpoint->append(m_notCellMask, ValueRep::lateReg(GPRInfo::notCellMaskRegister));
     5637            patchpoint->append(m_numberTag, ValueRep::lateReg(GPRInfo::numberTagRegister));
     5638            patchpoint->clobber(RegisterSet::macroScratchRegisters());
     5639            patchpoint->numGPScratchRegisters = JITCode::useDataIC(JITType::FTLJIT) ? 1 : 0;
     5640
     5641            RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
     5642
     5643            State* state = &m_ftlState;
     5644            CodeOrigin nodeSemanticOrigin = node->origin.semantic;
     5645            ECMAMode ecmaMode = m_node->ecmaMode();
     5646            bool isDirect = m_node->op() == PutByValDirect;
     5647            patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     5648                AllowMacroScratchRegisterUsage allowScratch(jit);
     5649
     5650                CallSiteIndex callSiteIndex = state->jitCode->common.codeOrigins->addUniqueCallSiteIndex(nodeSemanticOrigin);
     5651
     5652                // This is the direct exit target for operation calls.
     5653                Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
     5654
     5655                // This is the exit for call IC's created by the IC for getters. We don't have
     5656                // to do anything weird other than call this, since it will associate the exit with
     5657                // the callsite index.
     5658                exceptionHandle->scheduleExitCreationForUnwind(params, callSiteIndex);
     5659
     5660                GPRReg baseGPR = params[0].gpr();
     5661                GPRReg propertyGPR = params[1].gpr();
     5662                GPRReg valueGPR = params[2].gpr();
     5663                GPRReg stubInfoGPR = JITCode::useDataIC(JITType::FTLJIT) ? params.gpScratch(0) : InvalidGPRReg;
     5664
     5665                auto generator = Box<JITPutByValGenerator>::create(
     5666                    jit.codeBlock(), JITType::FTLJIT, nodeSemanticOrigin, callSiteIndex, AccessType::PutByVal,
     5667                    params.unavailableRegisters(), JSValueRegs(baseGPR), JSValueRegs(propertyGPR), JSValueRegs(valueGPR), InvalidGPRReg, stubInfoGPR);
     5668
     5669                generator->stubInfo()->propertyIsString = propertyIsString;
     5670                generator->stubInfo()->propertyIsInt32 = propertyIsInt32;
     5671                generator->stubInfo()->propertyIsSymbol = propertyIsSymbol;
     5672
     5673                generator->generateFastPath(jit);
     5674                CCallHelpers::Label done = jit.label();
     5675
     5676                params.addLatePath([=] (CCallHelpers& jit) {
     5677                    AllowMacroScratchRegisterUsage allowScratch(jit);
     5678
     5679                    if (!JITCode::useDataIC(JITType::FTLJIT))
     5680                        generator->slowPathJump().link(&jit);
     5681                    CCallHelpers::Label slowPathBegin = jit.label();
     5682                    CCallHelpers::Call slowPathCall;
     5683                    auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize);
     5684                    if (JITCode::useDataIC(JITType::FTLJIT)) {
     5685                        jit.move(CCallHelpers::TrustedImmPtr(generator->stubInfo()), stubInfoGPR);
     5686                        generator->stubInfo()->m_slowOperation = operation;
     5687                        slowPathCall = callOperation(
     5688                            *state, params.unavailableRegisters(), jit, nodeSemanticOrigin,
     5689                            exceptions.get(), CCallHelpers::Address(stubInfoGPR, StructureStubInfo::offsetOfSlowOperation()), InvalidGPRReg,
     5690                            jit.codeBlock()->globalObjectFor(nodeSemanticOrigin),
     5691                            baseGPR, propertyGPR, valueGPR, stubInfoGPR, CCallHelpers::TrustedImmPtr(nullptr)).call();
    55675692                    } else {
    5568                         if (m_node->ecmaMode().isStrict())
    5569                             operation = operationPutByValCellStringStrict;
    5570                         else
    5571                             operation = operationPutByValCellStringNonStrict;
     5693                        slowPathCall = callOperation(
     5694                            *state, params.unavailableRegisters(), jit, nodeSemanticOrigin,
     5695                            exceptions.get(), operation, InvalidGPRReg,
     5696                            jit.codeBlock()->globalObjectFor(nodeSemanticOrigin),
     5697                            baseGPR, propertyGPR, valueGPR, CCallHelpers::TrustedImmPtr(generator->stubInfo()), CCallHelpers::TrustedImmPtr(nullptr)).call();
    55725698                    }
    5573                     vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowString(child2), lowJSValue(child3));
    5574                     return;
    5575                 }
    5576 
    5577                 if (child2.useKind() == SymbolUse) {
    5578                     if (m_node->op() == PutByValDirect) {
    5579                         if (m_node->ecmaMode().isStrict())
    5580                             operation = operationPutByValDirectCellSymbolStrict;
    5581                         else
    5582                             operation = operationPutByValDirectCellSymbolNonStrict;
    5583                     } else {
    5584                         if (m_node->ecmaMode().isStrict())
    5585                             operation = operationPutByValCellSymbolStrict;
    5586                         else
    5587                             operation = operationPutByValCellSymbolNonStrict;
    5588                     }
    5589                     vmCall(Void, operation, weakPointer(globalObject), lowCell(child1), lowSymbol(child2), lowJSValue(child3));
    5590                     return;
    5591                 }
    5592             }
    5593 
    5594             V_JITOperation_GJJJ operation;
    5595             if (m_node->op() == PutByValDirect) {
    5596                 if (m_node->ecmaMode().isStrict())
    5597                     operation = operationPutByValDirectStrict;
    5598                 else
    5599                     operation = operationPutByValDirectNonStrict;
    5600             } else {
    5601                 if (m_node->ecmaMode().isStrict())
    5602                     operation = operationPutByValStrict;
    5603                 else
    5604                     operation = operationPutByValNonStrict;
    5605             }
    5606                
    5607             vmCall(
    5608                 Void, operation, weakPointer(globalObject),
    5609                 lowJSValue(child1), lowJSValue(child2), lowJSValue(child3));
     5699                    jit.jump().linkTo(done, &jit);
     5700
     5701                    generator->reportSlowPathCall(slowPathBegin, slowPathCall);
     5702
     5703                    jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
     5704                        generator->finalize(linkBuffer, linkBuffer);
     5705                    });
     5706                });
     5707            });
    56105708            return;
    56115709        }
     
    89529050        RegisteredStructureSet baseSet;
    89539051        for (unsigned i = data.variants.size(); i--;) {
    8954             PutByIdVariant variant = data.variants[i];
     9052            PutByVariant variant = data.variants[i];
    89559053            for (unsigned j = variant.oldStructure().size(); j--;) {
    89569054                RegisteredStructure structure = m_graph.registerStructure(variant.oldStructure()[j]);
     
    89679065            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
    89689066           
    8969             PutByIdVariant variant = data.variants[i];
     9067            PutByVariant variant = data.variants[i];
    89709068
    89719069            LValue storage;
    8972             if (variant.kind() == PutByIdVariant::Replace) {
     9070            if (variant.kind() == PutByVariant::Replace) {
    89739071                if (isInlineOffset(variant.offset()))
    89749072                    storage = base;
     
    89769074                    storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
    89779075            } else {
    8978                 DFG_ASSERT(m_graph, m_node, variant.kind() == PutByIdVariant::Transition, variant.kind());
     9076                DFG_ASSERT(m_graph, m_node, variant.kind() == PutByVariant::Transition, variant.kind());
    89799077                m_graph.m_plan.transitions().addLazily(
    89809078                    m_origin.semantic.codeOriginOwner(),
     
    89889086            storeProperty(value, storage, data.identifierNumber, variant.offset());
    89899087           
    8990             if (variant.kind() == PutByIdVariant::Transition) {
     9088            if (variant.kind() == PutByVariant::Transition) {
    89919089                ASSERT(variant.oldStructureForTransition()->indexingType() == variant.newStructure()->indexingType());
    89929090                ASSERT(variant.oldStructureForTransition()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
  • trunk/Source/JavaScriptCore/generator/DSL.rb

    r280760 r281615  
    142142#include "Opcode.h"
    143143#include "PrivateFieldPutKind.h"
    144 #include "PutByIdStatus.h"
     144#include "PutByStatus.h"
    145145#include "PutByIdFlags.h"
    146146#include "ToThisStatus.h"
  • trunk/Source/JavaScriptCore/jit/ICStats.h

    r278445 r281615  
    6868    macro(OperationPutByIdDefinePrivateFieldFieldStrictOptimize) \
    6969    macro(OperationPutByIdPutPrivateFieldFieldStrictOptimize) \
    70     macro(PutByIdAddAccessCase) \
    71     macro(PutByIdReplaceWithJump) \
    72     macro(PutByIdSelfPatch) \
    73     macro(InByIdSelfPatch) \
     70    macro(PutByAddAccessCase) \
     71    macro(PutByReplaceWithJump) \
     72    macro(PutBySelfPatch) \
     73    macro(InBySelfPatch) \
    7474    macro(DelByReplaceWithJump) \
    7575    macro(DelByReplaceWithGeneric) \
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r280760 r281615  
    511511    m_getByIdWithThisIndex = 0;
    512512    m_putByIdIndex = 0;
     513    m_putByValIndex = 0;
    513514    m_inByIdIndex = 0;
    514515    m_inByValIndex = 0;
     
    663664    RELEASE_ASSERT(m_getByIdWithThisIndex == m_getByIdsWithThis.size());
    664665    RELEASE_ASSERT(m_putByIdIndex == m_putByIds.size());
     666    RELEASE_ASSERT(m_putByValIndex == m_putByVals.size());
    665667    RELEASE_ASSERT(m_inByIdIndex == m_inByIds.size());
    666668    RELEASE_ASSERT(m_instanceOfIndex == m_instanceOfs.size());
     
    910912    finalizeInlineCaches(m_getByIdsWithThis, patchBuffer);
    911913    finalizeInlineCaches(m_putByIds, patchBuffer);
     914    finalizeInlineCaches(m_putByVals, patchBuffer);
    912915    finalizeInlineCaches(m_delByIds, patchBuffer);
    913916    finalizeInlineCaches(m_delByVals, patchBuffer);
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r281454 r281615  
    226226        }
    227227       
    228         static void compilePutByVal(const ConcurrentJSLocker& locker, VM& vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
    229         {
    230             JIT jit(vm, codeBlock);
    231             jit.m_bytecodeIndex = byValInfo->bytecodeIndex;
    232             jit.privateCompilePutByVal<OpPutByVal>(locker, byValInfo, returnAddress, arrayMode);
    233         }
    234        
    235         static void compileDirectPutByVal(const ConcurrentJSLocker& locker, VM& vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
    236         {
    237             JIT jit(vm, codeBlock);
    238             jit.m_bytecodeIndex = byValInfo->bytecodeIndex;
    239             jit.privateCompilePutByVal<OpPutByValDirect>(locker, byValInfo, returnAddress, arrayMode);
    240         }
    241 
    242         template<typename Op>
    243         static void compilePutByValWithCachedId(VM& vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, PutKind putKind, CacheableIdentifier propertyName)
    244         {
    245             JIT jit(vm, codeBlock);
    246             jit.m_bytecodeIndex = byValInfo->bytecodeIndex;
    247             jit.privateCompilePutByValWithCachedId<Op>(byValInfo, returnAddress, putKind, propertyName);
    248         }
    249 
    250228        static void compilePutPrivateNameWithCachedId(VM& vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, CacheableIdentifier propertyName)
    251229        {
     
    268246        CompilationResult privateCompile(JITCompilationEffort);
    269247       
    270         void privateCompileGetByVal(const ConcurrentJSLocker&, ByValInfo*, ReturnAddressPtr, JITArrayMode);
    271         template<typename Op>
    272         void privateCompilePutByVal(const ConcurrentJSLocker&, ByValInfo*, ReturnAddressPtr, JITArrayMode);
    273         template<typename Op>
    274         void privateCompilePutByValWithCachedId(ByValInfo*, ReturnAddressPtr, PutKind, CacheableIdentifier);
    275 
    276248        void privateCompilePutPrivateNameWithCachedId(ByValInfo*, ReturnAddressPtr, CacheableIdentifier);
    277 
    278         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
    279249
    280250        // Add a call out from JIT code, without an exception check.
     
    383353
    384354        void emitArrayProfilingSiteWithCell(RegisterID cellGPR, ArrayProfile*, RegisterID scratchGPR);
     355        void emitArrayProfilingSiteWithCell(RegisterID cellGPR, RegisterID arrayProfileGPR, RegisterID scratchGPR);
    385356        void emitArrayProfileStoreToHoleSpecialCase(ArrayProfile*);
    386357        void emitArrayProfileOutOfBoundsSpecialCase(ArrayProfile*);
    387        
    388         JITArrayMode chooseArrayMode(ArrayProfile*);
    389        
    390         // Property is in regT1, base is in regT0. regT2 contains indecing type.
    391         // The value to store is not yet loaded. Property is int-checked and
    392         // zero-extended. Base is cell checked. Structure is already profiled.
    393         // returns the slow cases.
    394         template<typename Op>
    395         JumpList emitInt32PutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo)
    396         {
    397             return emitGenericContiguousPutByVal(bytecode, badType, byValInfo, Int32Shape);
    398         }
    399         template<typename Op>
    400         JumpList emitDoublePutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo)
    401         {
    402             return emitGenericContiguousPutByVal(bytecode, badType, byValInfo, DoubleShape);
    403         }
    404         template<typename Op>
    405         JumpList emitContiguousPutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo)
    406         {
    407             return emitGenericContiguousPutByVal(bytecode, badType, byValInfo);
    408         }
    409         template<typename Op>
    410         JumpList emitGenericContiguousPutByVal(Op, PatchableJump& badType, ByValInfo*, IndexingType indexingShape = ContiguousShape);
    411         template<typename Op>
    412         JumpList emitArrayStoragePutByVal(Op, PatchableJump& badType, ByValInfo*);
    413         template<typename Op>
    414         JumpList emitIntTypedArrayPutByVal(Op, PatchableJump& badType, ByValInfo*, TypedArrayType);
    415         template<typename Op>
    416         JumpList emitFloatTypedArrayPutByVal(Op, PatchableJump& badType, ByValInfo*, TypedArrayType);
    417358
    418359        template<typename Op>
     
    10651006        Vector<JITGetByIdWithThisGenerator> m_getByIdsWithThis;
    10661007        Vector<JITPutByIdGenerator> m_putByIds;
     1008        Vector<JITPutByValGenerator> m_putByVals;
    10671009        Vector<JITInByIdGenerator> m_inByIds;
    10681010        Vector<JITInByValGenerator> m_inByVals;
     
    10921034        unsigned m_getByIdWithThisIndex { UINT_MAX };
    10931035        unsigned m_putByIdIndex { UINT_MAX };
     1036        unsigned m_putByValIndex { UINT_MAX };
    10941037        unsigned m_inByIdIndex { UINT_MAX };
    10951038        unsigned m_inByValIndex { UINT_MAX };
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp

    r279105 r281615  
    143143    JSValueRegs base, JSValueRegs value, GPRReg stubInfoGPR, GPRReg scratch,
    144144    ECMAMode ecmaMode, PutKind putKind)
    145         : JITByIdGenerator(codeBlock, jitType, codeOrigin, callSite, AccessType::Put, usedRegisters, base, value, stubInfoGPR)
     145        : JITByIdGenerator(codeBlock, jitType, codeOrigin, callSite, AccessType::PutById, usedRegisters, base, value, stubInfoGPR)
    146146        , m_ecmaMode(ecmaMode)
    147147        , m_putKind(putKind)
     
    382382}
    383383
     384JITPutByValGenerator::JITPutByValGenerator(CodeBlock* codeBlock, JITType jitType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, AccessType accessType, const RegisterSet& usedRegisters, JSValueRegs base, JSValueRegs property, JSValueRegs value, GPRReg arrayProfileGPR, GPRReg stubInfoGPR)
     385    : Base(codeBlock, jitType, codeOrigin, callSiteIndex, accessType, usedRegisters)
     386    , m_base(base)
     387    , m_value(value)
     388{
     389    m_stubInfo->hasConstantIdentifier = false;
     390
     391    m_stubInfo->baseGPR = base.payloadGPR();
     392    m_stubInfo->regs.propertyGPR = property.payloadGPR();
     393    m_stubInfo->valueGPR = value.payloadGPR();
     394    m_stubInfo->m_stubInfoGPR = stubInfoGPR;
     395    m_stubInfo->m_arrayProfileGPR = arrayProfileGPR;
     396#if USE(JSVALUE32_64)
     397    m_stubInfo->baseTagGPR = base.tagGPR();
     398    m_stubInfo->valueTagGPR = value.tagGPR();
     399    m_stubInfo->v.propertyTagGPR = property.tagGPR();
     400#endif
     401}
     402
     403void JITPutByValGenerator::generateFastPath(MacroAssembler& jit)
     404{
     405    m_start = jit.label();
     406    if (JITCode::useDataIC(m_jitType)) {
     407        jit.move(CCallHelpers::TrustedImmPtr(m_stubInfo), m_stubInfo->m_stubInfoGPR);
     408        jit.call(CCallHelpers::Address(m_stubInfo->m_stubInfoGPR, StructureStubInfo::offsetOfCodePtr()), JITStubRoutinePtrTag);
     409    } else
     410        m_slowPathJump = jit.patchableJump();
     411    m_done = jit.label();
     412}
     413
     414void JITPutByValGenerator::finalize(LinkBuffer& fastPath, LinkBuffer& slowPath)
     415{
     416    Base::finalize(fastPath, slowPath, fastPath.locationOf<JITStubRoutinePtrTag>(m_start));
     417    if (JITCode::useDataIC(m_jitType))
     418        m_stubInfo->m_codePtr = m_stubInfo->slowPathStartLocation;
     419}
     420
    384421JITPrivateBrandAccessGenerator::JITPrivateBrandAccessGenerator(CodeBlock* codeBlock, JITType jitType, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex, AccessType accessType, const RegisterSet& usedRegisters, JSValueRegs base, JSValueRegs brand, GPRReg stubInfoGPR)
    385422    : Base(codeBlock, jitType, codeOrigin, callSiteIndex, accessType, usedRegisters)
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h

    r279105 r281615  
    130130class JITPutByIdGenerator final : public JITByIdGenerator {
    131131public:
    132     JITPutByIdGenerator()
    133         : m_ecmaMode(ECMAMode::strict())
    134     { }
     132    JITPutByIdGenerator() = default;
    135133
    136134    JITPutByIdGenerator(
     
    143141
    144142private:
    145     ECMAMode m_ecmaMode;
     143    ECMAMode m_ecmaMode { ECMAMode::strict() };
    146144    PutKind m_putKind;
     145};
     146
     147class JITPutByValGenerator final : public JITInlineCacheGenerator {
     148    using Base = JITInlineCacheGenerator;
     149public:
     150    JITPutByValGenerator() = default;
     151
     152    JITPutByValGenerator(
     153        CodeBlock*, JITType, CodeOrigin, CallSiteIndex, AccessType, const RegisterSet& usedRegisters,
     154        JSValueRegs base, JSValueRegs property, JSValueRegs result, GPRReg arrayProfileGPR, GPRReg stubInfoGPR);
     155
     156    MacroAssembler::Jump slowPathJump() const
     157    {
     158        ASSERT(m_slowPathJump.m_jump.isSet());
     159        return m_slowPathJump.m_jump;
     160    }
     161
     162    void finalize(LinkBuffer& fastPathLinkBuffer, LinkBuffer& slowPathLinkBuffer);
     163
     164    void generateFastPath(MacroAssembler&);
     165
     166private:
     167    JSValueRegs m_base;
     168    JSValueRegs m_value;
     169
     170    MacroAssembler::Label m_start;
     171    MacroAssembler::PatchableJump m_slowPathJump;
    147172};
    148173
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r281454 r281615  
    353353}
    354354
     355inline void JIT::emitArrayProfilingSiteWithCell(RegisterID cellGPR, RegisterID arrayProfileGPR, RegisterID scratchGPR)
     356{
     357    if (shouldEmitProfiling()) {
     358        load32(MacroAssembler::Address(cellGPR, JSCell::structureIDOffset()), scratchGPR);
     359        store32(scratchGPR, Address(arrayProfileGPR, ArrayProfile::offsetOfLastSeenStructureID()));
     360    }
     361}
     362
    355363inline void JIT::emitArrayProfileStoreToHoleSpecialCase(ArrayProfile* arrayProfile)
    356364{
     
    361369{
    362370    store8(TrustedImm32(1), arrayProfile->addressOfOutOfBounds());
    363 }
    364 
    365 inline JITArrayMode JIT::chooseArrayMode(ArrayProfile* profile)
    366 {
    367     auto arrayProfileSaw = [] (ArrayModes arrayModes, IndexingType capability) {
    368         return arrayModesIncludeIgnoringTypedArrays(arrayModes, capability);
    369     };
    370 
    371     ConcurrentJSLocker locker(m_codeBlock->m_lock);
    372     profile->computeUpdatedPrediction(locker, m_codeBlock);
    373     ArrayModes arrayModes = profile->observedArrayModes(locker);
    374     if (arrayProfileSaw(arrayModes, DoubleShape))
    375         return JITDouble;
    376     if (arrayProfileSaw(arrayModes, Int32Shape))
    377         return JITInt32;
    378     if (arrayProfileSaw(arrayModes, ArrayStorageShape))
    379         return JITArrayStorage;
    380     return JITContiguous;
    381371}
    382372
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r281222 r281615  
    720720   
    721721    if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
    722         repatchPutByID(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutKind::NotDirect);
     722        repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect);
    723723}
    724724
     
    752752   
    753753    if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
    754         repatchPutByID(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutKind::NotDirect);
     754        repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::NotDirect);
    755755}
    756756
     
    783783   
    784784    if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
    785         repatchPutByID(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutKind::Direct);
     785        repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct);
    786786}
    787787
     
    814814   
    815815    if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
    816         repatchPutByID(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutKind::Direct);
     816        repatchPutBy(globalObject, codeBlock, baseObject, structure, identifier, slot, *stubInfo, PutByKind::ById, PutKind::Direct);
    817817}
    818818
     
    889889
    890890        if (stubInfo->considerCachingBy(vm, codeBlock, oldStructure, identifier))
    891             repatchPutByID(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutKind::DirectPrivateFieldDefine);
     891            repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldDefine);
    892892    });
    893893}
     
    925925
    926926        if (stubInfo->considerCachingBy(vm, codeBlock, oldStructure, identifier))
    927             repatchPutByID(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutKind::DirectPrivateFieldSet);
     927            repatchPutBy(globalObject, codeBlock, baseObject, oldStructure, identifier, putSlot, *stubInfo, PutByKind::ById, PutKind::DirectPrivateFieldSet);
    928928    });
    929929}
    930930
    931 static void putByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo, ECMAMode ecmaMode)
     931static void putByVal(JSGlobalObject* globalObject, JSValue baseValue, JSValue subscript, JSValue value, ArrayProfile* arrayProfile, ECMAMode ecmaMode)
    932932{
    933933    VM& vm = globalObject->vm();
    934934    auto scope = DECLARE_THROW_SCOPE(vm);
    935935    if (std::optional<uint32_t> index = subscript.tryGetAsUint32Index()) {
    936         byValInfo->tookSlowPath = true;
    937936        uint32_t i = *index;
    938937        if (baseValue.isObject()) {
     
    943942            }
    944943
    945             byValInfo->arrayProfile->setOutOfBounds();
     944            if (arrayProfile)
     945                arrayProfile->setOutOfBounds();
    946946            scope.release();
    947947            object->methodTable(vm)->putByIndex(object, globalObject, i, value, ecmaMode.isStrict());
     
    952952        baseValue.putByIndex(globalObject, i, value, ecmaMode.isStrict());
    953953        return;
    954     }
     954    }
     955
    955956    if (subscript.isNumber()) {
    956         byValInfo->tookSlowPath = true;
    957         if (baseValue.isObject())
    958             byValInfo->arrayProfile->setOutOfBounds();
     957        if (baseValue.isObject()) {
     958            if (arrayProfile)
     959                arrayProfile->setOutOfBounds();
     960        }
    959961    }
    960962
     
    963965    RETURN_IF_EXCEPTION(scope, void());
    964966
    965     if (byValInfo->stubInfo && (!CacheableIdentifier::isCacheableIdentifierCell(subscript) || byValInfo->cachedId.uid() != property))
    966         byValInfo->tookSlowPath = true;
    967 
    968967    scope.release();
    969968    PutPropertySlot slot(baseValue, ecmaMode.isStrict());
     
    971970}
    972971
    973 static void directPutByVal(JSGlobalObject* globalObject, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo, ECMAMode ecmaMode)
     972static void directPutByVal(JSGlobalObject* globalObject, JSObject* baseObject, JSValue subscript, JSValue value, ArrayProfile* arrayProfile, ECMAMode ecmaMode)
    974973{
    975974    VM& vm = globalObject->vm();
     
    977976
    978977    if (std::optional<uint32_t> maybeIndex = subscript.tryGetAsUint32Index()) {
    979         byValInfo->tookSlowPath = true;
    980978        uint32_t index = *maybeIndex;
    981979
     
    989987            FALLTHROUGH;
    990988        default:
    991             byValInfo->arrayProfile->setOutOfBounds();
     989            if (arrayProfile)
     990                arrayProfile->setOutOfBounds();
    992991            break;
    993992        }
     
    10031002
    10041003    if (std::optional<uint32_t> index = parseIndex(property)) {
    1005         byValInfo->tookSlowPath = true;
    10061004        scope.release();
    10071005        baseObject->putDirectIndex(globalObject, index.value(), value, 0, ecmaMode.isStrict() ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    10081006        return;
    10091007    }
    1010 
    1011     if (byValInfo->stubInfo && (!CacheableIdentifier::isCacheableIdentifierCell(subscript) || byValInfo->cachedId.uid() != property))
    1012         byValInfo->tookSlowPath = true;
    10131008
    10141009    scope.release();
     
    10241019};
    10251020
    1026 static OptimizationResult tryPutByValOptimize(JSGlobalObject* globalObject, CallFrame* callFrame, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
    1027 {
    1028     UNUSED_PARAM(callFrame);
    1029 
    1030     // See if it's worth optimizing at all.
    1031     OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
    1032 
    1033     VM& vm = globalObject->vm();
    1034     auto scope = DECLARE_THROW_SCOPE(vm);
    1035 
    1036     if (baseValue.isObject() && isCopyOnWrite(baseValue.getObject()->indexingMode()))
    1037         return OptimizationResult::GiveUp;
    1038 
    1039     if (baseValue.isObject() && subscript.isInt32()) {
    1040         JSObject* object = asObject(baseValue);
    1041 
    1042         ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
    1043         ASSERT(!byValInfo->stubRoutine);
    1044 
    1045         Structure* structure = object->structure(vm);
    1046         if (hasOptimizableIndexing(structure)) {
    1047             // Attempt to optimize.
    1048             JITArrayMode arrayMode = jitArrayModeForStructure(structure);
    1049             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
    1050                 ConcurrentJSLocker locker(codeBlock->m_lock);
    1051                 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
    1052                 JIT::compilePutByVal(locker, vm, codeBlock, byValInfo, returnAddress, arrayMode);
    1053                 optimizationResult = OptimizationResult::Optimized;
     1021static ALWAYS_INLINE void putByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode)
     1022{
     1023    VM& vm = globalObject->vm();
     1024    auto scope = DECLARE_THROW_SCOPE(vm);
     1025
     1026    if (baseValue.isObject()) {
     1027        JSObject* baseObject = asObject(baseValue);
     1028        if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
     1029            Structure* structure = baseObject->structure(vm);
     1030            if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
     1031                if (profile) {
     1032                    ConcurrentJSLocker locker(codeBlock->m_lock);
     1033                    profile->computeUpdatedPrediction(locker, codeBlock, structure);
     1034                }
     1035                repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::NotDirect, ecmaMode);
    10541036            }
    10551037        }
    10561038
    1057         // If we failed to patch and we have some object that intercepts indexed get, then don't even wait until 10 times.
    1058         if (optimizationResult != OptimizationResult::Optimized && object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
    1059             optimizationResult = OptimizationResult::GiveUp;
    1060     }
    1061 
    1062     if (baseValue.isObject() && CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
    1063         const Identifier propertyName = subscript.toPropertyKey(globalObject);
    1064         RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp);
    1065         if (subscript.isSymbol() || !parseIndex(propertyName)) {
    1066             ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
    1067             ASSERT(!byValInfo->stubRoutine);
    1068             if (byValInfo->seen) {
    1069                 if (byValInfo->cachedId.uid() == propertyName) {
    1070                     JIT::compilePutByValWithCachedId<OpPutByVal>(vm, codeBlock, byValInfo, returnAddress, PutKind::NotDirect, byValInfo->cachedId);
    1071                     optimizationResult = OptimizationResult::Optimized;
    1072                 } else {
    1073                     // Seem like a generic property access site.
    1074                     optimizationResult = OptimizationResult::GiveUp;
    1075                 }
    1076             } else {
    1077                 {
    1078                     ConcurrentJSLocker locker(codeBlock->m_lock);
    1079                     byValInfo->seen = true;
    1080                     byValInfo->cachedId = CacheableIdentifier::createFromCell(subscript.asCell());
    1081                     optimizationResult = OptimizationResult::SeenOnce;
    1082                 }
    1083                 vm.heap.writeBarrier(codeBlock, subscript.asCell());
     1039        if (CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
     1040            const Identifier propertyName = subscript.toPropertyKey(globalObject);
     1041            RETURN_IF_EXCEPTION(scope, void());
     1042            if (subscript.isSymbol() || !parseIndex(propertyName)) {
     1043                AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
     1044                PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext());
     1045
     1046                Structure* structure = CommonSlowPaths::originalStructureBeforePut(vm, baseValue);
     1047                baseObject->putInline(globalObject, propertyName, value, slot);
     1048                RETURN_IF_EXCEPTION(scope, void());
     1049
     1050                if (accessType != static_cast<AccessType>(stubInfo->accessType))
     1051                    return;
     1052
     1053                CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
     1054                if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
     1055                    repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::NotDirect);
     1056                return;
    10841057            }
    10851058        }
    10861059    }
    10871060
    1088     if (optimizationResult != OptimizationResult::Optimized && optimizationResult != OptimizationResult::SeenOnce) {
    1089         // If we take slow path more than 10 times without patching then make sure we
    1090         // never make that mistake again. For cases where we see non-index-intercepting
    1091         // objects, this gives 10 iterations worth of opportunity for us to observe
    1092         // that the put_by_val may be polymorphic. We count up slowPathCount even if
    1093         // the result is GiveUp.
    1094         if (++byValInfo->slowPathCount >= 10)
    1095             optimizationResult = OptimizationResult::GiveUp;
    1096     }
    1097 
    1098     return optimizationResult;
    1099 }
    1100 
    1101 JSC_DEFINE_JIT_OPERATION(operationPutByValOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo, ECMAMode ecmaMode))
    1102 {
    1103     VM& vm = globalObject->vm();
    1104     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    1105     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    1106     auto scope = DECLARE_THROW_SCOPE(vm);
     1061    RELEASE_AND_RETURN(scope, putByVal(globalObject, baseValue, subscript, value, profile, ecmaMode));
     1062}
     1063
     1064JSC_DEFINE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1065{
     1066    VM& vm = globalObject->vm();
     1067    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1068    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    11071069
    11081070    JSValue baseValue = JSValue::decode(encodedBaseValue);
    11091071    JSValue subscript = JSValue::decode(encodedSubscript);
    11101072    JSValue value = JSValue::decode(encodedValue);
    1111     CodeBlock* codeBlock = callFrame->codeBlock();
    1112     OptimizationResult result = tryPutByValOptimize(globalObject, callFrame, codeBlock, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
    1113     RETURN_IF_EXCEPTION(scope, void());
    1114     if (result == OptimizationResult::GiveUp) {
    1115         // Don't ever try to optimize.
    1116         byValInfo->tookSlowPath = true;
    1117         if (codeBlock->useDataIC())
    1118             byValInfo->m_slowOperation = operationPutByValGeneric;
    1119         else
    1120             ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), operationPutByValGeneric);
    1121     }
    1122     RELEASE_AND_RETURN(scope, putByVal(globalObject, baseValue, subscript, value, byValInfo, ecmaMode));
    1123 }
    1124 
    1125 static OptimizationResult tryDirectPutByValOptimize(JSGlobalObject* globalObject, CallFrame* callFrame, CodeBlock* codeBlock, JSObject* object, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
    1126 {
    1127     UNUSED_PARAM(callFrame);
    1128 
    1129     // See if it's worth optimizing at all.
    1130     OptimizationResult optimizationResult = OptimizationResult::NotOptimized;
    1131 
    1132     VM& vm = globalObject->vm();
    1133     auto scope = DECLARE_THROW_SCOPE(vm);
    1134 
    1135     if (subscript.isInt32()) {
    1136         ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
    1137         ASSERT(!byValInfo->stubRoutine);
    1138 
    1139         Structure* structure = object->structure(vm);
    1140         if (hasOptimizableIndexing(structure)) {
    1141             // Attempt to optimize.
    1142             JITArrayMode arrayMode = jitArrayModeForStructure(structure);
    1143             if (jitArrayModePermitsPutDirect(arrayMode) && arrayMode != byValInfo->arrayMode) {
     1073
     1074    putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict());
     1075}
     1076
     1077JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1078{
     1079    VM& vm = globalObject->vm();
     1080    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1081    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1082
     1083    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1084    JSValue subscript = JSValue::decode(encodedSubscript);
     1085    JSValue value = JSValue::decode(encodedValue);
     1086
     1087    putByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy());
     1088}
     1089
     1090static ALWAYS_INLINE void directPutByValOptimize(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue subscript, JSValue value, StructureStubInfo* stubInfo, ArrayProfile* profile, ECMAMode ecmaMode)
     1091{
     1092    VM& vm = globalObject->vm();
     1093    auto scope = DECLARE_THROW_SCOPE(vm);
     1094
     1095    RELEASE_ASSERT(baseValue.isObject());
     1096    JSObject* baseObject = asObject(baseValue);
     1097
     1098    if (!isCopyOnWrite(baseObject->indexingMode()) && subscript.isInt32()) {
     1099        Structure* structure = baseObject->structure(vm);
     1100        if (stubInfo->considerCachingGeneric(vm, codeBlock, structure)) {
     1101            if (profile) {
    11441102                ConcurrentJSLocker locker(codeBlock->m_lock);
    1145                 byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
    1146 
    1147                 JIT::compileDirectPutByVal(locker, vm, codeBlock, byValInfo, returnAddress, arrayMode);
    1148                 optimizationResult = OptimizationResult::Optimized;
     1103                profile->computeUpdatedPrediction(locker, codeBlock, structure);
    11491104            }
     1105            repatchArrayPutByVal(globalObject, codeBlock, baseValue, subscript, *stubInfo, PutKind::Direct, ecmaMode);
    11501106        }
    1151 
    1152         // If we failed to patch and we have some object that intercepts indexed get, then don't even wait until 10 times.
    1153         if (optimizationResult != OptimizationResult::Optimized && object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
    1154             optimizationResult = OptimizationResult::GiveUp;
    1155     } else if (CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
     1107    }
     1108
     1109    if (CacheableIdentifier::isCacheableIdentifierCell(subscript)) {
    11561110        const Identifier propertyName = subscript.toPropertyKey(globalObject);
    1157         RETURN_IF_EXCEPTION(scope, OptimizationResult::GiveUp);
     1111        RETURN_IF_EXCEPTION(scope, void());
    11581112        if (subscript.isSymbol() || !parseIndex(propertyName)) {
    1159             ASSERT(callFrame->bytecodeIndex() != BytecodeIndex(0));
    1160             ASSERT(!byValInfo->stubRoutine);
    1161             if (byValInfo->seen) {
    1162                 if (byValInfo->cachedId.uid() == propertyName) {
    1163                     JIT::compilePutByValWithCachedId<OpPutByValDirect>(vm, codeBlock, byValInfo, returnAddress, PutKind::Direct, byValInfo->cachedId);
    1164                     optimizationResult = OptimizationResult::Optimized;
    1165                 } else {
    1166                     // Seem like a generic property access site.
    1167                     optimizationResult = OptimizationResult::GiveUp;
    1168                 }
    1169             } else {
    1170                 {
    1171                     ConcurrentJSLocker locker(codeBlock->m_lock);
    1172                     byValInfo->seen = true;
    1173                     byValInfo->cachedId = CacheableIdentifier::createFromCell(subscript.asCell());
    1174                     optimizationResult = OptimizationResult::SeenOnce;
    1175                 }
    1176                 vm.heap.writeBarrier(codeBlock, subscript.asCell());
    1177             }
     1113            AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
     1114            PutPropertySlot slot(baseValue, ecmaMode.isStrict(), codeBlock->putByIdContext());
     1115
     1116            Structure* structure = CommonSlowPaths::originalStructureBeforePut(vm, baseValue);
     1117            CommonSlowPaths::putDirectWithReify(vm, globalObject, baseObject, propertyName, value, slot);
     1118
     1119            RETURN_IF_EXCEPTION(scope, void());
     1120
     1121            if (accessType != static_cast<AccessType>(stubInfo->accessType))
     1122                return;
     1123
     1124            CacheableIdentifier identifier = CacheableIdentifier::createFromCell(subscript.asCell());
     1125            if (stubInfo->considerCachingBy(vm, codeBlock, structure, identifier))
     1126                repatchPutBy(globalObject, codeBlock, baseValue, structure, identifier, slot, *stubInfo, PutByKind::ByVal, PutKind::Direct);
     1127            return;
    11781128        }
    11791129    }
    11801130
    1181     if (optimizationResult != OptimizationResult::Optimized && optimizationResult != OptimizationResult::SeenOnce) {
    1182         // If we take slow path more than 10 times without patching then make sure we
    1183         // never make that mistake again. For cases where we see non-index-intercepting
    1184         // objects, this gives 10 iterations worth of opportunity for us to observe
    1185         // that the get_by_val may be polymorphic. We count up slowPathCount even if
    1186         // the result is GiveUp.
    1187         if (++byValInfo->slowPathCount >= 10)
    1188             optimizationResult = OptimizationResult::GiveUp;
    1189     }
    1190 
    1191     return optimizationResult;
    1192 }
    1193 
    1194 JSC_DEFINE_JIT_OPERATION(operationDirectPutByValOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo, ECMAMode ecmaMode))
    1195 {
    1196     VM& vm = globalObject->vm();
    1197     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    1198     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    1199     auto scope = DECLARE_THROW_SCOPE(vm);
     1131    RELEASE_AND_RETURN(scope, directPutByVal(globalObject, baseObject, subscript, value, profile, ecmaMode));
     1132
     1133}
     1134
     1135JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1136{
     1137    VM& vm = globalObject->vm();
     1138    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1139    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1140
     1141    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1142    JSValue subscript = JSValue::decode(encodedSubscript);
     1143    JSValue value = JSValue::decode(encodedValue);
     1144
     1145    directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::strict());
     1146}
     1147
     1148JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictOptimize, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1149{
     1150    VM& vm = globalObject->vm();
     1151    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1152    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1153
     1154    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1155    JSValue subscript = JSValue::decode(encodedSubscript);
     1156    JSValue value = JSValue::decode(encodedValue);
     1157
     1158    directPutByValOptimize(globalObject, callFrame->codeBlock(), baseValue, subscript, value, stubInfo, profile, ECMAMode::sloppy());
     1159}
     1160
     1161JSC_DEFINE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1162{
     1163    VM& vm = globalObject->vm();
     1164    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1165    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1166
     1167    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1168    JSValue subscript = JSValue::decode(encodedSubscript);
     1169    JSValue value = JSValue::decode(encodedValue);
     1170
     1171    stubInfo->tookSlowPath = true;
     1172
     1173    putByVal(globalObject, baseValue, subscript, value, profile, ECMAMode::strict());
     1174}
     1175
     1176JSC_DEFINE_JIT_OPERATION(operationPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1177{
     1178    VM& vm = globalObject->vm();
     1179    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1180    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1181
     1182    JSValue baseValue = JSValue::decode(encodedBaseValue);
     1183    JSValue subscript = JSValue::decode(encodedSubscript);
     1184    JSValue value = JSValue::decode(encodedValue);
     1185
     1186    stubInfo->tookSlowPath = true;
     1187
     1188    putByVal(globalObject, baseValue, subscript, value, profile, ECMAMode::sloppy());
     1189}
     1190
     1191JSC_DEFINE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1192{
     1193    VM& vm = globalObject->vm();
     1194    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1195    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    12001196
    12011197    JSValue baseValue = JSValue::decode(encodedBaseValue);
     
    12031199    JSValue value = JSValue::decode(encodedValue);
    12041200    RELEASE_ASSERT(baseValue.isObject());
    1205     JSObject* object = asObject(baseValue);
    1206     CodeBlock* codeBlock = callFrame->codeBlock();
    1207     OptimizationResult result = tryDirectPutByValOptimize(globalObject, callFrame, codeBlock, object, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
    1208     RETURN_IF_EXCEPTION(scope, void());
    1209     if (result == OptimizationResult::GiveUp) {
    1210         // Don't ever try to optimize.
    1211         byValInfo->tookSlowPath = true;
    1212         if (codeBlock->useDataIC())
    1213             byValInfo->m_slowOperation = operationDirectPutByValGeneric;
    1214         else
    1215             ctiPatchCallByReturnAddress(ReturnAddressPtr(OUR_RETURN_ADDRESS), operationDirectPutByValGeneric);
    1216     }
    1217 
    1218     RELEASE_AND_RETURN(scope, directPutByVal(globalObject, object, subscript, value, byValInfo, ecmaMode));
    1219 }
    1220 
    1221 JSC_DEFINE_JIT_OPERATION(operationPutByValGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo, ECMAMode ecmaMode))
    1222 {
    1223     VM& vm = globalObject->vm();
    1224     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    1225     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    1226    
    1227     JSValue baseValue = JSValue::decode(encodedBaseValue);
    1228     JSValue subscript = JSValue::decode(encodedSubscript);
    1229     JSValue value = JSValue::decode(encodedValue);
    1230 
    1231     putByVal(globalObject, baseValue, subscript, value, byValInfo, ecmaMode);
    1232 }
    1233 
    1234 
    1235 JSC_DEFINE_JIT_OPERATION(operationDirectPutByValGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo, ECMAMode ecmaMode))
    1236 {
    1237     VM& vm = globalObject->vm();
    1238     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    1239     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    1240    
     1201
     1202    stubInfo->tookSlowPath = true;
     1203
     1204    directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::strict());
     1205}
     1206
     1207JSC_DEFINE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject* globalObject, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, StructureStubInfo* stubInfo, ArrayProfile* profile))
     1208{
     1209    VM& vm = globalObject->vm();
     1210    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     1211    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     1212
    12411213    JSValue baseValue = JSValue::decode(encodedBaseValue);
    12421214    JSValue subscript = JSValue::decode(encodedSubscript);
    12431215    JSValue value = JSValue::decode(encodedValue);
    12441216    RELEASE_ASSERT(baseValue.isObject());
    1245     directPutByVal(globalObject, asObject(baseValue), subscript, value, byValInfo, ecmaMode);
     1217
     1218    stubInfo->tookSlowPath = true;
     1219
     1220    directPutByVal(globalObject, asObject(baseValue), subscript, value, profile, ECMAMode::sloppy());
    12461221}
    12471222
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r281222 r281615  
    204204JSC_DECLARE_JIT_OPERATION(operationPutPrivateNameOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, PrivateFieldPutKind));
    205205JSC_DECLARE_JIT_OPERATION(operationPutPrivateNameGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, PrivateFieldPutKind));
    206 JSC_DECLARE_JIT_OPERATION(operationPutByValOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, ECMAMode));
    207 JSC_DECLARE_JIT_OPERATION(operationDirectPutByValOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, ECMAMode));
    208 JSC_DECLARE_JIT_OPERATION(operationPutByValGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, ECMAMode));
    209 JSC_DECLARE_JIT_OPERATION(operationDirectPutByValGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*, ECMAMode));
     206
     207JSC_DECLARE_JIT_OPERATION(operationPutByValNonStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     208JSC_DECLARE_JIT_OPERATION(operationPutByValStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     209JSC_DECLARE_JIT_OPERATION(operationDirectPutByValNonStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     210JSC_DECLARE_JIT_OPERATION(operationDirectPutByValStrictOptimize, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     211JSC_DECLARE_JIT_OPERATION(operationPutByValNonStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     212JSC_DECLARE_JIT_OPERATION(operationPutByValStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     213JSC_DECLARE_JIT_OPERATION(operationDirectPutByValStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
     214JSC_DECLARE_JIT_OPERATION(operationDirectPutByValNonStrictGeneric, void, (JSGlobalObject*, EncodedJSValue, EncodedJSValue, EncodedJSValue, StructureStubInfo*, ArrayProfile*));
    210215
    211216JSC_DECLARE_JIT_OPERATION(operationCallEval, EncodedJSValue, (JSGlobalObject*, CallFrame*, ECMAMode));
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r281565 r281615  
    439439    VirtualRegister base = bytecode.m_base;
    440440    VirtualRegister property = bytecode.m_property;
    441     ArrayProfile* profile = &metadata.m_arrayProfile;
    442     ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);
    443 
    444     emitGetVirtualRegister(base, regT0);
    445     bool propertyNameIsIntegerConstant = isOperandConstantInt(property);
    446     if (propertyNameIsIntegerConstant)
    447         move(Imm32(getOperandConstantInt(property)), regT1);
    448     else
    449         emitGetVirtualRegister(property, regT1);
    450 
    451     emitJumpSlowCaseIfNotJSCell(regT0, base);
    452     PatchableJump notIndex;
    453     if (!propertyNameIsIntegerConstant) {
    454         if (JITCode::useDataIC(JITType::BaselineJIT)) {
    455             auto isInt32 = branchIfInt32(regT1);
    456             farJump(AbsoluteAddress(&byValInfo->m_notIndexJumpTarget), JITStubRoutinePtrTag);
    457             isInt32.link(this);
    458         } else {
    459             notIndex = emitPatchableJumpIfNotInt(regT1);
    460             addSlowCase(notIndex);
    461         }
    462         // See comment in op_get_by_val.
    463         zeroExtend32ToWord(regT1, regT1);
    464     }
    465     emitArrayProfilingSiteWithCell(regT0, profile, regT2);
    466 
    467     PatchableJump badType;
    468     JumpList slowCases;
    469 
    470     // FIXME: Maybe we should do this inline?
    471     load8(Address(regT0, JSCell::indexingTypeAndMiscOffset()), regT2);
    472     addSlowCase(branchTest32(NonZero, regT2, TrustedImm32(CopyOnWrite)));
    473     and32(TrustedImm32(IndexingShapeMask), regT2);
    474 
    475     JITArrayMode mode = chooseArrayMode(profile);
    476     switch (mode) {
    477     case JITInt32:
    478         slowCases = emitInt32PutByVal(bytecode, badType, byValInfo);
    479         break;
    480     case JITDouble:
    481         slowCases = emitDoublePutByVal(bytecode, badType, byValInfo);
    482         break;
    483     case JITContiguous:
    484         slowCases = emitContiguousPutByVal(bytecode, badType, byValInfo);
    485         break;
    486     case JITArrayStorage:
    487         slowCases = emitArrayStoragePutByVal(bytecode, badType, byValInfo);
    488         break;
    489     default:
    490         CRASH();
    491         break;
    492     }
    493    
    494     if (!JITCode::useDataIC(JITType::BaselineJIT))
    495         addSlowCase(badType);
    496     addSlowCase(slowCases);
    497    
    498     Label done = label();
    499    
    500     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, notIndex, badType, mode, profile, done, done));
    501 }
    502 
    503 template<typename Op>
    504 JIT::JumpList JIT::emitGenericContiguousPutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo, IndexingType indexingShape)
    505 {
    506     auto& metadata = bytecode.metadata(m_codeBlock);
    507441    VirtualRegister value = bytecode.m_value;
    508442    ArrayProfile* profile = &metadata.m_arrayProfile;
    509    
    510     JumpList slowCases;
    511 
    512     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    513         if (byValInfo) {
    514             auto isCorrectType = branch32(Equal, regT2, TrustedImm32(indexingShape));
    515             farJump(AbsoluteAddress(&byValInfo->m_badTypeJumpTarget), JITStubRoutinePtrTag);
    516             isCorrectType.link(this);
    517         } else
    518             badType = patchableBranch32(NotEqual, regT2, TrustedImm32(indexingShape));
    519     } else
    520         badType = patchableBranch32(NotEqual, regT2, TrustedImm32(indexingShape));
    521 
    522    
    523     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2);
    524     Jump outOfBounds = branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfPublicLength()));
    525 
    526     Label storeResult = label();
    527     emitGetVirtualRegister(value, regT3);
    528     switch (indexingShape) {
    529     case Int32Shape:
    530         slowCases.append(branchIfNotInt32(regT3));
    531         store64(regT3, BaseIndex(regT2, regT1, TimesEight));
    532         break;
    533     case DoubleShape: {
    534         Jump notInt = branchIfNotInt32(regT3);
    535         convertInt32ToDouble(regT3, fpRegT0);
    536         Jump ready = jump();
    537         notInt.link(this);
    538         add64(numberTagRegister, regT3);
    539         move64ToDouble(regT3, fpRegT0);
    540         slowCases.append(branchIfNaN(fpRegT0));
    541         ready.link(this);
    542         storeDouble(fpRegT0, BaseIndex(regT2, regT1, TimesEight));
    543         break;
    544     }
    545     case ContiguousShape:
    546         store64(regT3, BaseIndex(regT2, regT1, TimesEight));
    547         emitWriteBarrier(bytecode.m_base, value, ShouldFilterValue);
    548         break;
    549     default:
    550         CRASH();
    551         break;
    552     }
    553    
    554     Jump done = jump();
    555     outOfBounds.link(this);
    556    
    557     slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfVectorLength())));
    558    
    559     emitArrayProfileStoreToHoleSpecialCase(profile);
    560    
    561     add32(TrustedImm32(1), regT1, regT3);
    562     store32(regT3, Address(regT2, Butterfly::offsetOfPublicLength()));
    563     jump().linkTo(storeResult, this);
    564    
    565     done.link(this);
    566    
    567     return slowCases;
    568 }
    569 
    570 template<typename Op>
    571 JIT::JumpList JIT::emitArrayStoragePutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo)
    572 {
    573     auto& metadata = bytecode.metadata(m_codeBlock);
    574     VirtualRegister value = bytecode.m_value;
    575     ArrayProfile* profile = &metadata.m_arrayProfile;
    576    
    577     JumpList slowCases;
    578    
    579     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    580         if (byValInfo) {
    581             auto isCorrectType = branch32(Equal, regT2, TrustedImm32(ArrayStorageShape));
    582             farJump(AbsoluteAddress(&byValInfo->m_badTypeJumpTarget), JITStubRoutinePtrTag);
    583             isCorrectType.link(this);
    584         } else
    585             badType = patchableBranch32(NotEqual, regT2, TrustedImm32(ArrayStorageShape));
    586     } else
    587         badType = patchableBranch32(NotEqual, regT2, TrustedImm32(ArrayStorageShape));
    588 
    589     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2);
    590     slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset())));
    591 
    592     Jump empty = branchTest64(Zero, BaseIndex(regT2, regT1, TimesEight, ArrayStorage::vectorOffset()));
    593 
    594     Label storeResult(this);
    595     emitGetVirtualRegister(value, regT3);
    596     store64(regT3, BaseIndex(regT2, regT1, TimesEight, ArrayStorage::vectorOffset()));
    597     emitWriteBarrier(bytecode.m_base, value, ShouldFilterValue);
    598     Jump end = jump();
    599    
    600     empty.link(this);
    601     emitArrayProfileStoreToHoleSpecialCase(profile);
    602     add32(TrustedImm32(1), Address(regT2, ArrayStorage::numValuesInVectorOffset()));
    603     branch32(Below, regT1, Address(regT2, ArrayStorage::lengthOffset())).linkTo(storeResult, this);
    604 
    605     add32(TrustedImm32(1), regT1);
    606     store32(regT1, Address(regT2, ArrayStorage::lengthOffset()));
    607     sub32(TrustedImm32(1), regT1);
    608     jump().linkTo(storeResult, this);
    609 
    610     end.link(this);
    611    
    612     return slowCases;
     443
     444    emitGetVirtualRegister(base, regT0);
     445    emitGetVirtualRegister(property, regT1);
     446    emitGetVirtualRegister(value, regT2);
     447    move(TrustedImmPtr(profile), regT3);
     448
     449    emitJumpSlowCaseIfNotJSCell(regT0, base);
     450    emitArrayProfilingSiteWithCell(regT0, regT3, regT4);
     451
     452    JITPutByValGenerator gen(
     453        m_codeBlock, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::PutByVal, RegisterSet::stubUnavailableRegisters(),
     454        JSValueRegs(regT0), JSValueRegs(regT1), JSValueRegs(regT2), regT3, regT4);
     455    if (isOperandConstantInt(property))
     456        gen.stubInfo()->propertyIsInt32 = true;
     457    gen.generateFastPath(*this);
     458    if (!JITCode::useDataIC(JITType::BaselineJIT))
     459        addSlowCase(gen.slowPathJump());
     460    else
     461        addSlowCase();
     462    m_putByVals.append(gen);
     463
     464    // IC can write new Structure without write-barrier if a base is cell.
     465    // FIXME: Use UnconditionalWriteBarrier in Baseline effectively to reduce code size.
     466    // https://bugs.webkit.org/show_bug.cgi?id=209395
     467    emitWriteBarrier(base, ShouldFilterBase);
    613468}
    614469
     
    663518    VirtualRegister value;
    664519    ECMAMode ecmaMode = ECMAMode::strict();
     520    ArrayProfile* profile = nullptr;
    665521
    666522    auto load = [&](auto bytecode) {
     
    669525        value = bytecode.m_value;
    670526        ecmaMode = bytecode.m_ecmaMode;
     527        auto& metadata = bytecode.metadata(m_codeBlock);
     528        profile = &metadata.m_arrayProfile;
    671529    };
    672530
     
    676534        load(currentInstruction->as<OpPutByVal>());
    677535
    678     ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
     536    JITPutByValGenerator& gen = m_putByVals[m_putByValIndex++];
    679537
    680538    linkAllSlowCases(iter);
    681     Label slowPath = label();
     539
     540    Label coldPathBegin = label();
    682541
    683542#if !ENABLE(EXTRA_CTI_THUNKS)
    684     emitGetVirtualRegister(base, regT0);
    685     emitGetVirtualRegister(property, regT1);
    686     emitGetVirtualRegister(value, regT2);
    687     Call call = callOperation(isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize, TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, regT2, byValInfo, TrustedImm32(ecmaMode.value()));
     543    // They are configured in the fast path and not clobbered.
     544    Call call = callOperation(isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize), TrustedImmPtr(m_codeBlock->globalObject()), regT0, regT1, regT2, gen.stubInfo(), regT3);
    688545#else
    689546    VM& vm = this->vm();
     
    691548    ASSERT(BytecodeIndex(bytecodeOffset) == m_bytecodeIndex);
    692549
    693     constexpr GPRReg bytecodeOffsetGPR = argumentGPR0;
     550    // They are configured in the fast path and not clobbered.
     551    // constexpr GPRReg baseGPR = regT0;
     552    // constexpr GPRReg propertyGPR = regT1;
     553    // constexpr GPRReg valueGPR = regT2;
     554    // constexpr GPRReg profileGPR = regT3;
     555    constexpr GPRReg stubInfoGPR = regT4;
     556    constexpr GPRReg bytecodeOffsetGPR = regT5;
    694557    move(TrustedImm32(bytecodeOffset), bytecodeOffsetGPR);
    695 
    696     constexpr GPRReg baseGPR = argumentGPR1;
    697     constexpr GPRReg propertyGPR = argumentGPR2;
    698     constexpr GPRReg valuePR = argumentGPR3;
    699     constexpr GPRReg byValInfoGPR = argumentGPR4;
    700     constexpr GPRReg ecmaModeGPR = argumentGPR5;
    701 
    702     emitGetVirtualRegister(base, baseGPR);
    703     emitGetVirtualRegister(property, propertyGPR);
    704     emitGetVirtualRegister(value, valuePR);
    705     move(TrustedImmPtr(byValInfo), byValInfoGPR);
    706     move(TrustedImm32(ecmaMode.value()), ecmaModeGPR);
     558    move(TrustedImmPtr(gen.stubInfo()), stubInfoGPR);
    707559    emitNakedNearCall(vm.getCTIStub(slow_op_put_by_val_prepareCallGenerator).retaggedCode<NoPtrTag>());
    708 
    709560    Call call;
     561    auto operation = isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize);
    710562    if (JITCode::useDataIC(JITType::BaselineJIT))
    711         byValInfo->m_slowOperation = isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize;
    712     else
    713         call = appendCall(isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize);
     563        gen.stubInfo()->m_slowOperation = operation;
     564    else
     565        call = appendCall(operation);
    714566    emitNakedNearCall(vm.getCTIStub(checkExceptionGenerator).retaggedCode<NoPtrTag>());
    715567#endif // ENABLE(EXTRA_CTI_THUNKS)
    716568
    717     m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
    718     m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
    719     m_byValInstructionIndex++;
     569    gen.reportSlowPathCall(coldPathBegin, call);
    720570}
    721571
     
    732582        jit.tagReturnAddress();
    733583
    734     constexpr GPRReg bytecodeOffsetGPR = argumentGPR0;
     584    constexpr GPRReg globalObjectGPR = regT5;
     585    constexpr GPRReg baseGPR = regT0;
     586    constexpr GPRReg propertyGPR = regT1;
     587    constexpr GPRReg valueGPR = regT2;
     588    constexpr GPRReg stubInfoGPR = regT4;
     589    constexpr GPRReg profileGPR = regT3;
     590    constexpr GPRReg bytecodeOffsetGPR = regT5;
     591
    735592    jit.store32(bytecodeOffsetGPR, tagFor(CallFrameSlot::argumentCountIncludingThis));
    736 
    737     constexpr GPRReg globalObjectGPR = argumentGPR0;
    738     constexpr GPRReg baseGPR = argumentGPR1;
    739     constexpr GPRReg propertyGPR = argumentGPR2;
    740     constexpr GPRReg valuePR = argumentGPR3;
    741     constexpr GPRReg byValInfoGPR = argumentGPR4;
    742     constexpr GPRReg ecmaModeGPR = argumentGPR5;
    743 
    744593    jit.loadPtr(addressFor(CallFrameSlot::codeBlock), globalObjectGPR);
    745594    jit.loadPtr(Address(globalObjectGPR, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
    746595
    747     jit.setupArguments<decltype(operationPutByValOptimize)>(globalObjectGPR, baseGPR, propertyGPR, valuePR, byValInfoGPR, ecmaModeGPR);
     596    jit.setupArguments<decltype(operationPutByValStrictOptimize)>(globalObjectGPR, baseGPR, propertyGPR, valueGPR, stubInfoGPR, profileGPR);
    748597    jit.prepareCallOperation(vm);
    749598
    750599    if (JITCode::useDataIC(JITType::BaselineJIT))
    751         jit.farJump(Address(argumentGPR4, ByValInfo::offsetOfSlowOperation()), OperationPtrTag);
     600        jit.farJump(Address(argumentGPR4, StructureStubInfo::offsetOfSlowOperation()), OperationPtrTag);
    752601    else
    753602        jit.ret();
     
    811660    constexpr GPRReg baseGPR = argumentGPR1;
    812661    constexpr GPRReg propertyGPR = argumentGPR2;
    813     constexpr GPRReg valuePR = argumentGPR3;
     662    constexpr GPRReg valueGPR = argumentGPR3;
    814663    constexpr GPRReg byValInfoGPR = argumentGPR4;
    815664    constexpr GPRReg putKindGPR = argumentGPR5;
     
    817666    emitGetVirtualRegister(bytecode.m_base, baseGPR);
    818667    emitGetVirtualRegister(bytecode.m_property, propertyGPR);
    819     emitGetVirtualRegister(bytecode.m_value, valuePR);
     668    emitGetVirtualRegister(bytecode.m_value, valueGPR);
    820669    move(TrustedImmPtr(byValInfo), byValInfoGPR);
    821670    move(TrustedImm32(putKind.value()), putKindGPR);
     
    853702    constexpr GPRReg baseGPR = argumentGPR1;
    854703    constexpr GPRReg propertyGPR = argumentGPR2;
    855     constexpr GPRReg valuePR = argumentGPR3;
     704    constexpr GPRReg valueGPR = argumentGPR3;
    856705    constexpr GPRReg byValInfoGPR = argumentGPR4;
    857706    constexpr GPRReg putKindGPR = argumentGPR5;
     
    860709    jit.loadPtr(Address(globalObjectGPR, CodeBlock::offsetOfGlobalObject()), globalObjectGPR);
    861710
    862     jit.setupArguments<decltype(operationPutPrivateNameOptimize)>(globalObjectGPR, baseGPR, propertyGPR, valuePR, byValInfoGPR, putKindGPR);
     711    jit.setupArguments<decltype(operationPutPrivateNameOptimize)>(globalObjectGPR, baseGPR, propertyGPR, valueGPR, byValInfoGPR, putKindGPR);
    863712    jit.prepareCallOperation(vm);
    864713
     
    32923141}
    32933142
    3294 template<typename Op>
    3295 void JIT::privateCompilePutByVal(const ConcurrentJSLocker&, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
    3296 {
    3297     const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr();
    3298     auto bytecode = currentInstruction->as<Op>();
    3299    
    3300     PatchableJump badType;
    3301     JumpList slowCases;
    3302 
    3303     bool needsLinkForWriteBarrier = false;
    3304 
    3305     switch (arrayMode) {
    3306     case JITInt32:
    3307         slowCases = emitInt32PutByVal(bytecode, badType, nullptr);
    3308         break;
    3309     case JITDouble:
    3310         slowCases = emitDoublePutByVal(bytecode, badType, nullptr);
    3311         break;
    3312     case JITContiguous:
    3313         slowCases = emitContiguousPutByVal(bytecode, badType, nullptr);
    3314         needsLinkForWriteBarrier = true;
    3315         break;
    3316     case JITArrayStorage:
    3317         slowCases = emitArrayStoragePutByVal(bytecode, badType, nullptr);
    3318         needsLinkForWriteBarrier = true;
    3319         break;
    3320     default:
    3321         TypedArrayType type = typedArrayTypeForJITArrayMode(arrayMode);
    3322         if (isInt(type))
    3323             slowCases = emitIntTypedArrayPutByVal(bytecode, badType, nullptr, type);
    3324         else {
    3325             // FIXME: Optimize BigInt64Array / BigUint64Array in IC
    3326             // Currently, BigInt64Array / BigUint64Array never comes here.
    3327             // https://bugs.webkit.org/show_bug.cgi?id=221183
    3328             ASSERT(isFloat(type));
    3329             slowCases = emitFloatTypedArrayPutByVal(bytecode, badType, nullptr, type);
    3330         }
    3331         break;
    3332     }
    3333    
    3334     Jump done = jump();
    3335 
    3336     LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache);
    3337     patchBuffer.link(badType, byValInfo->slowPathTarget);
    3338     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
    3339     patchBuffer.link(done, byValInfo->doneTarget);
    3340     if (needsLinkForWriteBarrier) {
    3341         ASSERT(removeCodePtrTag(m_farCalls.last().callee.executableAddress()) == removeCodePtrTag(operationWriteBarrierSlowPath));
    3342         patchBuffer.link(m_farCalls.last().from, m_farCalls.last().callee);
    3343     }
    3344    
    3345     bool isDirect = currentInstruction->opcodeID() == op_put_by_val_direct;
    3346     if (!isDirect) {
    3347         byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
    3348             m_codeBlock, patchBuffer, JITStubRoutinePtrTag,
    3349             "Baseline put_by_val stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue());
    3350        
    3351     } else {
    3352         byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
    3353             m_codeBlock, patchBuffer, JITStubRoutinePtrTag,
    3354             "Baseline put_by_val_direct stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.untaggedValue());
    3355     }
    3356 
    3357     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    3358         byValInfo->m_badTypeJumpTarget = CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code());
    3359         byValInfo->m_slowOperation = isDirect ? operationDirectPutByValGeneric : operationPutByValGeneric;
    3360     } else {
    3361         MacroAssembler::repatchJump(byValInfo->m_badTypeJump, CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code()));
    3362         MacroAssembler::repatchCall(CodeLocationCall<ReturnAddressPtrTag>(MacroAssemblerCodePtr<ReturnAddressPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(isDirect ? operationDirectPutByValGeneric : operationPutByValGeneric));
    3363     }
    3364 }
    3365 // This function is only consumed from another translation unit (JITOperations.cpp),
    3366 // so we list off the two expected specializations in advance.
    3367 template void JIT::privateCompilePutByVal<OpPutByVal>(const ConcurrentJSLocker&, ByValInfo*, ReturnAddressPtr, JITArrayMode);
    3368 template void JIT::privateCompilePutByVal<OpPutByValDirect>(const ConcurrentJSLocker&, ByValInfo*, ReturnAddressPtr, JITArrayMode);
    3369 
    33703143void JIT::privateCompilePutPrivateNameWithCachedId(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, CacheableIdentifier propertyName)
    33713144{
     
    34093182}
    34103183
    3411 template<typename Op>
    3412 void JIT::privateCompilePutByValWithCachedId(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, PutKind putKind, CacheableIdentifier propertyName)
    3413 {
    3414     ASSERT((putKind == PutKind::Direct && Op::opcodeID == op_put_by_val_direct) || (putKind == PutKind::NotDirect && Op::opcodeID == op_put_by_val));
    3415     const Instruction* currentInstruction = m_codeBlock->instructions().at(byValInfo->bytecodeIndex).ptr();
    3416     auto bytecode = currentInstruction->as<Op>();
    3417 
    3418     JumpList doneCases;
    3419     JumpList slowCases;
    3420 
    3421     JITPutByIdGenerator gen = emitPutByValWithCachedId(bytecode, putKind, propertyName, doneCases, slowCases);
    3422 
    3423     ConcurrentJSLocker locker(m_codeBlock->m_lock);
    3424     LinkBuffer patchBuffer(*this, m_codeBlock, LinkBuffer::Profile::InlineCache);
    3425     patchBuffer.link(slowCases, byValInfo->slowPathTarget);
    3426     patchBuffer.link(doneCases, byValInfo->doneTarget);
    3427     if (!m_exceptionChecks.empty())
    3428         patchBuffer.link(m_exceptionChecks, byValInfo->exceptionHandler);
    3429 
    3430     for (const auto& callSite : m_nearCalls) {
    3431         if (callSite.callee)
    3432             patchBuffer.link(callSite.from, callSite.callee);
    3433     }
    3434     for (const auto& callSite : m_farCalls) {
    3435         if (callSite.callee)
    3436             patchBuffer.link(callSite.from, callSite.callee);
    3437     }
    3438     gen.finalize(patchBuffer, patchBuffer);
    3439 
    3440     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
    3441         m_codeBlock, patchBuffer, JITStubRoutinePtrTag,
    3442         "Baseline put_by_val%s with cached property name '%s' stub for %s, return point %p", (putKind == PutKind::Direct) ? "_direct" : "", propertyName.uid()->utf8().data(), toCString(*m_codeBlock).data(), returnAddress.untaggedValue());
    3443     byValInfo->stubInfo = gen.stubInfo();
    3444 
    3445     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    3446         byValInfo->m_notIndexJumpTarget = CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code());
    3447         byValInfo->m_slowOperation = putKind == PutKind::Direct ? operationDirectPutByValGeneric : operationPutByValGeneric;
    3448     } else {
    3449         MacroAssembler::repatchJump(byValInfo->m_notIndexJump, CodeLocationLabel<JITStubRoutinePtrTag>(byValInfo->stubRoutine->code().code()));
    3450         MacroAssembler::repatchCall(CodeLocationCall<ReturnAddressPtrTag>(MacroAssemblerCodePtr<ReturnAddressPtrTag>(returnAddress)), FunctionPtr<OperationPtrTag>(putKind == PutKind::Direct ? operationDirectPutByValGeneric : operationPutByValGeneric));
    3451     }
    3452 }
    3453 // This function is only consumed from another translation unit (JITOperations.cpp),
    3454 // so we list off the two expected specializations in advance.
    3455 template void JIT::privateCompilePutByValWithCachedId<OpPutByVal>(ByValInfo*, ReturnAddressPtr, PutKind, CacheableIdentifier);
    3456 template void JIT::privateCompilePutByValWithCachedId<OpPutByValDirect>(ByValInfo*, ReturnAddressPtr, PutKind, CacheableIdentifier);
    3457 
    3458 template<typename Op>
    3459 JIT::JumpList JIT::emitIntTypedArrayPutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo, TypedArrayType type)
    3460 {
    3461     auto& metadata = bytecode.metadata(m_codeBlock);
    3462     ArrayProfile* profile = &metadata.m_arrayProfile;
    3463     ASSERT(isInt(type));
    3464    
    3465     VirtualRegister value = bytecode.m_value;
    3466 
    3467 #if USE(JSVALUE64)
    3468     RegisterID base = regT0;
    3469     RegisterID property = regT1;
    3470     RegisterID earlyScratch = regT3;
    3471     RegisterID lateScratch = regT2;
    3472     RegisterID lateScratch2 = regT4;
    3473 #else
    3474     RegisterID base = regT0;
    3475     RegisterID property = regT2;
    3476     RegisterID earlyScratch = regT3;
    3477     RegisterID lateScratch = regT1;
    3478     RegisterID lateScratch2 = regT4;
    3479 #endif
    3480    
    3481     JumpList slowCases;
    3482    
    3483     load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
    3484 
    3485     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    3486         if (byValInfo) {
    3487             auto isCorrectType = branch32(Equal, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3488             farJump(AbsoluteAddress(&byValInfo->m_badTypeJumpTarget), JITStubRoutinePtrTag);
    3489             isCorrectType.link(this);
    3490         } else
    3491             badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3492     } else
    3493         badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3494 
    3495     load32(Address(base, JSArrayBufferView::offsetOfLength()), lateScratch2);
    3496     Jump inBounds = branch32(Below, property, lateScratch2);
    3497     emitArrayProfileOutOfBoundsSpecialCase(profile);
    3498     slowCases.append(jump());
    3499     inBounds.link(this);
    3500    
    3501 #if USE(JSVALUE64)
    3502     emitGetVirtualRegister(value, earlyScratch);
    3503     slowCases.append(branchIfNotInt32(earlyScratch));
    3504 #else
    3505     emitLoad(value, lateScratch, earlyScratch);
    3506     slowCases.append(branchIfNotInt32(lateScratch));
    3507 #endif
    3508    
    3509     // We would be loading this into base as in get_by_val, except that the slow
    3510     // path expects the base to be unclobbered.
    3511     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
    3512     cageConditionallyAndUntag(Gigacage::Primitive, lateScratch, lateScratch2, lateScratch2, false);
    3513    
    3514     if (isClamped(type)) {
    3515         ASSERT(elementSize(type) == 1);
    3516         ASSERT(!JSC::isSigned(type));
    3517         Jump inBounds = branch32(BelowOrEqual, earlyScratch, TrustedImm32(0xff));
    3518         Jump tooBig = branch32(GreaterThan, earlyScratch, TrustedImm32(0xff));
    3519         xor32(earlyScratch, earlyScratch);
    3520         Jump clamped = jump();
    3521         tooBig.link(this);
    3522         move(TrustedImm32(0xff), earlyScratch);
    3523         clamped.link(this);
    3524         inBounds.link(this);
    3525     }
    3526    
    3527     switch (elementSize(type)) {
    3528     case 1:
    3529         store8(earlyScratch, BaseIndex(lateScratch, property, TimesOne));
    3530         break;
    3531     case 2:
    3532         store16(earlyScratch, BaseIndex(lateScratch, property, TimesTwo));
    3533         break;
    3534     case 4:
    3535         store32(earlyScratch, BaseIndex(lateScratch, property, TimesFour));
    3536         break;
    3537     default:
    3538         CRASH();
    3539     }
    3540    
    3541     return slowCases;
    3542 }
    3543 
    3544 template<typename Op>
    3545 JIT::JumpList JIT::emitFloatTypedArrayPutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo, TypedArrayType type)
    3546 {
    3547     auto& metadata = bytecode.metadata(m_codeBlock);
    3548     ArrayProfile* profile = &metadata.m_arrayProfile;
    3549     ASSERT(isFloat(type));
    3550    
    3551     VirtualRegister value = bytecode.m_value;
    3552 
    3553 #if USE(JSVALUE64)
    3554     RegisterID base = regT0;
    3555     RegisterID property = regT1;
    3556     RegisterID earlyScratch = regT3;
    3557     RegisterID lateScratch = regT2;
    3558     RegisterID lateScratch2 = regT4;
    3559 #else
    3560     RegisterID base = regT0;
    3561     RegisterID property = regT2;
    3562     RegisterID earlyScratch = regT3;
    3563     RegisterID lateScratch = regT1;
    3564     RegisterID lateScratch2 = regT4;
    3565 #endif
    3566    
    3567     JumpList slowCases;
    3568    
    3569     load8(Address(base, JSCell::typeInfoTypeOffset()), earlyScratch);
    3570 
    3571     if (JITCode::useDataIC(JITType::BaselineJIT)) {
    3572         if (byValInfo) {
    3573             auto isCorrectType = branch32(Equal, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3574             farJump(AbsoluteAddress(&byValInfo->m_badTypeJumpTarget), JITStubRoutinePtrTag);
    3575             isCorrectType.link(this);
    3576         } else
    3577             badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3578     } else
    3579         badType = patchableBranch32(NotEqual, earlyScratch, TrustedImm32(typeForTypedArrayType(type)));
    3580 
    3581     load32(Address(base, JSArrayBufferView::offsetOfLength()), lateScratch2);
    3582     Jump inBounds = branch32(Below, property, lateScratch2);
    3583     emitArrayProfileOutOfBoundsSpecialCase(profile);
    3584     slowCases.append(jump());
    3585     inBounds.link(this);
    3586    
    3587 #if USE(JSVALUE64)
    3588     emitGetVirtualRegister(value, earlyScratch);
    3589     Jump doubleCase = branchIfNotInt32(earlyScratch);
    3590     convertInt32ToDouble(earlyScratch, fpRegT0);
    3591     Jump ready = jump();
    3592     doubleCase.link(this);
    3593     slowCases.append(branchIfNotNumber(earlyScratch));
    3594     add64(numberTagRegister, earlyScratch);
    3595     move64ToDouble(earlyScratch, fpRegT0);
    3596     ready.link(this);
    3597 #else
    3598     emitLoad(value, lateScratch, earlyScratch);
    3599     Jump doubleCase = branchIfNotInt32(lateScratch);
    3600     convertInt32ToDouble(earlyScratch, fpRegT0);
    3601     Jump ready = jump();
    3602     doubleCase.link(this);
    3603     slowCases.append(branch32(Above, lateScratch, TrustedImm32(JSValue::LowestTag)));
    3604     moveIntsToDouble(earlyScratch, lateScratch, fpRegT0);
    3605     ready.link(this);
    3606 #endif
    3607    
    3608     // We would be loading this into base as in get_by_val, except that the slow
    3609     // path expects the base to be unclobbered.
    3610     loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
    3611     cageConditionallyAndUntag(Gigacage::Primitive, lateScratch, lateScratch2, lateScratch2, false);
    3612    
    3613     switch (elementSize(type)) {
    3614     case 4:
    3615         convertDoubleToFloat(fpRegT0, fpRegT0);
    3616         storeFloat(fpRegT0, BaseIndex(lateScratch, property, TimesFour));
    3617         break;
    3618     case 8:
    3619         storeDouble(fpRegT0, BaseIndex(lateScratch, property, TimesEight));
    3620         break;
    3621     default:
    3622         CRASH();
    3623     }
    3624    
    3625     return slowCases;
    3626 }
    3627 
    36283184} // namespace JSC
    36293185
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r281454 r281615  
    467467    VirtualRegister base = bytecode.m_base;
    468468    VirtualRegister property = bytecode.m_property;
    469     ArrayProfile* profile = &metadata.m_arrayProfile;
    470     ByValInfo* byValInfo = m_codeBlock->addByValInfo(m_bytecodeIndex);
    471    
    472     emitLoad2(base, regT1, regT0, property, regT3, regT2);
    473    
    474     emitJumpSlowCaseIfNotJSCell(base, regT1);
    475     PatchableJump notIndex = patchableBranch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag));
    476     addSlowCase(notIndex);
    477     emitArrayProfilingSiteWithCell(regT0, profile, regT1);
    478    
    479     PatchableJump badType;
    480     JumpList slowCases;
    481 
    482     // FIXME: Maybe we should do this inline?
    483     load8(Address(regT0, JSCell::indexingTypeAndMiscOffset()), regT1);
    484     addSlowCase(branchTest32(NonZero, regT1, TrustedImm32(CopyOnWrite)));
    485     and32(TrustedImm32(IndexingShapeMask), regT1);
    486    
    487     JITArrayMode mode = chooseArrayMode(profile);
    488     switch (mode) {
    489     case JITInt32:
    490         slowCases = emitInt32PutByVal(bytecode, badType, byValInfo);
    491         break;
    492     case JITDouble:
    493         slowCases = emitDoublePutByVal(bytecode, badType, byValInfo);
    494         break;
    495     case JITContiguous:
    496         slowCases = emitContiguousPutByVal(bytecode, badType, byValInfo);
    497         break;
    498     case JITArrayStorage:
    499         slowCases = emitArrayStoragePutByVal(bytecode, badType, byValInfo);
    500         break;
    501     default:
    502         CRASH();
    503         break;
    504     }
    505    
    506     addSlowCase(badType);
    507     addSlowCase(slowCases);
    508    
    509     Label done = label();
    510    
    511     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeIndex, notIndex, badType, mode, profile, done, done));
    512 }
    513 
    514 template <typename Op>
    515 JIT::JumpList JIT::emitGenericContiguousPutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo, IndexingType indexingShape)
    516 {
    517     auto& metadata = bytecode.metadata(m_codeBlock);
    518     VirtualRegister base = bytecode.m_base;
    519469    VirtualRegister value = bytecode.m_value;
    520470    ArrayProfile* profile = &metadata.m_arrayProfile;
    521471
    522     JumpList slowCases;
    523    
    524     UNUSED_PARAM(byValInfo);
    525     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ContiguousShape));
    526    
    527     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
    528     Jump outOfBounds = branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength()));
    529    
    530     Label storeResult = label();
    531     emitLoad(value, regT1, regT0);
    532     switch (indexingShape) {
    533     case Int32Shape:
    534         slowCases.append(branchIfNotInt32(regT1));
    535         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
    536         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
    537         break;
    538     case ContiguousShape:
    539         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
    540         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
    541         emitLoad(base, regT2, regT3);
    542         emitWriteBarrier(base, value, ShouldFilterValue);
    543         break;
    544     case DoubleShape: {
    545         Jump notInt = branchIfNotInt32(regT1);
    546         convertInt32ToDouble(regT0, fpRegT0);
    547         Jump ready = jump();
    548         notInt.link(this);
    549         moveIntsToDouble(regT0, regT1, fpRegT0);
    550         slowCases.append(branchIfNaN(fpRegT0));
    551         ready.link(this);
    552         storeDouble(fpRegT0, BaseIndex(regT3, regT2, TimesEight));
    553         break;
    554     }
    555     default:
    556         CRASH();
    557         break;
    558     }
    559        
    560     Jump done = jump();
    561    
    562     outOfBounds.link(this);
    563     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfVectorLength())));
    564    
    565     emitArrayProfileStoreToHoleSpecialCase(profile);
    566    
    567     add32(TrustedImm32(1), regT2, regT1);
    568     store32(regT1, Address(regT3, Butterfly::offsetOfPublicLength()));
    569     jump().linkTo(storeResult, this);
    570    
    571     done.link(this);
    572    
    573     return slowCases;
    574 }
    575 
    576 template <typename Op>
    577 JIT::JumpList JIT::emitArrayStoragePutByVal(Op bytecode, PatchableJump& badType, ByValInfo* byValInfo)
    578 {
    579     auto& metadata = bytecode.metadata(m_codeBlock);
    580     VirtualRegister base = bytecode.m_base;
    581     VirtualRegister value = bytecode.m_value;
    582     ArrayProfile* profile = &metadata.m_arrayProfile;
    583 
    584     JumpList slowCases;
    585    
    586     UNUSED_PARAM(byValInfo);
    587     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(ArrayStorageShape));
    588    
    589     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
    590     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
    591 
    592     Jump empty = branch32(Equal, BaseIndex(regT3, regT2, TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
    593    
    594     Label storeResult(this);
    595     emitLoad(value, regT1, regT0);
    596     store32(regT0, BaseIndex(regT3, regT2, TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); // payload
    597     store32(regT1, BaseIndex(regT3, regT2, TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); // tag
    598     Jump end = jump();
    599    
    600     empty.link(this);
    601     emitArrayProfileStoreToHoleSpecialCase(profile);
    602     add32(TrustedImm32(1), Address(regT3, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
    603     branch32(Below, regT2, Address(regT3, ArrayStorage::lengthOffset())).linkTo(storeResult, this);
    604    
    605     add32(TrustedImm32(1), regT2, regT0);
    606     store32(regT0, Address(regT3, ArrayStorage::lengthOffset()));
    607     jump().linkTo(storeResult, this);
    608    
    609     end.link(this);
    610    
    611     emitWriteBarrier(base, value, ShouldFilterValue);
    612    
    613     return slowCases;
     472    emitLoad2(base, regT1, regT0, property, regT3, regT2);
     473    emitLoad(value, regT5, regT4);
     474    move(TrustedImmPtr(profile), regT6);
     475    emitJumpSlowCaseIfNotJSCell(base, regT1);
     476    emitArrayProfilingSiteWithCell(regT0, regT6, regT7);
     477
     478    JITPutByValGenerator gen(
     479        m_codeBlock, JITType::BaselineJIT, CodeOrigin(m_bytecodeIndex), CallSiteIndex(m_bytecodeIndex), AccessType::PutByVal, RegisterSet::stubUnavailableRegisters(),
     480        JSValueRegs(regT1, regT0), JSValueRegs(regT3, regT2), JSValueRegs(regT5, regT4), regT6, InvalidGPRReg);
     481    gen.generateFastPath(*this);
     482    addSlowCase(gen.slowPathJump());
     483    m_putByVals.append(gen);
     484
     485    // IC can write new Structure without write-barrier if a base is cell.
     486    // FIXME: Use UnconditionalWriteBarrier in Baseline effectively to reduce code size.
     487    // https://bugs.webkit.org/show_bug.cgi?id=209395
     488    emitWriteBarrier(base, ShouldFilterBase);
    614489}
    615490
     
    621496    VirtualRegister value;
    622497    ECMAMode ecmaMode = ECMAMode::strict();
     498    ArrayProfile* profile = nullptr;
    623499
    624500    auto load = [&](auto bytecode) {
     
    627503        value = bytecode.m_value;
    628504        ecmaMode = JIT::ecmaMode(bytecode);
     505        auto& metadata = bytecode.metadata(m_codeBlock);
     506        profile = &metadata.m_arrayProfile;
    629507    };
    630508
     
    634512        load(currentInstruction->as<OpPutByVal>());
    635513
    636     ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
    637    
    638     linkAllSlowCases(iter);
    639     Label slowPath = label();
    640    
     514    JITPutByValGenerator& gen = m_putByVals[m_putByValIndex++];
     515
     516    linkAllSlowCases(iter);
     517
     518    Label coldPathBegin = label();
     519
    641520    // The register selection below is chosen to reduce register swapping on ARM.
    642521    // Swapping shouldn't happen on other platforms.
    643     emitLoad(base, regT2, regT1);
    644     emitLoad(property, regT3, regT0);
     522    emitLoad2(base, regT2, regT1, property, regT3, regT0);
    645523    emitLoad(value, regT5, regT4);
    646     Call call = callOperation(isDirect ? operationDirectPutByValOptimize : operationPutByValOptimize, m_codeBlock->globalObject(), JSValueRegs(regT2, regT1), JSValueRegs(regT3, regT0), JSValueRegs(regT5, regT4), byValInfo, TrustedImm32(ecmaMode.value()));
    647 
    648     m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
    649     m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
    650     m_byValInstructionIndex++;
     524
     525    Call call = callOperation(isDirect ? (ecmaMode.isStrict() ? operationDirectPutByValStrictOptimize : operationDirectPutByValNonStrictOptimize) : (ecmaMode.isStrict() ? operationPutByValStrictOptimize : operationPutByValNonStrictOptimize), TrustedImmPtr(m_codeBlock->globalObject()), JSValueRegs(regT2, regT1), JSValueRegs(regT3, regT0), JSValueRegs(regT5, regT4), gen.stubInfo(), profile);
     526
     527    gen.reportSlowPathCall(coldPathBegin, call);
    651528}
    652529
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r279635 r281615  
    569569}
    570570
    571 static auto appropriateGenericPutByIdFunction(const PutPropertySlot &slot, PutKind putKind) -> decltype(&operationPutByIdDirectStrict)
    572 {
    573     switch (putKind) {
    574     case PutKind::NotDirect:
    575         if (slot.isStrictMode())
    576             return operationPutByIdStrict;
    577         return operationPutByIdNonStrict;
    578     case PutKind::Direct:
    579         if (slot.isStrictMode())
    580             return operationPutByIdDirectStrict;
    581         return operationPutByIdDirectNonStrict;
    582     case PutKind::DirectPrivateFieldDefine:
    583         ASSERT(slot.isStrictMode());
    584         return operationPutByIdDefinePrivateFieldStrict;
    585     case PutKind::DirectPrivateFieldSet:
    586         ASSERT(slot.isStrictMode());
    587         return operationPutByIdSetPrivateFieldStrict;
     571static FunctionPtr<CFunctionPtrTag> appropriateGenericPutByFunction(const PutPropertySlot &slot, PutByKind putByKind, PutKind putKind)
     572{
     573    switch (putByKind) {
     574    case PutByKind::ById: {
     575        switch (putKind) {
     576        case PutKind::NotDirect:
     577            if (slot.isStrictMode())
     578                return operationPutByIdStrict;
     579            return operationPutByIdNonStrict;
     580        case PutKind::Direct:
     581            if (slot.isStrictMode())
     582                return operationPutByIdDirectStrict;
     583            return operationPutByIdDirectNonStrict;
     584        case PutKind::DirectPrivateFieldDefine:
     585            ASSERT(slot.isStrictMode());
     586            return operationPutByIdDefinePrivateFieldStrict;
     587        case PutKind::DirectPrivateFieldSet:
     588            ASSERT(slot.isStrictMode());
     589            return operationPutByIdSetPrivateFieldStrict;
     590        }
     591        break;
     592    }
     593    case PutByKind::ByVal: {
     594        switch (putKind) {
     595        case PutKind::NotDirect:
     596            if (slot.isStrictMode())
     597                return operationPutByValStrictGeneric;
     598            return operationPutByValNonStrictGeneric;
     599        case PutKind::Direct:
     600            if (slot.isStrictMode())
     601                return operationDirectPutByValStrictGeneric;
     602            return operationDirectPutByValNonStrictGeneric;
     603        default:
     604            RELEASE_ASSERT_NOT_REACHED();
     605            break;
     606        }
     607        break;
     608    }
    588609    }
    589610    // Make win port compiler happy
     
    592613}
    593614
    594 static auto appropriateOptimizingPutByIdFunction(const PutPropertySlot &slot, PutKind putKind) -> decltype(&operationPutByIdDirectStrictOptimize)
    595 {
    596     switch (putKind) {
    597     case PutKind::NotDirect:
    598         if (slot.isStrictMode())
    599             return operationPutByIdStrictOptimize;
    600         return operationPutByIdNonStrictOptimize;
    601     case PutKind::Direct:
    602         if (slot.isStrictMode())
    603             return operationPutByIdDirectStrictOptimize;
    604         return operationPutByIdDirectNonStrictOptimize;
    605     case PutKind::DirectPrivateFieldDefine:
    606         ASSERT(slot.isStrictMode());
    607         return operationPutByIdDefinePrivateFieldStrictOptimize;
    608     case PutKind::DirectPrivateFieldSet:
    609         ASSERT(slot.isStrictMode());
    610         return operationPutByIdSetPrivateFieldStrictOptimize;
     615static FunctionPtr<CFunctionPtrTag> appropriateOptimizingPutByFunction(const PutPropertySlot &slot, PutByKind putByKind, PutKind putKind)
     616{
     617    switch (putByKind) {
     618    case PutByKind::ById:
     619        switch (putKind) {
     620        case PutKind::NotDirect:
     621            if (slot.isStrictMode())
     622                return operationPutByIdStrictOptimize;
     623            return operationPutByIdNonStrictOptimize;
     624        case PutKind::Direct:
     625            if (slot.isStrictMode())
     626                return operationPutByIdDirectStrictOptimize;
     627            return operationPutByIdDirectNonStrictOptimize;
     628        case PutKind::DirectPrivateFieldDefine:
     629            ASSERT(slot.isStrictMode());
     630            return operationPutByIdDefinePrivateFieldStrictOptimize;
     631        case PutKind::DirectPrivateFieldSet:
     632            ASSERT(slot.isStrictMode());
     633            return operationPutByIdSetPrivateFieldStrictOptimize;
     634        }
     635        break;
     636    case PutByKind::ByVal: {
     637        switch (putKind) {
     638        case PutKind::NotDirect:
     639            if (slot.isStrictMode())
     640                return operationPutByValStrictOptimize;
     641            return operationPutByValNonStrictOptimize;
     642        case PutKind::Direct:
     643            if (slot.isStrictMode())
     644                return operationDirectPutByValStrictOptimize;
     645            return operationDirectPutByValNonStrictOptimize;
     646        default:
     647            RELEASE_ASSERT_NOT_REACHED();
     648            break;
     649        }
     650        break;
     651    }
    611652    }
    612653    // Make win port compiler happy
     
    615656}
    616657
    617 static InlineCacheAction tryCachePutByID(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
     658static InlineCacheAction tryCachePutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind, PutKind putKind)
    618659{
    619660    VM& vm = globalObject->vm();
     
    683724                    bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(stubInfo, oldStructure, slot.cachedOffset());
    684725                    if (generatedCodeInline) {
    685                         LOG_IC((ICEvent::PutByIdSelfPatch, oldStructure->classInfo(), ident, slot.base() == baseValue));
    686                         repatchSlowPathCall(codeBlock, stubInfo, appropriateOptimizingPutByIdFunction(slot, putKind));
     726                        LOG_IC((ICEvent::PutBySelfPatch, oldStructure->classInfo(), ident, slot.base() == baseValue));
     727                        repatchSlowPathCall(codeBlock, stubInfo, appropriateOptimizingPutByFunction(slot, putByKind, putKind));
    687728                        stubInfo.initPutByIdReplace(locker, codeBlock, oldStructure, slot.cachedOffset(), propertyName);
    688729                        return RetryCacheLater;
     
    818859        }
    819860
    820         LOG_IC((ICEvent::PutByIdAddAccessCase, oldStructure->classInfo(), ident, slot.base() == baseValue));
     861        LOG_IC((ICEvent::PutByAddAccessCase, oldStructure->classInfo(), ident, slot.base() == baseValue));
    821862       
    822863        result = stubInfo.addAccessCase(locker, globalObject, codeBlock, slot.isStrictMode() ? ECMAMode::strict() : ECMAMode::sloppy(), propertyName, WTFMove(newCase));
    823864
    824865        if (result.generatedSomeCode()) {
    825             LOG_IC((ICEvent::PutByIdReplaceWithJump, oldStructure->classInfo(), ident, slot.base() == baseValue));
     866            LOG_IC((ICEvent::PutByReplaceWithJump, oldStructure->classInfo(), ident, slot.base() == baseValue));
    826867           
    827868            RELEASE_ASSERT(result.code());
     
    836877}
    837878
    838 void repatchPutByID(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
     879void repatchPutBy(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, Structure* oldStructure, CacheableIdentifier propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutByKind putByKind, PutKind putKind)
    839880{
    840881    SuperSamplerScope superSamplerScope(false);
    841882   
    842     if (tryCachePutByID(globalObject, codeBlock, baseValue, oldStructure, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
    843         repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByIdFunction(slot, putKind));
     883    if (tryCachePutBy(globalObject, codeBlock, baseValue, oldStructure, propertyName, slot, stubInfo, putByKind, putKind) == GiveUpOnCache)
     884        repatchSlowPathCall(codeBlock, stubInfo, appropriateGenericPutByFunction(slot, putByKind, putKind));
     885}
     886
     887static InlineCacheAction tryCacheArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue baseValue, JSValue index, StructureStubInfo& stubInfo, PutKind)
     888{
     889    if (!baseValue.isCell())
     890        return GiveUpOnCache;
     891
     892    if (!index.isInt32())
     893        return RetryCacheLater;
     894
     895    VM& vm = globalObject->vm();
     896    AccessGenerationResult result;
     897
     898    {
     899        JSCell* base = baseValue.asCell();
     900
     901        AccessCase::AccessType accessType;
     902        if (isTypedView(base->classInfo(vm)->typedArrayStorageType)) {
     903            switch (base->classInfo(vm)->typedArrayStorageType) {
     904            case TypeInt8:
     905                accessType = AccessCase::IndexedTypedArrayInt8Store;
     906                break;
     907            case TypeUint8:
     908                accessType = AccessCase::IndexedTypedArrayUint8Store;
     909                break;
     910            case TypeUint8Clamped:
     911                accessType = AccessCase::IndexedTypedArrayUint8ClampedStore;
     912                break;
     913            case TypeInt16:
     914                accessType = AccessCase::IndexedTypedArrayInt16Store;
     915                break;
     916            case TypeUint16:
     917                accessType = AccessCase::IndexedTypedArrayUint16Store;
     918                break;
     919            case TypeInt32:
     920                accessType = AccessCase::IndexedTypedArrayInt32Store;
     921                break;
     922            case TypeUint32:
     923                accessType = AccessCase::IndexedTypedArrayUint32Store;
     924                break;
     925            case TypeFloat32:
     926                accessType = AccessCase::IndexedTypedArrayFloat32Store;
     927                break;
     928            case TypeFloat64:
     929                accessType = AccessCase::IndexedTypedArrayFloat64Store;
     930                break;
     931            // FIXME: Optimize BigInt64Array / BigUint64Array in IC
     932            // https://bugs.webkit.org/show_bug.cgi?id=221183
     933            case TypeBigInt64:
     934            case TypeBigUint64:
     935                return GiveUpOnCache;
     936            default:
     937                RELEASE_ASSERT_NOT_REACHED();
     938            }
     939        } else {
     940            IndexingType indexingShape = base->indexingType() & IndexingShapeMask;
     941            switch (indexingShape) {
     942            case Int32Shape:
     943                accessType = AccessCase::IndexedInt32Store;
     944                break;
     945            case DoubleShape:
     946                accessType = AccessCase::IndexedDoubleStore;
     947                break;
     948            case ContiguousShape:
     949                accessType = AccessCase::IndexedContiguousStore;
     950                break;
     951            case ArrayStorageShape:
     952                accessType = AccessCase::IndexedArrayStorageStore;
     953                break;
     954            default:
     955                return GiveUpOnCache;
     956            }
     957        }
     958
     959        GCSafeConcurrentJSLocker locker(codeBlock->m_lock, globalObject->vm().heap);
     960        result = stubInfo.addAccessCase(locker, globalObject, codeBlock, ECMAMode::strict(), nullptr, AccessCase::create(vm, codeBlock, accessType, nullptr));
     961
     962        if (result.generatedSomeCode()) {
     963            LOG_IC((ICEvent::PutByReplaceWithJump, baseValue.classInfoOrNull(vm), Identifier()));
     964
     965            RELEASE_ASSERT(result.code());
     966            InlineAccess::rewireStubAsJumpInAccessNotUsingInlineAccess(codeBlock, stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
     967        }
     968    }
     969
     970    fireWatchpointsAndClearStubIfNeeded(vm, stubInfo, codeBlock, result);
     971    return result.shouldGiveUpNow() ? GiveUpOnCache : RetryCacheLater;
     972}
     973
     974void repatchArrayPutByVal(JSGlobalObject* globalObject, CodeBlock* codeBlock, JSValue base, JSValue index, StructureStubInfo& stubInfo, PutKind putKind, ECMAMode ecmaMode)
     975{
     976    if (tryCacheArrayPutByVal(globalObject, codeBlock, base, index, stubInfo, putKind) == GiveUpOnCache)
     977        repatchSlowPathCall(codeBlock, stubInfo, putKind == PutKind::Direct ? (ecmaMode.isStrict() ? operationDirectPutByValStrictGeneric : operationDirectPutByValNonStrictGeneric) : (ecmaMode.isStrict() ? operationPutByValStrictGeneric : operationPutByValNonStrictGeneric));
    844978}
    845979
     
    9871121                bool generatedCodeInline = InlineAccess::generateSelfInAccess(stubInfo, structure);
    9881122                if (generatedCodeInline) {
    989                     LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident, slot.slotBase() == base));
     1123                    LOG_IC((ICEvent::InBySelfPatch, structure->classInfo(), ident, slot.slotBase() == base));
    9901124                    structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
    9911125                    repatchSlowPathCall(codeBlock, stubInfo, operationInByIdOptimize);
     
    17571891}
    17581892
    1759 void resetPutByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo)
    1760 {
    1761     using FunctionType = decltype(&operationPutByIdDirectStrictOptimize);
    1762     FunctionType unoptimizedFunction = reinterpret_cast<FunctionType>(readPutICCallTarget(codeBlock, stubInfo).executableAddress());
    1763     FunctionType optimizedFunction;
    1764     if (unoptimizedFunction == operationPutByIdStrict || unoptimizedFunction == operationPutByIdStrictOptimize)
    1765         optimizedFunction = operationPutByIdStrictOptimize;
    1766     else if (unoptimizedFunction == operationPutByIdNonStrict || unoptimizedFunction == operationPutByIdNonStrictOptimize)
    1767         optimizedFunction = operationPutByIdNonStrictOptimize;
    1768     else if (unoptimizedFunction == operationPutByIdDirectStrict || unoptimizedFunction == operationPutByIdDirectStrictOptimize)
    1769         optimizedFunction = operationPutByIdDirectStrictOptimize;
    1770     else if (unoptimizedFunction == operationPutByIdSetPrivateFieldStrict || unoptimizedFunction == operationPutByIdSetPrivateFieldStrictOptimize)
    1771         optimizedFunction = operationPutByIdSetPrivateFieldStrictOptimize;
    1772     else if (unoptimizedFunction == operationPutByIdDefinePrivateFieldStrict || unoptimizedFunction == operationPutByIdDefinePrivateFieldStrictOptimize)
    1773         optimizedFunction = operationPutByIdDefinePrivateFieldStrictOptimize;
    1774     else {
    1775         ASSERT(unoptimizedFunction == operationPutByIdDirectNonStrict || unoptimizedFunction == operationPutByIdDirectNonStrictOptimize);
    1776         optimizedFunction = operationPutByIdDirectNonStrictOptimize;
     1893void resetPutBy(CodeBlock* codeBlock, StructureStubInfo& stubInfo, PutByKind kind)
     1894{
     1895    FunctionPtr<CFunctionPtrTag> optimizedFunction;
     1896    switch (kind) {
     1897    case PutByKind::ById: {
     1898        using FunctionType = decltype(&operationPutByIdDirectStrictOptimize);
     1899        FunctionType unoptimizedFunction = reinterpret_cast<FunctionType>(readPutICCallTarget(codeBlock, stubInfo).executableAddress());
     1900        if (unoptimizedFunction == operationPutByIdStrict || unoptimizedFunction == operationPutByIdStrictOptimize)
     1901            optimizedFunction = operationPutByIdStrictOptimize;
     1902        else if (unoptimizedFunction == operationPutByIdNonStrict || unoptimizedFunction == operationPutByIdNonStrictOptimize)
     1903            optimizedFunction = operationPutByIdNonStrictOptimize;
     1904        else if (unoptimizedFunction == operationPutByIdDirectStrict || unoptimizedFunction == operationPutByIdDirectStrictOptimize)
     1905            optimizedFunction = operationPutByIdDirectStrictOptimize;
     1906        else if (unoptimizedFunction == operationPutByIdSetPrivateFieldStrict || unoptimizedFunction == operationPutByIdSetPrivateFieldStrictOptimize)
     1907            optimizedFunction = operationPutByIdSetPrivateFieldStrictOptimize;
     1908        else if (unoptimizedFunction == operationPutByIdDefinePrivateFieldStrict || unoptimizedFunction == operationPutByIdDefinePrivateFieldStrictOptimize)
     1909            optimizedFunction = operationPutByIdDefinePrivateFieldStrictOptimize;
     1910        else {
     1911            ASSERT(unoptimizedFunction == operationPutByIdDirectNonStrict || unoptimizedFunction == operationPutByIdDirectNonStrictOptimize);
     1912            optimizedFunction = operationPutByIdDirectNonStrictOptimize;
     1913        }
     1914        break;
     1915    }
     1916    case PutByKind::ByVal: {
     1917        using FunctionType = decltype(&operationPutByValStrictOptimize);
     1918        FunctionType unoptimizedFunction = reinterpret_cast<FunctionType>(readPutICCallTarget(codeBlock, stubInfo).executableAddress());
     1919        if (unoptimizedFunction == operationPutByValStrictGeneric || unoptimizedFunction == operationPutByValStrictOptimize)
     1920            optimizedFunction = operationPutByValStrictOptimize;
     1921        else if (unoptimizedFunction == operationPutByValNonStrictGeneric || unoptimizedFunction == operationPutByValNonStrictOptimize)
     1922            optimizedFunction = operationPutByValNonStrictOptimize;
     1923        else if (unoptimizedFunction == operationDirectPutByValStrictGeneric || unoptimizedFunction == operationDirectPutByValStrictOptimize)
     1924            optimizedFunction = operationDirectPutByValStrictOptimize;
     1925        else {
     1926            ASSERT(unoptimizedFunction == operationDirectPutByValNonStrictGeneric || unoptimizedFunction == operationDirectPutByValNonStrictOptimize);
     1927            optimizedFunction = operationDirectPutByValNonStrictOptimize;
     1928        }
     1929        break;
     1930    }
    17771931    }
    17781932
    17791933    repatchSlowPathCall(codeBlock, stubInfo, optimizedFunction);
    1780     InlineAccess::resetStubAsJumpInAccess(codeBlock, stubInfo);
     1934    switch (kind) {
     1935    case PutByKind::ById:
     1936        InlineAccess::resetStubAsJumpInAccess(codeBlock, stubInfo);
     1937        break;
     1938    case PutByKind::ByVal:
     1939        InlineAccess::resetStubAsJumpInAccessNotUsingInlineAccess(codeBlock, stubInfo);
     1940        break;
     1941    }
    17811942}
    17821943
  • trunk/Source/JavaScriptCore/jit/Repatch.h

    r279105 r281615  
    4444};
    4545
     46enum class PutByKind {
     47    ById,
     48    ByVal,
     49};
     50
    4651enum class DelByKind {
    4752    ById,
     
    5762void repatchArrayGetByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&);
    5863void repatchGetBy(JSGlobalObject*, CodeBlock*, JSValue, CacheableIdentifier, const PropertySlot&, StructureStubInfo&, GetByKind);
    59 void repatchPutByID(JSGlobalObject*, CodeBlock*, JSValue, Structure*, CacheableIdentifier, const PutPropertySlot&, StructureStubInfo&, PutKind);
     64void repatchArrayPutByVal(JSGlobalObject*, CodeBlock*, JSValue base, JSValue index, StructureStubInfo&, PutKind, ECMAMode);
     65void repatchPutBy(JSGlobalObject*, CodeBlock*, JSValue, Structure*, CacheableIdentifier, const PutPropertySlot&, StructureStubInfo&, PutByKind, PutKind);
    6066void repatchDeleteBy(JSGlobalObject*, CodeBlock*, DeletePropertySlot&, JSValue, Structure*, CacheableIdentifier, StructureStubInfo&, DelByKind, ECMAMode);
    6167void repatchInBy(JSGlobalObject*, CodeBlock*, JSObject*, CacheableIdentifier, bool wasFound, const PropertySlot&, StructureStubInfo&, InByKind);
     
    7076void linkPolymorphicCall(JSGlobalObject*, CallFrame*, CallLinkInfo&, CallVariant);
    7177void resetGetBy(CodeBlock*, StructureStubInfo&, GetByKind);
    72 void resetPutByID(CodeBlock*, StructureStubInfo&);
     78void resetPutBy(CodeBlock*, StructureStubInfo&, PutByKind);
    7379void resetDelBy(CodeBlock*, StructureStubInfo&, DelByKind);
    7480void resetInBy(CodeBlock*, StructureStubInfo&, InByKind);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.h

    r252684 r281615  
    3333
    3434// The following is a set of alias for the opcode names. This is needed
    35 // because there is code (e.g. in GetByStatus.cpp and PutByIdStatus.cpp)
     35// because there is code (e.g. in GetByStatus.cpp and PutByStatus.cpp)
    3636// which refers to the opcodes expecting them to be prefixed with "llint_".
    3737// In the CLoop implementation, the 2 are equivalent. Hence, we set up this
Note: See TracChangeset for help on using the changeset viewer.