Changeset 231998 in webkit


Ignore:
Timestamp:
May 19, 2018 1:21:30 PM (6 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] JSC should have consistent InById IC
https://bugs.webkit.org/show_bug.cgi?id=185682

Reviewed by Filip Pizlo.

JSTests:

  • stress/in-by-id-accessors.js: Added.

(shouldBe):
(test):
(protoGetter.proto.get hello):
(protoSetter.proto.set hello):
(i.shouldBe.test.get hello):
(i.shouldBe.test.set hello):

  • stress/in-by-id-ai.js: Added.

(shouldBe):
(test):

  • stress/in-by-id-custom-accessors.js: Added.

(shouldBe):
(test1):
(test2):

  • stress/in-by-id-custom-values.js: Added.

(shouldBe):
(test):

  • stress/in-by-id-operation.js: Added.

(shouldBe):
(test):
(selfCache):

  • stress/in-by-id-proxy.js: Added.

(shouldBe):
(test):
(handler.has):

Source/JavaScriptCore:

Current our op_in IC is adhoc: It is only emitted in DFG and FTL layers,
when we found that DFG::In's parameter is constant string. We should
align this IC to the other ById ICs to clean up and remove adhoc code
in DFG and FTL.

This patch cleans up our "In" IC by aligning it to the other ById ICs.
We split op_in bytecode to op_in_by_id and op_in_by_val. op_in_by_val
is the same to the original op_in. For op_in_by_id, we use JITInByIdGenerator
to emit InById IC code. In addition, our JITInByIdGenerator and op_in_by_id
has a inline access cache for own property case, which is the same to
JITGetByIdGenerator.

And we split DFG::In to DFG::InById and DFG::InByVal. InByVal is the same
to the original In DFG node. DFG AI attempts to lower InByVal to InById
if AI figured out that the property name is a constant string. And in
InById node, we use JITInByIdGenerator code.

This patch cleans up DFG and FTL's adhoc In IC code.

In a subsequent patch, we should introduce InByIdStatus to optimize
InById in DFG and FTL. We would like to have a new InByIdStatus instead of
reusing GetByIdStatus since GetByIdStatus becomes too complicated, and
AccessCase::Types are different from them (AccessCase::InHit / InMiss).

  • bytecode/AccessCase.cpp:

(JSC::AccessCase::fromStructureStubInfo):
(JSC::AccessCase::generateWithGuard):

  • bytecode/BytecodeDumper.cpp:

(JSC::BytecodeDumper<Block>::printInByIdCacheStatus):
(JSC::BytecodeDumper<Block>::dumpBytecode):

  • bytecode/BytecodeDumper.h:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::finishCreation):

  • bytecode/InlineAccess.cpp:

(JSC::InlineAccess::generateSelfInAccess):

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

(JSC::StructureStubInfo::initInByIdSelf):
(JSC::StructureStubInfo::deref):
(JSC::StructureStubInfo::aboutToDie):
(JSC::StructureStubInfo::reset):
(JSC::StructureStubInfo::visitWeakReferences):
(JSC::StructureStubInfo::propagateTransitions):

  • bytecode/StructureStubInfo.h:

(JSC::StructureStubInfo::patchableJump):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitInByVal):
(JSC::BytecodeGenerator::emitInById):
(JSC::BytecodeGenerator::emitIn): Deleted.

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::InNode::emitBytecode):

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • 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):

  • dfg/DFGJITCompiler.cpp:

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

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::addInById):
(JSC::DFG::InRecord::InRecord): Deleted.
(JSC::DFG::JITCompiler::addIn): Deleted.

  • dfg/DFGNode.h:

(JSC::DFG::Node::convertToInById):
(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::hasArrayMode):

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

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileInById):
(JSC::DFG::SpeculativeJIT::compileInByVal):
(JSC::DFG::SpeculativeJIT::compileIn): Deleted.

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

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileInByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileInById):
(JSC::FTL::DFG::LowerDFGToB3::compileIn): Deleted.

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

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

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

(JSC::JITInByIdGenerator::JITInByIdGenerator):
(JSC::JITInByIdGenerator::generateFastPath):

  • jit/JITInlineCacheGenerator.h:

(JSC::JITInByIdGenerator::JITInByIdGenerator):

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

(JSC::JIT::emit_op_in_by_id):
(JSC::JIT::emitSlow_op_in_by_id):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_in_by_id):
(JSC::JIT::emitSlow_op_in_by_id):

  • jit/Repatch.cpp:

(JSC::tryCacheInByID):
(JSC::repatchInByID):
(JSC::resetInByID):
(JSC::tryCacheIn): Deleted.
(JSC::repatchIn): Deleted.
(JSC::resetIn): Deleted.

  • jit/Repatch.h:
  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter64.asm:
  • parser/NodeConstructors.h:

(JSC::InNode::InNode):

  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/CommonSlowPaths.h:

(JSC::CommonSlowPaths::opInByVal):
(JSC::CommonSlowPaths::opIn): Deleted.

Location:
trunk
Files:
6 added
50 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r231990 r231998  
     12018-05-19  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] JSC should have consistent InById IC
     4        https://bugs.webkit.org/show_bug.cgi?id=185682
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * stress/in-by-id-accessors.js: Added.
     9        (shouldBe):
     10        (test):
     11        (protoGetter.__proto__.get hello):
     12        (protoSetter.__proto__.set hello):
     13        (i.shouldBe.test.get hello):
     14        (i.shouldBe.test.set hello):
     15        * stress/in-by-id-ai.js: Added.
     16        (shouldBe):
     17        (test):
     18        * stress/in-by-id-custom-accessors.js: Added.
     19        (shouldBe):
     20        (test1):
     21        (test2):
     22        * stress/in-by-id-custom-values.js: Added.
     23        (shouldBe):
     24        (test):
     25        * stress/in-by-id-operation.js: Added.
     26        (shouldBe):
     27        (test):
     28        (selfCache):
     29        * stress/in-by-id-proxy.js: Added.
     30        (shouldBe):
     31        (test):
     32        (handler.has):
     33
    1342018-05-18  Keith Miller  <keith_miller@apple.com>
    235
  • trunk/Source/JavaScriptCore/ChangeLog

    r231993 r231998  
     12018-05-19  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] JSC should have consistent InById IC
     4        https://bugs.webkit.org/show_bug.cgi?id=185682
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Current our op_in IC is adhoc: It is only emitted in DFG and FTL layers,
     9        when we found that DFG::In's parameter is constant string. We should
     10        align this IC to the other ById ICs to clean up and remove adhoc code
     11        in DFG and FTL.
     12
     13        This patch cleans up our "In" IC by aligning it to the other ById ICs.
     14        We split op_in bytecode to op_in_by_id and op_in_by_val. op_in_by_val
     15        is the same to the original op_in. For op_in_by_id, we use JITInByIdGenerator
     16        to emit InById IC code. In addition, our JITInByIdGenerator and op_in_by_id
     17        has a inline access cache for own property case, which is the same to
     18        JITGetByIdGenerator.
     19
     20        And we split DFG::In to DFG::InById and DFG::InByVal. InByVal is the same
     21        to the original In DFG node. DFG AI attempts to lower InByVal to InById
     22        if AI figured out that the property name is a constant string. And in
     23        InById node, we use JITInByIdGenerator code.
     24
     25        This patch cleans up DFG and FTL's adhoc In IC code.
     26
     27        In a subsequent patch, we should introduce InByIdStatus to optimize
     28        InById in DFG and FTL. We would like to have a new InByIdStatus instead of
     29        reusing GetByIdStatus since GetByIdStatus becomes too complicated, and
     30        AccessCase::Types are different from them (AccessCase::InHit / InMiss).
     31
     32        * bytecode/AccessCase.cpp:
     33        (JSC::AccessCase::fromStructureStubInfo):
     34        (JSC::AccessCase::generateWithGuard):
     35        * bytecode/BytecodeDumper.cpp:
     36        (JSC::BytecodeDumper<Block>::printInByIdCacheStatus):
     37        (JSC::BytecodeDumper<Block>::dumpBytecode):
     38        * bytecode/BytecodeDumper.h:
     39        * bytecode/BytecodeList.json:
     40        * bytecode/BytecodeUseDef.h:
     41        (JSC::computeUsesForBytecodeOffset):
     42        (JSC::computeDefsForBytecodeOffset):
     43        * bytecode/CodeBlock.cpp:
     44        (JSC::CodeBlock::finishCreation):
     45        * bytecode/InlineAccess.cpp:
     46        (JSC::InlineAccess::generateSelfInAccess):
     47        * bytecode/InlineAccess.h:
     48        * bytecode/StructureStubInfo.cpp:
     49        (JSC::StructureStubInfo::initInByIdSelf):
     50        (JSC::StructureStubInfo::deref):
     51        (JSC::StructureStubInfo::aboutToDie):
     52        (JSC::StructureStubInfo::reset):
     53        (JSC::StructureStubInfo::visitWeakReferences):
     54        (JSC::StructureStubInfo::propagateTransitions):
     55        * bytecode/StructureStubInfo.h:
     56        (JSC::StructureStubInfo::patchableJump):
     57        * bytecompiler/BytecodeGenerator.cpp:
     58        (JSC::BytecodeGenerator::emitInByVal):
     59        (JSC::BytecodeGenerator::emitInById):
     60        (JSC::BytecodeGenerator::emitIn): Deleted.
     61        * bytecompiler/BytecodeGenerator.h:
     62        * bytecompiler/NodesCodegen.cpp:
     63        (JSC::InNode::emitBytecode):
     64        * dfg/DFGAbstractInterpreterInlines.h:
     65        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     66        * dfg/DFGByteCodeParser.cpp:
     67        (JSC::DFG::ByteCodeParser::parseBlock):
     68        * dfg/DFGCapabilities.cpp:
     69        (JSC::DFG::capabilityLevel):
     70        * dfg/DFGClobberize.h:
     71        (JSC::DFG::clobberize):
     72        * dfg/DFGConstantFoldingPhase.cpp:
     73        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     74        * dfg/DFGDoesGC.cpp:
     75        (JSC::DFG::doesGC):
     76        * dfg/DFGFixupPhase.cpp:
     77        (JSC::DFG::FixupPhase::fixupNode):
     78        * dfg/DFGJITCompiler.cpp:
     79        (JSC::DFG::JITCompiler::link):
     80        * dfg/DFGJITCompiler.h:
     81        (JSC::DFG::JITCompiler::addInById):
     82        (JSC::DFG::InRecord::InRecord): Deleted.
     83        (JSC::DFG::JITCompiler::addIn): Deleted.
     84        * dfg/DFGNode.h:
     85        (JSC::DFG::Node::convertToInById):
     86        (JSC::DFG::Node::hasIdentifier):
     87        (JSC::DFG::Node::hasArrayMode):
     88        * dfg/DFGNodeType.h:
     89        * dfg/DFGPredictionPropagationPhase.cpp:
     90        * dfg/DFGSafeToExecute.h:
     91        (JSC::DFG::safeToExecute):
     92        * dfg/DFGSpeculativeJIT.cpp:
     93        (JSC::DFG::SpeculativeJIT::compileInById):
     94        (JSC::DFG::SpeculativeJIT::compileInByVal):
     95        (JSC::DFG::SpeculativeJIT::compileIn): Deleted.
     96        * dfg/DFGSpeculativeJIT.h:
     97        * dfg/DFGSpeculativeJIT32_64.cpp:
     98        (JSC::DFG::SpeculativeJIT::compile):
     99        * dfg/DFGSpeculativeJIT64.cpp:
     100        (JSC::DFG::SpeculativeJIT::compile):
     101        * ftl/FTLCapabilities.cpp:
     102        (JSC::FTL::canCompile):
     103        * ftl/FTLLowerDFGToB3.cpp:
     104        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     105        (JSC::FTL::DFG::LowerDFGToB3::compileInByVal):
     106        (JSC::FTL::DFG::LowerDFGToB3::compileInById):
     107        (JSC::FTL::DFG::LowerDFGToB3::compileIn): Deleted.
     108        * jit/ICStats.h:
     109        * jit/JIT.cpp:
     110        (JSC::JIT::JIT):
     111        (JSC::JIT::privateCompileMainPass):
     112        (JSC::JIT::privateCompileSlowCases):
     113        (JSC::JIT::link):
     114        * jit/JIT.h:
     115        * jit/JITInlineCacheGenerator.cpp:
     116        (JSC::JITInByIdGenerator::JITInByIdGenerator):
     117        (JSC::JITInByIdGenerator::generateFastPath):
     118        * jit/JITInlineCacheGenerator.h:
     119        (JSC::JITInByIdGenerator::JITInByIdGenerator):
     120        * jit/JITOperations.cpp:
     121        * jit/JITOperations.h:
     122        * jit/JITPropertyAccess.cpp:
     123        (JSC::JIT::emit_op_in_by_id):
     124        (JSC::JIT::emitSlow_op_in_by_id):
     125        * jit/JITPropertyAccess32_64.cpp:
     126        (JSC::JIT::emit_op_in_by_id):
     127        (JSC::JIT::emitSlow_op_in_by_id):
     128        * jit/Repatch.cpp:
     129        (JSC::tryCacheInByID):
     130        (JSC::repatchInByID):
     131        (JSC::resetInByID):
     132        (JSC::tryCacheIn): Deleted.
     133        (JSC::repatchIn): Deleted.
     134        (JSC::resetIn): Deleted.
     135        * jit/Repatch.h:
     136        * llint/LowLevelInterpreter.asm:
     137        * llint/LowLevelInterpreter64.asm:
     138        * parser/NodeConstructors.h:
     139        (JSC::InNode::InNode):
     140        * runtime/CommonSlowPaths.cpp:
     141        (JSC::SLOW_PATH_DECL):
     142        * runtime/CommonSlowPaths.h:
     143        (JSC::CommonSlowPaths::opInByVal):
     144        (JSC::CommonSlowPaths::opIn): Deleted.
     145
    11462018-05-18  Commit Queue  <commit-queue@webkit.org>
    2147
  • trunk/Source/JavaScriptCore/bytecode/AccessCase.cpp

    r231961 r231998  
    118118    case CacheType::PutByIdReplace:
    119119        return AccessCase::create(vm, owner, Replace, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get());
     120
     121    case CacheType::InByIdSelf:
     122        return AccessCase::create(vm, owner, InHit, stubInfo.u.byIdSelf.offset, stubInfo.u.byIdSelf.baseObjectStructure.get());
    120123
    121124    default:
     
    556559       
    557560        CCallHelpers::Label loop(&jit);
    558         failAndIgnore = jit.branch8(
    559             CCallHelpers::Equal,
    560             CCallHelpers::Address(valueGPR, JSCell::typeInfoTypeOffset()),
    561             CCallHelpers::TrustedImm32(ProxyObjectType));
     561        failAndIgnore = jit.branchIfType(valueGPR, ProxyObjectType);
    562562       
    563563        jit.emitLoadStructure(vm, valueGPR, scratch2GPR, scratchGPR);
  • trunk/Source/JavaScriptCore/bytecode/BytecodeDumper.cpp

    r231719 r231998  
    548548    }
    549549#else
     550    UNUSED_PARAM(map);
     551#endif
     552}
     553
     554template<class Block>
     555void BytecodeDumper<Block>::printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap& map)
     556{
     557    const auto* instruction = instructionsBegin() + location;
     558
     559    const Identifier& ident = identifier(instruction[3].u.operand);
     560
     561    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
     562
     563#if ENABLE(JIT)
     564    if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
     565        StructureStubInfo& stubInfo = *stubPtr;
     566        if (stubInfo.resetByGC)
     567            out.print(" (Reset By GC)");
     568
     569        out.printf(" jit(");
     570
     571        Structure* baseStructure = nullptr;
     572        PolymorphicAccess* stub = nullptr;
     573
     574        switch (stubInfo.cacheType) {
     575        case CacheType::InByIdSelf:
     576            out.printf("self");
     577            baseStructure = stubInfo.u.byIdSelf.baseObjectStructure.get();
     578            break;
     579        case CacheType::Stub:
     580            out.printf("stub");
     581            stub = stubInfo.u.stub;
     582            break;
     583        case CacheType::Unset:
     584            out.printf("unset");
     585            break;
     586        default:
     587            RELEASE_ASSERT_NOT_REACHED();
     588            break;
     589        }
     590
     591        if (baseStructure) {
     592            out.printf(", ");
     593            dumpStructure(out, "struct", baseStructure, ident);
     594        }
     595
     596        if (stub)
     597            out.print(", ", *stub);
     598
     599        out.printf(")");
     600    }
     601#else
     602    UNUSED_PARAM(out);
    550603    UNUSED_PARAM(map);
    551604#endif
     
    10131066        break;
    10141067    }
    1015     case op_in: {
    1016         printBinaryOp(out, location, it, "in");
     1068    case op_in_by_id: {
     1069        int r0 = (++it)->u.operand;
     1070        int r1 = (++it)->u.operand;
     1071        int id0 = (++it)->u.operand;
     1072        printLocationAndOp(out, location, it, "in_by_id");
     1073        out.printf("%s, %s, %s", registerName(r0).data(), registerName(r1).data(), idName(id0, identifier(id0)).data());
     1074        printInByIdCacheStatus(out, location, stubInfos);
     1075        break;
     1076    }
     1077    case op_in_by_val: {
     1078        printBinaryOp(out, location, it, "in_by_val");
    10171079        dumpArrayProfiling(out, it, hasPrintedProfiling);
    10181080        break;
  • trunk/Source/JavaScriptCore/bytecode/BytecodeDumper.h

    r223318 r231998  
    7272    void printGetByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&);
    7373    void printPutByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&);
     74    void printInByIdCacheStatus(PrintStream& out, int location, const StubInfoMap&);
    7475    enum CacheDumpMode { DumpCaches, DontDumpCaches };
    7576    void printCallOp(PrintStream& out, int location, const Instruction*& it, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r231719 r231998  
    8181            { "name" : "op_is_function", "length" : 3 },
    8282            { "name" : "op_is_cell_with_type", "length" : 4 },
    83             { "name" : "op_in", "length" : 5 },
     83            { "name" : "op_in_by_val", "length" : 5 },
     84            { "name" : "op_in_by_id", "length" : 4 },
    8485            { "name" : "op_get_array_length", "length" : 9 },
    8586            { "name" : "op_get_by_id", "length" : 9  },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r231719 r231998  
    187187    case op_get_by_id_direct:
    188188    case op_get_array_length:
     189    case op_in_by_id:
    189190    case op_typeof:
    190191    case op_is_empty:
     
    227228    case op_enumerator_generic_pname:
    228229    case op_get_by_val:
    229     case op_in:
     230    case op_in_by_val:
    230231    case op_overrides_has_instance:
    231232    case op_instanceof:
     
    455456    case op_is_cell_with_type:
    456457    case op_is_function:
    457     case op_in:
     458    case op_in_by_id:
     459    case op_in_by_val:
    458460    case op_to_number:
    459461    case op_to_string:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r231719 r231998  
    590590        }
    591591
    592         case op_in:
     592        case op_in_by_val:
    593593        case op_put_by_val:
    594594        case op_put_by_val_direct: {
  • trunk/Source/JavaScriptCore/bytecode/InlineAccess.cpp

    r231375 r231998  
    277277}
    278278
     279bool InlineAccess::generateSelfInAccess(StructureStubInfo& stubInfo, Structure* structure)
     280{
     281    CCallHelpers jit;
     282
     283    GPRReg base = static_cast<GPRReg>(stubInfo.patch.baseGPR);
     284    JSValueRegs value = stubInfo.valueRegs();
     285
     286    auto branchToSlowPath = jit.patchableBranch32(
     287        MacroAssembler::NotEqual,
     288        MacroAssembler::Address(base, JSCell::structureIDOffset()),
     289        MacroAssembler::TrustedImm32(bitwise_cast<uint32_t>(structure->id())));
     290    jit.boxBooleanPayload(true, value.payloadGPR());
     291
     292    bool linkedCodeInline = linkCodeInline("in access", jit, stubInfo, [&] (LinkBuffer& linkBuffer) {
     293        linkBuffer.link(branchToSlowPath, stubInfo.slowPathStartLocation());
     294    });
     295    return linkedCodeInline;
     296}
     297
    279298void InlineAccess::rewireStubAsJump(StructureStubInfo& stubInfo, CodeLocationLabel<JITStubRoutinePtrTag> target)
    280299{
  • trunk/Source/JavaScriptCore/bytecode/InlineAccess.h

    r230748 r231998  
    117117    static bool generateArrayLength(StructureStubInfo&, JSArray*);
    118118    static void rewireStubAsJump(StructureStubInfo&, CodeLocationLabel<JITStubRoutinePtrTag>);
     119    static bool generateSelfInAccess(StructureStubInfo&, Structure*);
    119120
    120121    // This is helpful when determining the size of an IC on
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp

    r231961 r231998  
    8282}
    8383
     84void StructureStubInfo::initInByIdSelf(CodeBlock* codeBlock, Structure* baseObjectStructure, PropertyOffset offset)
     85{
     86    cacheType = CacheType::InByIdSelf;
     87
     88    u.byIdSelf.baseObjectStructure.set(
     89        *codeBlock->vm(), codeBlock, baseObjectStructure);
     90    u.byIdSelf.offset = offset;
     91}
     92
    8493void StructureStubInfo::deref()
    8594{
     
    91100    case CacheType::GetByIdSelf:
    92101    case CacheType::PutByIdReplace:
     102    case CacheType::InByIdSelf:
    93103    case CacheType::ArrayLength:
    94104        return;
     
    107117    case CacheType::GetByIdSelf:
    108118    case CacheType::PutByIdReplace:
     119    case CacheType::InByIdSelf:
    109120    case CacheType::ArrayLength:
    110121        return;
     
    237248        break;
    238249    case AccessType::In:
    239         resetIn(*this);
     250        resetInByID(codeBlock, *this);
    240251        break;
    241252    case AccessType::InstanceOf:
     
    260271    case CacheType::GetByIdSelf:
    261272    case CacheType::PutByIdReplace:
     273    case CacheType::InByIdSelf:
    262274        if (Heap::isMarked(u.byIdSelf.baseObjectStructure.get()))
    263275            return;
     
    283295    case CacheType::GetByIdSelf:
    284296    case CacheType::PutByIdReplace:
     297    case CacheType::InByIdSelf:
    285298        return u.byIdSelf.baseObjectStructure->markIfCheap(visitor);
    286299    case CacheType::Stub:
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h

    r231961 r231998  
    5959    GetByIdSelf,
    6060    PutByIdReplace,
     61    InByIdSelf,
    6162    Stub,
    6263    ArrayLength
     
    7374    void initArrayLength();
    7475    void initPutByIdReplace(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
     76    void initInByIdSelf(CodeBlock*, Structure* baseObjectStructure, PropertyOffset);
    7577
    7678    AccessGenerationResult addAccessCase(const GCSafeConcurrentJSLocker&, CodeBlock*, const Identifier&, std::unique_ptr<AccessCase>);
     
    175177   
    176178    struct {
    177         CodeLocationLabel<JITStubRoutinePtrTag> start; // This is either the start of the inline IC for *byId caches, or the location of patchable jump for 'in' and 'instanceof' caches.
     179        CodeLocationLabel<JITStubRoutinePtrTag> start; // This is either the start of the inline IC for *byId caches. or the location of patchable jump for 'instanceof' caches.
    178180        RegisterSet usedRegisters;
    179181        uint32_t inlineSize;
     
    196198    CodeLocationJump<JSInternalPtrTag> patchableJump()
    197199    {
    198         ASSERT(accessType == AccessType::In || accessType == AccessType::InstanceOf);
     200        ASSERT(accessType == AccessType::InstanceOf);
    199201        return patch.start.jumpAtOffset<JSInternalPtrTag>(0);
    200202    }
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r231719 r231998  
    26682668}
    26692669
    2670 RegisterID* BytecodeGenerator::emitIn(RegisterID* dst, RegisterID* property, RegisterID* base)
     2670RegisterID* BytecodeGenerator::emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base)
    26712671{
    26722672    UnlinkedArrayProfile arrayProfile = newArrayProfile();
    2673     emitOpcode(op_in);
     2673    emitOpcode(op_in_by_val);
    26742674    instructions().append(dst->index());
    26752675    instructions().append(base->index());
    26762676    instructions().append(property->index());
    26772677    instructions().append(arrayProfile);
     2678    return dst;
     2679}
     2680
     2681RegisterID* BytecodeGenerator::emitInById(RegisterID* dst, RegisterID* base, const Identifier& property)
     2682{
     2683    emitOpcode(op_in_by_id);
     2684    instructions().append(dst->index());
     2685    instructions().append(base->index());
     2686    instructions().append(addConstant(property));
    26782687    return dst;
    26792688}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r230376 r231998  
    695695        RegisterID* emitInstanceOfCustom(RegisterID* dst, RegisterID* value, RegisterID* constructor, RegisterID* hasInstanceValue);
    696696        RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
    697         RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base);
     697        RegisterID* emitInByVal(RegisterID* dst, RegisterID* property, RegisterID* base);
     698        RegisterID* emitInById(RegisterID* dst, RegisterID* base, const Identifier& property);
    698699
    699700        RegisterID* emitTryGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r230459 r231998  
    22812281RegisterID* InNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    22822282{
     2283    if (isNonIndexStringElement(*m_expr1)) {
     2284        RefPtr<RegisterID> base = generator.emitNode(m_expr2);
     2285        generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
     2286        return generator.emitInById(generator.finalDestination(dst, base.get()), base.get(), static_cast<StringNode*>(m_expr1)->value());
     2287    }
     2288
    22832289    RefPtr<RegisterID> key = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator));
    22842290    RefPtr<RegisterID> base = generator.emitNode(m_expr2);
    22852291    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    2286     return generator.emitIn(generator.finalDestination(dst, key.get()), key.get(), base.get());
     2292    return generator.emitInByVal(generator.finalDestination(dst, key.get()), key.get(), base.get());
    22872293}
    22882294
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r231882 r231998  
    32603260        break;
    32613261       
    3262     case In: {
     3262    case InById: {
    32633263        // FIXME: We can determine when the property definitely exists based on abstract
    32643264        // value information.
    32653265        clobberWorld();
     3266        filter(node->child1(), SpecObject);
     3267        setNonCellTypeForNode(node, SpecBoolean);
     3268        break;
     3269    }
     3270
     3271    case InByVal: {
     3272        AbstractValue& property = forNode(node->child2());
     3273        if (JSValue constant = property.value()) {
     3274            if (constant.isString()) {
     3275                JSString* string = asString(constant);
     3276                const StringImpl* impl = string->tryGetValueImpl();
     3277                if (impl && impl->isAtomic())
     3278                    m_state.setFoundConstants(true);
     3279            }
     3280        }
     3281
     3282        // FIXME: We can determine when the property definitely exists based on abstract
     3283        // value information.
     3284        clobberWorld();
     3285        filter(node->child1(), SpecObject);
    32663286        setNonCellTypeForNode(node, SpecBoolean);
    32673287        break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r231961 r231998  
    63646364        }
    63656365
    6366         case op_in: {
    6367             ArrayMode arrayMode = getArrayMode(currentInstruction[OPCODE_LENGTH(op_in) - 1].u.arrayProfile);
     6366        case op_in_by_val: {
     6367            ArrayMode arrayMode = getArrayMode(currentInstruction[OPCODE_LENGTH(op_in_by_val) - 1].u.arrayProfile);
    63686368            set(VirtualRegister(currentInstruction[1].u.operand),
    6369                 addToGraph(In, OpInfo(arrayMode.asWord()), get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand))));
    6370             NEXT_OPCODE(op_in);
     6369                addToGraph(InByVal, OpInfo(arrayMode.asWord()), get(VirtualRegister(currentInstruction[2].u.operand)), get(VirtualRegister(currentInstruction[3].u.operand))));
     6370            NEXT_OPCODE(op_in_by_val);
     6371        }
     6372
     6373        case op_in_by_id: {
     6374            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
     6375            unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
     6376            set(VirtualRegister(currentInstruction[1].u.operand),
     6377                addToGraph(InById, OpInfo(identifierNumber), base));
     6378            NEXT_OPCODE(op_in_by_id);
     6379            break;
    63716380        }
    63726381
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r231719 r231998  
    237237    case op_switch_imm:
    238238    case op_switch_char:
    239     case op_in:
     239    case op_in_by_val:
     240    case op_in_by_id:
    240241    case op_get_scope:
    241242    case op_get_from_scope:
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r231871 r231998  
    620620    case ConstructForwardVarargs:
    621621    case ToPrimitive:
    622     case In:
     622    case InByVal:
     623    case InById:
    623624    case HasOwnProperty:
    624625    case ValueAdd:
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r231882 r231998  
    617617            }
    618618
     619            case InByVal: {
     620                AbstractValue& property = m_state.forNode(node->child2());
     621                if (JSValue constant = property.value()) {
     622                    if (constant.isString()) {
     623                        JSString* string = asString(constant);
     624                        const StringImpl* impl = string->tryGetValueImpl();
     625                        if (impl && impl->isAtomic()) {
     626                            unsigned identifierNumber = m_graph.identifiers().ensure(const_cast<UniquedStringImpl*>(static_cast<const UniquedStringImpl*>(impl)));
     627                            node->convertToInById(identifierNumber);
     628                            changed = true;
     629                            break;
     630                        }
     631                    }
     632                }
     633                break;
     634            }
     635
    619636            case ToPrimitive: {
    620637                if (m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r231224 r231998  
    194194    case NumberToStringWithRadix:
    195195    case NumberToStringWithValidRadixConstant:
    196     case In:
     196    case InByVal:
     197    case InById:
    197198    case HasOwnProperty:
    198199    case Jump:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r231961 r231998  
    14701470            break;
    14711471
    1472         case In: {
     1472        case InById: {
     1473            fixEdge<CellUse>(node->child1());
     1474            break;
     1475        }
     1476
     1477        case InByVal: {
    14731478            if (node->child2()->shouldSpeculateInt32()) {
    14741479                convertToHasIndexedProperty(node);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r231961 r231998  
    266266    finalizeInlineCaches(m_getByIdsWithThis, linkBuffer);
    267267    finalizeInlineCaches(m_putByIds, linkBuffer);
     268    finalizeInlineCaches(m_inByIds, linkBuffer);
    268269    finalizeInlineCaches(m_instanceOfs, linkBuffer);
    269270
    270     for (unsigned i = 0; i < m_ins.size(); ++i) {
    271         StructureStubInfo& info = *m_ins[i].m_stubInfo;
    272 
    273         CodeLocationLabel<JITStubRoutinePtrTag> start = linkBuffer.locationOf<JITStubRoutinePtrTag>(m_ins[i].m_jump);
    274         info.patch.start = start;
    275 
    276         ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr(
    277             start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_done));
    278         RELEASE_ASSERT(inlineSize >= 0);
    279         info.patch.inlineSize = inlineSize;
    280 
    281         info.patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
    282             start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_slowPathGenerator->call()));
    283 
    284         info.patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
    285             start, linkBuffer.locationOf<JSInternalPtrTag>(m_ins[i].m_slowPathGenerator->label()));
    286     }
    287    
    288271    auto linkCallThunk = FunctionPtr<NoPtrTag>(vm()->getCTIStub(linkCallThunkGenerator).retaggedCode<NoPtrTag>());
    289272    for (auto& record : m_jsCalls) {
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r231961 r231998  
    7777};
    7878
    79 struct InRecord {
    80     InRecord(
    81         MacroAssembler::PatchableJump jump, MacroAssembler::Label done,
    82         SlowPathGenerator* slowPathGenerator, StructureStubInfo* stubInfo)
    83         : m_jump(jump)
    84         , m_done(done)
    85         , m_slowPathGenerator(slowPathGenerator)
    86         , m_stubInfo(stubInfo)
    87     {
    88     }
    89    
    90     MacroAssembler::PatchableJump m_jump;
    91     MacroAssembler::Label m_done;
    92     SlowPathGenerator* m_slowPathGenerator;
    93     StructureStubInfo* m_stubInfo;
    94 };
    95 
    9679// === JITCompiler ===
    9780//
     
    210193    }
    211194
    212     void addIn(const InRecord& record)
    213     {
    214         m_ins.append(record);
    215     }
    216    
     195    void addInById(const JITInByIdGenerator& gen, SlowPathGenerator* slowPath)
     196    {
     197        m_inByIds.append(InlineCacheWrapper<JITInByIdGenerator>(gen, slowPath));
     198    }
     199
    217200    void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
    218201    {
     
    360343    Vector<InlineCacheWrapper<JITGetByIdWithThisGenerator>, 4> m_getByIdsWithThis;
    361344    Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds;
     345    Vector<InlineCacheWrapper<JITInByIdGenerator>, 4> m_inByIds;
    362346    Vector<InlineCacheWrapper<JITInstanceOfGenerator>, 4> m_instanceOfs;
    363     Vector<InRecord, 4> m_ins;
    364347    Vector<JSCallRecord, 4> m_jsCalls;
    365348    Vector<JSDirectCallRecord, 4> m_jsDirectCalls;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r230964 r231998  
    744744        m_opInfo = false;
    745745    }
     746
     747    void convertToInById(unsigned identifierNumber)
     748    {
     749        ASSERT(m_op == InByVal);
     750        setOpAndDefaultFlags(InById);
     751        children.setChild2(Edge());
     752        m_opInfo = identifierNumber;
     753        m_opInfo2 = OpInfoWrapper();
     754    }
    746755   
    747756    JSValue asJSValue()
     
    10111020        case PutGetterSetterById:
    10121021        case DeleteById:
     1022        case InById:
    10131023        case GetDynamicVar:
    10141024        case PutDynamicVar:
     
    19681978        case GetArrayLength:
    19691979        case GetVectorLength:
    1970         case In:
     1980        case InByVal:
    19711981        case PutByValDirect:
    19721982        case PutByVal:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r231871 r231998  
    370370    macro(NewStringObject, NodeResultJS) \
    371371    macro(MakeRope, NodeResultJS) \
    372     macro(In, NodeResultBoolean | NodeMustGenerate) \
     372    macro(InByVal, NodeResultBoolean | NodeMustGenerate) \
     373    macro(InById, NodeResultBoolean | NodeMustGenerate) \
    373374    macro(ProfileType, NodeMustGenerate) \
    374375    macro(ProfileControlFlow, NodeMustGenerate) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r231224 r231998  
    981981            break;
    982982
    983         case In:
     983        case InByVal:
     984        case InById:
    984985            setPrediction(SpecBoolean);
    985986            break;
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r231224 r231998  
    333333    case NewStringObject:
    334334    case MakeRope:
    335     case In:
     335    case InByVal:
     336    case InById:
    336337    case HasOwnProperty:
    337338    case PushWithScope:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r231961 r231998  
    10571057}
    10581058
    1059 void SpeculativeJIT::compileIn(Node* node)
     1059void SpeculativeJIT::compileInById(Node* node)
    10601060{
    10611061    SpeculateCellOperand base(this, node->child1());
     1062    JSValueRegsTemporary result(this, Reuse, base, PayloadWord);
     1063
    10621064    GPRReg baseGPR = base.gpr();
    1063    
    1064     if (JSString* string = node->child2()->dynamicCastConstant<JSString*>(*m_jit.vm())) {
    1065         if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
    1066             StructureStubInfo* stubInfo = m_jit.codeBlock()->addStubInfo(AccessType::In);
    1067            
    1068             GPRTemporary result(this);
    1069             GPRReg resultGPR = result.gpr();
    1070 
    1071             use(node->child2());
    1072            
    1073             MacroAssembler::PatchableJump jump = m_jit.patchableJump();
    1074             MacroAssembler::Label done = m_jit.label();
    1075            
    1076             // Since this block is executed only when the result of string->tryGetValueImpl() is atomic,
    1077             // we can cast it to const AtomicStringImpl* safely.
    1078             auto slowPath = slowPathCall(
    1079                 jump.m_jump, this, operationInOptimize,
    1080                 JSValueRegs::payloadOnly(resultGPR), stubInfo, baseGPR,
    1081                 static_cast<const AtomicStringImpl*>(string->tryGetValueImpl()));
    1082            
    1083             stubInfo->callSiteIndex = m_jit.addCallSite(node->origin.semantic);
    1084             stubInfo->codeOrigin = node->origin.semantic;
    1085             stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR);
    1086             stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR);
    1087             stubInfo->patch.thisGPR = static_cast<int8_t>(InvalidGPRReg);
    1088 #if USE(JSVALUE32_64)
    1089             stubInfo->patch.valueTagGPR = static_cast<int8_t>(InvalidGPRReg);
    1090             stubInfo->patch.baseTagGPR = static_cast<int8_t>(InvalidGPRReg);
    1091             stubInfo->patch.thisTagGPR = static_cast<int8_t>(InvalidGPRReg);
    1092 #endif
    1093             stubInfo->patch.usedRegisters = usedRegisters();
    1094 
    1095             m_jit.addIn(InRecord(jump, done, slowPath.get(), stubInfo));
    1096             addSlowPathGenerator(WTFMove(slowPath));
    1097 
    1098             base.use();
    1099 
    1100             blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
    1101             return;
    1102         }
    1103     }
    1104 
     1065    JSValueRegs resultRegs = result.regs();
     1066
     1067    base.use();
     1068
     1069    CodeOrigin codeOrigin = node->origin.semantic;
     1070    CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
     1071    RegisterSet usedRegisters = this->usedRegisters();
     1072    JITInByIdGenerator gen(
     1073        m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(node->identifierNumber()),
     1074        JSValueRegs::payloadOnly(baseGPR), resultRegs);
     1075    gen.generateFastPath(m_jit);
     1076
     1077    auto slowPath = slowPathCall(
     1078        gen.slowPathJump(), this, operationInByIdOptimize,
     1079        NeedToSpill, ExceptionCheckRequirement::CheckNeeded,
     1080        resultRegs, gen.stubInfo(), CCallHelpers::CellValue(baseGPR), identifierUID(node->identifierNumber()));
     1081
     1082    m_jit.addInById(gen, slowPath.get());
     1083    addSlowPathGenerator(WTFMove(slowPath));
     1084
     1085    blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
     1086}
     1087
     1088void SpeculativeJIT::compileInByVal(Node* node)
     1089{
     1090    SpeculateCellOperand base(this, node->child1());
    11051091    JSValueOperand key(this, node->child2());
     1092
     1093    GPRReg baseGPR = base.gpr();
    11061094    JSValueRegs regs = key.jsValueRegs();
    1107        
    1108     GPRFlushedCallResult result(this);
    1109     GPRReg resultGPR = result.gpr();
    1110        
     1095
    11111096    base.use();
    11121097    key.use();
    1113        
     1098
    11141099    flushRegisters();
    1115     callOperation(
    1116         operationGenericIn, extractResult(JSValueRegs::payloadOnly(resultGPR)),
    1117         baseGPR, regs);
     1100    JSValueRegsFlushedCallResult result(this);
     1101    JSValueRegs resultRegs = result.regs();
     1102    callOperation(operationInByVal, resultRegs, baseGPR, regs);
    11181103    m_jit.exceptionCheck();
    1119     blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
     1104    blessedBooleanResult(resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
    11201105}
    11211106
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r231961 r231998  
    736736    void compileGetById(Node*, AccessType);
    737737    void compileGetByIdFlush(Node*, AccessType);
    738     void compileIn(Node*);
     738    void compileInById(Node*);
     739    void compileInByVal(Node*);
    739740   
    740741    void nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r231905 r231998  
    37523752        break;
    37533753
    3754     case In:
    3755         compileIn(node);
     3754    case InById:
     3755        compileInById(node);
     3756        break;
     3757
     3758    case InByVal:
     3759        compileInByVal(node);
    37563760        break;
    37573761
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r231961 r231998  
    43024302        break;
    43034303
    4304     case In:
    4305         compileIn(node);
     4304    case InById:
     4305        compileInById(node);
     4306        break;
     4307
     4308    case InByVal:
     4309        compileInByVal(node);
    43064310        break;
    43074311
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r231224 r231998  
    206206    case ThrowStaticError:
    207207    case Unreachable:
    208     case In:
     208    case InByVal:
     209    case InById:
    209210    case HasOwnProperty:
    210211    case IsCellWithType:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r231961 r231998  
    709709            compileGetById(AccessType::GetDirect);
    710710            break;
    711         case In:
    712             compileIn();
     711        case InById:
     712            compileInById();
     713            break;
     714        case InByVal:
     715            compileInByVal();
    713716            break;
    714717        case HasOwnProperty:
     
    96709673    }
    96719674   
    9672     void compileIn()
    9673     {
    9674         DFG_ASSERT(m_graph, m_node, m_node->child1().useKind() == CellUse, m_node->child1().useKind());
    9675 
     9675    void compileInByVal()
     9676    {
     9677        setJSValue(vmCall(Int64, m_out.operation(operationInByVal), m_callFrame, lowCell(m_node->child1()), lowJSValue(m_node->child2())));
     9678    }
     9679
     9680    void compileInById()
     9681    {
    96769682        Node* node = m_node;
    9677         Edge base = node->child1();
    9678         LValue cell = lowCell(base);
    9679         if (JSString* string = node->child2()->dynamicCastConstant<JSString*>(vm())) {
    9680             if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
    9681                 UniquedStringImpl* str = bitwise_cast<UniquedStringImpl*>(string->tryGetValueImpl());
    9682                 PatchpointValue* patchpoint = m_out.patchpoint(Int64);
    9683                 patchpoint->appendSomeRegister(cell);
    9684                 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
    9685                 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
    9686                 patchpoint->clobber(RegisterSet::macroScratchRegisters());
    9687 
    9688                 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint);
    9689 
    9690                 State* state = &m_ftlState;
    9691                 patchpoint->setGenerator(
    9692                     [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     9683        UniquedStringImpl* uid = m_graph.identifiers()[node->identifierNumber()];
     9684        LValue base = lowCell(m_node->child1());
     9685
     9686        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
     9687        patchpoint->appendSomeRegister(base);
     9688        patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister));
     9689        patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister));
     9690
     9691        patchpoint->clobber(RegisterSet::macroScratchRegisters());
     9692
     9693        RefPtr<PatchpointExceptionHandle> exceptionHandle =
     9694            preparePatchpointForExceptions(patchpoint);
     9695
     9696        State* state = &m_ftlState;
     9697        patchpoint->setGenerator(
     9698            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     9699                AllowMacroScratchRegisterUsage allowScratch(jit);
     9700
     9701                CallSiteIndex callSiteIndex =
     9702                    state->jitCode->common.addUniqueCallSiteIndex(node->origin.semantic);
     9703
     9704                // This is the direct exit target for operation calls.
     9705                Box<CCallHelpers::JumpList> exceptions =
     9706                    exceptionHandle->scheduleExitCreation(params)->jumps(jit);
     9707
     9708                auto generator = Box<JITInByIdGenerator>::create(
     9709                    jit.codeBlock(), node->origin.semantic, callSiteIndex,
     9710                    params.unavailableRegisters(), uid, JSValueRegs(params[1].gpr()),
     9711                    JSValueRegs(params[0].gpr()));
     9712
     9713                generator->generateFastPath(jit);
     9714                CCallHelpers::Label done = jit.label();
     9715
     9716                params.addLatePath(
     9717                    [=] (CCallHelpers& jit) {
    96939718                        AllowMacroScratchRegisterUsage allowScratch(jit);
    96949719
    9695                         // This is the direct exit target for operation calls. We don't need a JS exceptionHandle because we don't
    9696                         // cache Proxy objects.
    9697                         Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit);
    9698 
    9699                         GPRReg baseGPR = params[1].gpr();
    9700                         GPRReg resultGPR = params[0].gpr();
    9701 
    9702                         StructureStubInfo* stubInfo =
    9703                             jit.codeBlock()->addStubInfo(AccessType::In);
    9704                         stubInfo->callSiteIndex =
    9705                             state->jitCode->common.addCodeOrigin(node->origin.semantic);
    9706                         stubInfo->codeOrigin = node->origin.semantic;
    9707                         stubInfo->patch.baseGPR = static_cast<int8_t>(baseGPR);
    9708                         stubInfo->patch.valueGPR = static_cast<int8_t>(resultGPR);
    9709                         stubInfo->patch.thisGPR = static_cast<int8_t>(InvalidGPRReg);
    9710                         stubInfo->patch.usedRegisters = params.unavailableRegisters();
    9711 
    9712                         CCallHelpers::PatchableJump jump = jit.patchableJump();
    9713                         CCallHelpers::Label done = jit.label();
    9714 
    9715                         params.addLatePath(
    9716                             [=] (CCallHelpers& jit) {
    9717                                 AllowMacroScratchRegisterUsage allowScratch(jit);
    9718 
    9719                                 jump.m_jump.link(&jit);
    9720                                 CCallHelpers::Label slowPathBegin = jit.label();
    9721                                 CCallHelpers::Call slowPathCall = callOperation(
    9722                                     *state, params.unavailableRegisters(), jit,
    9723                                     node->origin.semantic, exceptions.get(), operationInOptimize,
    9724                                     resultGPR, CCallHelpers::TrustedImmPtr(stubInfo), baseGPR,
    9725                                     CCallHelpers::TrustedImmPtr(str)).call();
    9726                                 jit.jump().linkTo(done, &jit);
    9727 
    9728                                 jit.addLinkTask(
    9729                                     [=] (LinkBuffer& linkBuffer) {
    9730                                         CodeLocationLabel<JITStubRoutinePtrTag> start = linkBuffer.locationOf<JITStubRoutinePtrTag>(jump);
    9731                                         stubInfo->patch.start = start;
    9732                                         ptrdiff_t inlineSize = MacroAssembler::differenceBetweenCodePtr(
    9733                                             start, linkBuffer.locationOf<NoPtrTag>(done));
    9734                                         RELEASE_ASSERT(inlineSize >= 0);
    9735                                         stubInfo->patch.inlineSize = inlineSize;
    9736 
    9737                                         stubInfo->patch.deltaFromStartToSlowPathCallLocation = MacroAssembler::differenceBetweenCodePtr(
    9738                                             start, linkBuffer.locationOf<NoPtrTag>(slowPathCall));
    9739 
    9740                                         stubInfo->patch.deltaFromStartToSlowPathStart = MacroAssembler::differenceBetweenCodePtr(
    9741                                             start, linkBuffer.locationOf<NoPtrTag>(slowPathBegin));
    9742 
    9743                                     });
     9720                        generator->slowPathJump().link(&jit);
     9721                        CCallHelpers::Label slowPathBegin = jit.label();
     9722                        CCallHelpers::Call slowPathCall = callOperation(
     9723                            *state, params.unavailableRegisters(), jit, node->origin.semantic,
     9724                            exceptions.get(), operationInByIdOptimize, params[0].gpr(),
     9725                            CCallHelpers::TrustedImmPtr(generator->stubInfo()), params[1].gpr(),
     9726                            CCallHelpers::TrustedImmPtr(uid)).call();
     9727                        jit.jump().linkTo(done, &jit);
     9728
     9729                        generator->reportSlowPathCall(slowPathBegin, slowPathCall);
     9730
     9731                        jit.addLinkTask(
     9732                            [=] (LinkBuffer& linkBuffer) {
     9733                                generator->finalize(linkBuffer, linkBuffer);
    97449734                            });
    97459735                    });
    9746 
    9747                 setJSValue(patchpoint);
    9748                 return;
    9749             }
    9750         }
    9751 
    9752         setJSValue(vmCall(Int64, m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child2())));
     9736            });
     9737
     9738        setJSValue(patchpoint);
    97539739    }
    97549740
  • trunk/Source/JavaScriptCore/jit/ICStats.h

    r231961 r231998  
    5151    macro(OperationGetByIdOptimize) \
    5252    macro(OperationGetByIdWithThisOptimize) \
    53     macro(OperationInOptimize) \
    54     macro(OperationIn) \
    5553    macro(OperationGenericIn) \
     54    macro(OperationInById) \
     55    macro(OperationInByIdGeneric) \
     56    macro(OperationInByIdOptimize) \
    5657    macro(OperationPutByIdStrict) \
    5758    macro(OperationPutByIdNonStrict) \
     
    6869    macro(PutByIdAddAccessCase) \
    6970    macro(PutByIdReplaceWithJump) \
    70     macro(PutByIdSelfPatch)
     71    macro(PutByIdSelfPatch) \
     72    macro(InByIdSelfPatch)
    7173
    7274class ICEvent {
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r231961 r231998  
    7979    , m_labels(codeBlock ? codeBlock->numberOfInstructions() : 0)
    8080    , m_bytecodeOffset(std::numeric_limits<unsigned>::max())
    81     , m_getByIdIndex(UINT_MAX)
    82     , m_getByIdWithThisIndex(UINT_MAX)
    83     , m_putByIdIndex(UINT_MAX)
    84     , m_byValInstructionIndex(UINT_MAX)
    85     , m_callLinkInfoIndex(UINT_MAX)
    8681    , m_pcToCodeOriginMapBuilder(*vm)
    8782    , m_canBeOptimized(false)
     
    278273
    279274        switch (opcodeID) {
    280         DEFINE_SLOW_OP(in)
     275        DEFINE_SLOW_OP(in_by_val)
    281276        DEFINE_SLOW_OP(less)
    282277        DEFINE_SLOW_OP(lesseq)
     
    342337        DEFINE_OP(op_beloweq)
    343338        DEFINE_OP(op_try_get_by_id)
     339        DEFINE_OP(op_in_by_id)
    344340        case op_get_array_length:
    345341        case op_get_by_id_proto_load:
     
    479475    m_getByIdWithThisIndex = 0;
    480476    m_putByIdIndex = 0;
     477    m_inByIdIndex = 0;
    481478    m_instanceOfIndex = 0;
    482479    m_byValInstructionIndex = 0;
     
    522519        DEFINE_SLOWCASE_OP(op_eq)
    523520        DEFINE_SLOWCASE_OP(op_try_get_by_id)
     521        DEFINE_SLOWCASE_OP(op_in_by_id)
    524522        case op_get_array_length:
    525523        case op_get_by_id_proto_load:
     
    601599    RELEASE_ASSERT(m_getByIdWithThisIndex == m_getByIdsWithThis.size());
    602600    RELEASE_ASSERT(m_putByIdIndex == m_putByIds.size());
     601    RELEASE_ASSERT(m_inByIdIndex == m_inByIds.size());
    603602    RELEASE_ASSERT(m_instanceOfIndex == m_instanceOfs.size());
    604603    RELEASE_ASSERT(m_callLinkInfoIndex == m_callCompilationInfo.size());
     
    843842    finalizeInlineCaches(m_getByIdsWithThis, patchBuffer);
    844843    finalizeInlineCaches(m_putByIds, patchBuffer);
     844    finalizeInlineCaches(m_inByIds, patchBuffer);
    845845    finalizeInlineCaches(m_instanceOfs, patchBuffer);
    846846
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r231961 r231998  
    501501        void emit_op_get_by_val(Instruction*);
    502502        void emit_op_get_argument_by_val(Instruction*);
     503        void emit_op_in_by_id(Instruction*);
    503504        void emit_op_init_lazy_reg(Instruction*);
    504505        void emit_op_overrides_has_instance(Instruction*);
     
    612613        void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
    613614        void emitSlow_op_get_argument_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
     615        void emitSlow_op_in_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
    614616        void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
    615617        void emitSlow_op_instanceof_custom(Instruction*, Vector<SlowCaseEntry>::iterator&);
     
    866868        Vector<JITGetByIdWithThisGenerator> m_getByIdsWithThis;
    867869        Vector<JITPutByIdGenerator> m_putByIds;
     870        Vector<JITInByIdGenerator> m_inByIds;
    868871        Vector<JITInstanceOfGenerator> m_instanceOfs;
    869872        Vector<ByValCompilationInfo> m_byValCompilationInfo;
     
    879882        Label m_exceptionHandler;
    880883
    881         unsigned m_getByIdIndex;
    882         unsigned m_getByIdWithThisIndex;
    883         unsigned m_putByIdIndex;
    884         unsigned m_instanceOfIndex;
    885         unsigned m_byValInstructionIndex;
    886         unsigned m_callLinkInfoIndex;
     884        unsigned m_getByIdIndex { UINT_MAX };
     885        unsigned m_getByIdWithThisIndex { UINT_MAX };
     886        unsigned m_putByIdIndex { UINT_MAX };
     887        unsigned m_inByIdIndex { UINT_MAX };
     888        unsigned m_instanceOfIndex { UINT_MAX };
     889        unsigned m_byValInstructionIndex { UINT_MAX };
     890        unsigned m_callLinkInfoIndex { UINT_MAX };
    887891       
    888892        Label m_arityCheck;
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp

    r231961 r231998  
    167167}
    168168
     169JITInByIdGenerator::JITInByIdGenerator(
     170    CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSite, const RegisterSet& usedRegisters,
     171    UniquedStringImpl* propertyName, JSValueRegs base, JSValueRegs value)
     172    : JITByIdGenerator(codeBlock, codeOrigin, callSite, AccessType::In, usedRegisters, base, value)
     173{
     174    // FIXME: We are not supporting fast path for "length" property.
     175    UNUSED_PARAM(propertyName);
     176    RELEASE_ASSERT(base.payloadGPR() != value.tagGPR());
     177}
     178
     179void JITInByIdGenerator::generateFastPath(MacroAssembler& jit)
     180{
     181    generateFastCommon(jit, InlineAccess::sizeForPropertyAccess());
     182}
     183
    169184JITInstanceOfGenerator::JITInstanceOfGenerator(
    170185    CodeBlock* codeBlock, CodeOrigin codeOrigin, CallSiteIndex callSiteIndex,
  • trunk/Source/JavaScriptCore/jit/JITInlineCacheGenerator.h

    r231961 r231998  
    144144};
    145145
     146class JITInByIdGenerator : public JITByIdGenerator {
     147public:
     148    JITInByIdGenerator() { }
     149
     150    JITInByIdGenerator(
     151        CodeBlock*, CodeOrigin, CallSiteIndex, const RegisterSet& usedRegisters, UniquedStringImpl* propertyName,
     152        JSValueRegs base, JSValueRegs value);
     153
     154    void generateFastPath(MacroAssembler&);
     155};
     156
    146157class JITInstanceOfGenerator : public JITInlineCacheGenerator {
    147158public:
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r231976 r231998  
    378378}
    379379
    380 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
     380EncodedJSValue JIT_OPERATION operationInById(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
    381381{
    382382    SuperSamplerScope superSamplerScope(false);
    383    
    384     VM* vm = &exec->vm();
    385     NativeCallFrameTracer tracer(vm, exec);
    386     auto scope = DECLARE_THROW_SCOPE(*vm);
    387 
    388     if (!base->isObject()) {
    389         throwException(exec, scope, createInvalidInParameterError(exec, base));
     383
     384    VM& vm = exec->vm();
     385    NativeCallFrameTracer tracer(&vm, exec);
     386    auto scope = DECLARE_THROW_SCOPE(vm);
     387
     388    stubInfo->tookSlowPath = true;
     389
     390    Identifier ident = Identifier::fromUid(&vm, uid);
     391
     392    JSValue baseValue = JSValue::decode(base);
     393    if (!baseValue.isObject()) {
     394        throwException(exec, scope, createInvalidInParameterError(exec, baseValue));
    390395        return JSValue::encode(jsUndefined());
    391396    }
    392    
    393     AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
    394 
    395     Identifier ident = Identifier::fromUid(vm, key);
    396     LOG_IC((ICEvent::OperationInOptimize, base->classInfo(*vm), ident));
    397     PropertySlot slot(base, PropertySlot::InternalMethodType::HasProperty);
    398     bool result = asObject(base)->getPropertySlot(exec, ident, slot);
    399     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    400    
    401     RELEASE_ASSERT(accessType == stubInfo->accessType);
    402    
    403     if (stubInfo->considerCaching(exec->codeBlock(), asObject(base)->structure()))
    404         repatchIn(exec, base, ident, result, slot, *stubInfo);
    405    
    406     return JSValue::encode(jsBoolean(result));
    407 }
    408 
    409 EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, UniquedStringImpl* key)
     397    JSObject* baseObject = asObject(baseValue);
     398
     399    LOG_IC((ICEvent::OperationInById, baseObject->classInfo(vm), ident));
     400
     401    PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
     402    return JSValue::encode(jsBoolean(baseObject->getPropertySlot(exec, ident, slot)));
     403}
     404
     405EncodedJSValue JIT_OPERATION operationInByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
    410406{
    411407    SuperSamplerScope superSamplerScope(false);
    412    
    413     VM* vm = &exec->vm();
    414     NativeCallFrameTracer tracer(vm, exec);
    415     auto scope = DECLARE_THROW_SCOPE(*vm);
    416 
    417     stubInfo->tookSlowPath = true;
    418 
    419     if (!base->isObject()) {
    420         throwException(exec, scope, createInvalidInParameterError(exec, base));
     408
     409    VM& vm = exec->vm();
     410    NativeCallFrameTracer tracer(&vm, exec);
     411    auto scope = DECLARE_THROW_SCOPE(vm);
     412
     413    Identifier ident = Identifier::fromUid(&vm, uid);
     414
     415    JSValue baseValue = JSValue::decode(base);
     416    if (!baseValue.isObject()) {
     417        throwException(exec, scope, createInvalidInParameterError(exec, baseValue));
    421418        return JSValue::encode(jsUndefined());
    422419    }
    423 
    424     Identifier ident = Identifier::fromUid(vm, key);
    425     LOG_IC((ICEvent::OperationIn, base->classInfo(*vm), ident));
    426     scope.release();
    427     return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
    428 }
    429 
    430 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key)
     420    JSObject* baseObject = asObject(baseValue);
     421
     422    LOG_IC((ICEvent::OperationInByIdGeneric, baseObject->classInfo(vm), ident));
     423
     424    PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
     425    return JSValue::encode(jsBoolean(baseObject->getPropertySlot(exec, ident, slot)));
     426}
     427
     428EncodedJSValue JIT_OPERATION operationInByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
    431429{
    432430    SuperSamplerScope superSamplerScope(false);
    433    
    434     VM* vm = &exec->vm();
    435     NativeCallFrameTracer tracer(vm, exec);
    436 
    437     return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, base, JSValue::decode(key))));
     431
     432    VM& vm = exec->vm();
     433    NativeCallFrameTracer tracer(&vm, exec);
     434    auto scope = DECLARE_THROW_SCOPE(vm);
     435
     436    Identifier ident = Identifier::fromUid(&vm, uid);
     437
     438    JSValue baseValue = JSValue::decode(base);
     439    if (!baseValue.isObject()) {
     440        throwException(exec, scope, createInvalidInParameterError(exec, baseValue));
     441        return JSValue::encode(jsUndefined());
     442    }
     443    JSObject* baseObject = asObject(baseValue);
     444
     445    LOG_IC((ICEvent::OperationInByIdOptimize, baseObject->classInfo(vm), ident));
     446
     447    PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
     448    bool found = baseObject->getPropertySlot(exec, ident, slot);
     449    if (stubInfo->considerCaching(exec->codeBlock(), baseObject->structure(vm)))
     450        repatchInByID(exec, baseObject, ident, found, slot, *stubInfo);
     451    return JSValue::encode(jsBoolean(found));
     452}
     453
     454EncodedJSValue JIT_OPERATION operationInByVal(ExecState* exec, JSCell* base, EncodedJSValue key)
     455{
     456    SuperSamplerScope superSamplerScope(false);
     457   
     458    VM* vm = &exec->vm();
     459    NativeCallFrameTracer tracer(vm, exec);
     460
     461    return JSValue::encode(jsBoolean(CommonSlowPaths::opInByVal(exec, base, JSValue::decode(key))));
    438462}
    439463
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r231961 r231998  
    372372EncodedJSValue JIT_OPERATION operationGetByIdDirectGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    373373EncodedJSValue JIT_OPERATION operationGetByIdDirectOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
     374EncodedJSValue JIT_OPERATION operationInById(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
     375EncodedJSValue JIT_OPERATION operationInByIdGeneric(ExecState*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
     376EncodedJSValue JIT_OPERATION operationInByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, UniquedStringImpl*) WTF_INTERNAL;
    374377EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
    375378EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, UniquedStringImpl*) WTF_INTERNAL;
    376 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
     379EncodedJSValue JIT_OPERATION operationInByVal(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
    377380void JIT_OPERATION operationPutByIdStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL;
    378381void JIT_OPERATION operationPutByIdNonStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r231961 r231998  
    748748
    749749    Call call = callOperation(gen.slowPathFunction(), gen.stubInfo(), regT1, regT0, ident->impl());
     750
     751    gen.reportSlowPathCall(coldPathBegin, call);
     752}
     753
     754void JIT::emit_op_in_by_id(Instruction* currentInstruction)
     755{
     756    int resultVReg = currentInstruction[1].u.operand;
     757    int baseVReg = currentInstruction[2].u.operand;
     758    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     759
     760    emitGetVirtualRegister(baseVReg, regT0);
     761
     762    emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
     763
     764    JITInByIdGenerator gen(
     765        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
     766        ident->impl(), JSValueRegs(regT0), JSValueRegs(regT0));
     767    gen.generateFastPath(*this);
     768    addSlowCase(gen.slowPathJump());
     769    m_inByIds.append(gen);
     770
     771    emitPutVirtualRegister(resultVReg);
     772}
     773
     774void JIT::emitSlow_op_in_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     775{
     776    linkAllSlowCases(iter);
     777
     778    int resultVReg = currentInstruction[1].u.operand;
     779    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     780
     781    JITInByIdGenerator& gen = m_inByIds[m_inByIdIndex++];
     782
     783    Label coldPathBegin = label();
     784
     785    Call call = callOperation(operationInByIdOptimize, resultVReg, gen.stubInfo(), regT0, ident->impl());
    750786
    751787    gen.reportSlowPathCall(coldPathBegin, call);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r231905 r231998  
    769769        gen.slowPathFunction(), gen.stubInfo(), JSValueRegs(regT3, regT2), JSValueRegs(regT1, regT0), ident->impl());
    770770   
     771    gen.reportSlowPathCall(coldPathBegin, call);
     772}
     773
     774void JIT::emit_op_in_by_id(Instruction* currentInstruction)
     775{
     776    int dst = currentInstruction[1].u.operand;
     777    int base = currentInstruction[2].u.operand;
     778    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     779
     780    emitLoad(base, regT1, regT0);
     781    emitJumpSlowCaseIfNotJSCell(base, regT1);
     782
     783    JITInByIdGenerator gen(
     784        m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
     785        ident->impl(), JSValueRegs::payloadOnly(regT0), JSValueRegs(regT1, regT0));
     786    gen.generateFastPath(*this);
     787    addSlowCase(gen.slowPathJump());
     788    m_inByIds.append(gen);
     789
     790    emitStore(dst, regT1, regT0);
     791}
     792
     793void JIT::emitSlow_op_in_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
     794{
     795    linkAllSlowCases(iter);
     796
     797    int resultVReg = currentInstruction[1].u.operand;
     798    const Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
     799
     800    JITInByIdGenerator& gen = m_inByIds[m_getByIdIndex++];
     801
     802    Label coldPathBegin = label();
     803
     804    Call call = callOperationWithProfile(operationInByIdOptimize, resultVReg, gen.stubInfo(), JSValueRegs(regT1, regT0), ident->impl());
     805
    771806    gen.reportSlowPathCall(coldPathBegin, call);
    772807}
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r231961 r231998  
    606606}
    607607
    608 static InlineCacheAction tryCacheIn(
    609     ExecState* exec, JSCell* base, const Identifier& ident,
     608static InlineCacheAction tryCacheInByID(
     609    ExecState* exec, JSObject* base, const Identifier& ident,
    610610    bool wasFound, const PropertySlot& slot, StructureStubInfo& stubInfo)
    611611{
     
    632632        ObjectPropertyConditionSet conditionSet;
    633633        if (wasFound) {
     634            InlineCacheAction action = actionForCell(vm, base);
     635            if (action != AttemptToCache)
     636                return action;
     637
     638            // Optimize self access.
     639            if (stubInfo.cacheType == CacheType::Unset
     640                && slot.isCacheableValue()
     641                && slot.slotBase() == base
     642                && !slot.watchpointSet()
     643                && !structure->needImpurePropertyWatchpoint()) {
     644                bool generatedCodeInline = InlineAccess::generateSelfInAccess(stubInfo, structure);
     645                if (generatedCodeInline) {
     646                    LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident));
     647                    structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
     648                    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize);
     649                    stubInfo.initInByIdSelf(codeBlock, structure, slot.cachedOffset());
     650                    return RetryCacheLater;
     651                }
     652            }
     653
    634654            if (slot.slotBase() != base) {
    635655                bool usesPolyProto;
     
    665685
    666686        std::unique_ptr<AccessCase> newCase = AccessCase::create(
    667             vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain));
     687            vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, wasFound ? slot.cachedOffset() : invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain));
    668688
    669689        result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase));
     
    673693           
    674694            RELEASE_ASSERT(result.code());
    675 
    676             MacroAssembler::repatchJump(
    677                 stubInfo.patchableJump(),
    678                 CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
     695            InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
    679696        }
    680697    }
     
    685702}
    686703
    687 void repatchIn(
    688     ExecState* exec, JSCell* base, const Identifier& ident, bool wasFound,
    689     const PropertySlot& slot, StructureStubInfo& stubInfo)
     704void repatchInByID(ExecState* exec, JSObject* baseObject, const Identifier& propertyName, bool wasFound, const PropertySlot& slot, StructureStubInfo& stubInfo)
    690705{
    691706    SuperSamplerScope superSamplerScope(false);
    692     if (tryCacheIn(exec, base, ident, wasFound, slot, stubInfo) == GiveUpOnCache)
    693         ftlThunkAwareRepatchCall(exec->codeBlock(), stubInfo.slowPathCallLocation(), operationIn);
     707
     708    if (tryCacheInByID(exec, baseObject, propertyName, wasFound, slot, stubInfo) == GiveUpOnCache) {
     709        CodeBlock* codeBlock = exec->codeBlock();
     710        ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInById);
     711    }
    694712}
    695713
     
    12371255}
    12381256
    1239 void resetIn(StructureStubInfo& stubInfo)
     1257void resetInByID(CodeBlock* codeBlock, StructureStubInfo& stubInfo)
     1258{
     1259    ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize);
     1260    InlineAccess::rewireStubAsJump(stubInfo, stubInfo.slowPathStartLocation());
     1261}
     1262
     1263void resetInstanceOf(StructureStubInfo& stubInfo)
    12401264{
    12411265    resetPatchableJump(stubInfo);
    12421266}
    12431267
    1244 void resetInstanceOf(StructureStubInfo& stubInfo)
    1245 {
    1246     resetPatchableJump(stubInfo);
    1247 }
    1248 
    12491268} // namespace JSC
    12501269
  • trunk/Source/JavaScriptCore/jit/Repatch.h

    r231961 r231998  
    4545void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
    4646void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
    47 void repatchIn(ExecState*, JSCell*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
     47void repatchInByID(ExecState*, JSObject*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
    4848void repatchInstanceOf(ExecState*, JSValue value, JSValue prototype, StructureStubInfo&, bool wasFound);
    4949void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSObject* callee, MacroAssemblerCodePtr<JSEntryPtrTag>);
     
    5555void resetGetByID(CodeBlock*, StructureStubInfo&, GetByIDKind);
    5656void resetPutByID(CodeBlock*, StructureStubInfo&);
    57 void resetIn(StructureStubInfo&);
     57void resetInByID(CodeBlock*, StructureStubInfo&);
    5858void resetInstanceOf(StructureStubInfo&);
    5959void ftlThunkAwareRepatchCall(CodeBlock*, CodeLocationCall<JSInternalPtrTag>, FunctionPtr<CFunctionPtrTag> newCalleeFunction);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r231751 r231998  
    15081508
    15091509
    1510 _llint_op_in:
    1511     traceExecution()
    1512     callSlowPath(_slow_path_in)
    1513     dispatch(constexpr op_in_length)
     1510_llint_op_in_by_id:
     1511    traceExecution()
     1512    callSlowPath(_slow_path_in_by_id)
     1513    dispatch(constexpr op_in_by_id_length)
     1514
     1515
     1516_llint_op_in_by_val:
     1517    traceExecution()
     1518    callSlowPath(_slow_path_in_by_val)
     1519    dispatch(constexpr op_in_by_val_length)
    15141520
    15151521
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r231719 r231998  
    15521552    callSlowPath(_llint_slow_path_put_by_id)
    15531553    dispatch(constexpr op_put_by_id_length)
     1554
    15541555
    15551556macro finishGetByVal(result, scratch)
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r229608 r231998  
    624624
    625625    inline InNode::InNode(const JSTokenLocation& location, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments)
    626         : ThrowableBinaryOpNode(location, expr1, expr2, op_in, rightHasAssignments)
     626        : ThrowableBinaryOpNode(location, expr1, expr2, op_in_by_val, rightHasAssignments)
    627627    {
    628628    }
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r231886 r231998  
    649649}
    650650
    651 SLOW_PATH_DECL(slow_path_in)
    652 {
    653     BEGIN();
    654     RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile)));
     651SLOW_PATH_DECL(slow_path_in_by_val)
     652{
     653    BEGIN();
     654    RETURN(jsBoolean(CommonSlowPaths::opInByVal(exec, OP_C(2).jsValue(), OP_C(3).jsValue(), pc[4].u.arrayProfile)));
     655}
     656
     657SLOW_PATH_DECL(slow_path_in_by_id)
     658{
     659    BEGIN();
     660
     661    JSValue baseValue = OP_C(2).jsValue();
     662    if (!baseValue.isObject())
     663        THROW(createInvalidInParameterError(exec, baseValue));
     664
     665    RETURN(jsBoolean(asObject(baseValue)->hasProperty(exec, exec->codeBlock()->identifier(pc[3].u.operand))));
    655666}
    656667
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r231990 r231998  
    8686}
    8787
    88 inline bool opIn(ExecState* exec, JSValue baseVal, JSValue propName, ArrayProfile* arrayProfile = nullptr)
     88inline bool opInByVal(ExecState* exec, JSValue baseVal, JSValue propName, ArrayProfile* arrayProfile = nullptr)
    8989{
    9090    VM& vm = exec->vm();
     
    309309SLOW_PATH_HIDDEN_DECL(slow_path_is_object_or_null);
    310310SLOW_PATH_HIDDEN_DECL(slow_path_is_function);
    311 SLOW_PATH_HIDDEN_DECL(slow_path_in);
     311SLOW_PATH_HIDDEN_DECL(slow_path_in_by_id);
     312SLOW_PATH_HIDDEN_DECL(slow_path_in_by_val);
    312313SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
    313314SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
Note: See TracChangeset for help on using the changeset viewer.