JSC should have InstanceOf inline caching
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 May 2018 17:29:56 +0000 (17:29 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 May 2018 17:29:56 +0000 (17:29 +0000)
commit452d1e42bc764d04f58d179dd759ca353eab2d5b
treeb896fb12c01d222cc9dbbf7b9646c9f9dc94d198
parent32b81930c14f86af006e0834cd4b00854ab41578
JSC should have InstanceOf inline caching
https://bugs.webkit.org/show_bug.cgi?id=185652

Reviewed by Saam Barati.
JSTests:

* microbenchmarks/instanceof-always-hit-one.js: Added.
* microbenchmarks/instanceof-always-hit-two.js: Added.
* microbenchmarks/instanceof-dynamic.js: Added.
* microbenchmarks/instanceof-sometimes-hit.js: Added.
* stress/instanceof-dynamic-proxy-check-structure.js: Added.
* stress/instanceof-dynamic-proxy-loop.js: Added.
* stress/instanceof-dynamic-proxy.js: Added.
* stress/instanceof-hit-one-object-then-another.js: Added.
* stress/instanceof-hit-two-objects-then-another.js: Added.
* stress/instanceof-prototype-change.js: Added.
* stress/instanceof-prototype-change-to-hit.js: Added.
* stress/instanceof-prototype-change-to-null.js: Added.
* stress/instanceof-prototype-change-watchpointable.js: Added.

Source/JavaScriptCore:

This adds a polymorphic inline cache for instanceof. It caches hits and misses. It uses the
existing PolymorphicAccess IC machinery along with all of its heuristics. If we ever generate
too many cases, we emit the generic instanceof implementation instead.

All of the JIT tiers use the same InstanceOf IC. It uses the existing JITInlineCacheGenerator
abstraction.

This is a ~40% speed-up on instanceof microbenchmarks. It's a *tiny* (~1%) speed-up on
Octane/boyer. I think I can make that speed-up bigger by inlining the inline cache.

* API/tests/testapi.mm:
(testObjectiveCAPIMain):
* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* b3/B3Effects.h:
(JSC::B3::Effects::forReadOnlyCall):
* bytecode/AccessCase.cpp:
(JSC::AccessCase::guardedByStructureCheck const):
(JSC::AccessCase::canReplace const):
(JSC::AccessCase::visitWeak const):
(JSC::AccessCase::generateWithGuard):
(JSC::AccessCase::generateImpl):
* bytecode/AccessCase.h:
* bytecode/InstanceOfAccessCase.cpp: Added.
(JSC::InstanceOfAccessCase::create):
(JSC::InstanceOfAccessCase::dumpImpl const):
(JSC::InstanceOfAccessCase::clone const):
(JSC::InstanceOfAccessCase::~InstanceOfAccessCase):
(JSC::InstanceOfAccessCase::InstanceOfAccessCase):
* bytecode/InstanceOfAccessCase.h: Added.
(JSC::InstanceOfAccessCase::prototype const):
* bytecode/ObjectPropertyCondition.h:
(JSC::ObjectPropertyCondition::hasPrototypeWithoutBarrier):
(JSC::ObjectPropertyCondition::hasPrototype):
* bytecode/ObjectPropertyConditionSet.cpp:
(JSC::generateConditionsForInstanceOf):
* bytecode/ObjectPropertyConditionSet.h:
* bytecode/PolymorphicAccess.cpp:
(JSC::PolymorphicAccess::addCases):
(JSC::PolymorphicAccess::regenerate):
(WTF::printInternal):
* bytecode/PropertyCondition.cpp:
(JSC::PropertyCondition::dumpInContext const):
(JSC::PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint const):
(JSC::PropertyCondition::validityRequiresImpurePropertyWatchpoint const):
(WTF::printInternal):
* bytecode/PropertyCondition.h:
(JSC::PropertyCondition::absenceWithoutBarrier):
(JSC::PropertyCondition::absenceOfSetEffectWithoutBarrier):
(JSC::PropertyCondition::hasPrototypeWithoutBarrier):
(JSC::PropertyCondition::hasPrototype):
(JSC::PropertyCondition::hasPrototype const):
(JSC::PropertyCondition::prototype const):
(JSC::PropertyCondition::hash const):
(JSC::PropertyCondition::operator== const):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::StructureStubInfo):
(JSC::StructureStubInfo::reset):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::considerCaching):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGInlineCacheWrapper.h:
* dfg/DFGInlineCacheWrapperInlines.h:
(JSC::DFG::InlineCacheWrapper<GeneratorType>::finalize):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::addInstanceOf):
* dfg/DFGOperations.cpp:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::usedRegisters):
(JSC::DFG::SpeculativeJIT::compileInstanceOfForCells):
(JSC::DFG::SpeculativeJIT::compileInstanceOf):
(JSC::DFG::SpeculativeJIT::compileInstanceOfForObject): Deleted.
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::cachedGetById):
(JSC::DFG::SpeculativeJIT::cachedGetByIdWithThis):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileAssertNotEmpty):
(JSC::FTL::DFG::LowerDFGToB3::compilePutById):
(JSC::FTL::DFG::LowerDFGToB3::compileNumberIsInteger):
(JSC::FTL::DFG::LowerDFGToB3::compileIn):
(JSC::FTL::DFG::LowerDFGToB3::compileInstanceOf):
(JSC::FTL::DFG::LowerDFGToB3::getById):
(JSC::FTL::DFG::LowerDFGToB3::getByIdWithThis):
* jit/ICStats.h:
* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::link):
* jit/JIT.h:
* jit/JITInlineCacheGenerator.cpp:
(JSC::JITInlineCacheGenerator::JITInlineCacheGenerator):
(JSC::JITInlineCacheGenerator::finalize):
(JSC::JITByIdGenerator::JITByIdGenerator):
(JSC::JITByIdGenerator::finalize):
(JSC::JITInstanceOfGenerator::JITInstanceOfGenerator):
(JSC::JITInstanceOfGenerator::generateFastPath):
(JSC::JITInstanceOfGenerator::finalize):
* jit/JITInlineCacheGenerator.h:
(JSC::JITInlineCacheGenerator::reportSlowPathCall):
(JSC::JITInlineCacheGenerator::slowPathBegin const):
(JSC::JITInstanceOfGenerator::JITInstanceOfGenerator):
(JSC::finalizeInlineCaches):
(JSC::JITByIdGenerator::reportSlowPathCall): Deleted.
(JSC::JITByIdGenerator::slowPathBegin const): Deleted.
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_instanceof):
(JSC::JIT::emitSlow_op_instanceof):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::privateCompileGetByValWithCachedId):
(JSC::JIT::privateCompilePutByValWithCachedId):
* jit/RegisterSet.cpp:
(JSC::RegisterSet::stubUnavailableRegisters):
* jit/Repatch.cpp:
(JSC::tryCacheIn):
(JSC::tryCacheInstanceOf):
(JSC::repatchInstanceOf):
(JSC::resetPatchableJump):
(JSC::resetIn):
(JSC::resetInstanceOf):
* jit/Repatch.h:
* runtime/Options.h:
* runtime/Structure.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231961 268f45cc-cd09-0410-ab3c-d52691b4dbfc
59 files changed:
JSTests/ChangeLog
JSTests/microbenchmarks/instanceof-always-hit-one.js [new file with mode: 0644]
JSTests/microbenchmarks/instanceof-always-hit-two.js [new file with mode: 0644]
JSTests/microbenchmarks/instanceof-dynamic.js [new file with mode: 0644]
JSTests/microbenchmarks/instanceof-sometimes-hit.js [new file with mode: 0644]
JSTests/microbenchmarks/instanceof-tricky-dynamic.js [new file with mode: 0644]
JSTests/stress/instanceof-dynamic-proxy-check-structure.js [new file with mode: 0644]
JSTests/stress/instanceof-dynamic-proxy-loop.js [new file with mode: 0644]
JSTests/stress/instanceof-dynamic-proxy.js [new file with mode: 0644]
JSTests/stress/instanceof-hit-one-object-then-another.js [new file with mode: 0644]
JSTests/stress/instanceof-hit-two-objects-then-another.js [new file with mode: 0644]
JSTests/stress/instanceof-prototype-change-to-hit.js [new file with mode: 0644]
JSTests/stress/instanceof-prototype-change-to-null.js [new file with mode: 0644]
JSTests/stress/instanceof-prototype-change-watchpointable.js [new file with mode: 0644]
JSTests/stress/instanceof-prototype-change.js [new file with mode: 0644]
JSTests/stress/string-instanceof.js [new file with mode: 0644]
JSTests/stress/symbol-instanceof.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/b3/B3Effects.h
Source/JavaScriptCore/bytecode/AccessCase.cpp
Source/JavaScriptCore/bytecode/AccessCase.h
Source/JavaScriptCore/bytecode/InstanceOfAccessCase.cpp [new file with mode: 0644]
Source/JavaScriptCore/bytecode/InstanceOfAccessCase.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h
Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp
Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h
Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp
Source/JavaScriptCore/bytecode/PropertyCondition.cpp
Source/JavaScriptCore/bytecode/PropertyCondition.h
Source/JavaScriptCore/bytecode/StructureStubInfo.cpp
Source/JavaScriptCore/bytecode/StructureStubInfo.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGInlineCacheWrapper.h
Source/JavaScriptCore/dfg/DFGInlineCacheWrapperInlines.h
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/jit/ICStats.h
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITInlineCacheGenerator.cpp
Source/JavaScriptCore/jit/JITInlineCacheGenerator.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITOperations.h
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/RegisterSet.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/jit/Repatch.h
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/Structure.h