Commit ce995b22 authored by fpizlo@apple.com's avatar fpizlo@apple.com

Fold typedArray.length if typedArray is constant

https://bugs.webkit.org/show_bug.cgi?id=125252

Source/JavaScriptCore: 

Reviewed by Sam Weinig.
        
This was meant to be easy. The problem is that there was no good place for putting
the folding of typedArray.length to a constant. You can't quite do it in the
bytecode parser because at that point you don't yet know if typedArray is really
a typed array. You can't do it as part of constant folding because the folder
assumes that it can opportunistically forward-flow a constant value without changing
the IR; this doesn't work since we need to first change the IR to register a
desired watchpoint and only after that can we introduce that constant. We could have
done it in Fixup but that would have been awkward since Fixup's code for turning a
GetById of "length" into GetArrayLength is already somewhat complex. We could have
done it in CSE but CSE is already fairly gnarly and will probably get rewritten.
        
So I introduced a new phase, called StrengthReduction. This phase should have any
transformations that don't requite CFA or CSE and that it would be weird to put into
those other phases.
        
I also took the opportunity to refactor some of the other folding code.
        
This also adds a test, but the test couldn't quite be a LayoutTests/js/regress so I
introduced the notion of JavaScriptCore/tests/stress.
        
The goal of this patch isn't really to improve performance or anything like that.
It adds an optimization for completeness, and in doing so it unlocks a bunch of new
possibilities. The one that I'm most excited about is revealing array length checks
in DFG IR, which will allow for array bounds check hoisting and elimination.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetFoldableView):
(JSC::DFG::Graph::tryGetFoldableViewForChild1):
* dfg/DFGGraph.h:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasTypedArray):
(JSC::DFG::Node::typedArray):
* dfg/DFGNodeType.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
(JSC::DFG::SpeculativeJIT::compileConstantIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp: Added.
(JSC::DFG::StrengthReductionPhase::StrengthReductionPhase):
(JSC::DFG::StrengthReductionPhase::run):
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::foldTypedArrayPropertyToConstant):
(JSC::DFG::performStrengthReduction):
* dfg/DFGStrengthReductionPhase.h: Added.
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::typedArrayLength):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionTransferArrayBuffer):
* runtime/ArrayBufferView.h:
* tests/stress: Added.
* tests/stress/fold-typed-array-properties.js: Added.
(foo):

Tools: 

Reviewed by Sam Weinig.
        
Add Source/JavaScriptCore/tests/stress to the set of JS tests. This is where you
should put tests that run just like JSRegress but don't run as part of LayoutTests.
Currently I'm using it for tests that require some surgical support from jsc.cpp.

* Scripts/run-javascriptcore-tests:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160292 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5398143b
......@@ -166,6 +166,7 @@ set(JavaScriptCore_SOURCES
dfg/DFGSpeculativeJIT32_64.cpp
dfg/DFGSpeculativeJIT64.cpp
dfg/DFGStackLayoutPhase.cpp
dfg/DFGStrengthReductionPhase.cpp
dfg/DFGThunks.cpp
dfg/DFGTierUpCheckInjectionPhase.cpp
dfg/DFGTypeCheckHoistingPhase.cpp
......
2013-12-07 Filip Pizlo <fpizlo@apple.com>
Fold typedArray.length if typedArray is constant
https://bugs.webkit.org/show_bug.cgi?id=125252
Reviewed by Sam Weinig.
This was meant to be easy. The problem is that there was no good place for putting
the folding of typedArray.length to a constant. You can't quite do it in the
bytecode parser because at that point you don't yet know if typedArray is really
a typed array. You can't do it as part of constant folding because the folder
assumes that it can opportunistically forward-flow a constant value without changing
the IR; this doesn't work since we need to first change the IR to register a
desired watchpoint and only after that can we introduce that constant. We could have
done it in Fixup but that would have been awkward since Fixup's code for turning a
GetById of "length" into GetArrayLength is already somewhat complex. We could have
done it in CSE but CSE is already fairly gnarly and will probably get rewritten.
So I introduced a new phase, called StrengthReduction. This phase should have any
transformations that don't requite CFA or CSE and that it would be weird to put into
those other phases.
I also took the opportunity to refactor some of the other folding code.
This also adds a test, but the test couldn't quite be a LayoutTests/js/regress so I
introduced the notion of JavaScriptCore/tests/stress.
The goal of this patch isn't really to improve performance or anything like that.
It adds an optimization for completeness, and in doing so it unlocks a bunch of new
possibilities. The one that I'm most excited about is revealing array length checks
in DFG IR, which will allow for array bounds check hoisting and elimination.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetFoldableView):
(JSC::DFG::Graph::tryGetFoldableViewForChild1):
* dfg/DFGGraph.h:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasTypedArray):
(JSC::DFG::Node::typedArray):
* dfg/DFGNodeType.h:
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
(JSC::DFG::SpeculativeJIT::compileConstantIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStrengthReductionPhase.cpp: Added.
(JSC::DFG::StrengthReductionPhase::StrengthReductionPhase):
(JSC::DFG::StrengthReductionPhase::run):
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::foldTypedArrayPropertyToConstant):
(JSC::DFG::performStrengthReduction):
* dfg/DFGStrengthReductionPhase.h: Added.
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::typedArrayLength):
* jsc.cpp:
(GlobalObject::finishCreation):
(functionTransferArrayBuffer):
* runtime/ArrayBufferView.h:
* tests/stress: Added.
* tests/stress/fold-typed-array-properties.js: Added.
(foo):
2013-12-07 peavo@outlook.com <peavo@outlook.com>
[Win][64-bit] Hitting breakpoint assembler instruction in callToJavaScript.
......
......@@ -379,6 +379,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/dfg/DFGSSAConversionPhase.h \
Source/JavaScriptCore/dfg/DFGStackLayoutPhase.cpp \
Source/JavaScriptCore/dfg/DFGStackLayoutPhase.h \
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp \
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.h \
Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h \
Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp \
Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.h \
......
......@@ -412,6 +412,7 @@
<ClCompile Include="..\dfg\DFGSpeculativeJIT64.cpp" />
<ClCompile Include="..\dfg\DFGSSAConversionPhase.cpp" />
<ClCompile Include="..\dfg\DFGStackLayoutPhase.cpp" />
<ClCompile Include="..\dfg\DFGStrengthReductionPhase.cpp" />
<ClCompile Include="..\dfg\DFGThunks.cpp" />
<ClCompile Include="..\dfg\DFGTierUpCheckInjectionPhase.cpp" />
<ClCompile Include="..\dfg\DFGToFTLDeferredCompilationCallback.cpp" />
......@@ -918,6 +919,7 @@
<ClInclude Include="..\dfg\DFGSpeculativeJIT.h" />
<ClInclude Include="..\dfg\DFGSSAConversionPhase.h" />
<ClInclude Include="..\dfg\DFGStackLayoutPhase.h" />
<ClInclude Include="..\dfg\DFGStrengthReductionPhase.h" />
<ClInclude Include="..\dfg\DFGStructureAbstractValue.h" />
<ClInclude Include="..\dfg\DFGThunks.h" />
<ClInclude Include="..\dfg\DFGTierUpCheckInjectionPhase.h" />
......
......@@ -379,6 +379,8 @@
0FC09792146A6F7300CF2442 /* DFGOSRExitCompiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0978F146A6F6300CF2442 /* DFGOSRExitCompiler.cpp */; };
0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC0979F146B28C700CF2442 /* DFGThunks.cpp */; };
0FC097A2146B28CC00CF2442 /* DFGThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097A0146B28C700CF2442 /* DFGThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */; };
0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC314121814559100033232 /* RegisterSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC314101814559100033232 /* RegisterSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC314131814559100033232 /* TempRegisterSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC314111814559100033232 /* TempRegisterSet.cpp */; };
0FC3141518146D7000033232 /* RegisterSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC3141418146D7000033232 /* RegisterSet.cpp */; };
......@@ -541,9 +543,9 @@
0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFB921F16D033050055A5DB /* (null) in Headers */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Private, ); }; };
0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; };
0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */; };
......@@ -1701,6 +1703,8 @@
0FC0978F146A6F6300CF2442 /* DFGOSRExitCompiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompiler.cpp; path = dfg/DFGOSRExitCompiler.cpp; sourceTree = "<group>"; };
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThunks.cpp; path = dfg/DFGThunks.cpp; sourceTree = "<group>"; };
0FC097A0146B28C700CF2442 /* DFGThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThunks.h; path = dfg/DFGThunks.h; sourceTree = "<group>"; };
0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStrengthReductionPhase.cpp; path = dfg/DFGStrengthReductionPhase.cpp; sourceTree = "<group>"; };
0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStrengthReductionPhase.h; path = dfg/DFGStrengthReductionPhase.h; sourceTree = "<group>"; };
0FC314101814559100033232 /* RegisterSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterSet.h; sourceTree = "<group>"; };
0FC314111814559100033232 /* TempRegisterSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TempRegisterSet.cpp; sourceTree = "<group>"; };
0FC3141418146D7000033232 /* RegisterSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterSet.cpp; sourceTree = "<group>"; };
......@@ -1848,9 +1852,9 @@
0FF729A1166AD347000F5BA3 /* ProfilerOriginStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOriginStack.cpp; path = profiler/ProfilerOriginStack.cpp; sourceTree = "<group>"; };
0FF729A2166AD347000F5BA3 /* ProfilerOriginStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOriginStack.h; path = profiler/ProfilerOriginStack.h; sourceTree = "<group>"; };
0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = "<group>"; };
0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = "<group>"; };
0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = "<group>"; };
0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; };
0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCSEPhase.cpp; path = dfg/DFGCSEPhase.cpp; sourceTree = "<group>"; };
......@@ -3962,6 +3966,8 @@
A7D89CF117A0B8CC00773AD8 /* DFGSSAConversionPhase.h */,
0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */,
0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */,
0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */,
0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */,
0F63947615DCE347006A597C /* DFGStructureAbstractValue.h */,
0FC0979F146B28C700CF2442 /* DFGThunks.cpp */,
0FC097A0146B28C700CF2442 /* DFGThunks.h */,
......@@ -4584,6 +4590,7 @@
0FAF7EFE165BA91F000C8455 /* JITDisassembler.h in Headers */,
A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
0F46808214BA572D00BFE272 /* JITExceptions.h in Headers */,
0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
0FB14E1F18124ACE009B6B4D /* JITInlineCacheGenerator.h in Headers */,
86CC85A10EE79A4700288682 /* JITInlines.h in Headers */,
0F24E54D17EE274900ABB217 /* JITOperations.h in Headers */,
......@@ -5480,6 +5487,7 @@
0F235BEB17178E7300690C7F /* DFGOSRExitBase.cpp in Sources */,
0FC09792146A6F7300CF2442 /* DFGOSRExitCompiler.cpp in Sources */,
0FC09776146943B000CF2442 /* DFGOSRExitCompiler32_64.cpp in Sources */,
0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
0FC0977214693AF900CF2442 /* DFGOSRExitCompiler64.cpp in Sources */,
0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */,
0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,
......
......@@ -1148,6 +1148,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
break;
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
break;
case CreateArguments:
......
......@@ -144,7 +144,9 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
return;
case VariableWatchpoint:
case TypedArrayWatchpoint:
read(Watchpoint_fire);
write(SideState);
return;
case NotifyWrite:
......
......@@ -95,17 +95,6 @@ private:
}
case BitOr: {
// Optimize X|0 -> X.
if (node->child2()->isConstant()) {
JSValue C2 = m_graph.valueOfJSConstant(node->child2().node());
if (C2.isInt32() && !C2.asInt32()) {
m_insertionSet.insertNode(m_indexInBlock, SpecNone, Phantom, node->codeOrigin,
Edge(node->child2().node(), KnownInt32Use));
node->children.removeEdge(1);
node->convertToIdentity();
break;
}
}
fixIntEdge(node->child1());
fixIntEdge(node->child2());
break;
......@@ -951,6 +940,7 @@ private:
case ExtractOSREntryLocal:
case LoopHint:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
break;
#else
default:
......
......@@ -740,10 +740,8 @@ WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node)
return activation->registers();
}
JSArrayBufferView* Graph::tryGetFoldableView(Node* node, ArrayMode arrayMode)
JSArrayBufferView* Graph::tryGetFoldableView(Node* node)
{
if (arrayMode.typedArrayType() == NotTypedArray)
return 0;
if (!node->hasConstant())
return 0;
JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(valueOfJSConstant(node));
......@@ -754,6 +752,18 @@ JSArrayBufferView* Graph::tryGetFoldableView(Node* node, ArrayMode arrayMode)
return view;
}
JSArrayBufferView* Graph::tryGetFoldableView(Node* node, ArrayMode arrayMode)
{
if (arrayMode.typedArrayType() == NotTypedArray)
return 0;
return tryGetFoldableView(node);
}
JSArrayBufferView* Graph::tryGetFoldableViewForChild1(Node* node)
{
return tryGetFoldableView(child(node, 0).node(), node->arrayMode());
}
} } // namespace JSC::DFG
#endif
......@@ -806,7 +806,9 @@ public:
JSActivation* tryGetActivation(Node*);
WriteBarrierBase<Unknown>* tryGetRegisters(Node*);
JSArrayBufferView* tryGetFoldableView(Node*);
JSArrayBufferView* tryGetFoldableView(Node*, ArrayMode);
JSArrayBufferView* tryGetFoldableViewForChild1(Node*);
VM& m_vm;
Plan& m_plan;
......
......@@ -972,6 +972,16 @@ struct Node {
{
return reinterpret_cast<VariableWatchpointSet*>(m_opInfo);
}
bool hasTypedArray()
{
return op() == TypedArrayWatchpoint;
}
JSArrayBufferView* typedArray()
{
return reinterpret_cast<JSArrayBufferView*>(m_opInfo);
}
bool hasStructureTransitionData()
{
......
......@@ -171,6 +171,7 @@ namespace JSC { namespace DFG {
macro(Arrayify, NodeMustGenerate) \
macro(ArrayifyToStructure, NodeMustGenerate) \
macro(GetIndexedPropertyStorage, NodeResultStorage) \
macro(TypedArrayWatchpoint, NodeMustGenerate) \
macro(GetByOffset, NodeResultJS) \
macro(PutByOffset, NodeMustGenerate) \
macro(GetArrayLength, NodeResultInt32) \
......
......@@ -53,6 +53,7 @@
#include "DFGResurrectionForValidationPhase.h"
#include "DFGSSAConversionPhase.h"
#include "DFGStackLayoutPhase.h"
#include "DFGStrengthReductionPhase.h"
#include "DFGTierUpCheckInjectionPhase.h"
#include "DFGTypeCheckHoistingPhase.h"
#include "DFGUnificationPhase.h"
......@@ -203,6 +204,7 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
if (validationEnabled())
validate(dfg);
changed |= performStrengthReduction(dfg);
performCFA(dfg);
changed |= performConstantFolding(dfg);
changed |= performArgumentsSimplification(dfg);
......
......@@ -577,6 +577,7 @@ private:
case LoopHint:
case NotifyWrite:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
break;
// This gets ignored because it already has a prediction.
......
......@@ -244,6 +244,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
case InvalidationPoint:
case NotifyWrite:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
return true;
case GetByVal:
......
......@@ -2329,7 +2329,7 @@ JITCompiler::Jump SpeculativeJIT::jumpForTypedArrayOutOfBounds(Node* node, GPRRe
{
if (node->op() == PutByValAlias)
return JITCompiler::Jump();
if (JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(m_jit.graph().child(node, 0).node(), node->arrayMode())) {
if (JSArrayBufferView* view = m_jit.graph().tryGetFoldableViewForChild1(node)) {
uint32_t length = view->length();
Node* indexNode = m_jit.graph().child(node, 1).node();
if (m_jit.graph().isInt32Constant(indexNode) && static_cast<uint32_t>(m_jit.graph().valueOfInt32Constant(indexNode)) < length)
......@@ -4044,8 +4044,7 @@ void SpeculativeJIT::compileStringZeroLength(Node* node)
bool SpeculativeJIT::compileConstantIndexedPropertyStorage(Node* node)
{
JSArrayBufferView* view = m_jit.graph().tryGetFoldableView(
node->child1().node(), node->arrayMode());
JSArrayBufferView* view = m_jit.graph().tryGetFoldableViewForChild1(node);
if (!view)
return false;
if (view->mode() == FastTypedArray)
......
......@@ -3591,7 +3591,8 @@ void SpeculativeJIT::compile(Node* node)
break;
}
case AllocationProfileWatchpoint: {
case AllocationProfileWatchpoint:
case TypedArrayWatchpoint: {
noResult(node);
break;
}
......
......@@ -3895,7 +3895,8 @@ void SpeculativeJIT::compile(Node* node)
break;
}
case AllocationProfileWatchpoint: {
case AllocationProfileWatchpoint:
case TypedArrayWatchpoint: {
noResult(node);
break;
}
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "DFGStrengthReductionPhase.h"
#if ENABLE(DFG_JIT)
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
#include "Operations.h"
namespace JSC { namespace DFG {
class StrengthReductionPhase : public Phase {
public:
StrengthReductionPhase(Graph& graph)
: Phase(graph, "strength reduction")
, m_insertionSet(graph)
{
}
bool run()
{
ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
m_changed = false;
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
m_block = m_graph.block(blockIndex);
if (!m_block)
continue;
for (m_nodeIndex = 0; m_nodeIndex < m_block->size(); ++m_nodeIndex) {
m_node = m_block->at(m_nodeIndex);
handleNode();
}
m_insertionSet.execute(m_block);
}
return m_changed;
}
private:
void handleNode()
{
switch (m_node->op()) {
case BitOr:
// Optimize X|0 -> X.
if (m_node->child2()->isConstant()) {
JSValue C2 = m_graph.valueOfJSConstant(m_node->child2().node());
if (C2.isInt32() && !C2.asInt32()) {
m_insertionSet.insertNode(
m_nodeIndex, SpecNone, Phantom, m_node->codeOrigin,
m_node->child2());
m_node->children.removeEdge(1);
m_node->convertToIdentity();
m_changed = true;
break;
}
}
break;
case GetArrayLength:
if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node))
foldTypedArrayPropertyToConstant(view, jsNumber(view->length()));
break;
case GetTypedArrayByteOffset:
if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node()))
foldTypedArrayPropertyToConstant(view, jsNumber(view->byteOffset()));
break;
// FIXME: The constant-folding of GetIndexedPropertyStorage should be expressed
// as an IR transformation in this phase.
// https://bugs.webkit.org/show_bug.cgi?id=125395
default:
break;
}
}
void foldTypedArrayPropertyToConstant(JSArrayBufferView* view, JSValue constant)
{
m_insertionSet.insertNode(
m_nodeIndex, SpecNone, TypedArrayWatchpoint, m_node->codeOrigin,
OpInfo(view));
m_graph.convertToConstant(m_node, constant);
m_changed = true;
}
InsertionSet m_insertionSet;
BasicBlock* m_block;
unsigned m_nodeIndex;
Node* m_node;
bool m_changed;
};
bool performStrengthReduction(Graph& graph)
{
SamplingRegion samplingRegion("DFG Strength Reduction Phase");
return runPhase<StrengthReductionPhase>(graph);
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DFGStrengthReductionPhase_h
#define DFGStrengthReductionPhase_h
#if ENABLE(DFG_JIT)
namespace JSC { namespace DFG {
class Graph;
// Performs simplifications that don't depend on CFA or CSE but that should be
// fixpointed with CFA and CSE.
bool performStrengthReduction(Graph&);
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
#endif // DFGStrengthReductionPhase_h
......@@ -95,17 +95,12 @@ private:
if (m_node->arrayMode().type() == Array::String)
handleStringGetByVal();
if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node(), m_node->arrayMode()))
if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node))
addLazily(view);
break;
case PutByVal:
if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_graph.varArgChild(m_node, 0).node(), m_node->arrayMode()))
addLazily(view);
break;
case GetArrayLength:
if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node(), m_node->arrayMode()))
if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node))
addLazily(view);
break;
......@@ -144,7 +139,7 @@ private:
break;
case GetIndexedPropertyStorage:
if (JSArrayBufferView* view = m_graph.tryGetFoldableView(m_node->child1().node(), m_node->arrayMode())) {
if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) {
// FIXME: It would be awesome to be able to fold the property storage for
// these GC-allocated typed arrays. For now it doesn't matter because the
// most common use-cases for constant typed arrays involve large arrays with
......@@ -155,6 +150,10 @@ private:
}
break;
case TypedArrayWatchpoint:
addLazily(m_node->typedArray());
break;
default:
break;
}
......
......@@ -103,6 +103,7 @@ inline CapabilityLevel canCompile(Node* node)
case StringCharCodeAt:
case AllocatePropertyStorage:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
case VariableWatchpoint:
case NotifyWrite:
case ValueToInt32:
......
......@@ -266,11 +266,6 @@ private:
case Phantom:
compilePhantom();
break;
case Flush:
case PhantomLocal:
case SetArgument:
case LoopHint:
break;
case ArithAdd:
case ValueAdd:
compileAddSub();
......@@ -398,10 +393,6 @@ private:
case NotifyWrite:
compileNotifyWrite();
break;
case VariableWatchpoint:
break;
case FunctionReentryWatchpoint:
break;
case GetMyScope:
compileGetMyScope();
break;
......@@ -472,6 +463,14 @@ private:
case Int52ToValue:
compileInt52ToValue();
break;
case Flush:
case PhantomLocal:
case SetArgument:
case LoopHint:
case VariableWatchpoint:
case FunctionReentryWatchpoint:
case TypedArrayWatchpoint:
break;
default: