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

Fold constant typed arrays

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

Source/JavaScriptCore: 

Reviewed by Oliver Hunt and Mark Hahnenberg.
        
If by some other mechanism we have a typed array access on a compile-time constant
typed array pointer, then fold:
        
- Array bounds checks. Specifically, fold the load of length.
        
- Loading the vector.
        
This needs to install a watchpoint on the array itself because of the possibility of
neutering. Neutering is ridiculous. We do this without bloating the size of
ArrayBuffer or JSArrayBufferView in the common case (i.e. the case where you
allocated an array that didn't end up becoming a compile-time constant). To install
the watchpoint, we slowDownAndWasteMemory and then create an incoming reference to
the ArrayBuffer, where that incoming reference is from a watchpoint object. The
ArrayBuffer already knows about such incoming references and can fire the
watchpoints that way.
        
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
(JSC::DFG::DesiredWatchpoints::addLazily):
* dfg/DFGDesiredWatchpoints.h:
(JSC::DFG::GenericSetAdaptor::add):
(JSC::DFG::GenericSetAdaptor::hasBeenInvalidated):
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::hasBeenInvalidated):
(JSC::DFG::GenericDesiredWatchpoints::reallyAdd):
(JSC::DFG::GenericDesiredWatchpoints::areStillValid):
(JSC::DFG::GenericDesiredWatchpoints::isStillValid):
(JSC::DFG::GenericDesiredWatchpoints::shouldAssumeMixedState):
(JSC::DFG::DesiredWatchpoints::isStillValid):
(JSC::DFG::DesiredWatchpoints::shouldAssumeMixedState):
(JSC::DFG::DesiredWatchpoints::isValidOrMixed):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetFoldableView):
* dfg/DFGGraph.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
(JSC::DFG::SpeculativeJIT::emitTypedArrayBoundsCheck):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileConstantIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
(JSC::DFG::WatchpointCollectionPhase::addLazily):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::typedArrayLength):
* runtime/ArrayBuffer.cpp:
(JSC::ArrayBuffer::transfer):
* runtime/ArrayBufferNeuteringWatchpoint.cpp: Added.
(JSC::ArrayBufferNeuteringWatchpoint::ArrayBufferNeuteringWatchpoint):
(JSC::ArrayBufferNeuteringWatchpoint::~ArrayBufferNeuteringWatchpoint):
(JSC::ArrayBufferNeuteringWatchpoint::finishCreation):
(JSC::ArrayBufferNeuteringWatchpoint::destroy):
(JSC::ArrayBufferNeuteringWatchpoint::create):
(JSC::ArrayBufferNeuteringWatchpoint::createStructure):
* runtime/ArrayBufferNeuteringWatchpoint.h: Added.
(JSC::ArrayBufferNeuteringWatchpoint::set):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

LayoutTests: 

Reviewed by Oliver Hunt and Mark Hahnenberg.

* js/regress/fixed-typed-array-storage-expected.txt: Added.
* js/regress/fixed-typed-array-storage-var-index-expected.txt: Added.
* js/regress/fixed-typed-array-storage-var-index.html: Added.
* js/regress/fixed-typed-array-storage.html: Added.
* js/regress/script-tests/fixed-typed-array-storage-var-index.js: Added.
(foo):
* js/regress/script-tests/fixed-typed-array-storage.js: Added.
(foo):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@160150 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 16c7d7a2
2013-12-04 Filip Pizlo <fpizlo@apple.com>
Fold constant typed arrays
https://bugs.webkit.org/show_bug.cgi?id=125205
Reviewed by Oliver Hunt and Mark Hahnenberg.
* js/regress/fixed-typed-array-storage-expected.txt: Added.
* js/regress/fixed-typed-array-storage-var-index-expected.txt: Added.
* js/regress/fixed-typed-array-storage-var-index.html: Added.
* js/regress/fixed-typed-array-storage.html: Added.
* js/regress/script-tests/fixed-typed-array-storage-var-index.js: Added.
(foo):
* js/regress/script-tests/fixed-typed-array-storage.js: Added.
(foo):
2013-12-04 Zoltan Horvath <zoltan@webkit.org> 2013-12-04 Zoltan Horvath <zoltan@webkit.org>
[CSS Shapes] Support inset for shape-outside [CSS Shapes] Support inset for shape-outside
......
JSRegress/fixed-typed-array-storage
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
JSRegress/fixed-typed-array-storage-var-index
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS no exception thrown
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/fixed-typed-array-storage-var-index.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<script src="resources/regress-pre.js"></script>
<script src="script-tests/fixed-typed-array-storage.js"></script>
<script src="resources/regress-post.js"></script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
var array = new Int8Array(new ArrayBuffer(100));
function foo(i) {
return array[i];
}
for (var i = 0; i < 100000; ++i) {
if (foo(i % 100) != 0)
throw "Error";
}
var array = new Int8Array(new ArrayBuffer(100));
function foo() {
return array[0];
}
for (var i = 0; i < 100000; ++i) {
if (foo() != 0)
throw "Error";
}
...@@ -281,6 +281,7 @@ set(JavaScriptCore_SOURCES ...@@ -281,6 +281,7 @@ set(JavaScriptCore_SOURCES
runtime/ArgumentsIteratorConstructor.cpp runtime/ArgumentsIteratorConstructor.cpp
runtime/ArgumentsIteratorPrototype.cpp runtime/ArgumentsIteratorPrototype.cpp
runtime/ArrayBuffer.cpp runtime/ArrayBuffer.cpp
runtime/ArrayBufferNeuteringWatchpoint.cpp
runtime/ArrayBufferView.cpp runtime/ArrayBufferView.cpp
runtime/ArrayConstructor.cpp runtime/ArrayConstructor.cpp
runtime/ArrayIteratorConstructor.cpp runtime/ArrayIteratorConstructor.cpp
......
2013-12-04 Filip Pizlo <fpizlo@apple.com>
Fold constant typed arrays
https://bugs.webkit.org/show_bug.cgi?id=125205
Reviewed by Oliver Hunt and Mark Hahnenberg.
If by some other mechanism we have a typed array access on a compile-time constant
typed array pointer, then fold:
- Array bounds checks. Specifically, fold the load of length.
- Loading the vector.
This needs to install a watchpoint on the array itself because of the possibility of
neutering. Neutering is ridiculous. We do this without bloating the size of
ArrayBuffer or JSArrayBufferView in the common case (i.e. the case where you
allocated an array that didn't end up becoming a compile-time constant). To install
the watchpoint, we slowDownAndWasteMemory and then create an incoming reference to
the ArrayBuffer, where that incoming reference is from a watchpoint object. The
ArrayBuffer already knows about such incoming references and can fire the
watchpoints that way.
* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::add):
(JSC::DFG::DesiredWatchpoints::addLazily):
* dfg/DFGDesiredWatchpoints.h:
(JSC::DFG::GenericSetAdaptor::add):
(JSC::DFG::GenericSetAdaptor::hasBeenInvalidated):
(JSC::DFG::ArrayBufferViewWatchpointAdaptor::hasBeenInvalidated):
(JSC::DFG::GenericDesiredWatchpoints::reallyAdd):
(JSC::DFG::GenericDesiredWatchpoints::areStillValid):
(JSC::DFG::GenericDesiredWatchpoints::isStillValid):
(JSC::DFG::GenericDesiredWatchpoints::shouldAssumeMixedState):
(JSC::DFG::DesiredWatchpoints::isStillValid):
(JSC::DFG::DesiredWatchpoints::shouldAssumeMixedState):
(JSC::DFG::DesiredWatchpoints::isValidOrMixed):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::tryGetFoldableView):
* dfg/DFGGraph.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
(JSC::DFG::SpeculativeJIT::emitTypedArrayBoundsCheck):
(JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
(JSC::DFG::SpeculativeJIT::compileGetByValOnFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray):
(JSC::DFG::SpeculativeJIT::compileConstantIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGWatchpointCollectionPhase.cpp:
(JSC::DFG::WatchpointCollectionPhase::handle):
(JSC::DFG::WatchpointCollectionPhase::addLazily):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::typedArrayLength):
* runtime/ArrayBuffer.cpp:
(JSC::ArrayBuffer::transfer):
* runtime/ArrayBufferNeuteringWatchpoint.cpp: Added.
(JSC::ArrayBufferNeuteringWatchpoint::ArrayBufferNeuteringWatchpoint):
(JSC::ArrayBufferNeuteringWatchpoint::~ArrayBufferNeuteringWatchpoint):
(JSC::ArrayBufferNeuteringWatchpoint::finishCreation):
(JSC::ArrayBufferNeuteringWatchpoint::destroy):
(JSC::ArrayBufferNeuteringWatchpoint::create):
(JSC::ArrayBufferNeuteringWatchpoint::createStructure):
* runtime/ArrayBufferNeuteringWatchpoint.h: Added.
(JSC::ArrayBufferNeuteringWatchpoint::set):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
2013-12-04 Commit Queue <commit-queue@webkit.org> 2013-12-04 Commit Queue <commit-queue@webkit.org>
Unreviewed, rolling out r160116. Unreviewed, rolling out r160116.
......
...@@ -782,6 +782,8 @@ javascriptcore_sources += \ ...@@ -782,6 +782,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/runtime/ArgumentsIteratorPrototype.h \ Source/JavaScriptCore/runtime/ArgumentsIteratorPrototype.h \
Source/JavaScriptCore/runtime/ArrayBuffer.cpp \ Source/JavaScriptCore/runtime/ArrayBuffer.cpp \
Source/JavaScriptCore/runtime/ArrayBuffer.h \ Source/JavaScriptCore/runtime/ArrayBuffer.h \
Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp \
Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h \
Source/JavaScriptCore/runtime/ArrayBufferView.cpp \ Source/JavaScriptCore/runtime/ArrayBufferView.cpp \
Source/JavaScriptCore/runtime/ArrayBufferView.h \ Source/JavaScriptCore/runtime/ArrayBufferView.h \
Source/JavaScriptCore/runtime/ArrayConstructor.cpp \ Source/JavaScriptCore/runtime/ArrayConstructor.cpp \
......
...@@ -524,6 +524,7 @@ ...@@ -524,6 +524,7 @@
<ClCompile Include="..\runtime\ArgumentsIteratorConstructor.cpp" /> <ClCompile Include="..\runtime\ArgumentsIteratorConstructor.cpp" />
<ClCompile Include="..\runtime\ArgumentsIteratorPrototype.cpp" /> <ClCompile Include="..\runtime\ArgumentsIteratorPrototype.cpp" />
<ClCompile Include="..\runtime\ArrayBuffer.cpp" /> <ClCompile Include="..\runtime\ArrayBuffer.cpp" />
<ClCompile Include="..\runtime\ArrayBufferNeuteringWatchpoint.cpp" />
<ClCompile Include="..\runtime\ArrayBufferView.cpp" /> <ClCompile Include="..\runtime\ArrayBufferView.cpp" />
<ClCompile Include="..\runtime\ArrayConstructor.cpp" /> <ClCompile Include="..\runtime\ArrayConstructor.cpp" />
<ClCompile Include="..\runtime\ArrayIteratorConstructor.cpp" /> <ClCompile Include="..\runtime\ArrayIteratorConstructor.cpp" />
...@@ -1090,6 +1091,7 @@ ...@@ -1090,6 +1091,7 @@
<ClInclude Include="..\runtime\ArgList.h" /> <ClInclude Include="..\runtime\ArgList.h" />
<ClInclude Include="..\runtime\Arguments.h" /> <ClInclude Include="..\runtime\Arguments.h" />
<ClInclude Include="..\runtime\ArrayBuffer.h" /> <ClInclude Include="..\runtime\ArrayBuffer.h" />
<ClInclude Include="..\runtime\ArrayBufferNeuteringWatchpoint.h" />
<ClInclude Include="..\runtime\ArrayBufferView.h" /> <ClInclude Include="..\runtime\ArrayBufferView.h" />
<ClInclude Include="..\runtime\ArrayConstructor.h" /> <ClInclude Include="..\runtime\ArrayConstructor.h" />
<ClInclude Include="..\runtime\ArrayConventions.h" /> <ClInclude Include="..\runtime\ArrayConventions.h" />
......
...@@ -541,6 +541,8 @@ ...@@ -541,6 +541,8 @@
0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFB921E16D02F470055A5DB /* DFGVariadicFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F85A31E16AB76AE0077571E /* DFGVariadicFunction.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FFB921F16D033050055A5DB /* (null) in Headers */ = {isa = PBXBuildFile; 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, ); }; }; 0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.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, ); }; }; 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 */; }; 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, ); }; }; 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
...@@ -1846,6 +1848,8 @@ ...@@ -1846,6 +1848,8 @@
0FF729A1166AD347000F5BA3 /* ProfilerOriginStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOriginStack.cpp; path = profiler/ProfilerOriginStack.cpp; sourceTree = "<group>"; }; 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>"; }; 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; }; 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; }; 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>"; }; 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>"; }; 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; };
...@@ -3366,6 +3370,8 @@ ...@@ -3366,6 +3370,8 @@
A76140CA182982CB00750624 /* ArgumentsIteratorPrototype.h */, A76140CA182982CB00750624 /* ArgumentsIteratorPrototype.h */,
A7A8AF2517ADB5F2005AB174 /* ArrayBuffer.cpp */, A7A8AF2517ADB5F2005AB174 /* ArrayBuffer.cpp */,
A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */, A7A8AF2617ADB5F3005AB174 /* ArrayBuffer.h */,
0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */,
0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */,
A7A8AF2717ADB5F3005AB174 /* ArrayBufferView.cpp */, A7A8AF2717ADB5F3005AB174 /* ArrayBufferView.cpp */,
A7A8AF2817ADB5F3005AB174 /* ArrayBufferView.h */, A7A8AF2817ADB5F3005AB174 /* ArrayBufferView.h */,
BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */, BC7952060E15E8A800A898AB /* ArrayConstructor.cpp */,
...@@ -4478,6 +4484,7 @@ ...@@ -4478,6 +4484,7 @@
A7A8AF3817ADB5F3005AB174 /* Float32Array.h in Headers */, A7A8AF3817ADB5F3005AB174 /* Float32Array.h in Headers */,
A7A8AF3917ADB5F3005AB174 /* Float64Array.h in Headers */, A7A8AF3917ADB5F3005AB174 /* Float64Array.h in Headers */,
0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */, 0F24E54317EA9F5900ABB217 /* FPRInfo.h in Headers */,
0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */,
0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */, 0FDB2CC9173DA520007B3C1B /* FTLAbbreviatedTypes.h in Headers */,
0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */, 0FEA0A08170513DB00BB722C /* FTLAbbreviations.h in Headers */,
0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */, 0FEA0A1D1708B00700BB722C /* FTLAbstractHeap.h in Headers */,
...@@ -5641,6 +5648,7 @@ ...@@ -5641,6 +5648,7 @@
1428083A107EC0750013E7B2 /* JSStack.cpp in Sources */, 1428083A107EC0750013E7B2 /* JSStack.cpp in Sources */,
147F39D5107EC37600427A48 /* JSString.cpp in Sources */, 147F39D5107EC37600427A48 /* JSString.cpp in Sources */,
2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */, 2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */,
0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */,
1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */, 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */,
146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */, 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */,
0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */, 0F919D0C157EE09F004A4E7D /* JSSymbolTableObject.cpp in Sources */,
......
...@@ -28,8 +28,22 @@ ...@@ -28,8 +28,22 @@
#if ENABLE(DFG_JIT) #if ENABLE(DFG_JIT)
#include "ArrayBufferNeuteringWatchpoint.h"
#include "CodeBlock.h"
#include "Operations.h"
namespace JSC { namespace DFG { namespace JSC { namespace DFG {
void ArrayBufferViewWatchpointAdaptor::add(
CodeBlock* codeBlock, JSArrayBufferView* view, Watchpoint* watchpoint)
{
ArrayBufferNeuteringWatchpoint* neuteringWatchpoint =
ArrayBufferNeuteringWatchpoint::create(*codeBlock->vm());
neuteringWatchpoint->set()->add(watchpoint);
codeBlock->addConstant(neuteringWatchpoint);
codeBlock->vm()->heap.addReference(neuteringWatchpoint, view->buffer());
}
DesiredWatchpoints::DesiredWatchpoints() { } DesiredWatchpoints::DesiredWatchpoints() { }
DesiredWatchpoints::~DesiredWatchpoints() { } DesiredWatchpoints::~DesiredWatchpoints() { }
...@@ -43,6 +57,11 @@ void DesiredWatchpoints::addLazily(InlineWatchpointSet& set) ...@@ -43,6 +57,11 @@ void DesiredWatchpoints::addLazily(InlineWatchpointSet& set)
m_inlineSets.addLazily(&set); m_inlineSets.addLazily(&set);
} }
void DesiredWatchpoints::addLazily(JSArrayBufferView* view)
{
m_bufferViews.addLazily(view);
}
void DesiredWatchpoints::addLazily(CodeOrigin codeOrigin, ExitKind exitKind, WatchpointSet* set) void DesiredWatchpoints::addLazily(CodeOrigin codeOrigin, ExitKind exitKind, WatchpointSet* set)
{ {
m_sets.addLazily(codeOrigin, exitKind, set); m_sets.addLazily(codeOrigin, exitKind, set);
...@@ -57,11 +76,14 @@ void DesiredWatchpoints::reallyAdd(CodeBlock* codeBlock, CommonData& commonData) ...@@ -57,11 +76,14 @@ void DesiredWatchpoints::reallyAdd(CodeBlock* codeBlock, CommonData& commonData)
{ {
m_sets.reallyAdd(codeBlock, commonData); m_sets.reallyAdd(codeBlock, commonData);
m_inlineSets.reallyAdd(codeBlock, commonData); m_inlineSets.reallyAdd(codeBlock, commonData);
m_bufferViews.reallyAdd(codeBlock, commonData);
} }
bool DesiredWatchpoints::areStillValid() const bool DesiredWatchpoints::areStillValid() const
{ {
return m_sets.areStillValid() && m_inlineSets.areStillValid(); return m_sets.areStillValid()
&& m_inlineSets.areStillValid()
&& m_bufferViews.areStillValid();
} }
} } // namespace JSC::DFG } } // namespace JSC::DFG
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "CodeOrigin.h" #include "CodeOrigin.h"
#include "DFGCommonData.h" #include "DFGCommonData.h"
#include "JSArrayBufferView.h"
#include "Watchpoint.h" #include "Watchpoint.h"
#include <wtf/HashMap.h> #include <wtf/HashMap.h>
#include <wtf/HashSet.h> #include <wtf/HashSet.h>
...@@ -61,7 +62,26 @@ struct WatchpointForGenericWatchpointSet { ...@@ -61,7 +62,26 @@ struct WatchpointForGenericWatchpointSet {
WatchpointSetType* m_set; WatchpointSetType* m_set;
}; };
template<typename WatchpointSetType> template<typename T>
struct GenericSetAdaptor {
static void add(CodeBlock*, T* set, Watchpoint* watchpoint)
{
return set->add(watchpoint);
}
static bool hasBeenInvalidated(T* set) { return set->hasBeenInvalidated(); }
};
struct ArrayBufferViewWatchpointAdaptor {
static void add(CodeBlock*, JSArrayBufferView*, Watchpoint*);
static bool hasBeenInvalidated(JSArrayBufferView* view)
{
bool result = !view->length();
WTF::loadLoadFence();
return result;
}
};
template<typename WatchpointSetType, typename Adaptor = GenericSetAdaptor<WatchpointSetType>>
class GenericDesiredWatchpoints { class GenericDesiredWatchpoints {
WTF_MAKE_NONCOPYABLE(GenericDesiredWatchpoints); WTF_MAKE_NONCOPYABLE(GenericDesiredWatchpoints);
#if !ASSERT_DISABLED #if !ASSERT_DISABLED
...@@ -92,7 +112,7 @@ public: ...@@ -92,7 +112,7 @@ public:
typename HashSet<WatchpointSetType*>::iterator end = m_sets.end(); typename HashSet<WatchpointSetType*>::iterator end = m_sets.end();
for (; iter != end; ++iter) { for (; iter != end; ++iter) {
common.watchpoints.append(CodeBlockJettisoningWatchpoint(codeBlock)); common.watchpoints.append(CodeBlockJettisoningWatchpoint(codeBlock));
(*iter)->add(&common.watchpoints.last()); Adaptor::add(codeBlock, *iter, &common.watchpoints.last());
} }
for (unsigned i = m_profiledWatchpoints.size(); i--;) { for (unsigned i = m_profiledWatchpoints.size(); i--;) {
...@@ -100,7 +120,7 @@ public: ...@@ -100,7 +120,7 @@ public:
m_profiledWatchpoints[i]; m_profiledWatchpoints[i];
common.profiledWatchpoints.append( common.profiledWatchpoints.append(
ProfiledCodeBlockJettisoningWatchpoint(watchpoint.m_codeOrigin, watchpoint.m_exitKind, codeBlock)); ProfiledCodeBlockJettisoningWatchpoint(watchpoint.m_codeOrigin, watchpoint.m_exitKind, codeBlock));
watchpoint.m_set->add(&common.profiledWatchpoints.last()); Adaptor::add(codeBlock, watchpoint.m_set, &common.profiledWatchpoints.last());
} }
m_reallyAdded = true; m_reallyAdded = true;
...@@ -111,12 +131,12 @@ public: ...@@ -111,12 +131,12 @@ public:
typename HashSet<WatchpointSetType*>::iterator iter = m_sets.begin(); typename HashSet<WatchpointSetType*>::iterator iter = m_sets.begin();
typename HashSet<WatchpointSetType*>::iterator end = m_sets.end(); typename HashSet<WatchpointSetType*>::iterator end = m_sets.end();
for (; iter != end; ++iter) { for (; iter != end; ++iter) {
if ((*iter)->hasBeenInvalidated()) if (Adaptor::hasBeenInvalidated(*iter))
return false; return false;
} }
for (unsigned i = m_profiledWatchpoints.size(); i--;) { for (unsigned i = m_profiledWatchpoints.size(); i--;) {
if (m_profiledWatchpoints[i].m_set->hasBeenInvalidated()) if (Adaptor::hasBeenInvalidated(m_profiledWatchpoints[i].m_set))
return false; return false;
} }
...@@ -126,7 +146,7 @@ public: ...@@ -126,7 +146,7 @@ public:
#if ASSERT_DISABLED #if ASSERT_DISABLED
bool isStillValid(WatchpointSetType* set) bool isStillValid(WatchpointSetType* set)
{ {
return set->isStillValid(); return !Adaptor::hasBeenInvalidated(set);
} }
bool shouldAssumeMixedState(WatchpointSetType*) bool shouldAssumeMixedState(WatchpointSetType*)
...@@ -136,7 +156,7 @@ public: ...@@ -136,7 +156,7 @@ public:
#else #else
bool isStillValid(WatchpointSetType* set) bool isStillValid(WatchpointSetType* set)
{ {
bool result = set->isStillValid(); bool result = !Adaptor::hasBeenInvalidated(set);
m_firstKnownState.add(set, result); m_firstKnownState.add(set, result);
return result; return result;
} }
...@@ -147,7 +167,7 @@ public: ...@@ -147,7 +167,7 @@ public:
if (iter == m_firstKnownState.end()) if (iter == m_firstKnownState.end())
return false; return false;
return iter->value != set->isStillValid(); return iter->value != !Adaptor::hasBeenInvalidated(set);
} }
#endif #endif
...@@ -172,6 +192,7 @@ public: ...@@ -172,6 +192,7 @@ public:
void addLazily(WatchpointSet*); void addLazily(WatchpointSet*);
void addLazily(InlineWatchpointSet&); void addLazily(InlineWatchpointSet&);
void addLazily(JSArrayBufferView*);
void addLazily(CodeOrigin, ExitKind, WatchpointSet*); void addLazily(CodeOrigin, ExitKind, WatchpointSet*);
void addLazily(CodeOrigin, ExitKind, InlineWatchpointSet&); void addLazily(CodeOrigin, ExitKind, InlineWatchpointSet&);
...@@ -187,6 +208,10 @@ public: ...@@ -187,6 +208,10 @@ public:
{ {
return m_inlineSets.isStillValid(&set); return m_inlineSets.isStillValid(&set);
} }
bool isStillValid(JSArrayBufferView* view)
{
return m_bufferViews.isStillValid(view);
}
bool shouldAssumeMixedState(WatchpointSet* set) bool shouldAssumeMixedState(WatchpointSet* set)
{ {
return m_sets.shouldAssumeMixedState(set); return m_sets.shouldAssumeMixedState(set);
...@@ -195,6 +220,10 @@ public: ...@@ -195,6 +220,10 @@ public:
{ {
return m_inlineSets.shouldAssumeMixedState(&set); return m_inlineSets.shouldAssumeMixedState(&set);
} }
bool shouldAssumeMixedState(JSArrayBufferView* view)
{
return m_bufferViews.shouldAssumeMixedState(view);
}
bool isValidOrMixed(WatchpointSet* set) bool isValidOrMixed(WatchpointSet* set)
{ {
return m_sets.isValidOrMixed(set); return m_sets.isValidOrMixed(set);
...@@ -203,10 +232,15 @@ public: ...@@ -203,10 +232,15 @@ public:
{ {
return m_inlineSets.isValidOrMixed(&set); return m_inlineSets.isValidOrMixed(&set);
} }
bool isValidOrMixed(JSArrayBufferView* view)
{
return m_bufferViews.isValidOrMixed(view);
}
private: private:
GenericDesiredWatchpoints<WatchpointSet> m_sets; GenericDesiredWatchpoints<WatchpointSet> m_sets;
GenericDesiredWatchpoints<InlineWatchpointSet> m_inlineSets; GenericDesiredWatchpoints<InlineWatchpointSet> m_inlineSets;
GenericDesiredWatchpoints<JSArrayBufferView, ArrayBufferViewWatchpointAdaptor> m_bufferViews;
}; };
} } // namespace JSC::DFG } } // namespace JSC::DFG
......
...@@ -740,6 +740,20 @@ WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node) ...@@ -740,6 +740,20 @@ WriteBarrierBase<Unknown>* Graph::tryGetRegisters(Node* node)
return activation->registers(); return activation->registers();
} }
JSArrayBufferView* Graph::tryGetFoldableView(Node* node, ArrayMode arrayMode)
{
if (arrayMode.typedArrayType() == NotTypedArray)
return 0;
if (!node->hasConstant())
return 0;
JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(valueOfJSConstant(node));
if (!view)
return 0;
if (!watchpoints().isStillValid(view))
return 0;
return view;
}
} } // namespace JSC::DFG } } // namespace JSC::DFG
#endif #endif
...@@ -794,6 +794,8 @@ public: ...@@ -794,6 +794,8 @@ public:
JSActivation* tryGetActivation(Node*); JSActivation* tryGetActivation(Node*);
WriteBarrierBase<Unknown>* tryGetRegisters(Node*); WriteBarrierBase<Unknown>* tryGetRegisters(Node*);
JSArrayBufferView* tryGetFoldableView(Node*, ArrayMode);