Skip to content
Permalink
Browse files
[DOMJIT] Add initial CheckDOM and CallDOM implementations
https://bugs.webkit.org/show_bug.cgi?id=162941

Reviewed by Filip Pizlo.

JSTests:

* stress/domjit-getter-poly.js: Added.
(shouldBe):
(access):
* stress/domjit-getter-proto.js: Added.
(shouldBe):
(access):
* stress/domjit-getter-super-poly.js: Added.
(shouldBe):
(access):
* stress/domjit-getter.js: Added.
(shouldBe):
(access):

Source/JavaScriptCore:

This patch implements a prototype of DOMJIT accelerated getter.
We add two new DFG nodes, CheckDOM and CallDOM.

CheckDOM is used to filter inappropriate |this| object for DOM getter. Its functionality
is equivalent to jsDynamicCast's Check. You can use like "CheckDOM, @1, JSNode::info()",
and this CheckDOM incurs a BadType exit if the class of the given @1 is not a subclass of
JSNode::info().

CallDOM is used to emit actual DOM operations. It takes GlobalObject and checked DOM
object. And it returns JSValue as its result.

Both CheckDOM and CallDOM can take a DOMJIT::Patchpoint. This is somewhat code snippet
generator, and is injectable to DFG and FTL. DFG and FTL set up registers correctly
according to DOMJIT::Patchpoint's requirement and invoke this patchpoint generator to emit code.
While CallDOM always requires a patchpoint, ideally CheckDOM does not require it since
isSubclassOf check can be implemented in DFG / FTL side. However, some classes have a
faster way to query isSubclassOf. For example, JSNode in WebCore introduces a special
JSType to optimize this query. CheckDOM's patchpoint gives us a chance to emit special
faster code for such a case.

By leveraging above nodes, we can construct DOMJIT accelerated getter. When DFG recognizes the
given getter call is CustomGetter and it has DOMJIT::GetterSetter information, DFG emits the above nodes.
We implemented a prototype in jsc.cpp shell as DOMJITGetter to test the functionality.

Notes about the future extensions.

1. Currently, we do not allow CallDOM to emit any function calls. This will be extended by
   adding `addSlowPathCall` functionality to DOMJIT::Patchpoint later. Interesting thing is that
   we need to create an abstraction over DFG slow path call and FTL slow path call!

2. CheckDOM is not handled in DFGTypeCheckHoistingPhase yet. And we have a chance to merge several CheckDOM into one.
   For example, given CheckDOM A and CheckDOM B to the same target. If A is subclass of B, we can merge them to CheckDOM A.

* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3Effects.h:
(JSC::B3::Effects::forCheck):
* b3/B3Value.cpp:
(JSC::B3::Value::effects):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::GetByIdStatus::makesCalls):
(JSC::GetByIdStatus::dump):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::isCustom):
(JSC::GetByIdStatus::takesSlowPath):
(JSC::GetByIdStatus::isSimple): Deleted.
* bytecode/SpeculatedType.cpp:
(JSC::speculationFromClassInfo):
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::filterClassInfo):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::filterClassInfo):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::filterClassInfo):
* dfg/DFGAbstractValue.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleDOMJITGetter):
(JSC::DFG::ByteCodeParser::handleGetById):
* 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/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasDOMJIT):
(JSC::DFG::Node::domJIT):
(JSC::DFG::Node::hasClassInfo):
(JSC::DFG::Node::classInfo):
(JSC::DFG::Node::OpInfoWrapper::OpInfoWrapper):
(JSC::DFG::Node::OpInfoWrapper::operator=):
* dfg/DFGNodeType.h:
* dfg/DFGOpInfo.h:
(JSC::DFG::OpInfo::OpInfo):
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::allocateTemporaryRegistersForPatchpoint):
(JSC::DFG::SpeculativeJIT::compileCallDOM):
(JSC::DFG::SpeculativeJIT::compileCheckDOM):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureAbstractValue.cpp:
(JSC::DFG::StructureAbstractValue::filterClassInfoSlow):
(JSC::DFG::StructureAbstractValue::isSubClassOf):
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::filterClassInfo):
(JSC::DFG::StructureAbstractValue::filter): Deleted.
* domjit/DOMJITPatchpointParams.h: Copied from Source/JavaScriptCore/dfg/DFGOpInfo.h.
(JSC::DOMJIT::PatchpointParams::~PatchpointParams):
(JSC::DOMJIT::PatchpointParams::size):
(JSC::DOMJIT::PatchpointParams::at):
(JSC::DOMJIT::PatchpointParams::operator[]):
(JSC::DOMJIT::PatchpointParams::gpScratch):
(JSC::DOMJIT::PatchpointParams::fpScratch):
(JSC::DOMJIT::PatchpointParams::PatchpointParams):
* domjit/DOMJITReg.h: Added.
(JSC::DOMJIT::Reg::Reg):
(JSC::DOMJIT::Reg::isGPR):
(JSC::DOMJIT::Reg::isFPR):
(JSC::DOMJIT::Reg::isJSValueRegs):
(JSC::DOMJIT::Reg::gpr):
(JSC::DOMJIT::Reg::fpr):
(JSC::DOMJIT::Reg::jsValueRegs):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM):
(JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):
(JSC::FTL::DFG::LowerDFGToB3::compileUnreachable): Deleted.
* jit/AssemblyHelpers.h:
* jsc.cpp:
(WTF::DOMJITNode::DOMJITNode):
(WTF::DOMJITNode::createStructure):
(WTF::DOMJITNode::create):
(WTF::DOMJITNode::value):
(WTF::DOMJITNode::offsetOfValue):
(WTF::DOMJITGetter::DOMJITGetter):
(WTF::DOMJITGetter::createStructure):
(WTF::DOMJITGetter::create):
(WTF::DOMJITGetter::DOMJITNodeDOMJIT::DOMJITNodeDOMJIT):
(WTF::DOMJITGetter::domJITNodeGetterSetter):
(WTF::DOMJITGetter::finishCreation):
(WTF::DOMJITGetter::customGetter):
(GlobalObject::finishCreation):
(functionCreateDOMJITNodeObject):
(functionCreateDOMJITGetterObject):

Source/WTF:

* wtf/Box.h:
(WTF::Box::Box):

Canonical link: https://commits.webkit.org/180899@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@206846 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Constellation committed Oct 6, 2016
1 parent 647d011 commit 2465184eea93735a46137c6a2e4bbb29bf89362a
Showing 40 changed files with 1,007 additions and 10 deletions.
@@ -1,3 +1,23 @@
2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com>

[DOMJIT] Add initial CheckDOM and CallDOM implementations
https://bugs.webkit.org/show_bug.cgi?id=162941

Reviewed by Filip Pizlo.

* stress/domjit-getter-poly.js: Added.
(shouldBe):
(access):
* stress/domjit-getter-proto.js: Added.
(shouldBe):
(access):
* stress/domjit-getter-super-poly.js: Added.
(shouldBe):
(access):
* stress/domjit-getter.js: Added.
(shouldBe):
(access):

2016-10-04 Saam Barati <sbarati@apple.com>

String.prototype.toLowerCase should be a DFG/FTL intrinsic
@@ -0,0 +1,19 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`bad value: ${String(actual)}`);
}

var domjit1 = createDOMJITGetterObject();
var domjit2 = createDOMJITGetterObject();

function access(domjit)
{
return domjit.customGetter + domjit.customGetter;
}

for (var i = 0; i < 1e4; ++i)
shouldBe(access((i & 0x1) ? domjit1 : domjit2), 84);

shouldBe(access({ customGetter: 42 }), 84);
domjit1.test = 44;
shouldBe(access(domjit1), 84);
@@ -0,0 +1,17 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`bad value: ${String(actual)}`);
}

var domjit = createDOMJITNodeObject();
function access(domjit)
{
return domjit.customGetter + domjit.customGetter;
}

for (var i = 0; i < 1e4; ++i)
shouldBe(access(domjit), 84);

shouldBe(access({ customGetter: 42 }), 84);
domjit.test = 44;
shouldBe(access(domjit), 84);
@@ -0,0 +1,18 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`bad value: ${String(actual)}`);
}

var domjits = [];
for (var i = 0; i < 100; ++i)
domjits.push(createDOMJITGetterObject());

function access(domjit)
{
return domjit.customGetter + domjit.customGetter;
}

for (var i = 0; i < 1e2; ++i) {
for (var j = 0; j < domjits.length; ++j)
shouldBe(access(domjits[j]), 84);
}
@@ -0,0 +1,18 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error(`bad value: ${String(actual)}`);
}

var domjit = createDOMJITGetterObject();

function access(domjit)
{
return domjit.customGetter + domjit.customGetter;
}

for (var i = 0; i < 1e4; ++i)
shouldBe(access(domjit), 84);

shouldBe(access({ customGetter: 42 }), 84);
domjit.test = 44;
shouldBe(access(domjit), 84);
@@ -1,3 +1,148 @@
2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com>

[DOMJIT] Add initial CheckDOM and CallDOM implementations
https://bugs.webkit.org/show_bug.cgi?id=162941

Reviewed by Filip Pizlo.

This patch implements a prototype of DOMJIT accelerated getter.
We add two new DFG nodes, CheckDOM and CallDOM.

CheckDOM is used to filter inappropriate |this| object for DOM getter. Its functionality
is equivalent to jsDynamicCast's Check. You can use like "CheckDOM, @1, JSNode::info()",
and this CheckDOM incurs a BadType exit if the class of the given @1 is not a subclass of
JSNode::info().

CallDOM is used to emit actual DOM operations. It takes GlobalObject and checked DOM
object. And it returns JSValue as its result.

Both CheckDOM and CallDOM can take a DOMJIT::Patchpoint. This is somewhat code snippet
generator, and is injectable to DFG and FTL. DFG and FTL set up registers correctly
according to DOMJIT::Patchpoint's requirement and invoke this patchpoint generator to emit code.
While CallDOM always requires a patchpoint, ideally CheckDOM does not require it since
isSubclassOf check can be implemented in DFG / FTL side. However, some classes have a
faster way to query isSubclassOf. For example, JSNode in WebCore introduces a special
JSType to optimize this query. CheckDOM's patchpoint gives us a chance to emit special
faster code for such a case.

By leveraging above nodes, we can construct DOMJIT accelerated getter. When DFG recognizes the
given getter call is CustomGetter and it has DOMJIT::GetterSetter information, DFG emits the above nodes.
We implemented a prototype in jsc.cpp shell as DOMJITGetter to test the functionality.

Notes about the future extensions.

1. Currently, we do not allow CallDOM to emit any function calls. This will be extended by
adding `addSlowPathCall` functionality to DOMJIT::Patchpoint later. Interesting thing is that
we need to create an abstraction over DFG slow path call and FTL slow path call!

2. CheckDOM is not handled in DFGTypeCheckHoistingPhase yet. And we have a chance to merge several CheckDOM into one.
For example, given CheckDOM A and CheckDOM B to the same target. If A is subclass of B, we can merge them to CheckDOM A.

* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3Effects.h:
(JSC::B3::Effects::forCheck):
* b3/B3Value.cpp:
(JSC::B3::Value::effects):
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback):
(JSC::GetByIdStatus::makesCalls):
(JSC::GetByIdStatus::dump):
* bytecode/GetByIdStatus.h:
(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::isCustom):
(JSC::GetByIdStatus::takesSlowPath):
(JSC::GetByIdStatus::isSimple): Deleted.
* bytecode/SpeculatedType.cpp:
(JSC::speculationFromClassInfo):
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::filterClassInfo):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::filterClassInfo):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::filterClassInfo):
* dfg/DFGAbstractValue.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleDOMJITGetter):
(JSC::DFG::ByteCodeParser::handleGetById):
* 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/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasDOMJIT):
(JSC::DFG::Node::domJIT):
(JSC::DFG::Node::hasClassInfo):
(JSC::DFG::Node::classInfo):
(JSC::DFG::Node::OpInfoWrapper::OpInfoWrapper):
(JSC::DFG::Node::OpInfoWrapper::operator=):
* dfg/DFGNodeType.h:
* dfg/DFGOpInfo.h:
(JSC::DFG::OpInfo::OpInfo):
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::allocateTemporaryRegistersForPatchpoint):
(JSC::DFG::SpeculativeJIT::compileCallDOM):
(JSC::DFG::SpeculativeJIT::compileCheckDOM):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureAbstractValue.cpp:
(JSC::DFG::StructureAbstractValue::filterClassInfoSlow):
(JSC::DFG::StructureAbstractValue::isSubClassOf):
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::filterClassInfo):
(JSC::DFG::StructureAbstractValue::filter): Deleted.
* domjit/DOMJITPatchpointParams.h: Copied from Source/JavaScriptCore/dfg/DFGOpInfo.h.
(JSC::DOMJIT::PatchpointParams::~PatchpointParams):
(JSC::DOMJIT::PatchpointParams::size):
(JSC::DOMJIT::PatchpointParams::at):
(JSC::DOMJIT::PatchpointParams::operator[]):
(JSC::DOMJIT::PatchpointParams::gpScratch):
(JSC::DOMJIT::PatchpointParams::fpScratch):
(JSC::DOMJIT::PatchpointParams::PatchpointParams):
* domjit/DOMJITReg.h: Added.
(JSC::DOMJIT::Reg::Reg):
(JSC::DOMJIT::Reg::isGPR):
(JSC::DOMJIT::Reg::isFPR):
(JSC::DOMJIT::Reg::isJSValueRegs):
(JSC::DOMJIT::Reg::gpr):
(JSC::DOMJIT::Reg::fpr):
(JSC::DOMJIT::Reg::jsValueRegs):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM):
(JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):
(JSC::FTL::DFG::LowerDFGToB3::compileUnreachable): Deleted.
* jit/AssemblyHelpers.h:
* jsc.cpp:
(WTF::DOMJITNode::DOMJITNode):
(WTF::DOMJITNode::createStructure):
(WTF::DOMJITNode::create):
(WTF::DOMJITNode::value):
(WTF::DOMJITNode::offsetOfValue):
(WTF::DOMJITGetter::DOMJITGetter):
(WTF::DOMJITGetter::createStructure):
(WTF::DOMJITGetter::create):
(WTF::DOMJITGetter::DOMJITNodeDOMJIT::DOMJITNodeDOMJIT):
(WTF::DOMJITGetter::domJITNodeGetterSetter):
(WTF::DOMJITGetter::finishCreation):
(WTF::DOMJITGetter::customGetter):
(GlobalObject::finishCreation):
(functionCreateDOMJITNodeObject):
(functionCreateDOMJITGetterObject):

2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com>

[JSC] Do not construct Simple GetByIdStatus against self-custom-accessor case
@@ -2098,6 +2098,8 @@
E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */; };
E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */; settings = {ATTRIBUTES = (Private, ); }; };
E37AD83D1DA4928600F3D412 /* DOMJITReg.h in Headers */ = {isa = PBXBuildFile; fileRef = E37AD83B1DA4928000F3D412 /* DOMJITReg.h */; settings = {ATTRIBUTES = (Private, ); }; };
E3963CEE1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */; };
E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
E39DA4A61B7E8B7C0084F33A /* JSModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */; };
@@ -4397,6 +4399,8 @@
E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InspectorInstrumentationObject.js; sourceTree = "<group>"; };
E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; };
E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; };
E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITPatchpointParams.h; sourceTree = "<group>"; };
E37AD83B1DA4928000F3D412 /* DOMJITReg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITReg.h; sourceTree = "<group>"; };
E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; };
E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; };
E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; };
@@ -7183,6 +7187,8 @@
children = (
E3FF752F1D9CEA1200C7E16D /* DOMJITGetterSetter.h */,
E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */,
E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */,
E37AD83B1DA4928000F3D412 /* DOMJITReg.h */,
);
path = domjit;
sourceTree = "<group>";
@@ -7600,6 +7606,7 @@
E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */,
0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */,
E37AD83D1DA4928600F3D412 /* DOMJITReg.h in Headers */,
0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */,
0F392C8A1B46188400844728 /* DFGOSRExitFuzz.h in Headers */,
0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */,
@@ -8428,6 +8435,7 @@
9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */,
451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */,
86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */,
86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */,
0FB4767F1D99AEAD008EA6CB /* GCDeferralContextInlines.h in Headers */,
@@ -78,6 +78,15 @@ struct Effects {
return result;
}

static Effects forCheck()
{
Effects result;
result.exitsSideways = true;
// The program could read anything after exiting, and it's on us to declare this.
result.reads = HeapRange::top();
return result;
}

bool mustExecute() const
{
return terminal || exitsSideways || writesLocalState || writes;
@@ -614,9 +614,7 @@ Effects Value::effects() const
case CheckSub:
case CheckMul:
case Check:
result.exitsSideways = true;
// The program could read anything after exiting, and it's on us to declare this.
result.reads = HeapRange::top();
result = Effects::forCheck();
break;
case Upsilon:
case Set:
@@ -246,6 +246,7 @@ GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(
domJIT = access.domJIT();
if (!domJIT)
return GetByIdStatus(slowPathState, true);
result.m_state = Custom;
break;
}
default: {
@@ -263,6 +264,16 @@ GetByIdStatus GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback(

if (!result.appendVariant(variant))
return GetByIdStatus(slowPathState, true);

if (domJIT) {
// Give up when cutom accesses are not merged into one.
if (result.numVariants() != 1)
return GetByIdStatus(slowPathState, true);
} else {
// Give up when custom access and simple access are mixed.
if (result.m_state == Custom)
return GetByIdStatus(slowPathState, true);
}
break;
} }
}
@@ -362,6 +373,7 @@ bool GetByIdStatus::makesCalls() const
switch (m_state) {
case NoInformation:
case TakesSlowPath:
case Custom:
return false;
case Simple:
for (unsigned i = m_variants.size(); i--;) {
@@ -403,6 +415,9 @@ void GetByIdStatus::dump(PrintStream& out) const
case Simple:
out.print("Simple");
break;
case Custom:
out.print("Custom");
break;
case TakesSlowPath:
out.print("TakesSlowPath");
break;
@@ -44,6 +44,7 @@ class GetByIdStatus {
NoInformation, // It's uncached so we have no information.
Simple, // It's cached for a simple access to a known object property with
// a possible structure chain and a possible specific value.
Custom, // It's cached for a custom accessor with a possible structure chain.
TakesSlowPath, // It's known to often take slow path.
MakesCalls // It's known to take paths that make calls.
};
@@ -64,7 +65,7 @@ class GetByIdStatus {
: m_state(state)
, m_wasSeenInJIT(wasSeenInJIT)
{
ASSERT((state == Simple) == variant.isSet());
ASSERT((state == Simple || state == Custom) == variant.isSet());
m_variants.append(variant);
}

@@ -82,13 +83,14 @@ class GetByIdStatus {
bool isSet() const { return m_state != NoInformation; }
bool operator!() const { return !isSet(); }
bool isSimple() const { return m_state == Simple; }
bool isCustom() const { return m_state == Custom; }

size_t numVariants() const { return m_variants.size(); }
const Vector<GetByIdVariant, 1>& variants() const { return m_variants; }
const GetByIdVariant& at(size_t index) const { return m_variants[index]; }
const GetByIdVariant& operator[](size_t index) const { return at(index); }

bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom; }
bool makesCalls() const;

bool wasSeenInJIT() const { return m_wasSeenInJIT; }

0 comments on commit 2465184

Please sign in to comment.