Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JSC] Reland megamorphic IC
https://bugs.webkit.org/show_bug.cgi?id=255316
rdar://107920311

Reviewed by Justin Michaud.

This patch relands megamorphic IC change. The change from the previous one is that,
we need to consider CacheableDictionary case for the instance's Structure itself.
If prototype has CacheableDictionary, then mayBePrototype based invalidation just works.
But if the instance is CacheableDictionary, then,

1. If it is own property hit. It does not matter! We can just cache it since CacheableDictionary
   monotonically increases offsets.
2. If it is prototype-chain property hit, then we cannot use it since CacheableDictionary can hide
   the property. Currently we conservatively give up this thing since flattening is also a bit costly
   operation.
3. If it is miss case, dictionary cannot work too, same as (2) since CacheableDictionary can hide the
   property miss.

                                       ToT                     Patched

megamorphic-own-load             91.9477+-1.2898     ^     36.5782+-0.0943        ^ definitely 2.5137x faster
megamorphic-load                 13.2700+-0.0586     ^      4.4819+-0.0197        ^ definitely 2.9608x faster
megamorphic-prototype-load      112.6192+-1.5504     ^     36.6802+-0.1328        ^ definitely 3.0703x faster
megamorphic-miss                 94.1059+-1.2833     ^     30.3792+-0.0875        ^ definitely 3.0977x faster

* JSTests/microbenchmarks/megamorphic-miss.js: Added.
(f):
* JSTests/microbenchmarks/megamorphic-own-load.js: Added.
(f):
* JSTests/microbenchmarks/megamorphic-prototype-load.js: Added.
(f):
* Source/JavaScriptCore/CMakeLists.txt:
* Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj:
* Source/JavaScriptCore/Sources.txt:
* Source/JavaScriptCore/bytecode/AccessCase.cpp:
(JSC::AccessCase::create):
(JSC::AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck const):
(JSC::AccessCase::requiresIdentifierNameMatch const):
(JSC::AccessCase::requiresInt32PropertyCheck const):
(JSC::AccessCase::needsScratchFPR const):
(JSC::AccessCase::forEachDependentCell const):
(JSC::AccessCase::doesCalls const):
(JSC::AccessCase::canReplace const):
(JSC::AccessCase::runWithDowncast):
(JSC::AccessCase::canBeShared):
* Source/JavaScriptCore/bytecode/AccessCase.h:
* Source/JavaScriptCore/bytecode/CheckPrivateBrandStatus.cpp:
(JSC::CheckPrivateBrandStatus::CheckPrivateBrandStatus):
* Source/JavaScriptCore/bytecode/DeleteByStatus.cpp:
(JSC::DeleteByStatus::DeleteByStatus):
* Source/JavaScriptCore/bytecode/GetByStatus.cpp:
(JSC::GetByStatus::GetByStatus):
* Source/JavaScriptCore/bytecode/InByStatus.h:
* Source/JavaScriptCore/bytecode/InlineCacheCompiler.cpp:
(JSC::InlineCacheCompiler::generateWithGuard):
(JSC::InlineCacheCompiler::generateImpl):
(JSC::InlineCacheCompiler::regenerate):
(WTF::printInternal):
* Source/JavaScriptCore/bytecode/InlineCacheCompiler.h:
(JSC::AccessGenerationResult::AccessGenerationResult):
(JSC::AccessGenerationResult::generatedMegamorphicCode const):
(JSC::AccessGenerationResult::generatedSomeCode const):
* Source/JavaScriptCore/bytecode/InstanceOfStatus.h:
* Source/JavaScriptCore/bytecode/PutByStatus.cpp:
(JSC::PutByStatus::PutByStatus):
(JSC::PutByStatus::computeFor):
* Source/JavaScriptCore/bytecode/Repatch.cpp:
(JSC::tryCacheGetBy):
(JSC::repatchGetBy):
(JSC::repatchGetBySlowPathCall):
(JSC::tryCachePutBy):
(JSC::tryCacheDeleteBy):
* Source/JavaScriptCore/bytecode/Repatch.h:
* Source/JavaScriptCore/bytecode/SetPrivateBrandStatus.cpp:
(JSC::SetPrivateBrandStatus::SetPrivateBrandStatus):
* Source/JavaScriptCore/bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::summary const):
* Source/JavaScriptCore/bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::considerRepatchingCacheGeneric):
(JSC::StructureStubInfo::considerRepatchingCacheBy):
(JSC::StructureStubInfo::considerRepatchingCacheMegamorphic):
(JSC::StructureStubInfo::considerRepatchingCacheImpl):
(JSC::StructureStubInfo::considerCachingGeneric): Deleted.
(JSC::StructureStubInfo::considerCachingBy): Deleted.
(JSC::StructureStubInfo::considerCaching): Deleted.
* Source/JavaScriptCore/bytecode/StubInfoSummary.cpp:
(WTF::printInternal):
* Source/JavaScriptCore/bytecode/StubInfoSummary.h:
(JSC::isInlineable):
(JSC::slowVersion):
* Source/JavaScriptCore/dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* Source/JavaScriptCore/heap/Heap.cpp:
(JSC::Heap::finalize):
* Source/JavaScriptCore/jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
(JSC::putByValOptimize):
(JSC::directPutByValOptimize):
(JSC::putPrivateNameOptimize):
* Source/JavaScriptCore/jit/JITOperations.h:
* Source/JavaScriptCore/llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* Source/JavaScriptCore/runtime/CommonSlowPaths.cpp:
(JSC::JSC_DEFINE_COMMON_SLOW_PATH):
* Source/JavaScriptCore/runtime/HasOwnPropertyCache.h:
(JSC::VM::ensureHasOwnPropertyCache):
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* Source/JavaScriptCore/runtime/JSObject.cpp:
(JSC::JSObject::setPrototypeDirect):
(JSC::JSObject::deleteProperty):
(JSC::JSObject::convertToUncacheableDictionary):
* Source/JavaScriptCore/runtime/JSObject.h:
* Source/JavaScriptCore/runtime/JSObjectInlines.h:
(JSC::JSObject::prepareToPutDirectWithoutTransition):
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::mayBePrototype const):
(JSC::JSObject::didBecomePrototype):
* Source/JavaScriptCore/runtime/MegamorphicCache.cpp: Copied from Source/JavaScriptCore/bytecode/StubInfoSummary.cpp.
(JSC::MegamorphicCache::age):
(JSC::MegamorphicCache::clearEntries):
* Source/JavaScriptCore/runtime/MegamorphicCache.h: Added.
(JSC::MegamorphicCache::Entry::offsetOfUid):
(JSC::MegamorphicCache::Entry::offsetOfStructureID):
(JSC::MegamorphicCache::Entry::offsetOfEpoch):
(JSC::MegamorphicCache::Entry::offsetOfOffset):
(JSC::MegamorphicCache::Entry::offsetOfHolder):
(JSC::MegamorphicCache::Entry::initAsMiss):
(JSC::MegamorphicCache::Entry::initAsHit):
(JSC::MegamorphicCache::offsetOfPrimaryEntries):
(JSC::MegamorphicCache::offsetOfSecondaryEntries):
(JSC::MegamorphicCache::offsetOfEpoch):
(JSC::MegamorphicCache::primaryHash):
(JSC::MegamorphicCache::secondaryHash):
(JSC::MegamorphicCache::initAsMiss):
(JSC::MegamorphicCache::initAsHit):
(JSC::MegamorphicCache::epoch const):
(JSC::MegamorphicCache::bumpEpoch):
* Source/JavaScriptCore/runtime/ObjectPrototype.cpp:
(JSC::objectPrototypeHasOwnProperty):
* Source/JavaScriptCore/runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::becomePrototypeTransition):
(JSC::Structure::nonPropertyTransitionSlow):
* Source/JavaScriptCore/runtime/Structure.h:
* Source/JavaScriptCore/runtime/StructureCache.cpp:
(JSC::StructureCache::createEmptyStructure):
* Source/JavaScriptCore/runtime/StructureInlines.h:
(JSC::Structure::create):
(JSC::Structure::nonPropertyTransition):
* Source/JavaScriptCore/runtime/StructureTransitionTable.h:
* Source/JavaScriptCore/runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::ensureMegamorphicCacheSlow):
(JSC::VM::invalidateStructureChainIntegrity):
* Source/JavaScriptCore/runtime/VM.h:
(JSC::VM::megamorphicCache):
(JSC::VM::ensureMegamorphicCache):
* Source/WebCore/bindings/js/JSDOMAsyncIterator.h:
(WebCore::JSDOMAsyncIteratorBase::createPrototype):
* Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h:
(WebCore::JSDOMBuiltinConstructor<JSClass>::createStructure):
* Source/WebCore/bindings/js/JSDOMConstructor.h:
(WebCore::JSDOMConstructor<JSClass>::createStructure):
* Source/WebCore/bindings/js/JSDOMConstructorNotCallable.h:
(WebCore::JSDOMConstructorNotCallable<JSClass>::createStructure):
* Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h:
(WebCore::JSDOMConstructorNotConstructable<JSClass>::createStructure):
* Source/WebCore/bindings/js/JSDOMIterator.h:
(WebCore::JSDOMIteratorBase::createPrototype):
* Source/WebCore/bindings/js/JSWindowProxy.cpp:
(WebCore::JSWindowProxy::setWindow):
* Source/WebCore/bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):
* Source/WebCore/bindings/scripts/test/JS/JSExposedStar.cpp:
(WebCore::JSExposedStar::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSExposedToWorkerAndWindow.cpp:
(WebCore::JSExposedToWorkerAndWindow::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestAsyncIterable.cpp:
(WebCore::JSTestAsyncIterable::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestAsyncKeyValueIterable.cpp:
(WebCore::JSTestAsyncKeyValueIterable::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestCEReactions.cpp:
(WebCore::JSTestCEReactions::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestCEReactionsStringifier.cpp:
(WebCore::JSTestCEReactionsStringifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestCallTracer.cpp:
(WebCore::JSTestCallTracer::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestClassWithJSBuiltinConstructor.cpp:
(WebCore::JSTestClassWithJSBuiltinConstructor::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestConditionalIncludes.cpp:
(WebCore::JSTestConditionalIncludes::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestConditionallyReadWrite.cpp:
(WebCore::JSTestConditionallyReadWrite::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDOMJIT.cpp:
(WebCore::JSTestDOMJIT::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSON.cpp:
(WebCore::JSTestDefaultToJSON::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSONFilteredByExposed.cpp:
(WebCore::JSTestDefaultToJSONFilteredByExposed::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSONIndirectInheritance.cpp:
(WebCore::JSTestDefaultToJSONIndirectInheritance::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSONInherit.cpp:
(WebCore::JSTestDefaultToJSONInherit::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDefaultToJSONInheritFinal.cpp:
(WebCore::JSTestDefaultToJSONInheritFinal::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDelegateToSharedSyntheticAttribute.cpp:
(WebCore::JSTestDelegateToSharedSyntheticAttribute::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestDomainSecurity.cpp:
(WebCore::JSTestDomainSecurity::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestEnabledBySetting.cpp:
(WebCore::JSTestEnabledBySetting::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestEnabledForContext.cpp:
(WebCore::JSTestEnabledForContext::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestEventConstructor.cpp:
(WebCore::JSTestEventConstructor::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestEventTarget.cpp:
(WebCore::JSTestEventTarget::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestException.cpp:
(WebCore::JSTestException::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestGenerateAddOpaqueRoot.cpp:
(WebCore::JSTestGenerateAddOpaqueRoot::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestGenerateIsReachable.cpp:
(WebCore::JSTestGenerateIsReachable::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestIndexedSetterNoIdentifier.cpp:
(WebCore::JSTestIndexedSetterNoIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestIndexedSetterThrowingException.cpp:
(WebCore::JSTestIndexedSetterThrowingException::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestIndexedSetterWithIdentifier.cpp:
(WebCore::JSTestIndexedSetterWithIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp:
(WebCore::JSTestInterface::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestInterfaceLeadingUnderscore.cpp:
(WebCore::JSTestInterfaceLeadingUnderscore::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestIterable.cpp:
(WebCore::JSTestIterable::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestJSBuiltinConstructor.cpp:
(WebCore::JSTestJSBuiltinConstructor::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestLegacyFactoryFunction.cpp:
(WebCore::JSTestLegacyFactoryFunction::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestLegacyNoInterfaceObject.cpp:
(WebCore::JSTestLegacyNoInterfaceObject::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestLegacyOverrideBuiltIns.cpp:
(WebCore::JSTestLegacyOverrideBuiltIns::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestMapLike.cpp:
(WebCore::JSTestMapLike::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestMapLikeWithOverriddenOperations.cpp:
(WebCore::JSTestMapLikeWithOverriddenOperations::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedAndIndexedSetterNoIdentifier.cpp:
(WebCore::JSTestNamedAndIndexedSetterNoIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedAndIndexedSetterThrowingException.cpp:
(WebCore::JSTestNamedAndIndexedSetterThrowingException::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedAndIndexedSetterWithIdentifier.cpp:
(WebCore::JSTestNamedAndIndexedSetterWithIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterNoIdentifier.cpp:
(WebCore::JSTestNamedDeleterNoIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterThrowingException.cpp:
(WebCore::JSTestNamedDeleterThrowingException::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIdentifier.cpp:
(WebCore::JSTestNamedDeleterWithIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedDeleterWithIndexedGetter.cpp:
(WebCore::JSTestNamedDeleterWithIndexedGetter::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedGetterCallWith.cpp:
(WebCore::JSTestNamedGetterCallWith::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedGetterNoIdentifier.cpp:
(WebCore::JSTestNamedGetterNoIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedGetterWithIdentifier.cpp:
(WebCore::JSTestNamedGetterWithIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterNoIdentifier.cpp:
(WebCore::JSTestNamedSetterNoIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterThrowingException.cpp:
(WebCore::JSTestNamedSetterThrowingException::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithIdentifier.cpp:
(WebCore::JSTestNamedSetterWithIdentifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithIndexedGetter.cpp:
(WebCore::JSTestNamedSetterWithIndexedGetter::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithIndexedGetterAndSetter.cpp:
(WebCore::JSTestNamedSetterWithIndexedGetterAndSetter::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithLegacyOverrideBuiltIns.cpp:
(WebCore::JSTestNamedSetterWithLegacyOverrideBuiltIns::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithLegacyUnforgeableProperties.cpp:
(WebCore::JSTestNamedSetterWithLegacyUnforgeableProperties::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNamedSetterWithLegacyUnforgeablePropertiesAndLegacyOverrideBuiltIns.cpp:
(WebCore::JSTestNamedSetterWithLegacyUnforgeablePropertiesAndLegacyOverrideBuiltIns::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp:
(WebCore::JSTestNode::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::JSTestObj::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestOperationConditional.cpp:
(WebCore::JSTestOperationConditional::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
(WebCore::JSTestOverloadedConstructors::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructorsWithSequence.cpp:
(WebCore::JSTestOverloadedConstructorsWithSequence::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestPluginInterface.cpp:
(WebCore::JSTestPluginInterface::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestPromiseRejectionEvent.cpp:
(WebCore::JSTestPromiseRejectionEvent::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestReadOnlyMapLike.cpp:
(WebCore::JSTestReadOnlyMapLike::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestReadOnlySetLike.cpp:
(WebCore::JSTestReadOnlySetLike::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestReportExtraMemoryCost.cpp:
(WebCore::JSTestReportExtraMemoryCost::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestSerializedScriptValueInterface.cpp:
(WebCore::JSTestSerializedScriptValueInterface::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestSetLike.cpp:
(WebCore::JSTestSetLike::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestSetLikeWithOverriddenOperations.cpp:
(WebCore::JSTestSetLikeWithOverriddenOperations::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifier.cpp:
(WebCore::JSTestStringifier::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierAnonymousOperation.cpp:
(WebCore::JSTestStringifierAnonymousOperation::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierNamedOperation.cpp:
(WebCore::JSTestStringifierNamedOperation::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierOperationImplementedAs.cpp:
(WebCore::JSTestStringifierOperationImplementedAs::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierOperationNamedToString.cpp:
(WebCore::JSTestStringifierOperationNamedToString::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierReadOnlyAttribute.cpp:
(WebCore::JSTestStringifierReadOnlyAttribute::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestStringifierReadWriteAttribute.cpp:
(WebCore::JSTestStringifierReadWriteAttribute::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestTaggedWrapper.cpp:
(WebCore::JSTestTaggedWrapper::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSTestTypedefs.cpp:
(WebCore::JSTestTypedefs::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSWorkerGlobalScope.cpp:
(WebCore::JSWorkerGlobalScope::createPrototype):
* Source/WebCore/bindings/scripts/test/JS/JSWorkletGlobalScope.cpp:
(WebCore::JSWorkletGlobalScope::createPrototype):
* Source/WebCore/workers/WorkerOrWorkletScriptController.cpp:
(WebCore::WorkerOrWorkletScriptController::initScriptWithSubclass):

Canonical link: https://commits.webkit.org/262872@main
  • Loading branch information
Constellation committed Apr 12, 2023
1 parent 1f4abbc commit 2f4c8f0
Show file tree
Hide file tree
Showing 135 changed files with 1,106 additions and 193 deletions.
20 changes: 20 additions & 0 deletions JSTests/microbenchmarks/megamorphic-miss.js
@@ -0,0 +1,20 @@
function f(arr) {
var res = 0;
for (var i=0; i<10000000; i++) {
var o = arr[i % arr.length];
if (o.someprop)
res = 1;
}
return res;
}
noInline(f);

var arr = [];

for (var i=0; i<40; i++) {
var o = {};
o["a" + i] = i;
arr.push(o);
}

f(arr);
21 changes: 21 additions & 0 deletions JSTests/microbenchmarks/megamorphic-own-load.js
@@ -0,0 +1,21 @@
function f(arr) {
var res = 0;
for (var i=0; i<10000000; i++) {
var o = arr[i % arr.length];
if (o.someprop)
res = 1;
}
return res;
}
noInline(f);

var arr = [];

for (var i=0; i<40; i++) {
var o = {};
o.someprop = 42;
o["a" + i] = i;
arr.push(o);
}

f(arr);
22 changes: 22 additions & 0 deletions JSTests/microbenchmarks/megamorphic-prototype-load.js
@@ -0,0 +1,22 @@
function f(arr) {
var res = 0;
for (var i=0; i<10000000; i++) {
var o = arr[i % arr.length];
if (o.someprop)
res = 1;
}
return res;
}
noInline(f);

var arr = [];

for (var i=0; i<40; i++) {
var o = {
__proto__: { __proto__: { __proto__: { someprop: 42 } } }
};
o["a" + i] = i;
arr.push(o);
}

f(arr);
28 changes: 28 additions & 0 deletions JSTests/stress/megamorphic-instance-dictionary-hit.js
@@ -0,0 +1,28 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

var array = [];
var proto = {
test2: 0,
};

for (var i = 0; i < 0x100; ++i) {
var object = {
__proto__: proto,
test: 42,
["prop" + i]: 42
};
$vm.toCacheableDictionary(object);
array.push(object);
}
function access(object) { return object.test2; }

for (var i = 0; i < 1e6; ++i) {
var index = i & (0x100 - 1);
var object = array[index];
shouldBe(access(object), 0);
}
array[0].test2 = 42;
shouldBe(access(array[0]), 42);
32 changes: 32 additions & 0 deletions JSTests/stress/megamorphic-instance-dictionary-many.js
@@ -0,0 +1,32 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

var array = [];
var proto = {
test2: 0,
};

for (var i = 0; i < 0x100; ++i) {
var object = {
__proto__: proto,
test: 42,
};
for (var j = 0; j < 1000; ++j)
object['prop' + j] = j;
object['id' + i] = 42;
$vm.toCacheableDictionary(object);
array.push(object);
}
function access(object) { return object.prop999; }

for (var i = 0; i < 1e6; ++i) {
var index = i & (0x100 - 1);
var object = array[index];
shouldBe(access(object), 999);
}
array[0].prop999 = 42;
shouldBe(access(array[0]), 42);
array[0].test999 = 42;
shouldBe(access(array[0]), 42);
23 changes: 23 additions & 0 deletions JSTests/stress/megamorphic-instance-dictionary-miss.js
@@ -0,0 +1,23 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

var array = [];
for (var i = 0; i < 0x100; ++i) {
var object = {
test: 42,
["prop" + i]: 42
};
$vm.toCacheableDictionary(object);
array.push(object);
}
function access(object) { return object.test2; }

for (var i = 0; i < 1e6; ++i) {
var index = i & (0x100 - 1);
var object = array[index];
shouldBe(access(object), undefined);
}
array[0].test2 = 42;
shouldBe(access(array[0]), 42);
1 change: 1 addition & 0 deletions Source/JavaScriptCore/CMakeLists.txt
Expand Up @@ -1146,6 +1146,7 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS
runtime/Lookup.h
runtime/MatchResult.h
runtime/MathCommon.h
runtime/MegamorphicCache.h
runtime/MemoryMode.h
runtime/MemoryStatistics.h
runtime/Microtask.h
Expand Down
Expand Up @@ -1996,6 +1996,7 @@
E3A421431D6F58930007C617 /* PreciseJumpTargetsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3AC277721FDB4940024452C /* RegExpCachedResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3B24859291224540029C08A /* BufferMemoryHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = E3B24857291224530029C08A /* BufferMemoryHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3BAEA8B29CEA43900A8E3BB /* MegamorphicCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BAEA8929CEA43800A8E3BB /* MegamorphicCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3BD2B7622F275020011765C /* WasmCompilationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BD2B7522F275020011765C /* WasmCompilationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3BF1BAE238AAEDB003A1C2B /* IsoHeapCellType.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BF1BAD238AAED1003A1C2B /* IsoHeapCellType.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3BF3C4D2390D1E8008BC752 /* JSWebAssemblyGlobal.h in Headers */ = {isa = PBXBuildFile; fileRef = E3BF3C4B2390D1E2008BC752 /* JSWebAssemblyGlobal.h */; };
Expand Down Expand Up @@ -5517,6 +5518,8 @@
E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargetsInlines.h; sourceTree = "<group>"; };
E3B24857291224530029C08A /* BufferMemoryHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BufferMemoryHandle.h; sourceTree = "<group>"; };
E3B24858291224530029C08A /* BufferMemoryHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BufferMemoryHandle.cpp; sourceTree = "<group>"; };
E3BAEA8929CEA43800A8E3BB /* MegamorphicCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MegamorphicCache.h; sourceTree = "<group>"; };
E3BAEA8A29CEA43800A8E3BB /* MegamorphicCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MegamorphicCache.cpp; sourceTree = "<group>"; };
E3BD2B7522F275020011765C /* WasmCompilationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCompilationMode.h; sourceTree = "<group>"; };
E3BF1BAD238AAED1003A1C2B /* IsoHeapCellType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IsoHeapCellType.h; sourceTree = "<group>"; };
E3BF3C4B2390D1E2008BC752 /* JSWebAssemblyGlobal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JSWebAssemblyGlobal.h; path = js/JSWebAssemblyGlobal.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -8159,6 +8162,8 @@
4340A4831A9051AF00D73CCA /* MathCommon.h */,
F692A86A0255597D01FF60F7 /* MathObject.cpp */,
F692A86B0255597D01FF60F7 /* MathObject.h */,
E3BAEA8A29CEA43800A8E3BB /* MegamorphicCache.cpp */,
E3BAEA8929CEA43800A8E3BB /* MegamorphicCache.h */,
E320B66B2912298000E87CDB /* MemoryMode.cpp */,
E320B66A2912298000E87CDB /* MemoryMode.h */,
90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */,
Expand Down Expand Up @@ -10965,6 +10970,7 @@
4340A4851A9051AF00D73CCA /* MathCommon.h in Headers */,
BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */,
E328C6C71DA4304500D255FD /* MaxFrameExtentForSlowPathCall.h in Headers */,
E3BAEA8B29CEA43900A8E3BB /* MegamorphicCache.h in Headers */,
E320B66C2912298100E87CDB /* MemoryMode.h in Headers */,
90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */,
142F16E021558802003D49C9 /* MetadataTable.h in Headers */,
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/Sources.txt
Expand Up @@ -968,6 +968,7 @@ runtime/MapPrototype.cpp
runtime/MatchResult.cpp
runtime/MathCommon.cpp
runtime/MathObject.cpp
runtime/MegamorphicCache.cpp
runtime/MemoryMode.cpp
runtime/MemoryStatistics.cpp
runtime/ModuleProgramExecutable.cpp
Expand Down
48 changes: 46 additions & 2 deletions Source/JavaScriptCore/bytecode/AccessCase.cpp
Expand Up @@ -72,6 +72,7 @@ AccessCase::AccessCase(VM& vm, JSCell* owner, AccessType type, CacheableIdentifi
Ref<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, CacheableIdentifier identifier, PropertyOffset offset, Structure* structure, const ObjectPropertyConditionSet& conditionSet, RefPtr<PolyProtoAccessChain>&& prototypeAccessChain)
{
switch (type) {
case LoadMegamorphic:
case InHit:
case InMiss:
case DeleteNonConfigurable:
Expand Down Expand Up @@ -137,7 +138,22 @@ Ref<AccessCase> AccessCase::create(VM& vm, JSCell* owner, AccessType type, Cache
case IndexedResizableTypedArrayFloat64Store:
RELEASE_ASSERT(!prototypeAccessChain);
break;
default:
case Load:
case Miss:
case Delete:
case Transition:
case GetGetter:
case Getter:
case Setter:
case CustomValueGetter:
case CustomValueSetter:
case CustomAccessorGetter:
case CustomAccessorSetter:
case IntrinsicGetter:
case InstanceOfHit:
case InstanceOfMiss:
case CheckPrivateBrand:
case SetPrivateBrand:
RELEASE_ASSERT_NOT_REACHED();
};

Expand Down Expand Up @@ -321,6 +337,7 @@ bool AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck() const
return false;

switch (m_type) {
case LoadMegamorphic:
case ArrayLength:
case StringLength:
case DirectArgumentsLength:
Expand Down Expand Up @@ -380,16 +397,36 @@ bool AccessCase::guardedByStructureCheckSkippingConstantIdentifierCheck() const
case IndexedResizableTypedArrayFloat32Store:
case IndexedResizableTypedArrayFloat64Store:
return false;
case Load:
case Miss:
case Delete:
case DeleteNonConfigurable:
case DeleteMiss:
case Replace:
case IndexedNoIndexingMiss:
default:
case Transition:
case GetGetter:
case Getter:
case Setter:
case CustomValueGetter:
case CustomValueSetter:
case CustomAccessorGetter:
case CustomAccessorSetter:
case InHit:
case InMiss:
case IntrinsicGetter:
case CheckPrivateBrand:
case SetPrivateBrand:
return true;
}
RELEASE_ASSERT_NOT_REACHED();
}

bool AccessCase::requiresIdentifierNameMatch() const
{
switch (m_type) {
case Load:
case LoadMegamorphic:
// We don't currently have a by_val for these puts, but we do care about the identifier.
case Transition:
case Delete:
Expand Down Expand Up @@ -478,6 +515,7 @@ bool AccessCase::requiresInt32PropertyCheck() const
{
switch (m_type) {
case Load:
case LoadMegamorphic:
case Transition:
case Delete:
case DeleteNonConfigurable:
Expand Down Expand Up @@ -565,6 +603,7 @@ bool AccessCase::needsScratchFPR() const
{
switch (m_type) {
case Load:
case LoadMegamorphic:
case Transition:
case Delete:
case DeleteNonConfigurable:
Expand Down Expand Up @@ -705,6 +744,7 @@ void AccessCase::forEachDependentCell(VM&, const Functor& functor) const
case CustomAccessorGetter:
case CustomAccessorSetter:
case Load:
case LoadMegamorphic:
case Transition:
case Delete:
case DeleteNonConfigurable:
Expand Down Expand Up @@ -799,6 +839,7 @@ bool AccessCase::doesCalls(VM& vm, Vector<JSCell*>* cellsToMarkIfDoesCalls) cons
case DeleteNonConfigurable:
case DeleteMiss:
case Load:
case LoadMegamorphic:
case Miss:
case GetGetter:
case InHit:
Expand Down Expand Up @@ -922,6 +963,7 @@ bool AccessCase::canReplace(const AccessCase& other) const
};

switch (type()) {
case LoadMegamorphic:
case IndexedInt32Load:
case IndexedDoubleLoad:
case IndexedContiguousLoad:
Expand Down Expand Up @@ -1129,6 +1171,7 @@ template<typename Func>
inline void AccessCase::runWithDowncast(const Func& func)
{
switch (m_type) {
case LoadMegamorphic:
case Transition:
case Delete:
case DeleteNonConfigurable:
Expand Down Expand Up @@ -1266,6 +1309,7 @@ bool AccessCase::canBeShared(const AccessCase& lhs, const AccessCase& rhs)

switch (lhs.m_type) {
case Load:
case LoadMegamorphic:
case Transition:
case Delete:
case DeleteNonConfigurable:
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/AccessCase.h
Expand Up @@ -91,6 +91,7 @@ DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(AccessCase);

#define JSC_FOR_EACH_ACCESS_TYPE(macro) \
macro(Load) \
macro(LoadMegamorphic) \
macro(Transition) \
macro(Delete) \
macro(DeleteNonConfigurable) \
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/CheckPrivateBrandStatus.cpp
Expand Up @@ -75,6 +75,7 @@ CheckPrivateBrandStatus::CheckPrivateBrandStatus(StubInfoSummary summary, Struct
m_state = NoInformation;
return;
case StubInfoSummary::Simple:
case StubInfoSummary::Megamorphic:
case StubInfoSummary::MakesCalls:
case StubInfoSummary::TakesSlowPathAndMakesCalls:
RELEASE_ASSERT_NOT_REACHED();
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/DeleteByStatus.cpp
Expand Up @@ -74,6 +74,7 @@ DeleteByStatus::DeleteByStatus(StubInfoSummary summary, StructureStubInfo& stubI
m_state = NoInformation;
return;
case StubInfoSummary::Simple:
case StubInfoSummary::Megamorphic:
case StubInfoSummary::MakesCalls:
case StubInfoSummary::TakesSlowPathAndMakesCalls:
RELEASE_ASSERT_NOT_REACHED();
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/GetByStatus.cpp
Expand Up @@ -183,6 +183,7 @@ GetByStatus::GetByStatus(StubInfoSummary summary, StructureStubInfo* stubInfo)
case StubInfoSummary::MakesCalls:
RELEASE_ASSERT_NOT_REACHED();
return;
case StubInfoSummary::Megamorphic:
case StubInfoSummary::TakesSlowPath:
ASSERT(stubInfo);
m_state = stubInfo->tookSlowPath ? ObservedTakesSlowPath : LikelyTakesSlowPath;
Expand Down
1 change: 1 addition & 0 deletions Source/JavaScriptCore/bytecode/InByStatus.h
Expand Up @@ -67,6 +67,7 @@ class InByStatus final {
m_state = NoInformation;
return;
case StubInfoSummary::Simple:
case StubInfoSummary::Megamorphic:
case StubInfoSummary::MakesCalls:
RELEASE_ASSERT_NOT_REACHED();
return;
Expand Down

0 comments on commit 2f4c8f0

Please sign in to comment.