Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
[JSC] Add NoIndexing miss optimization
https://bugs.webkit.org/show_bug.cgi?id=240290 rdar://problem/93456330 Reviewed by Saam Barati. `Array.from({ length: 42 })` idiom becomes common. And this is currently inefficient since we perform missed indexed access of the object 42 times. But if we do not have indexed properties for this object and it is plain normal object, then we can have optimization folding it to undefined as we are skipping prototype-chain access for OOB array access. This patch introduces IndexedNoIndexingMiss IC. It guards via structures, and they are ensured that they do not have indexing types. To represent it in PropertyCondition, this patch addds AbsenceOfIndexedProperties PropertyCondition. When we found NoIndexing, we attempt to create IC by collecting structures. In the future, we would like to further optimize it in DFG and FTL by using this condition. But for now, we just use IC. We also add simple optimization via AI-proven structures. PropertyCondition AbsenceOfIndexedProperties is useful, and in the future patches, we should use it to ensure that iterator protocol is met more efficiently. Attached benchmark gets 7x performance improvement. ToT Patched array-from-object 697.6093+-0.9029 ^ 89.7427+-0.7996 ^ definitely 7.7734x faster array-from-object-func 698.9900+-0.5077 ^ 103.7614+-1.7910 ^ definitely 6.7365x faster * JSTests/microbenchmarks/array-from-derived-object-func.js: Added. (shouldBe): (Derived): * JSTests/microbenchmarks/array-from-object-func.js: Added. (shouldBe): * JSTests/microbenchmarks/array-from-object.js: Added. (shouldBe): * JSTests/stress/no-indexing-shape-invalidate.js: Added. (shouldBe): (test): * JSTests/stress/no-indexing-shape-multiple.js: Added. (shouldBe): (test): * JSTests/stress/no-indexing-shape-negative.js: Added. (shouldBe): (test): * JSTests/stress/no-indexing-shape-other-array.js: Added. (shouldBe): (test): * JSTests/stress/no-indexing-shape-prototype-invalidate.js: Added. (shouldBe): (test): * Source/JavaScriptCore/assembler/MacroAssemblerARM64.h: (JSC::MacroAssemblerARM64::add8): * 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::generateWithGuard): (JSC::AccessCase::generateImpl): (JSC::AccessCase::canBeShared): * Source/JavaScriptCore/bytecode/AccessCase.h: (JSC::AccessCase::create): Deleted. * Source/JavaScriptCore/bytecode/ArrayProfile.h: (JSC::ArrayProfile::ArrayProfile): Deleted. * Source/JavaScriptCore/bytecode/ObjectPropertyCondition.h: (JSC::ObjectPropertyCondition::absenceOfIndexedPropertiesWithoutBarrier): (JSC::ObjectPropertyCondition::absenceOfIndexedProperties): * Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.cpp: (JSC::generateConditionsForIndexedMiss): * Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h: * Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp: (JSC::PolymorphicAccess::regenerate): (WTF::printInternal): * Source/JavaScriptCore/bytecode/PropertyCondition.cpp: (JSC::PropertyCondition::dumpInContext const): (JSC::PropertyCondition::isStillValidAssumingImpurePropertyWatchpoint const): (JSC::PropertyCondition::validityRequiresImpurePropertyWatchpoint const): (JSC::PropertyCondition::isStillValid const): (WTF::printInternal): * Source/JavaScriptCore/bytecode/PropertyCondition.h: (JSC::PropertyCondition::absenceOfIndexedPropertiesWithoutBarrier): (JSC::PropertyCondition::absenceOfIndexedProperties): (JSC::PropertyCondition::hasPrototype const): (JSC::PropertyCondition::hash const): (JSC::PropertyCondition::operator== const): * Source/JavaScriptCore/bytecode/Repatch.cpp: (JSC::tryCacheArrayGetByVal): Canonical link: https://commits.webkit.org/253120@main
- Loading branch information
1 parent
1f03945
commit 801dcc1
Showing
19 changed files
with
295 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
class Derived { | ||
constructor() | ||
{ | ||
this.length = 1024 * 1024 * 2; | ||
} | ||
} | ||
|
||
let object = new Derived(); | ||
for (let i = 0; i < 30; i++) { | ||
let array = Array.from(object, () => 42); | ||
shouldBe(array.length, 1024 * 1024 * 2); | ||
shouldBe(1 in array, true); | ||
shouldBe(array[0], 42); | ||
shouldBe(array[1], 42); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
for (let i = 0; i < 30; i++) { | ||
let array = Array.from({ length: 1024 * 1024 * 2 }, () => 42); | ||
shouldBe(array.length, 1024 * 1024 * 2); | ||
shouldBe(1 in array, true); | ||
shouldBe(array[0], 42); | ||
shouldBe(array[1], 42); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
for (let i = 0; i < 30; i++) { | ||
let array = Array.from({ length: 1024 * 1024 * 2 }); | ||
shouldBe(array.length, 1024 * 1024 * 2); | ||
shouldBe(1 in array, true); | ||
shouldBe(array[0], undefined); | ||
shouldBe(array[1], undefined); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function test(object, index) { | ||
return object[index]; | ||
} | ||
noInline(test); | ||
|
||
var object = {}; | ||
for (var i = 0; i < 1e3; ++i) | ||
shouldBe(test(object, i), undefined); | ||
Object.prototype[30] = 42; | ||
shouldBe(test(object, 30), 42); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function test(object, index) { | ||
return object[index]; | ||
} | ||
noInline(test); | ||
|
||
let v1 = { length: 42 }; | ||
let v2 = { length: 42, test: 42 }; | ||
for (let i = 0; i < 1e6; ++i) { | ||
shouldBe(test(v1, i), undefined); | ||
shouldBe(test(v2, i), undefined); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function test(object, index) { | ||
return object[index]; | ||
} | ||
noInline(test); | ||
|
||
Object.prototype[-30] = 42; | ||
var object = {}; | ||
for (var i = 0; i < 1e3; ++i) | ||
shouldBe(test(object, i), undefined); | ||
shouldBe(test(object, -30), 42); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function test(object, index) { | ||
return object[index]; | ||
} | ||
noInline(test); | ||
|
||
var object = {}; | ||
object.__proto__ = new Uint8Array(0); | ||
for (var i = 0; i < 1e3; ++i) | ||
shouldBe(test(object, i), undefined); | ||
shouldBe(test(object, 30), undefined); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
function shouldBe(actual, expected) { | ||
if (actual !== expected) | ||
throw new Error('bad value: ' + actual); | ||
} | ||
|
||
function test(object, index) { | ||
return object[index]; | ||
} | ||
noInline(test); | ||
|
||
var object = {}; | ||
for (var i = 0; i < 1e3; ++i) | ||
shouldBe(test(object, i), undefined); | ||
|
||
object.__proto__ = { | ||
__proto__: Object.prototype, | ||
[30]: 42 | ||
}; | ||
shouldBe(test(object, 30), 42); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.