Changeset 188105 in webkit


Ignore:
Timestamp:
Aug 6, 2015 7:08:07 PM (9 years ago)
Author:
Yusuke Suzuki
Message:

Introduce get_by_id like IC into get_by_val when the given name is String or Symbol
https://bugs.webkit.org/show_bug.cgi?id=147480

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch adds get_by_id IC to get_by_val operation by caching the string / symbol id.
The IC site only caches one id. After checking that the given id is the same to the
cached one, we perform the get_by_id IC onto it.
And by collecting IC StructureStubInfo information, we pass it to the DFG and DFG
compiles get_by_val op code into CheckIdent (with edge type check) and GetById related
operations when the given get_by_val leverages the property load with the cached id.

To ensure the incoming value is the expected id, in DFG layer, we use SymbolUse and
StringIdentUse to enforce the type. To use it, this patch implements SymbolUse.
This can be leveraged to optimize symbol operations in DFG.

And since byValInfo is frequently used, we align the byValInfo design to the stubInfo like one.
Allocated by the Bag and operations take the raw byValInfo pointer directly instead of performing
binary search onto m_byValInfos. And by storing ArrayProfile* under the ByValInfo, we replaced the
argument ArrayProfile* in the operations with ByValInfo*.

  • bytecode/ByValInfo.h:

(JSC::ByValInfo::ByValInfo):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::getByValInfoMap):
(JSC::CodeBlock::addByValInfo):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::getByValInfo): Deleted.
(JSC::CodeBlock::setNumberOfByValInfos): Deleted.
(JSC::CodeBlock::numberOfByValInfos): Deleted.
(JSC::CodeBlock::byValInfo): Deleted.

  • bytecode/ExitKind.cpp:

(JSC::exitKindToString):

  • bytecode/ExitKind.h:
  • bytecode/GetByIdStatus.cpp:

(JSC::GetByIdStatus::computeFor):
(JSC::GetByIdStatus::computeForStubInfo):
(JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):

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

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

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasUidOperand):
(JSC::DFG::Node::uidOperand):

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

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCheckIdent):
(JSC::DFG::SpeculativeJIT::speculateSymbol):
(JSC::DFG::SpeculativeJIT::speculate):

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

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::isCell):

  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckIdent):
(JSC::FTL::DFG::LowerDFGToLLVM::lowSymbol):
(JSC::FTL::DFG::LowerDFGToLLVM::speculate):
(JSC::FTL::DFG::LowerDFGToLLVM::isNotSymbol):
(JSC::FTL::DFG::LowerDFGToLLVM::speculateSymbol):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JIT.h:

(JSC::ByValCompilationInfo::ByValCompilationInfo):
(JSC::JIT::compileGetByValWithCachedId):

  • jit/JITInlines.h:

(JSC::JIT::callOperation):

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):

  • jit/JITOperations.cpp:

(JSC::getByVal):

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

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):
(JSC::JIT::privateCompileGetByVal):
(JSC::JIT::privateCompileGetByValWithCachedId):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitSlow_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitSlow_op_put_by_val):

  • runtime/Symbol.h:
  • tests/stress/get-by-val-with-string-constructor.js: Added.

(Hello):
(get Hello.prototype.generate):
(ok):

  • tests/stress/get-by-val-with-string-exit.js: Added.

(shouldBe):
(getByVal):
(getStr1):
(getStr2):

  • tests/stress/get-by-val-with-string-generated.js: Added.

(shouldBe):
(getByVal):
(getStr1):
(getStr2):

  • tests/stress/get-by-val-with-string-getter.js: Added.

(object.get hello):
(ok):

  • tests/stress/get-by-val-with-string.js: Added.

(shouldBe):
(getByVal):
(getStr1):
(getStr2):

  • tests/stress/get-by-val-with-symbol-constructor.js: Added.

(Hello):
(get Hello.prototype.generate):
(ok):

  • tests/stress/get-by-val-with-symbol-exit.js: Added.

(shouldBe):
(getByVal):
(getSym1):
(getSym2):

  • tests/stress/get-by-val-with-symbol-getter.js: Added.

(object.get hello):
(.get ok):

  • tests/stress/get-by-val-with-symbol.js: Added.

(shouldBe):
(getByVal):
(getSym1):
(getSym2):

LayoutTests:

Add synthetic benchmarks that replaces normal property load with symbol/string keyed load.

  • js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-expected.txt: Added.
  • js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple-expected.txt: Added.
  • js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple.html: Added.
  • js/regress/get-by-val-with-string-bimorphic-check-structure-elimination.html: Added.
  • js/regress/get-by-val-with-string-chain-from-try-block-expected.txt: Added.
  • js/regress/get-by-val-with-string-chain-from-try-block.html: Added.
  • js/regress/get-by-val-with-string-check-structure-elimination-expected.txt: Added.
  • js/regress/get-by-val-with-string-check-structure-elimination.html: Added.
  • js/regress/get-by-val-with-string-proto-or-self-expected.txt: Added.
  • js/regress/get-by-val-with-string-proto-or-self.html: Added.
  • js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple-expected.txt: Added.
  • js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.html: Added.
  • js/regress/get-by-val-with-string-self-or-proto-expected.txt: Added.
  • js/regress/get-by-val-with-string-self-or-proto.html: Added.
  • js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.html: Added.
  • js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination.html: Added.
  • js/regress/get-by-val-with-symbol-chain-from-try-block-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-chain-from-try-block.html: Added.
  • js/regress/get-by-val-with-symbol-check-structure-elimination-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-check-structure-elimination.html: Added.
  • js/regress/get-by-val-with-symbol-proto-or-self-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-proto-or-self.html: Added.
  • js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.html: Added.
  • js/regress/get-by-val-with-symbol-self-or-proto-expected.txt: Added.
  • js/regress/get-by-val-with-symbol-self-or-proto.html: Added.
  • js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination-simple.js: Added.
  • js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination.js: Added.
  • js/regress/script-tests/get-by-val-with-string-chain-from-try-block.js: Added.

(A):
(B):
(C):
(D):
(E):
(F):
(G):
(foo):

  • js/regress/script-tests/get-by-val-with-string-check-structure-elimination.js: Added.
  • js/regress/script-tests/get-by-val-with-string-proto-or-self.js: Added.

(foo):
(bar):
(Foo):

  • js/regress/script-tests/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.js: Added.
  • js/regress/script-tests/get-by-val-with-string-self-or-proto.js: Added.

(foo):
(bar):
(Foo):

  • js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.js: Added.
  • js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination.js: Added.
  • js/regress/script-tests/get-by-val-with-symbol-chain-from-try-block.js: Added.

(A):
(B):
(C):
(D):
(E):
(F):
(G):
(foo):

  • js/regress/script-tests/get-by-val-with-symbol-check-structure-elimination.js: Added.
  • js/regress/script-tests/get-by-val-with-symbol-proto-or-self.js: Added.

(foo):
(bar):
(Foo):

  • js/regress/script-tests/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.js: Added.
  • js/regress/script-tests/get-by-val-with-symbol-self-or-proto.js: Added.

(foo):
(bar):
(Foo):

Location:
trunk
Files:
51 added
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r188085 r188105  
     12015-08-06  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Introduce get_by_id like IC into get_by_val when the given name is String or Symbol
     4        https://bugs.webkit.org/show_bug.cgi?id=147480
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Add synthetic benchmarks that replaces normal property load with symbol/string keyed load.
     9
     10        * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-expected.txt: Added.
     11        * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple-expected.txt: Added.
     12        * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination-simple.html: Added.
     13        * js/regress/get-by-val-with-string-bimorphic-check-structure-elimination.html: Added.
     14        * js/regress/get-by-val-with-string-chain-from-try-block-expected.txt: Added.
     15        * js/regress/get-by-val-with-string-chain-from-try-block.html: Added.
     16        * js/regress/get-by-val-with-string-check-structure-elimination-expected.txt: Added.
     17        * js/regress/get-by-val-with-string-check-structure-elimination.html: Added.
     18        * js/regress/get-by-val-with-string-proto-or-self-expected.txt: Added.
     19        * js/regress/get-by-val-with-string-proto-or-self.html: Added.
     20        * js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple-expected.txt: Added.
     21        * js/regress/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.html: Added.
     22        * js/regress/get-by-val-with-string-self-or-proto-expected.txt: Added.
     23        * js/regress/get-by-val-with-string-self-or-proto.html: Added.
     24        * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-expected.txt: Added.
     25        * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple-expected.txt: Added.
     26        * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.html: Added.
     27        * js/regress/get-by-val-with-symbol-bimorphic-check-structure-elimination.html: Added.
     28        * js/regress/get-by-val-with-symbol-chain-from-try-block-expected.txt: Added.
     29        * js/regress/get-by-val-with-symbol-chain-from-try-block.html: Added.
     30        * js/regress/get-by-val-with-symbol-check-structure-elimination-expected.txt: Added.
     31        * js/regress/get-by-val-with-symbol-check-structure-elimination.html: Added.
     32        * js/regress/get-by-val-with-symbol-proto-or-self-expected.txt: Added.
     33        * js/regress/get-by-val-with-symbol-proto-or-self.html: Added.
     34        * js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple-expected.txt: Added.
     35        * js/regress/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.html: Added.
     36        * js/regress/get-by-val-with-symbol-self-or-proto-expected.txt: Added.
     37        * js/regress/get-by-val-with-symbol-self-or-proto.html: Added.
     38        * js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination-simple.js: Added.
     39        * js/regress/script-tests/get-by-val-with-string-bimorphic-check-structure-elimination.js: Added.
     40        * js/regress/script-tests/get-by-val-with-string-chain-from-try-block.js: Added.
     41        (A):
     42        (B):
     43        (C):
     44        (D):
     45        (E):
     46        (F):
     47        (G):
     48        (foo):
     49        * js/regress/script-tests/get-by-val-with-string-check-structure-elimination.js: Added.
     50        * js/regress/script-tests/get-by-val-with-string-proto-or-self.js: Added.
     51        (foo):
     52        (bar):
     53        (Foo):
     54        * js/regress/script-tests/get-by-val-with-string-quadmorphic-check-structure-elimination-simple.js: Added.
     55        * js/regress/script-tests/get-by-val-with-string-self-or-proto.js: Added.
     56        (foo):
     57        (bar):
     58        (Foo):
     59        * js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination-simple.js: Added.
     60        * js/regress/script-tests/get-by-val-with-symbol-bimorphic-check-structure-elimination.js: Added.
     61        * js/regress/script-tests/get-by-val-with-symbol-chain-from-try-block.js: Added.
     62        (A):
     63        (B):
     64        (C):
     65        (D):
     66        (E):
     67        (F):
     68        (G):
     69        (foo):
     70        * js/regress/script-tests/get-by-val-with-symbol-check-structure-elimination.js: Added.
     71        * js/regress/script-tests/get-by-val-with-symbol-proto-or-self.js: Added.
     72        (foo):
     73        (bar):
     74        (Foo):
     75        * js/regress/script-tests/get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple.js: Added.
     76        * js/regress/script-tests/get-by-val-with-symbol-self-or-proto.js: Added.
     77        (foo):
     78        (bar):
     79        (Foo):
     80
    1812015-08-06  Keith Miller  <keith_miller@apple.com>
    282
  • trunk/Source/JavaScriptCore/ChangeLog

    r188100 r188105  
     12015-08-06  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Introduce get_by_id like IC into get_by_val when the given name is String or Symbol
     4        https://bugs.webkit.org/show_bug.cgi?id=147480
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch adds get_by_id IC to get_by_val operation by caching the string / symbol id.
     9        The IC site only caches one id. After checking that the given id is the same to the
     10        cached one, we perform the get_by_id IC onto it.
     11        And by collecting IC StructureStubInfo information, we pass it to the DFG and DFG
     12        compiles get_by_val op code into CheckIdent (with edge type check) and GetById related
     13        operations when the given get_by_val leverages the property load with the cached id.
     14
     15        To ensure the incoming value is the expected id, in DFG layer, we use SymbolUse and
     16        StringIdentUse to enforce the type. To use it, this patch implements SymbolUse.
     17        This can be leveraged to optimize symbol operations in DFG.
     18
     19        And since byValInfo is frequently used, we align the byValInfo design to the stubInfo like one.
     20        Allocated by the Bag and operations take the raw byValInfo pointer directly instead of performing
     21        binary search onto m_byValInfos. And by storing ArrayProfile* under the ByValInfo, we replaced the
     22        argument ArrayProfile* in the operations with ByValInfo*.
     23
     24        * bytecode/ByValInfo.h:
     25        (JSC::ByValInfo::ByValInfo):
     26        * bytecode/CodeBlock.cpp:
     27        (JSC::CodeBlock::getByValInfoMap):
     28        (JSC::CodeBlock::addByValInfo):
     29        * bytecode/CodeBlock.h:
     30        (JSC::CodeBlock::getByValInfo): Deleted.
     31        (JSC::CodeBlock::setNumberOfByValInfos): Deleted.
     32        (JSC::CodeBlock::numberOfByValInfos): Deleted.
     33        (JSC::CodeBlock::byValInfo): Deleted.
     34        * bytecode/ExitKind.cpp:
     35        (JSC::exitKindToString):
     36        * bytecode/ExitKind.h:
     37        * bytecode/GetByIdStatus.cpp:
     38        (JSC::GetByIdStatus::computeFor):
     39        (JSC::GetByIdStatus::computeForStubInfo):
     40        (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
     41        * bytecode/GetByIdStatus.h:
     42        * dfg/DFGAbstractInterpreterInlines.h:
     43        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     44        * dfg/DFGByteCodeParser.cpp:
     45        (JSC::DFG::ByteCodeParser::parseBlock):
     46        (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
     47        * dfg/DFGClobberize.h:
     48        (JSC::DFG::clobberize):
     49        * dfg/DFGConstantFoldingPhase.cpp:
     50        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     51        * dfg/DFGDoesGC.cpp:
     52        (JSC::DFG::doesGC):
     53        * dfg/DFGFixupPhase.cpp:
     54        (JSC::DFG::FixupPhase::fixupNode):
     55        (JSC::DFG::FixupPhase::observeUseKindOnNode):
     56        * dfg/DFGNode.h:
     57        (JSC::DFG::Node::hasUidOperand):
     58        (JSC::DFG::Node::uidOperand):
     59        * dfg/DFGNodeType.h:
     60        * dfg/DFGPredictionPropagationPhase.cpp:
     61        (JSC::DFG::PredictionPropagationPhase::propagate):
     62        * dfg/DFGSafeToExecute.h:
     63        (JSC::DFG::SafeToExecuteEdge::operator()):
     64        (JSC::DFG::safeToExecute):
     65        * dfg/DFGSpeculativeJIT.cpp:
     66        (JSC::DFG::SpeculativeJIT::compileCheckIdent):
     67        (JSC::DFG::SpeculativeJIT::speculateSymbol):
     68        (JSC::DFG::SpeculativeJIT::speculate):
     69        * dfg/DFGSpeculativeJIT.h:
     70        * dfg/DFGSpeculativeJIT32_64.cpp:
     71        (JSC::DFG::SpeculativeJIT::compile):
     72        * dfg/DFGSpeculativeJIT64.cpp:
     73        (JSC::DFG::SpeculativeJIT::compile):
     74        * dfg/DFGUseKind.cpp:
     75        (WTF::printInternal):
     76        * dfg/DFGUseKind.h:
     77        (JSC::DFG::typeFilterFor):
     78        (JSC::DFG::isCell):
     79        * ftl/FTLAbstractHeapRepository.h:
     80        * ftl/FTLCapabilities.cpp:
     81        (JSC::FTL::canCompile):
     82        * ftl/FTLLowerDFGToLLVM.cpp:
     83        (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
     84        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckIdent):
     85        (JSC::FTL::DFG::LowerDFGToLLVM::lowSymbol):
     86        (JSC::FTL::DFG::LowerDFGToLLVM::speculate):
     87        (JSC::FTL::DFG::LowerDFGToLLVM::isNotSymbol):
     88        (JSC::FTL::DFG::LowerDFGToLLVM::speculateSymbol):
     89        * jit/JIT.cpp:
     90        (JSC::JIT::privateCompile):
     91        * jit/JIT.h:
     92        (JSC::ByValCompilationInfo::ByValCompilationInfo):
     93        (JSC::JIT::compileGetByValWithCachedId):
     94        * jit/JITInlines.h:
     95        (JSC::JIT::callOperation):
     96        * jit/JITOpcodes.cpp:
     97        (JSC::JIT::emit_op_has_indexed_property):
     98        (JSC::JIT::emitSlow_op_has_indexed_property):
     99        * jit/JITOpcodes32_64.cpp:
     100        (JSC::JIT::emit_op_has_indexed_property):
     101        (JSC::JIT::emitSlow_op_has_indexed_property):
     102        * jit/JITOperations.cpp:
     103        (JSC::getByVal):
     104        * jit/JITOperations.h:
     105        * jit/JITPropertyAccess.cpp:
     106        (JSC::JIT::emit_op_get_by_val):
     107        (JSC::JIT::emitGetByValWithCachedId):
     108        (JSC::JIT::emitSlow_op_get_by_val):
     109        (JSC::JIT::emit_op_put_by_val):
     110        (JSC::JIT::emitSlow_op_put_by_val):
     111        (JSC::JIT::privateCompileGetByVal):
     112        (JSC::JIT::privateCompileGetByValWithCachedId):
     113        * jit/JITPropertyAccess32_64.cpp:
     114        (JSC::JIT::emit_op_get_by_val):
     115        (JSC::JIT::emitGetByValWithCachedId):
     116        (JSC::JIT::emitSlow_op_get_by_val):
     117        (JSC::JIT::emit_op_put_by_val):
     118        (JSC::JIT::emitSlow_op_put_by_val):
     119        * runtime/Symbol.h:
     120        * tests/stress/get-by-val-with-string-constructor.js: Added.
     121        (Hello):
     122        (get Hello.prototype.generate):
     123        (ok):
     124        * tests/stress/get-by-val-with-string-exit.js: Added.
     125        (shouldBe):
     126        (getByVal):
     127        (getStr1):
     128        (getStr2):
     129        * tests/stress/get-by-val-with-string-generated.js: Added.
     130        (shouldBe):
     131        (getByVal):
     132        (getStr1):
     133        (getStr2):
     134        * tests/stress/get-by-val-with-string-getter.js: Added.
     135        (object.get hello):
     136        (ok):
     137        * tests/stress/get-by-val-with-string.js: Added.
     138        (shouldBe):
     139        (getByVal):
     140        (getStr1):
     141        (getStr2):
     142        * tests/stress/get-by-val-with-symbol-constructor.js: Added.
     143        (Hello):
     144        (get Hello.prototype.generate):
     145        (ok):
     146        * tests/stress/get-by-val-with-symbol-exit.js: Added.
     147        (shouldBe):
     148        (getByVal):
     149        (getSym1):
     150        (getSym2):
     151        * tests/stress/get-by-val-with-symbol-getter.js: Added.
     152        (object.get hello):
     153        (.get ok):
     154        * tests/stress/get-by-val-with-symbol.js: Added.
     155        (shouldBe):
     156        (getByVal):
     157        (getSym1):
     158        (getSym2):
     159
    11602015-08-05  Filip Pizlo  <fpizlo@apple.com>
    2161
  • trunk/Source/JavaScriptCore/bytecode/ByValInfo.h

    r181993 r188105  
    2727#define ByValInfo_h
    2828
    29 #if ENABLE(JIT)
    30 
    3129#include "ClassInfo.h"
    3230#include "CodeLocation.h"
     31#include "CodeOrigin.h"
    3332#include "IndexingType.h"
    3433#include "JITStubRoutine.h"
    3534#include "Structure.h"
     35#include "StructureStubInfo.h"
    3636
    3737namespace JSC {
     38
     39#if ENABLE(JIT)
    3840
    3941enum JITArrayMode {
     
    202204struct ByValInfo {
    203205    ByValInfo() { }
    204    
    205     ByValInfo(unsigned bytecodeIndex, CodeLocationJump badTypeJump, JITArrayMode arrayMode, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath)
     206
     207    ByValInfo(unsigned bytecodeIndex, CodeLocationJump notIndexJump, CodeLocationJump badTypeJump, JITArrayMode arrayMode, ArrayProfile* arrayProfile, int16_t badTypeJumpToDone, int16_t returnAddressToSlowPath)
    206208        : bytecodeIndex(bytecodeIndex)
     209        , notIndexJump(notIndexJump)
    207210        , badTypeJump(badTypeJump)
    208211        , arrayMode(arrayMode)
     212        , arrayProfile(arrayProfile)
    209213        , badTypeJumpToDone(badTypeJumpToDone)
    210214        , returnAddressToSlowPath(returnAddressToSlowPath)
    211215        , slowPathCount(0)
     216        , stubInfo(nullptr)
     217        , tookSlowPath(false)
    212218    {
    213219    }
    214    
     220
    215221    unsigned bytecodeIndex;
     222    CodeLocationJump notIndexJump;
    216223    CodeLocationJump badTypeJump;
    217224    JITArrayMode arrayMode; // The array mode that was baked into the inline JIT code.
     225    ArrayProfile* arrayProfile;
    218226    int16_t badTypeJumpToDone;
    219227    int16_t returnAddressToSlowPath;
    220228    unsigned slowPathCount;
    221229    RefPtr<JITStubRoutine> stubRoutine;
     230    Identifier cachedId;
     231    StructureStubInfo* stubInfo;
     232    bool tookSlowPath;
    222233};
    223234
     
    227238}
    228239
     240typedef HashMap<CodeOrigin, ByValInfo*, CodeOriginApproximateHash> ByValInfoMap;
     241
     242#else // ENABLE(JIT)
     243
     244typedef HashMap<int, void*> ByValInfoMap;
     245
     246#endif // ENABLE(JIT)
     247
    229248} // namespace JSC
    230249
    231 #endif // ENABLE(JIT)
    232 
    233250#endif // ByValInfo_h
    234251
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r187969 r188105  
    26742674}
    26752675
     2676void CodeBlock::getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result)
     2677{
     2678#if ENABLE(JIT)
     2679    for (auto* byValInfo : m_byValInfos)
     2680        result.add(CodeOrigin(byValInfo->bytecodeIndex), byValInfo);
     2681#else
     2682    UNUSED_PARAM(result);
     2683#endif
     2684}
     2685
     2686void CodeBlock::getByValInfoMap(ByValInfoMap& result)
     2687{
     2688    ConcurrentJITLocker locker(m_lock);
     2689    getByValInfoMap(locker, result);
     2690}
     2691
    26762692#if ENABLE(JIT)
    26772693StructureStubInfo* CodeBlock::addStubInfo()
     
    26882704    }
    26892705    return nullptr;
     2706}
     2707
     2708ByValInfo* CodeBlock::addByValInfo()
     2709{
     2710    ConcurrentJITLocker locker(m_lock);
     2711    return m_byValInfos.add();
    26902712}
    26912713
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r187524 r188105  
    201201    void getCallLinkInfoMap(const ConcurrentJITLocker&, CallLinkInfoMap& result);
    202202    void getCallLinkInfoMap(CallLinkInfoMap& result);
     203
     204    void getByValInfoMap(const ConcurrentJITLocker&, ByValInfoMap& result);
     205    void getByValInfoMap(ByValInfoMap& result);
    203206   
    204207#if ENABLE(JIT)
     
    212215
    213216    void resetStub(StructureStubInfo&);
    214    
    215     ByValInfo& getByValInfo(unsigned bytecodeIndex)
    216     {
    217         return *(binarySearch<ByValInfo, unsigned>(m_byValInfos, m_byValInfos.size(), bytecodeIndex, getByValInfoBytecodeIndex));
    218     }
     217
     218    ByValInfo* addByValInfo();
    219219
    220220    CallLinkInfo* addCallLinkInfo();
     
    367367
    368368    String nameForRegister(VirtualRegister);
    369 
    370 #if ENABLE(JIT)
    371     void setNumberOfByValInfos(size_t size) { m_byValInfos.resizeToFit(size); }
    372     size_t numberOfByValInfos() const { return m_byValInfos.size(); }
    373     ByValInfo& byValInfo(size_t index) { return m_byValInfos[index]; }
    374 #endif
    375369
    376370    unsigned numberOfArgumentValueProfiles()
     
    10171011#if ENABLE(JIT)
    10181012    Bag<StructureStubInfo> m_stubInfos;
    1019     Vector<ByValInfo> m_byValInfos;
     1013    Bag<ByValInfo> m_byValInfos;
    10201014    Bag<CallLinkInfo> m_callLinkInfos;
    10211015    SentinelLinkedList<CallLinkInfo, BasicRawSentinelNode<CallLinkInfo>> m_incomingCalls;
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.cpp

    r181466 r188105  
    4141    case BadCell:
    4242        return "BadCell";
     43    case BadIdent:
     44        return "BadIdent";
    4345    case BadExecutable:
    4446        return "BadExecutable";
  • trunk/Source/JavaScriptCore/bytecode/ExitKind.h

    r181466 r188105  
    3333    BadType, // We exited because a type prediction was wrong.
    3434    BadCell, // We exited because we made an incorrect assumption about what cell we would see. Usually used for function checks.
     35    BadIdent, // We exited because we made an incorrect assumption about what identifier we would see. Usually used for cached Id check in get_by_val.
    3536    BadExecutable, // We exited because we made an incorrect assumption about what executable we would see.
    3637    BadCache, // We exited because an inline cache was wrong.
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

    r187780 r188105  
    9999
    100100#if ENABLE(DFG_JIT)
    101     result = computeForStubInfo(
     101    result = computeForStubInfoWithoutExitSiteFeedback(
    102102        locker, profiledBlock, map.get(CodeOrigin(bytecodeIndex)), uid,
    103103        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
     
    117117
    118118#if ENABLE(JIT)
    119 GetByIdStatus GetByIdStatus::computeForStubInfo(
     119GetByIdStatus GetByIdStatus::computeForStubInfo(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, CodeOrigin codeOrigin, UniquedStringImpl* uid)
     120{
     121    GetByIdStatus result = GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
     122        locker, profiledBlock, stubInfo, uid,
     123        CallLinkStatus::computeExitSiteData(locker, profiledBlock, codeOrigin.bytecodeIndex));
     124
     125    if (!result.takesSlowPath() && GetByIdStatus::hasExitSite(locker, profiledBlock, codeOrigin.bytecodeIndex))
     126        return GetByIdStatus(result.makesCalls() ? GetByIdStatus::MakesCalls : GetByIdStatus::TakesSlowPath, true);
     127    return result;
     128}
     129#endif // ENABLE(JIT)
     130
     131#if ENABLE(JIT)
     132GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
    120133    const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, UniquedStringImpl* uid,
    121134    CallLinkStatus::ExitSiteData callExitSiteData)
     
    243256        {
    244257            ConcurrentJITLocker locker(dfgBlock->m_lock);
    245             result = computeForStubInfo(
     258            result = computeForStubInfoWithoutExitSiteFeedback(
    246259                locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
    247260        }
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h

    r185103 r188105  
    7272   
    7373    static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, UniquedStringImpl* uid);
    74    
     74
     75#if ENABLE(JIT)
     76    static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock* baselineBlock, StructureStubInfo*, CodeOrigin, UniquedStringImpl* uid);
     77#endif
     78
    7579    State state() const { return m_state; }
    7680   
     
    96100#endif
    97101#if ENABLE(JIT)
    98     static GetByIdStatus computeForStubInfo(
     102    static GetByIdStatus computeForStubInfoWithoutExitSiteFeedback(
    99103        const ConcurrentJITLocker&, CodeBlock* profiledBlock, StructureStubInfo*,
    100104        UniquedStringImpl* uid, CallLinkStatus::ExitSiteData);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r187780 r188105  
    21642164    }
    21652165
     2166    case CheckIdent: {
     2167        AbstractValue& value = forNode(node->child1());
     2168        UniquedStringImpl* uid = node->uidOperand();
     2169        ASSERT(uid->isSymbol() ? !(value.m_type & ~SpecSymbol) : !(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.
     2170
     2171        JSValue childConstant = value.value();
     2172        if (childConstant) {
     2173            if (uid->isSymbol()) {
     2174                ASSERT(childConstant.isSymbol());
     2175                if (asSymbol(childConstant)->privateName().uid() == uid) {
     2176                    m_state.setFoundConstants(true);
     2177                    break;
     2178                }
     2179            } else {
     2180                ASSERT(childConstant.isString());
     2181                if (asString(childConstant)->tryGetValueImpl() == uid) {
     2182                    m_state.setFoundConstants(true);
     2183                    break;
     2184                }
     2185            }
     2186        }
     2187
     2188        filter(value, uid->isSymbol() ? SpecSymbol : SpecStringIdent);
     2189        break;
     2190    }
     2191
    21662192    case CheckInBounds: {
    21672193        JSValue left = forNode(node->child1()).value();
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r187780 r188105  
    970970        CallLinkInfoMap m_callLinkInfos;
    971971        StubInfoMap m_stubInfos;
     972        ByValInfoMap m_byValInfos;
    972973       
    973974        // Did we see any returns? We need to handle the (uncommon but necessary)
     
    33983399        case op_get_by_val: {
    33993400            SpeculatedType prediction = getPredictionWithoutOSRExit();
    3400            
     3401
    34013402            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
    3402             ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read);
    34033403            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
    3404             Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property);
    3405             set(VirtualRegister(currentInstruction[1].u.operand), getByVal);
     3404            bool compiledAsGetById = false;
     3405            {
     3406                ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
     3407                ByValInfo* byValInfo = m_inlineStackTop->m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex));
     3408                // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
     3409                // At that time, there is no information.
     3410                if (byValInfo && byValInfo->stubInfo && !byValInfo->tookSlowPath && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) {
     3411                    compiledAsGetById = true;
     3412                    unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo->cachedId.impl());
     3413                    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
     3414
     3415                    addToGraph(CheckIdent, OpInfo(uid), property);
     3416
     3417                    GetByIdStatus getByIdStatus = GetByIdStatus::computeForStubInfo(
     3418                        locker, m_inlineStackTop->m_profiledBlock,
     3419                        byValInfo->stubInfo, currentCodeOrigin(), uid);
     3420
     3421                    handleGetById(currentInstruction[1].u.operand, prediction, base, identifierNumber, getByIdStatus);
     3422                }
     3423            }
     3424
     3425            if (!compiledAsGetById) {
     3426                ArrayMode arrayMode = getArrayMode(currentInstruction[4].u.arrayProfile, Array::Read);
     3427                Node* getByVal = addToGraph(GetByVal, OpInfo(arrayMode.asWord()), OpInfo(prediction), base, property);
     3428                set(VirtualRegister(currentInstruction[1].u.operand), getByVal);
     3429            }
    34063430
    34073431            NEXT_OPCODE(op_get_by_val);
     
    43064330            m_profiledBlock->getStubInfoMap(locker, m_stubInfos);
    43074331            m_profiledBlock->getCallLinkInfoMap(locker, m_callLinkInfos);
     4332            m_profiledBlock->getByValInfoMap(locker, m_byValInfos);
    43084333        }
    43094334    }
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r187555 r188105  
    269269        return;
    270270
     271    case CheckIdent:
     272        def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->uidOperand()));
     273        return;
     274
    271275    case ConstantStoragePointer:
    272276        def(PureValue(node, node->storagePointer()));
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r187780 r188105  
    209209            }
    210210
     211            case CheckIdent: {
     212                UniquedStringImpl* uid = node->uidOperand();
     213                JSValue childConstant = m_state.forNode(node->child1()).value();
     214                const UniquedStringImpl* constantUid = nullptr;
     215                if (childConstant) {
     216                    if (uid->isSymbol()) {
     217                        if (childConstant.isSymbol())
     218                            constantUid = asSymbol(childConstant)->privateName().uid();
     219                    } else {
     220                        if (childConstant.isString()) {
     221                            // Since we already filtered the value with StringIdentUse,
     222                            // the held impl is always atomic.
     223                            if (const auto* impl = asString(childConstant)->tryGetValueImpl()) {
     224                                ASSERT(impl->isAtomic());
     225                                constantUid = static_cast<const UniquedStringImpl*>(impl);
     226                            }
     227                        }
     228                    }
     229                }
     230
     231                if (constantUid == uid) {
     232                    node->remove();
     233                    eliminated = true;
     234                }
     235                break;
     236            }
     237
    211238            case CheckInBounds: {
    212239                JSValue left = m_state.forNode(node->child1()).value();
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r187555 r188105  
    108108    case CheckCell:
    109109    case CheckNotEmpty:
     110    case CheckIdent:
    110111    case RegExpExec:
    111112    case RegExpTest:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r187555 r188105  
    10131013            break;
    10141014        }
     1015
     1016        case CheckIdent: {
     1017            UniquedStringImpl* uid = node->uidOperand();
     1018            if (uid->isSymbol())
     1019                fixEdge<SymbolUse>(node->child1());
     1020            else
     1021                fixEdge<StringIdentUse>(node->child1());
     1022            break;
     1023        }
    10151024           
    10161025        case Arrayify:
     
    17611770        case StringUse:
    17621771        case KnownStringUse:
     1772        case SymbolUse:
    17631773        case StringObjectUse:
    17641774        case StringOrStringObjectUse:
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r187780 r188105  
    13291329    }
    13301330
     1331    bool hasUidOperand()
     1332    {
     1333        return op() == CheckIdent;
     1334    }
     1335
     1336    UniquedStringImpl* uidOperand()
     1337    {
     1338        ASSERT(hasUidOperand());
     1339        return reinterpret_cast<UniquedStringImpl*>(m_opInfo);
     1340    }
     1341
    13311342    bool hasTransition()
    13321343    {
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r187555 r188105  
    210210    macro(CheckBadCell, NodeMustGenerate) \
    211211    macro(CheckInBounds, NodeMustGenerate) \
     212    macro(CheckIdent, NodeMustGenerate) \
    212213    \
    213214    /* Optimizations for array mutation. */\
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r187555 r188105  
    650650        case CheckCell:
    651651        case CheckNotEmpty:
     652        case CheckIdent:
    652653        case CheckBadCell:
    653654        case PutStructure:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r187780 r188105  
    6060        case StringIdentUse:
    6161        case StringUse:
     62        case SymbolUse:
    6263        case StringObjectUse:
    6364        case StringOrStringObjectUse:
     
    189190    case CheckBadCell:
    190191    case CheckNotEmpty:
     192    case CheckIdent:
    191193    case RegExpExec:
    192194    case RegExpTest:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r186860 r188105  
    45774577}
    45784578
     4579void SpeculativeJIT::compileCheckIdent(Node* node)
     4580{
     4581    SpeculateCellOperand operand(this, node->child1());
     4582    UniquedStringImpl* uid = node->uidOperand();
     4583    if (uid->isSymbol()) {
     4584        speculateSymbol(node->child1(), operand.gpr());
     4585        speculationCheck(
     4586            BadIdent, JSValueSource(), nullptr,
     4587            m_jit.branchPtr(
     4588                JITCompiler::NotEqual,
     4589                JITCompiler::Address(operand.gpr(), Symbol::offsetOfPrivateName()),
     4590                TrustedImmPtr(uid)));
     4591    } else {
     4592        speculateString(node->child1(), operand.gpr());
     4593        speculateStringIdent(node->child1(), operand.gpr());
     4594        speculationCheck(
     4595            BadIdent, JSValueSource(), nullptr,
     4596            m_jit.branchPtr(
     4597                JITCompiler::NotEqual,
     4598                JITCompiler::Address(operand.gpr(), JSString::offsetOfValue()),
     4599                TrustedImmPtr(uid)));
     4600    }
     4601    noResult(node);
     4602}
     4603
    45794604void SpeculativeJIT::compileNewFunction(Node* node)
    45804605{
     
    57325757}
    57335758
     5759void SpeculativeJIT::speculateSymbol(Edge edge, GPRReg cell)
     5760{
     5761    DFG_TYPE_CHECK(JSValueSource::unboxedCell(cell), edge, SpecSymbol, m_jit.branchIfNotSymbol(cell));
     5762}
     5763
     5764void SpeculativeJIT::speculateSymbol(Edge edge)
     5765{
     5766    if (!needsTypeCheck(edge, SpecSymbol))
     5767        return;
     5768
     5769    SpeculateCellOperand operand(this, edge);
     5770    speculateSymbol(edge, operand.gpr());
     5771}
     5772
    57345773void SpeculativeJIT::speculateNotCell(Edge edge)
    57355774{
     
    58425881    case StringUse:
    58435882        speculateString(edge);
     5883        break;
     5884    case SymbolUse:
     5885        speculateSymbol(edge);
    58445886        break;
    58455887    case StringObjectUse:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r186860 r188105  
    21922192
    21932193    void compileGetArrayLength(Node*);
     2194
     2195    void compileCheckIdent(Node*);
    21942196   
    21952197    void compileValueRep(Node*);
     
    24072409    void speculateStringObject(Edge);
    24082410    void speculateStringOrStringObject(Edge);
     2411    void speculateSymbol(Edge, GPRReg cell);
     2412    void speculateSymbol(Edge);
    24092413    void speculateNotCell(Edge);
    24102414    void speculateOther(Edge);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r187555 r188105  
    38213821    }
    38223822
     3823    case CheckIdent:
     3824        compileCheckIdent(node);
     3825        break;
     3826
    38233827    case GetExecutable: {
    38243828        SpeculateCellOperand function(this, node->child1());
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r187555 r188105  
    38513851    }
    38523852
     3853    case CheckIdent:
     3854        compileCheckIdent(node);
     3855        break;
     3856
    38533857    case GetExecutable: {
    38543858        SpeculateCellOperand function(this, node->child1());
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp

    r185239 r188105  
    9898        out.print("KnownString");
    9999        return;
     100    case SymbolUse:
     101        out.print("Symbol");
     102        return;
    100103    case StringObjectUse:
    101104        out.print("StringObject");
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r185239 r188105  
    5858    StringUse,
    5959    KnownStringUse,
     60    SymbolUse,
    6061    StringObjectUse,
    6162    StringOrStringObjectUse,
     
    118119    case KnownStringUse:
    119120        return SpecString;
     121    case SymbolUse:
     122        return SpecSymbol;
    120123    case StringObjectUse:
    121124        return SpecStringObject;
     
    197200    case StringUse:
    198201    case KnownStringUse:
     202    case SymbolUse:
    199203    case StringObjectUse:
    200204    case StringOrStringObjectUse:
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r182929 r188105  
    8888    macro(Structure_globalObject, Structure::globalObjectOffset()) \
    8989    macro(Structure_prototype, Structure::prototypeOffset()) \
    90     macro(Structure_structureID, Structure::structureIDOffset())
     90    macro(Structure_structureID, Structure::structureIDOffset()) \
     91    macro(Symbol_privateName, Symbol::offsetOfPrivateName())
    9192
    9293#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r187555 r188105  
    119119    case CheckBadCell:
    120120    case CheckNotEmpty:
     121    case CheckIdent:
    121122    case StringCharCodeAt:
    122123    case AllocatePropertyStorage:
     
    416417                case StringObjectUse:
    417418                case StringOrStringObjectUse:
     419                case SymbolUse:
    418420                case FinalObjectUse:
    419421                case NotCellUse:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r188086 r188105  
    533533            compileCheckBadCell();
    534534            break;
     535        case CheckIdent:
     536            compileCheckIdent();
     537            break;
    535538        case GetExecutable:
    536539            compileGetExecutable();
     
    20282031    {
    20292032        speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node->child1())));
     2033    }
     2034
     2035    void compileCheckIdent()
     2036    {
     2037        UniquedStringImpl* uid = m_node->uidOperand();
     2038        if (uid->isSymbol()) {
     2039            LValue symbol = lowSymbol(m_node->child1());
     2040            LValue stringImpl = m_out.loadPtr(symbol, m_heaps.Symbol_privateName);
     2041            speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
     2042        } else {
     2043            LValue string = lowStringIdent(m_node->child1());
     2044            LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
     2045            speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
     2046        }
    20302047    }
    20312048
     
    70217038        return stringImpl;
    70227039    }
    7023    
     7040
     7041    LValue lowSymbol(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     7042    {
     7043        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == SymbolUse);
     7044
     7045        LValue result = lowCell(edge, mode);
     7046        speculateSymbol(edge, result);
     7047        return result;
     7048    }
     7049
    70247050    LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
    70257051    {
     
    74187444            speculateStringIdent(edge);
    74197445            break;
     7446        case SymbolUse:
     7447            speculateSymbol(edge);
     7448            break;
    74207449        case StringObjectUse:
    74217450            speculateStringObject(edge);
     
    75147543            m_out.constInt32(vm().stringStructure->id()));
    75157544    }
    7516    
     7545
     7546    LValue isNotSymbol(LValue cell, SpeculatedType type = SpecFullTop)
     7547    {
     7548        if (LValue proven = isProvenValue(type & SpecCell, ~SpecSymbol))
     7549            return proven;
     7550        return m_out.notEqual(
     7551            m_out.load32(cell, m_heaps.JSCell_structureID),
     7552            m_out.constInt32(vm().symbolStructure->id()));
     7553    }
     7554
    75177555    LValue isArrayType(LValue cell, ArrayMode arrayMode)
    75187556    {
     
    77377775            m_out.notEqual(structureID, weakStructureID(stringObjectStructure)));
    77387776    }
    7739    
     7777
     7778    void speculateSymbol(Edge edge, LValue cell)
     7779    {
     7780        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecSymbol | ~SpecCell, isNotSymbol(cell));
     7781    }
     7782
     7783    void speculateSymbol(Edge edge)
     7784    {
     7785        speculateSymbol(edge, lowCell(edge));
     7786    }
     7787
    77407788    void speculateNonNullObject(Edge edge, LValue cell)
    77417789    {
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r187969 r188105  
    658658        m_putByIds[i].finalize(patchBuffer);
    659659
    660     m_codeBlock->setNumberOfByValInfos(m_byValCompilationInfo.size());
    661     for (unsigned i = 0; i < m_byValCompilationInfo.size(); ++i) {
    662         CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(m_byValCompilationInfo[i].badTypeJump));
    663         CodeLocationLabel doneTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].doneTarget);
    664         CodeLocationLabel slowPathTarget = patchBuffer.locationOf(m_byValCompilationInfo[i].slowPathTarget);
    665         CodeLocationCall returnAddress = patchBuffer.locationOf(m_byValCompilationInfo[i].returnAddress);
    666        
    667         m_codeBlock->byValInfo(i) = ByValInfo(
    668             m_byValCompilationInfo[i].bytecodeIndex,
     660    for (const auto& byValCompilationInfo : m_byValCompilationInfo) {
     661        PatchableJump patchableNotIndexJump = byValCompilationInfo.notIndexJump;
     662        CodeLocationJump notIndexJump = CodeLocationJump();
     663        if (Jump(patchableNotIndexJump).isSet())
     664            notIndexJump = CodeLocationJump(patchBuffer.locationOf(patchableNotIndexJump));
     665        CodeLocationJump badTypeJump = CodeLocationJump(patchBuffer.locationOf(byValCompilationInfo.badTypeJump));
     666        CodeLocationLabel doneTarget = patchBuffer.locationOf(byValCompilationInfo.doneTarget);
     667        CodeLocationLabel slowPathTarget = patchBuffer.locationOf(byValCompilationInfo.slowPathTarget);
     668        CodeLocationCall returnAddress = patchBuffer.locationOf(byValCompilationInfo.returnAddress);
     669
     670        *byValCompilationInfo.byValInfo = ByValInfo(
     671            byValCompilationInfo.bytecodeIndex,
     672            notIndexJump,
    669673            badTypeJump,
    670             m_byValCompilationInfo[i].arrayMode,
     674            byValCompilationInfo.arrayMode,
     675            byValCompilationInfo.arrayProfile,
    671676            differenceBetweenCodePtr(badTypeJump, doneTarget),
    672677            differenceBetweenCodePtr(returnAddress, slowPathTarget));
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r187969 r188105  
    150150        ByValCompilationInfo() { }
    151151       
    152         ByValCompilationInfo(unsigned bytecodeIndex, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, MacroAssembler::Label doneTarget)
    153             : bytecodeIndex(bytecodeIndex)
     152        ByValCompilationInfo(ByValInfo* byValInfo, unsigned bytecodeIndex, MacroAssembler::PatchableJump notIndexJump, MacroAssembler::PatchableJump badTypeJump, JITArrayMode arrayMode, ArrayProfile* arrayProfile, MacroAssembler::Label doneTarget)
     153            : byValInfo(byValInfo)
     154            , bytecodeIndex(bytecodeIndex)
     155            , notIndexJump(notIndexJump)
    154156            , badTypeJump(badTypeJump)
    155157            , arrayMode(arrayMode)
     158            , arrayProfile(arrayProfile)
    156159            , doneTarget(doneTarget)
    157160        {
    158161        }
    159        
     162
     163        ByValInfo* byValInfo;
    160164        unsigned bytecodeIndex;
     165        MacroAssembler::PatchableJump notIndexJump;
    161166        MacroAssembler::PatchableJump badTypeJump;
    162167        JITArrayMode arrayMode;
     168        ArrayProfile* arrayProfile;
    163169        MacroAssembler::Label doneTarget;
    164170        MacroAssembler::Label slowPathTarget;
     
    205211        }
    206212
     213        static void compileGetByValWithCachedId(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, const Identifier& propertyName)
     214        {
     215            JIT jit(vm, codeBlock);
     216            jit.m_bytecodeOffset = byValInfo->bytecodeIndex;
     217            jit.privateCompileGetByValWithCachedId(byValInfo, returnAddress, propertyName);
     218        }
     219
    207220        static void compilePutByVal(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
    208221        {
     
    247260       
    248261        void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
     262        void privateCompileGetByValWithCachedId(ByValInfo*, ReturnAddressPtr, const Identifier&);
    249263        void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
    250264
     
    372386        JumpList emitIntTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType);
    373387        JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump& badType, TypedArrayType);
    374        
     388
     389        JITGetByIdGenerator emitGetByValWithCachedId(Instruction*, const Identifier&, JumpList& doneCases, JumpList& slowCases);
     390
    375391        enum FinalObjectMode { MayBeFinal, KnownNotFinal };
    376392
     
    702718        MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg);
    703719        MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, ArrayProfile*);
     720        MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, ByValInfo*);
    704721        MacroAssembler::Call callOperation(C_JITOperation_EJsc, GPRReg);
    705722        MacroAssembler::Call callOperation(J_JITOperation_EJscC, int, GPRReg, JSCell*);
     
    746763        MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID);
    747764        MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, ArrayProfile*);
     765        MacroAssembler::Call callOperation(V_JITOperation_EJJJBy, RegisterID, RegisterID, RegisterID, ByValInfo*);
    748766        MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, int32_t, RegisterID);
    749767        MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, int32_t);
     
    762780        MacroAssembler::Call callOperation(J_JITOperation_EJJ, int, GPRReg, GPRReg, GPRReg, GPRReg);
    763781        MacroAssembler::Call callOperation(J_JITOperation_EJJAp, int, GPRReg, GPRReg, GPRReg, GPRReg, ArrayProfile*);
     782        MacroAssembler::Call callOperation(J_JITOperation_EJJBy, int, GPRReg, GPRReg, GPRReg, GPRReg, ByValInfo*);
    764783        MacroAssembler::Call callOperation(P_JITOperation_EJS, GPRReg, GPRReg, size_t);
    765784        MacroAssembler::Call callOperation(S_JITOperation_EJ, RegisterID, RegisterID);
     
    769788        MacroAssembler::Call callOperation(V_JITOperation_EJJJ, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID);
    770789        MacroAssembler::Call callOperation(V_JITOperation_EJJJAp, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, ArrayProfile*);
     790        MacroAssembler::Call callOperation(V_JITOperation_EJJJBy, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, RegisterID, ByValInfo*);
    771791        MacroAssembler::Call callOperation(V_JITOperation_EJZ, RegisterID, RegisterID, int32_t);
    772792        MacroAssembler::Call callOperation(V_JITOperation_EJZJ, RegisterID, RegisterID, int32_t, RegisterID, RegisterID);
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r186860 r188105  
    412412}
    413413
     414ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJBy operation, RegisterID regOp1, RegisterID regOp2, RegisterID regOp3, ByValInfo* byValInfo)
     415{
     416    setupArgumentsWithExecState(regOp1, regOp2, regOp3, TrustedImmPtr(byValInfo));
     417    return appendCallWithExceptionCheck(operation);
     418}
     419
    414420ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EZJ operation, int dst, GPRReg arg)
    415421{
     
    457463{
    458464    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(arrayProfile));
     465    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
     466}
     467
     468ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJBy operation, int dst, GPRReg arg1, GPRReg arg2, ByValInfo* byValInfo)
     469{
     470    setupArgumentsWithExecState(arg1, arg2, TrustedImmPtr(byValInfo));
    459471    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
    460472}
     
    601613}
    602614
     615ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EJJBy operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload, ByValInfo* byValInfo)
     616{
     617    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, SH4_32BIT_DUMMY_ARG arg2Payload, arg2Tag, TrustedImmPtr(byValInfo));
     618    return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
     619}
     620
    603621ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(JIT::WithProfileTag, J_JITOperation_EJJ operation, int dst, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload)
    604622{
     
    664682{
    665683    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag, TrustedImmPtr(arrayProfile));
     684    return appendCallWithExceptionCheck(operation);
     685}
     686
     687ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EJJJBy operation, RegisterID regOp1Tag, RegisterID regOp1Payload, RegisterID regOp2Tag, RegisterID regOp2Payload, RegisterID regOp3Tag, RegisterID regOp3Payload, ByValInfo* byValInfo)
     688{
     689    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG regOp1Payload, regOp1Tag, SH4_32BIT_DUMMY_ARG regOp2Payload, regOp2Tag, regOp3Payload, regOp3Tag, TrustedImmPtr(byValInfo));
    666690    return appendCallWithExceptionCheck(operation);
    667691}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r187969 r188105  
    10691069    int property = currentInstruction[3].u.operand;
    10701070    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1071    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
    10711072   
    10721073    emitGetVirtualRegisters(base, regT0, property, regT1);
     
    11001101    emitPutVirtualRegister(dst);
    11011102   
    1102     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     1103    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done));
    11031104}
    11041105
     
    11081109    int base = currentInstruction[2].u.operand;
    11091110    int property = currentInstruction[3].u.operand;
    1110     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1111    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
    11111112   
    11121113    linkSlowCaseIfNotJSCell(iter, base); // base cell check
     
    11191120    emitGetVirtualRegister(base, regT0);
    11201121    emitGetVirtualRegister(property, regT1);
    1121     Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1, profile);
     1122    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1, byValInfo);
    11221123
    11231124    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r187969 r188105  
    10691069    int property = currentInstruction[3].u.operand;
    10701070    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1071    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
    10711072   
    10721073    emitLoadPayload(base, regT0);
     
    11011102    emitStoreBool(dst, regT0);
    11021103   
    1103     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     1104    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done));
    11041105}
    11051106
     
    11091110    int base = currentInstruction[2].u.operand;
    11101111    int property = currentInstruction[3].u.operand;
    1111     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     1112    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
    11121113   
    11131114    linkSlowCaseIfNotJSCell(iter, base); // base cell check
     
    11201121    emitLoad(base, regT1, regT0);
    11211122    emitLoad(property, regT3, regT2);
    1122     Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2, profile);
     1123    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2, byValInfo);
    11231124
    11241125    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r187969 r188105  
    479479}
    480480
    481 static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)
     481static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value, ByValInfo* byValInfo)
    482482{
    483483    VM& vm = callFrame->vm();
     
    489489                object->setIndexQuickly(callFrame->vm(), i, value);
    490490            else {
    491                 arrayProfile->setOutOfBounds();
     491                byValInfo->arrayProfile->setOutOfBounds();
    492492                object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
    493493            }
     
    503503}
    504504
    505 static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ArrayProfile* arrayProfile)
     505static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value, ByValInfo* byValInfo)
    506506{
    507507    bool isStrictMode = callFrame->codeBlock()->isStrictMode();
     
    515515        }
    516516
    517         arrayProfile->setOutOfBounds();
     517        byValInfo->arrayProfile->setOutOfBounds();
    518518        baseObject->putDirectIndex(callFrame, index, value, 0, isStrictMode ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
    519519        return;
     
    541541    }
    542542}
    543 void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
     543void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
    544544{
    545545    VM& vm = exec->vm();
     
    555555        bool didOptimize = false;
    556556
    557         unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
    558         ASSERT(bytecodeOffset);
    559         ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
    560         ASSERT(!byValInfo.stubRoutine);
     557        ASSERT(exec->locationAsBytecodeOffset());
     558        ASSERT(!byValInfo->stubRoutine);
    561559
    562560        Structure* structure = object->structure(vm);
     
    564562            // Attempt to optimize.
    565563            JITArrayMode arrayMode = jitArrayModeForStructure(structure);
    566             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
     564            if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
    567565                CodeBlock* codeBlock = exec->codeBlock();
    568566                ConcurrentJITLocker locker(codeBlock->m_lock);
    569                 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
    570 
    571                 JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
     567                byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
     568
     569                JIT::compilePutByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
    572570                didOptimize = true;
    573571            }
     
    580578            // where we see non-index-intercepting objects, this gives 10 iterations worth of
    581579            // opportunity for us to observe that the get_by_val may be polymorphic.
    582             if (++byValInfo.slowPathCount >= 10
     580            if (++byValInfo->slowPathCount >= 10
    583581                || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
    584582                // Don't ever try to optimize.
     
    588586    }
    589587
    590     putByVal(exec, baseValue, subscript, value, arrayProfile);
    591 }
    592 
    593 void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
     588    putByVal(exec, baseValue, subscript, value, byValInfo);
     589}
     590
     591void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
    594592{
    595593    VM& vm = callFrame->vm();
     
    604602        // See if it's worth optimizing at all.
    605603        bool didOptimize = false;
    606        
    607         unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
    608         ASSERT(bytecodeOffset);
    609         ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
    610         ASSERT(!byValInfo.stubRoutine);
     604
     605        ASSERT(callFrame->locationAsBytecodeOffset());
     606        ASSERT(!byValInfo->stubRoutine);
    611607
    612608        Structure* structure = object->structure(vm);
     
    614610            // Attempt to optimize.
    615611            JITArrayMode arrayMode = jitArrayModeForStructure(structure);
    616             if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo.arrayMode) {
     612            if (jitArrayModePermitsPut(arrayMode) && arrayMode != byValInfo->arrayMode) {
    617613                CodeBlock* codeBlock = callFrame->codeBlock();
    618614                ConcurrentJITLocker locker(codeBlock->m_lock);
    619                 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
    620 
    621                 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
     615                byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
     616
     617                JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
    622618                didOptimize = true;
    623619            }
     
    630626            // where we see non-index-intercepting objects, this gives 10 iterations worth of
    631627            // opportunity for us to observe that the get_by_val may be polymorphic.
    632             if (++byValInfo.slowPathCount >= 10
     628            if (++byValInfo->slowPathCount >= 10
    633629                || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
    634630                // Don't ever try to optimize.
     
    637633        }
    638634    }
    639     directPutByVal(callFrame, object, subscript, value, arrayProfile);
    640 }
    641 
    642 void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
     635    directPutByVal(callFrame, object, subscript, value, byValInfo);
     636}
     637
     638void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
    643639{
    644640    VM& vm = exec->vm();
     
    649645    JSValue value = JSValue::decode(encodedValue);
    650646
    651     putByVal(exec, baseValue, subscript, value, arrayProfile);
    652 }
    653 
    654 
    655 void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ArrayProfile* arrayProfile)
     647    putByVal(exec, baseValue, subscript, value, byValInfo);
     648}
     649
     650
     651void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue, ByValInfo* byValInfo)
    656652{
    657653    VM& vm = exec->vm();
     
    662658    JSValue value = JSValue::decode(encodedValue);
    663659    RELEASE_ASSERT(baseValue.isObject());
    664     directPutByVal(exec, asObject(baseValue), subscript, value, arrayProfile);
     660    directPutByVal(exec, asObject(baseValue), subscript, value, byValInfo);
    665661}
    666662
     
    14301426}
    14311427
    1432 static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ArrayProfile* arrayProfile, ReturnAddressPtr returnAddress)
     1428static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ByValInfo* byValInfo, ReturnAddressPtr returnAddress)
    14331429{
    14341430    if (LIKELY(baseValue.isCell() && subscript.isString())) {
     
    14371433        if (JSCell::canUseFastGetOwnProperty(structure)) {
    14381434            if (RefPtr<AtomicStringImpl> existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
    1439                 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get()))
     1435                if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString.get())) {
     1436                    ASSERT(exec->locationAsBytecodeOffset());
     1437                    if (byValInfo->stubInfo && byValInfo->cachedId.impl() != existingAtomicString)
     1438                        byValInfo->tookSlowPath = true;
    14401439                    return result;
     1440                }
    14411441            }
    14421442        }
     
    14441444
    14451445    if (subscript.isUInt32()) {
     1446        ASSERT(exec->locationAsBytecodeOffset());
     1447        byValInfo->tookSlowPath = true;
     1448
    14461449        uint32_t i = subscript.asUInt32();
    14471450        if (isJSString(baseValue)) {
     
    14501453                return asString(baseValue)->getIndex(exec, i);
    14511454            }
    1452             arrayProfile->setOutOfBounds();
     1455            byValInfo->arrayProfile->setOutOfBounds();
    14531456        } else if (baseValue.isObject()) {
    14541457            JSObject* object = asObject(baseValue);
     
    14571460
    14581461            if (!canAccessArgumentIndexQuickly(*object, i))
    1459                 arrayProfile->setOutOfBounds();
     1462                byValInfo->arrayProfile->setOutOfBounds();
    14601463        }
    14611464
     
    14691472    if (exec->hadException())
    14701473        return jsUndefined();
     1474
     1475    ASSERT(exec->locationAsBytecodeOffset());
     1476    if (byValInfo->stubInfo && byValInfo->cachedId != property)
     1477        byValInfo->tookSlowPath = true;
     1478
    14711479    return baseValue.get(exec, property);
    14721480}
     
    14741482extern "C" {
    14751483   
    1476 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
     1484EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
    14771485{
    14781486    VM& vm = exec->vm();
     
    14811489    JSValue subscript = JSValue::decode(encodedSubscript);
    14821490
    1483     JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS));
     1491    JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
    14841492    return JSValue::encode(result);
    14851493}
    14861494
    1487 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
     1495EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
    14881496{
    14891497    VM& vm = exec->vm();
     
    14911499    JSValue baseValue = JSValue::decode(encodedBase);
    14921500    JSValue subscript = JSValue::decode(encodedSubscript);
    1493    
     1501
    14941502    if (baseValue.isObject() && subscript.isInt32()) {
    14951503        // See if it's worth optimizing this at all.
     
    14971505        bool didOptimize = false;
    14981506
    1499         unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
    1500         ASSERT(bytecodeOffset);
    1501         ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
    1502         ASSERT(!byValInfo.stubRoutine);
    1503        
     1507        ASSERT(exec->locationAsBytecodeOffset());
     1508        ASSERT(!byValInfo->stubRoutine);
     1509
    15041510        if (hasOptimizableIndexing(object->structure(vm))) {
    15051511            // Attempt to optimize.
    15061512            Structure* structure = object->structure(vm);
    15071513            JITArrayMode arrayMode = jitArrayModeForStructure(structure);
    1508             if (arrayMode != byValInfo.arrayMode) {
     1514            if (arrayMode != byValInfo->arrayMode) {
    15091515                // If we reached this case, we got an interesting array mode we did not expect when we compiled.
    15101516                // Let's update the profile to do better next time.
    15111517                CodeBlock* codeBlock = exec->codeBlock();
    15121518                ConcurrentJITLocker locker(codeBlock->m_lock);
    1513                 arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
    1514 
    1515                 JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
     1519                byValInfo->arrayProfile->computeUpdatedPrediction(locker, codeBlock, structure);
     1520
     1521                JIT::compileGetByVal(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
    15161522                didOptimize = true;
    15171523            }
    15181524        }
    1519        
     1525
    15201526        if (!didOptimize) {
    15211527            // If we take slow path more than 10 times without patching then make sure we
     
    15241530            // where we see non-index-intercepting objects, this gives 10 iterations worth of
    15251531            // opportunity for us to observe that the get_by_val may be polymorphic.
    1526             if (++byValInfo.slowPathCount >= 10
     1532            if (++byValInfo->slowPathCount >= 10
    15271533                || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
    15281534                // Don't ever try to optimize.
     
    15311537        }
    15321538    }
    1533    
    1534     JSValue result = getByVal(exec, baseValue, subscript, arrayProfile, ReturnAddressPtr(OUR_RETURN_ADDRESS));
     1539
     1540    if (baseValue.isObject() && (subscript.isSymbol() || subscript.isString())) {
     1541        const Identifier propertyName = subscript.toPropertyKey(exec);
     1542
     1543        if (!subscript.isString() || !parseIndex(propertyName)) {
     1544            ASSERT(exec->locationAsBytecodeOffset());
     1545            ASSERT(!byValInfo->stubRoutine);
     1546            JIT::compileGetByValWithCachedId(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), propertyName);
     1547        }
     1548
     1549        PropertySlot slot(baseValue);
     1550        bool hasResult = baseValue.getPropertySlot(exec, propertyName, slot);
     1551        return JSValue::encode(hasResult ? slot.getValue(exec, propertyName) : jsUndefined());
     1552    }
     1553
     1554    JSValue result = getByVal(exec, baseValue, subscript, byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS));
    15351555    return JSValue::encode(result);
    15361556}
    1537    
    1538 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
     1557
     1558EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
    15391559{
    15401560    VM& vm = exec->vm();
     
    15491569    bool didOptimize = false;
    15501570
    1551     unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
    1552     ASSERT(bytecodeOffset);
    1553     ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
    1554     ASSERT(!byValInfo.stubRoutine);
     1571    ASSERT(exec->locationAsBytecodeOffset());
     1572    ASSERT(!byValInfo->stubRoutine);
    15551573   
    15561574    if (hasOptimizableIndexing(object->structure(vm))) {
    15571575        // Attempt to optimize.
    15581576        JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
    1559         if (arrayMode != byValInfo.arrayMode) {
    1560             JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
     1577        if (arrayMode != byValInfo->arrayMode) {
     1578            JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
    15611579            didOptimize = true;
    15621580        }
     
    15691587        // where we see non-index-intercepting objects, this gives 10 iterations worth of
    15701588        // opportunity for us to observe that the get_by_val may be polymorphic.
    1571         if (++byValInfo.slowPathCount >= 10
     1589        if (++byValInfo->slowPathCount >= 10
    15721590            || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
    15731591            // Don't ever try to optimize.
    1574             ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric)); 
     1592            ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
    15751593        }
    15761594    }
     
    15811599
    15821600    if (!canAccessArgumentIndexQuickly(*object, index))
    1583         arrayProfile->setOutOfBounds();
     1601        byValInfo->arrayProfile->setOutOfBounds();
    15841602    return JSValue::encode(jsBoolean(object->hasProperty(exec, index)));
    15851603}
    15861604   
    1587 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile* arrayProfile)
     1605EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
    15881606{
    15891607    VM& vm = exec->vm();
     
    16011619
    16021620    if (!canAccessArgumentIndexQuickly(*object, index))
    1603         arrayProfile->setOutOfBounds();
     1621        byValInfo->arrayProfile->setOutOfBounds();
    16041622    return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
    16051623}
    16061624   
    1607 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
     1625EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo* byValInfo)
    16081626{
    16091627    VM& vm = exec->vm();
     
    16201638            result = baseValue.get(exec, i);
    16211639            if (!isJSString(baseValue)) {
    1622                 unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
    1623                 ASSERT(bytecodeOffset);
    1624                 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
    1625                 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo.stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
     1640                ASSERT(exec->locationAsBytecodeOffset());
     1641                ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(byValInfo->stubRoutine ? operationGetByValGeneric : operationGetByValOptimize));
    16261642            }
    16271643        }
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r187750 r188105  
    5959    Aap: ArrayAllocationProfile*
    6060    Ap: ArrayProfile*
     61    By: ByValInfo*
    6162    C: JSCell*
    6263    Cb: CodeBlock*
     
    114115typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
    115116typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, ArrayProfile*);
     117typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, ByValInfo*);
    116118typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJssZ)(ExecState*, JSString*, int32_t);
    117119typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJP)(ExecState*, EncodedJSValue, void*);
     
    196198typedef void JIT_OPERATION (*V_JITOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue);
    197199typedef void JIT_OPERATION (*V_JITOperation_EJJJAp)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*);
     200typedef void JIT_OPERATION (*V_JITOperation_EJJJBy)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*);
    198201typedef void JIT_OPERATION (*V_JITOperation_EJPP)(ExecState*, EncodedJSValue, void*, void*);
    199202typedef void JIT_OPERATION (*V_JITOperation_EJZJ)(ExecState*, EncodedJSValue, int32_t, EncodedJSValue);
     
    260263void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL;
    261264void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL;
    262 void JIT_OPERATION operationPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;
    263 void JIT_OPERATION operationDirectPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;
    264 void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;
    265 void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ArrayProfile*) WTF_INTERNAL;
     265void JIT_OPERATION operationPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
     266void JIT_OPERATION operationDirectPutByVal(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
     267void JIT_OPERATION operationPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
     268void JIT_OPERATION operationDirectPutByValGeneric(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue, ByValInfo*) WTF_INTERNAL;
    266269EncodedJSValue JIT_OPERATION operationCallEval(ExecState*, ExecState*) WTF_INTERNAL;
    267270char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
     
    311314void JIT_OPERATION operationProfileWillCall(ExecState*, EncodedJSValue) WTF_INTERNAL;
    312315EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState*, EncodedJSValue, EncodedJSValue baseVal) WTF_INTERNAL;
    313 EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;
    314 EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;
    315 EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
    316 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;
    317 EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ArrayProfile*) WTF_INTERNAL;
     316EncodedJSValue JIT_OPERATION operationGetByValOptimize(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     317EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     318EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     319EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
     320EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript, ByValInfo*) WTF_INTERNAL;
    318321EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL;
    319322JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r187750 r188105  
    9999    int property = currentInstruction[3].u.operand;
    100100    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
    101    
     101    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
     102
    102103    emitGetVirtualRegisters(base, regT0, property, regT1);
    103     emitJumpSlowCaseIfNotImmediateInteger(regT1);
    104 
     104
     105    emitJumpSlowCaseIfNotJSCell(regT0, base);
     106
     107    // FIXME: patchableBranch64 could reduce the following 2 jumps into 1. Like,
     108    //
     109    // PatchableJump notIndex = emitJumpIfNotImmediateInteger(regT1);
     110    //
     111    // To use patchableBranch64, we need to fix the existing patchableBranchPtr in ARM64
     112    // and introduce patchableBranch64 helper function for 64bit environments.
     113    // https://bugs.webkit.org/show_bug.cgi?id=147761
     114    Jump isIndex = emitJumpIfImmediateInteger(regT1);
     115    PatchableJump notIndex = patchableJump();
     116    addSlowCase(notIndex);
     117
     118    isIndex.link(this);
    105119    // This is technically incorrect - we're zero-extending an int32.  On the hot path this doesn't matter.
    106120    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
     
    111125    zeroExtend32ToPtr(regT1, regT1);
    112126
    113     emitJumpSlowCaseIfNotJSCell(regT0, base);
    114127    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
    115128    and32(TrustedImm32(IndexingShapeMask), regT2);
     
    150163    emitValueProfilingSite();
    151164    emitPutVirtualRegister(dst);
    152    
    153     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     165
     166    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done));
    154167}
    155168
     
    196209}
    197210
     211JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
     212{
     213    // base: regT0
     214    // property: regT1
     215    // scratch: regT3
     216
     217    int dst = currentInstruction[1].u.operand;
     218
     219    slowCases.append(emitJumpIfNotJSCell(regT1));
     220    if (propertyName.isSymbol()) {
     221        slowCases.append(branchStructure(NotEqual, Address(regT1, JSCell::structureIDOffset()), m_vm->symbolStructure.get()));
     222        loadPtr(Address(regT1, Symbol::offsetOfPrivateName()), regT3);
     223    } else {
     224        slowCases.append(branchStructure(NotEqual, Address(regT1, JSCell::structureIDOffset()), m_vm->stringStructure.get()));
     225        loadPtr(Address(regT1, JSString::offsetOfValue()), regT3);
     226        slowCases.append(branchTestPtr(Zero, regT3));
     227        slowCases.append(branchTest32(Zero, Address(regT3, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIsAtomic())));
     228    }
     229    slowCases.append(branchPtr(NotEqual, regT3, TrustedImmPtr(propertyName.impl())));
     230
     231    JITGetByIdGenerator gen(
     232        m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
     233        JSValueRegs(regT0), JSValueRegs(regT0), DontSpill);
     234    gen.generateFastPath(*this);
     235
     236    doneCases.append(jump());
     237
     238    Label coldPathBegin = label();
     239    gen.slowPathJump().link(this);
     240
     241    Call call = callOperation(WithProfile, operationGetByIdOptimize, dst, gen.stubInfo(), regT0, propertyName.impl());
     242    gen.reportSlowPathCall(coldPathBegin, call);
     243    doneCases.append(jump());
     244
     245    return gen;
     246}
     247
    198248void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    199249{
     
    201251    int base = currentInstruction[2].u.operand;
    202252    int property = currentInstruction[3].u.operand;
    203     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
    204    
     253    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
     254   
     255    linkSlowCaseIfNotJSCell(iter, base); // base cell check
    205256    linkSlowCase(iter); // property int32 check
    206     linkSlowCaseIfNotJSCell(iter, base); // base cell check
    207257    Jump nonCell = jump();
    208258    linkSlowCase(iter); // base array check
     
    225275    emitGetVirtualRegister(base, regT0);
    226276    emitGetVirtualRegister(property, regT1);
    227     Call call = callOperation(operationGetByValOptimize, dst, regT0, regT1, profile);
     277    Call call = callOperation(operationGetByValOptimize, dst, regT0, regT1, byValInfo);
    228278
    229279    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
     
    264314    int property = currentInstruction[2].u.operand;
    265315    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     316    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
    266317
    267318    emitGetVirtualRegisters(base, regT0, property, regT1);
     
    300351    Label done = label();
    301352   
    302     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
    303 
     353    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done));
    304354}
    305355
     
    400450    int value = currentInstruction[3].u.operand;
    401451    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     452    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
    402453
    403454    linkSlowCase(iter); // property int32 check
     
    425476    emitGetVirtualRegister(value, regT2);
    426477    bool isDirect = m_interpreter->getOpcodeID(currentInstruction->u.opcode) == op_put_by_val_direct;
    427     Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT0, regT1, regT2, profile);
     478    Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT0, regT1, regT2, byValInfo);
    428479
    429480    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
     
    9971048    RepatchBuffer repatchBuffer(m_codeBlock);
    9981049    repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code()));
     1050    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationGetByValGeneric));
     1051}
     1052
     1053void JIT::privateCompileGetByValWithCachedId(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, const Identifier& propertyName)
     1054{
     1055    Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex;
     1056
     1057    JumpList doneCases;
     1058    JumpList slowCases;
     1059
     1060    JITGetByIdGenerator gen = emitGetByValWithCachedId(currentInstruction, propertyName, doneCases, slowCases);
     1061
     1062    ConcurrentJITLocker locker(m_codeBlock->m_lock);
     1063    LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock);
     1064    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
     1065    patchBuffer.link(doneCases, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
     1066    for (const auto& callSite : m_calls) {
     1067        if (callSite.to)
     1068            patchBuffer.link(callSite.from, FunctionPtr(callSite.to));
     1069    }
     1070    gen.finalize(patchBuffer);
     1071
     1072    byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
     1073        m_codeBlock, patchBuffer,
     1074        ("Baseline get_by_val with cached property name '%s' stub for %s, return point %p", propertyName.impl()->utf8().data(), toCString(*m_codeBlock).data(), returnAddress.value()));
     1075    byValInfo->cachedId = propertyName;
     1076    byValInfo->stubInfo = gen.stubInfo();
     1077
     1078    RepatchBuffer repatchBuffer(m_codeBlock);
     1079    repatchBuffer.relink(byValInfo->notIndexJump, CodeLocationLabel(byValInfo->stubRoutine->code().code()));
    9991080    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationGetByValGeneric));
    10001081}
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r187750 r188105  
    150150    int property = currentInstruction[3].u.operand;
    151151    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     152    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
    152153   
    153154    emitLoad2(base, regT1, regT0, property, regT3, regT2);
    154155   
    155     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    156156    emitJumpSlowCaseIfNotJSCell(base, regT1);
     157    PatchableJump notIndex = patchableBranch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag));
     158    addSlowCase(notIndex);
    157159    emitArrayProfilingSiteWithCell(regT0, regT1, profile);
    158160    and32(TrustedImm32(IndexingShapeMask), regT1);
     
    193195    emitStore(dst, regT1, regT0);
    194196   
    195     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     197    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, notIndex, badType, mode, profile, done));
    196198}
    197199
     
    237239    return slowCases;
    238240}
    239    
     241
     242JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier& propertyName, JumpList& doneCases, JumpList& slowCases)
     243{
     244    int dst = currentInstruction[1].u.operand;
     245
     246    // base: tag(regT1), payload(regT0)
     247    // property: tag(regT3), payload(regT2)
     248    // scratch: regT4
     249
     250    slowCases.append(emitJumpIfNotJSCell(regT3));
     251    if (propertyName.isSymbol()) {
     252        slowCases.append(branchStructure(NotEqual, Address(regT2, JSCell::structureIDOffset()), m_vm->symbolStructure.get()));
     253        loadPtr(Address(regT2, Symbol::offsetOfPrivateName()), regT4);
     254    } else {
     255        slowCases.append(branchStructure(NotEqual, Address(regT2, JSCell::structureIDOffset()), m_vm->stringStructure.get()));
     256        loadPtr(Address(regT2, JSString::offsetOfValue()), regT4);
     257        slowCases.append(branchTestPtr(Zero, regT4));
     258        slowCases.append(branchTest32(Zero, Address(regT4, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIsAtomic())));
     259    }
     260    slowCases.append(branchPtr(NotEqual, regT4, TrustedImmPtr(propertyName.impl())));
     261
     262    JITGetByIdGenerator gen(
     263        m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
     264        JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0), DontSpill);
     265    gen.generateFastPath(*this);
     266
     267    doneCases.append(jump());
     268
     269    Label coldPathBegin = label();
     270    gen.slowPathJump().link(this);
     271
     272    Call call = callOperation(WithProfile, operationGetByIdOptimize, dst, gen.stubInfo(), regT1, regT0, propertyName.impl());
     273    gen.reportSlowPathCall(coldPathBegin, call);
     274    doneCases.append(jump());
     275
     276    return gen;
     277}
     278
    240279void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    241280{
     
    243282    int base = currentInstruction[2].u.operand;
    244283    int property = currentInstruction[3].u.operand;
    245     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
    246    
     284    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
     285
     286    linkSlowCaseIfNotJSCell(iter, base); // base cell check
    247287    linkSlowCase(iter); // property int32 check
    248     linkSlowCaseIfNotJSCell(iter, base); // base cell check
    249288
    250289    Jump nonCell = jump();
     
    266305    emitLoad(base, regT1, regT0);
    267306    emitLoad(property, regT3, regT2);
    268     Call call = callOperation(operationGetByValOptimize, dst, regT1, regT0, regT3, regT2, profile);
     307    Call call = callOperation(operationGetByValOptimize, dst, regT1, regT0, regT3, regT2, byValInfo);
    269308
    270309    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
     
    280319    int property = currentInstruction[2].u.operand;
    281320    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     321    ByValInfo* byValInfo = m_codeBlock->addByValInfo();
    282322   
    283323    emitLoad2(base, regT1, regT0, property, regT3, regT2);
     
    315355    Label done = label();
    316356   
    317     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
     357    m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done));
    318358}
    319359
     
    420460    int value = currentInstruction[3].u.operand;
    421461    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     462    ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
    422463   
    423464    linkSlowCase(iter); // property int32 check
     
    459500    addCallArgument(regT1);
    460501    addCallArgument(regT0);
    461     addCallArgument(TrustedImmPtr(profile));
     502    addCallArgument(TrustedImmPtr(byValInfo));
    462503    Call call = appendCallWithExceptionCheck(isDirect ? operationDirectPutByVal : operationPutByVal);
    463504#else
     
    467508    emitLoad(property, regT3, regT0);
    468509    emitLoad(value, regT5, regT4);
    469     Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT2, regT1, regT3, regT0, regT5, regT4, profile);
     510    Call call = callOperation(isDirect ? operationDirectPutByVal : operationPutByVal, regT2, regT1, regT3, regT0, regT5, regT4, byValInfo);
    470511#endif
    471512
  • trunk/Source/JavaScriptCore/runtime/Symbol.h

    r185002 r188105  
    8080    double toNumber(ExecState*) const;
    8181
     82    static size_t offsetOfPrivateName() { return OBJECT_OFFSETOF(Symbol, m_privateName); }
     83
    8284protected:
    8385    static void destroy(JSCell*);
Note: See TracChangeset for help on using the changeset viewer.