Title: [214408] trunk/Source
Revision
214408
Author
[email protected]
Date
2017-03-26 14:39:27 -0700 (Sun, 26 Mar 2017)

Log Message

Air should use RegisterSet for RegLiveness
https://bugs.webkit.org/show_bug.cgi?id=170108

Reviewed by Yusuke Suzuki.
Source/_javascript_Core:

        
The biggest change here is the introduction of the new RegLiveness class. This is a
drop-in replacement for the old RegLiveness, which was a specialization of
AbstractLiveness<>, but it's about 30% faster. It gets its speed boost from just using
sets everywhere, which is efficient for registers since RegisterSet is just two (on
x86-64) or three 32-bit (on ARM64) statically allocated words. This looks like a 1%
compile time progression on WasmBench.

* CMakeLists.txt:
* _javascript_Core.xcodeproj/project.pbxproj:
* b3/B3TimingScope.cpp: Records phase timing totals.
(JSC::B3::TimingScope::TimingScope):
(JSC::B3::TimingScope::~TimingScope):
* b3/B3TimingScope.h:
* b3/air/AirAllocateRegistersByGraphColoring.cpp:
(JSC::B3::Air::allocateRegistersByGraphColoring):
* b3/air/AirLiveness.h: Move code around and rename a bit to make it more like RegLiveness; in particular we want the `iterator` to be called `iterator` not `Iterator`, and we want it to be internal to its iterable. Also rename this template to Liveness, to match the header filename.
(JSC::B3::Air::Liveness::Liveness):
(JSC::B3::Air::Liveness::LocalCalc::LocalCalc):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::Iterable):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::iterator):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator++):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator*):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator==):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator!=):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::begin):
(JSC::B3::Air::Liveness::LocalCalc::Iterable::end):
(JSC::B3::Air::Liveness::Iterable::Iterable):
(JSC::B3::Air::Liveness::Iterable::iterator::iterator):
(JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter): Deleted.
(JSC::B3::Air::RegLivenessAdapter::numIndices): Deleted.
(JSC::B3::Air::RegLivenessAdapter::acceptsBank): Deleted.
(JSC::B3::Air::RegLivenessAdapter::acceptsRole): Deleted.
(JSC::B3::Air::RegLivenessAdapter::valueToIndex): Deleted.
(JSC::B3::Air::RegLivenessAdapter::indexToValue): Deleted.
(JSC::B3::Air::AbstractLiveness::AbstractLiveness): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::LocalCalc): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::Iterator): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator++): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator*): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator==): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator!=): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::Iterable): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::live): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::isLive): Deleted.
(JSC::B3::Air::AbstractLiveness::LocalCalc::execute): Deleted.
(JSC::B3::Air::AbstractLiveness::rawLiveAtHead): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::Iterable): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::iterator): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator*): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator++): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator==): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator!=): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::begin): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::end): Deleted.
(JSC::B3::Air::AbstractLiveness::Iterable::contains): Deleted.
(JSC::B3::Air::AbstractLiveness::liveAtHead): Deleted.
(JSC::B3::Air::AbstractLiveness::liveAtTail): Deleted.
(JSC::B3::Air::AbstractLiveness::workset): Deleted.
* b3/air/AirLogRegisterPressure.cpp:
* b3/air/AirLowerAfterRegAlloc.cpp:
* b3/air/AirRegLiveness.cpp: Added.
(JSC::B3::Air::RegLiveness::RegLiveness):
(JSC::B3::Air::RegLiveness::~RegLiveness):
(JSC::B3::Air::RegLiveness::LocalCalc::execute):
* b3/air/AirRegLiveness.h: Added.
(JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
(JSC::B3::Air::RegLiveness::LocalCalc::live):
(JSC::B3::Air::RegLiveness::LocalCalc::isLive):
(JSC::B3::Air::RegLiveness::liveAtHead):
(JSC::B3::Air::RegLiveness::liveAtTail):
* b3/air/AirReportUsedRegisters.cpp:
* jit/RegisterSet.h:
(JSC::RegisterSet::add):
(JSC::RegisterSet::remove):
(JSC::RegisterSet::contains):
(JSC::RegisterSet::subsumes):
(JSC::RegisterSet::iterator::iterator):
(JSC::RegisterSet::iterator::operator*):
(JSC::RegisterSet::iterator::operator++):
(JSC::RegisterSet::iterator::operator==):
(JSC::RegisterSet::iterator::operator!=):
(JSC::RegisterSet::begin):
(JSC::RegisterSet::end):

Source/WTF:


* wtf/Atomics.h:
(WTF::ensurePointer): This is a useful replacement for std::once, which requires less fencing.
* wtf/Bitmap.h: Add more utilities.
(WTF::Bitmap::iterator::iterator): An iterator for set bits.
(WTF::Bitmap::iterator::operator*):
(WTF::Bitmap::iterator::operator++):
(WTF::Bitmap::iterator::operator==):
(WTF::Bitmap::iterator::operator!=):
(WTF::Bitmap::begin):
(WTF::Bitmap::end):
(WTF::WordType>::subsumes): a.subsumes(b) if all of b's set bits are set in a.
(WTF::WordType>::findBit): find next set or clear bit.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (214407 => 214408)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2017-03-26 21:39:27 UTC (rev 214408)
@@ -101,6 +101,7 @@
     b3/air/AirOptimizeBlockOrder.cpp
     b3/air/AirPadInterference.cpp
     b3/air/AirPhaseScope.cpp
+    b3/air/AirRegLiveness.cpp
     b3/air/AirReportUsedRegisters.cpp
     b3/air/AirSimplifyCFG.cpp
     b3/air/AirSpecial.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (214407 => 214408)


--- trunk/Source/_javascript_Core/ChangeLog	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,3 +1,97 @@
+2017-03-26  Filip Pizlo  <[email protected]>
+
+        Air should use RegisterSet for RegLiveness
+        https://bugs.webkit.org/show_bug.cgi?id=170108
+
+        Reviewed by Yusuke Suzuki.
+        
+        The biggest change here is the introduction of the new RegLiveness class. This is a
+        drop-in replacement for the old RegLiveness, which was a specialization of
+        AbstractLiveness<>, but it's about 30% faster. It gets its speed boost from just using
+        sets everywhere, which is efficient for registers since RegisterSet is just two (on
+        x86-64) or three 32-bit (on ARM64) statically allocated words. This looks like a 1%
+        compile time progression on WasmBench.
+
+        * CMakeLists.txt:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * b3/B3TimingScope.cpp: Records phase timing totals.
+        (JSC::B3::TimingScope::TimingScope):
+        (JSC::B3::TimingScope::~TimingScope):
+        * b3/B3TimingScope.h:
+        * b3/air/AirAllocateRegistersByGraphColoring.cpp:
+        (JSC::B3::Air::allocateRegistersByGraphColoring):
+        * b3/air/AirLiveness.h: Move code around and rename a bit to make it more like RegLiveness; in particular we want the `iterator` to be called `iterator` not `Iterator`, and we want it to be internal to its iterable. Also rename this template to Liveness, to match the header filename.
+        (JSC::B3::Air::Liveness::Liveness):
+        (JSC::B3::Air::Liveness::LocalCalc::LocalCalc):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::Iterable):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::iterator):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator++):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator*):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator==):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::iterator::operator!=):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::begin):
+        (JSC::B3::Air::Liveness::LocalCalc::Iterable::end):
+        (JSC::B3::Air::Liveness::Iterable::Iterable):
+        (JSC::B3::Air::Liveness::Iterable::iterator::iterator):
+        (JSC::B3::Air::RegLivenessAdapter::RegLivenessAdapter): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::numIndices): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::acceptsBank): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::acceptsRole): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::valueToIndex): Deleted.
+        (JSC::B3::Air::RegLivenessAdapter::indexToValue): Deleted.
+        (JSC::B3::Air::AbstractLiveness::AbstractLiveness): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::LocalCalc): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::Iterator): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator++): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator*): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator==): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterator::operator!=): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::Iterable): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::begin): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::end): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::Iterable::contains): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::live): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::isLive): Deleted.
+        (JSC::B3::Air::AbstractLiveness::LocalCalc::execute): Deleted.
+        (JSC::B3::Air::AbstractLiveness::rawLiveAtHead): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::Iterable): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::iterator): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator*): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator++): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator==): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::iterator::operator!=): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::begin): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::end): Deleted.
+        (JSC::B3::Air::AbstractLiveness::Iterable::contains): Deleted.
+        (JSC::B3::Air::AbstractLiveness::liveAtHead): Deleted.
+        (JSC::B3::Air::AbstractLiveness::liveAtTail): Deleted.
+        (JSC::B3::Air::AbstractLiveness::workset): Deleted.
+        * b3/air/AirLogRegisterPressure.cpp:
+        * b3/air/AirLowerAfterRegAlloc.cpp:
+        * b3/air/AirRegLiveness.cpp: Added.
+        (JSC::B3::Air::RegLiveness::RegLiveness):
+        (JSC::B3::Air::RegLiveness::~RegLiveness):
+        (JSC::B3::Air::RegLiveness::LocalCalc::execute):
+        * b3/air/AirRegLiveness.h: Added.
+        (JSC::B3::Air::RegLiveness::LocalCalc::LocalCalc):
+        (JSC::B3::Air::RegLiveness::LocalCalc::live):
+        (JSC::B3::Air::RegLiveness::LocalCalc::isLive):
+        (JSC::B3::Air::RegLiveness::liveAtHead):
+        (JSC::B3::Air::RegLiveness::liveAtTail):
+        * b3/air/AirReportUsedRegisters.cpp:
+        * jit/RegisterSet.h:
+        (JSC::RegisterSet::add):
+        (JSC::RegisterSet::remove):
+        (JSC::RegisterSet::contains):
+        (JSC::RegisterSet::subsumes):
+        (JSC::RegisterSet::iterator::iterator):
+        (JSC::RegisterSet::iterator::operator*):
+        (JSC::RegisterSet::iterator::operator++):
+        (JSC::RegisterSet::iterator::operator==):
+        (JSC::RegisterSet::iterator::operator!=):
+        (JSC::RegisterSet::begin):
+        (JSC::RegisterSet::end):
+
 2017-03-25  Filip Pizlo  <[email protected]>
 
         Fix wasm by returning after we do TLS.

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (214407 => 214408)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1005,6 +1005,8 @@
 		0FF4275715914A20004CB9FF /* LinkBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4275615914A20004CB9FF /* LinkBuffer.cpp */; };
 		0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */; };
 		0FF427651591A1CE004CB9FF /* DFGDisassembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF427621591A1C9004CB9FF /* DFGDisassembler.h */; };
+		0FF4B4BC1E88449700DBBE86 /* AirRegLiveness.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */; };
+		0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */; };
 		0FF60AC216740F8300029779 /* ReduceWhitespace.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF60AC016740F8100029779 /* ReduceWhitespace.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FF60AC316740F8800029779 /* ReduceWhitespace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */; };
 		0FF7168C15A3B235008F5DAA /* PropertyOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF7168A15A3B231008F5DAA /* PropertyOffset.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -3520,6 +3522,8 @@
 		0FF4275615914A20004CB9FF /* LinkBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinkBuffer.cpp; sourceTree = "<group>"; };
 		0FF427611591A1C9004CB9FF /* DFGDisassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDisassembler.cpp; path = dfg/DFGDisassembler.cpp; sourceTree = "<group>"; };
 		0FF427621591A1C9004CB9FF /* DFGDisassembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDisassembler.h; path = dfg/DFGDisassembler.h; sourceTree = "<group>"; };
+		0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirRegLiveness.cpp; path = b3/air/AirRegLiveness.cpp; sourceTree = "<group>"; };
+		0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirRegLiveness.h; path = b3/air/AirRegLiveness.h; sourceTree = "<group>"; };
 		0FF60ABF16740F8100029779 /* ReduceWhitespace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ReduceWhitespace.cpp; sourceTree = "<group>"; };
 		0FF60AC016740F8100029779 /* ReduceWhitespace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReduceWhitespace.h; sourceTree = "<group>"; };
 		0FF7168A15A3B231008F5DAA /* PropertyOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyOffset.h; sourceTree = "<group>"; };
@@ -5578,6 +5582,8 @@
 				0F9CABC71DB54A760008E83B /* AirPadInterference.h */,
 				0FEC855E1BDACDC70080FF74 /* AirPhaseScope.cpp */,
 				0FEC855F1BDACDC70080FF74 /* AirPhaseScope.h */,
+				0FF4B4BA1E88449500DBBE86 /* AirRegLiveness.cpp */,
+				0FF4B4BB1E88449500DBBE86 /* AirRegLiveness.h */,
 				0F45703A1BE45F0A0062A629 /* AirReportUsedRegisters.cpp */,
 				0F45703B1BE45F0A0062A629 /* AirReportUsedRegisters.h */,
 				0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */,
@@ -8236,6 +8242,7 @@
 				0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */,
 				1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
 				62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */,
+				0FF4B4BD1E88449A00DBBE86 /* AirRegLiveness.h in Headers */,
 				62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
 				0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
 				0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
@@ -10625,6 +10632,7 @@
 				A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
 				14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */,
 				ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
+				0FF4B4BC1E88449700DBBE86 /* AirRegLiveness.cpp in Sources */,
 				65FB5117184EEE7000C12B70 /* ProtoCallFrame.cpp in Sources */,
 				1474C33C16AA2D9B0062F01D /* PrototypeMap.cpp in Sources */,
 				79B00CBC1C6AB07E0088C65D /* ProxyConstructor.cpp in Sources */,

Modified: trunk/Source/_javascript_Core/b3/B3TimingScope.cpp (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/B3TimingScope.cpp	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/B3TimingScope.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -29,23 +29,53 @@
 #if ENABLE(B3_JIT)
 
 #include "B3Common.h"
-#include <wtf/CurrentTime.h>
 #include <wtf/DataLog.h>
+#include <wtf/HashMap.h>
+#include <wtf/Lock.h>
 
 namespace JSC { namespace B3 {
 
+namespace {
+
+class State {
+    WTF_MAKE_NONCOPYABLE(State);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    State() { }
+    
+    Seconds addToTotal(const char* name, Seconds duration)
+    {
+        auto locker = holdLock(lock);
+        return totals.add(name, Seconds(0)).iterator->value += duration;
+    }
+    
+private:
+    HashMap<const char*, Seconds> totals;
+    Lock lock;
+};
+
+State& state()
+{
+    static Atomic<State*> s_state;
+    return ensurePointer(s_state, [] { return new State(); });
+}
+
+} // anonymous namespace
+
 TimingScope::TimingScope(const char* name)
     : m_name(name)
 {
     if (shouldMeasurePhaseTiming())
-        m_before = monotonicallyIncreasingTimeMS();
+        m_before = MonotonicTime::now();
 }
 
 TimingScope::~TimingScope()
 {
     if (shouldMeasurePhaseTiming()) {
-        double after = monotonicallyIncreasingTimeMS();
-        dataLog("[B3] ", m_name, " took: ", after - m_before, " ms.\n");
+        Seconds duration = MonotonicTime::now() - m_before;
+        dataLog(
+            "[B3] ", m_name, " took: ", duration.milliseconds(), " ms ",
+            "(total: ", state().addToTotal(m_name, duration).milliseconds(), " ms).\n");
     }
 }
 

Modified: trunk/Source/_javascript_Core/b3/B3TimingScope.h (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/B3TimingScope.h	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/B3TimingScope.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
 
 #if ENABLE(B3_JIT)
 
+#include <wtf/MonotonicTime.h>
 #include <wtf/Noncopyable.h>
 
 namespace JSC { namespace B3 {
@@ -39,7 +40,7 @@
 
 private:
     const char* m_name;
-    double m_before;
+    MonotonicTime m_before;
 };
 
 } } // namespace JSC::B3

Modified: trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersByGraphColoring.cpp (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersByGraphColoring.cpp	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/air/AirAllocateRegistersByGraphColoring.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -2257,7 +2257,7 @@
 
 void allocateRegistersByGraphColoring(Code& code)
 {
-    PhaseScope phaseScope(code, "Air::allocateRegistersByGraphColoring");
+    PhaseScope phaseScope(code, "allocateRegistersByGraphColoring");
     
     if (false)
         dataLog("Code before graph coloring:\n", code);

Modified: trunk/Source/_javascript_Core/b3/air/AirLiveness.h (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirLiveness.h	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/air/AirLiveness.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -79,30 +79,14 @@
     Code& m_code;
 };
 
-struct RegLivenessAdapter {
-    typedef Reg Thing;
-    typedef BitVector IndexSet;
-
-    RegLivenessAdapter(Code&) { }
-
-    static unsigned numIndices(Code&)
-    {
-        return Reg::maxIndex() + 1;
-    }
-
-    static bool acceptsBank(Bank) { return true; }
-    static bool acceptsRole(Arg::Role) { return true; }
-    static unsigned valueToIndex(Reg reg) { return reg.index(); }
-    Reg indexToValue(unsigned index) { return Reg::fromIndex(index); }
-};
-
+// HEADS UP: The algorithm here is duplicated in AirRegLiveness.h.
 template<typename Adapter>
-class AbstractLiveness : public Adapter {
+class Liveness : public Adapter {
     struct Workset;
 public:
     typedef typename Adapter::Thing Thing;
     
-    AbstractLiveness(Code& code)
+    Liveness(Code& code)
         : Adapter(code)
         , m_workset(Adapter::numIndices(code))
         , m_liveAtHead(code.size())
@@ -131,7 +115,7 @@
             changed = false;
 
             for (size_t blockIndex = code.size(); blockIndex--;) {
-                BasicBlock* block = code.at(blockIndex);
+                BasicBlock* block = code[blockIndex];
                 if (!block)
                     continue;
 
@@ -187,7 +171,7 @@
     // This calculator has to be run in reverse.
     class LocalCalc {
     public:
-        LocalCalc(AbstractLiveness& liveness, BasicBlock* block)
+        LocalCalc(Liveness& liveness, BasicBlock* block)
             : m_liveness(liveness)
             , m_block(block)
         {
@@ -198,40 +182,42 @@
                 workset.add(index);
         }
 
-        struct Iterator {
-            Iterator(Adapter& adapter, IndexSparseSet<UnsafeVectorOverflow>::const_iterator sparceSetIterator)
-                : m_adapter(adapter)
-                , m_sparceSetIterator(sparceSetIterator)
+        class Iterable {
+        public:
+            Iterable(Liveness& liveness)
+                : m_liveness(liveness)
             {
             }
 
-            Iterator& operator++()
-            {
-                ++m_sparceSetIterator;
-                return *this;
-            }
+            class iterator {
+            public:
+                iterator(Adapter& adapter, IndexSparseSet<UnsafeVectorOverflow>::const_iterator sparceSetIterator)
+                    : m_adapter(adapter)
+                    , m_sparceSetIterator(sparceSetIterator)
+                {
+                }
 
-            typename Adapter::Thing operator*() const
-            {
-                return m_adapter.indexToValue(*m_sparceSetIterator);
-            }
+                iterator& operator++()
+                {
+                    ++m_sparceSetIterator;
+                    return *this;
+                }
 
-            bool operator==(const Iterator& other) { return m_sparceSetIterator == other.m_sparceSetIterator; }
-            bool operator!=(const Iterator& other) { return m_sparceSetIterator != other.m_sparceSetIterator; }
+                typename Adapter::Thing operator*() const
+                {
+                    return m_adapter.indexToValue(*m_sparceSetIterator);
+                }
 
-        private:
-            Adapter& m_adapter;
-            IndexSparseSet<UnsafeVectorOverflow>::const_iterator m_sparceSetIterator;
-        };
+                bool operator==(const iterator& other) { return m_sparceSetIterator == other.m_sparceSetIterator; }
+                bool operator!=(const iterator& other) { return m_sparceSetIterator != other.m_sparceSetIterator; }
 
-        struct Iterable {
-            Iterable(AbstractLiveness& liveness)
-                : m_liveness(liveness)
-            {
-            }
+            private:
+                Adapter& m_adapter;
+                IndexSparseSet<UnsafeVectorOverflow>::const_iterator m_sparceSetIterator;
+            };
 
-            Iterator begin() const { return Iterator(m_liveness, m_liveness.m_workset.begin()); }
-            Iterator end() const { return Iterator(m_liveness, m_liveness.m_workset.end()); }
+            iterator begin() const { return iterator(m_liveness, m_liveness.m_workset.begin()); }
+            iterator end() const { return iterator(m_liveness, m_liveness.m_workset.end()); }
             
             bool contains(const typename Adapter::Thing& thing) const
             {
@@ -239,7 +225,7 @@
             }
 
         private:
-            AbstractLiveness& m_liveness;
+            Liveness& m_liveness;
         };
 
         Iterable live() const
@@ -301,7 +287,7 @@
         }
         
     private:
-        AbstractLiveness& m_liveness;
+        Liveness& m_liveness;
         BasicBlock* m_block;
     };
 
@@ -313,7 +299,7 @@
     template<typename UnderlyingIterable>
     class Iterable {
     public:
-        Iterable(AbstractLiveness& liveness, const UnderlyingIterable& iterable)
+        Iterable(Liveness& liveness, const UnderlyingIterable& iterable)
             : m_liveness(liveness)
             , m_iterable(iterable)
         {
@@ -327,7 +313,7 @@
             {
             }
             
-            iterator(AbstractLiveness& liveness, typename UnderlyingIterable::const_iterator iter)
+            iterator(Liveness& liveness, typename UnderlyingIterable::const_iterator iter)
                 : m_liveness(&liveness)
                 , m_iter(iter)
             {
@@ -356,7 +342,7 @@
             }
 
         private:
-            AbstractLiveness* m_liveness;
+            Liveness* m_liveness;
             typename UnderlyingIterable::const_iterator m_iter;
         };
 
@@ -369,7 +355,7 @@
         }
 
     private:
-        AbstractLiveness& m_liveness;
+        Liveness& m_liveness;
         const UnderlyingIterable& m_iterable;
     };
 
@@ -387,7 +373,7 @@
 
 private:
     friend class LocalCalc;
-    friend struct LocalCalc::Iterable;
+    friend class LocalCalc::Iterable;
 
     IndexSparseSet<UnsafeVectorOverflow> m_workset;
     IndexMap<BasicBlock, Vector<unsigned>> m_liveAtHead;
@@ -395,12 +381,11 @@
 };
 
 template<Bank bank, Arg::Temperature minimumTemperature = Arg::Cold>
-using TmpLiveness = AbstractLiveness<TmpLivenessAdapter<bank, minimumTemperature>>;
+using TmpLiveness = Liveness<TmpLivenessAdapter<bank, minimumTemperature>>;
 
-typedef AbstractLiveness<TmpLivenessAdapter<GP>> GPLiveness;
-typedef AbstractLiveness<TmpLivenessAdapter<FP>> FPLiveness;
-typedef AbstractLiveness<StackSlotLivenessAdapter> StackSlotLiveness;
-typedef AbstractLiveness<RegLivenessAdapter> RegLiveness;
+typedef Liveness<TmpLivenessAdapter<GP>> GPLiveness;
+typedef Liveness<TmpLivenessAdapter<FP>> FPLiveness;
+typedef Liveness<StackSlotLivenessAdapter> StackSlotLiveness;
 
 } } } // namespace JSC::B3::Air
 

Modified: trunk/Source/_javascript_Core/b3/air/AirLogRegisterPressure.cpp (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirLogRegisterPressure.cpp	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/air/AirLogRegisterPressure.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -31,7 +31,7 @@
 #include "AirArgInlines.h"
 #include "AirCode.h"
 #include "AirInstInlines.h"
-#include "AirLiveness.h"
+#include "AirRegLiveness.h"
 
 namespace JSC { namespace B3 { namespace Air {
 

Modified: trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/air/AirLowerAfterRegAlloc.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -34,7 +34,7 @@
 #include "AirEmitShuffle.h"
 #include "AirInsertionSet.h"
 #include "AirInstInlines.h"
-#include "AirLiveness.h"
+#include "AirRegLiveness.h"
 #include "AirPhaseScope.h"
 #include "B3CCallValue.h"
 #include "B3ValueInlines.h"

Added: trunk/Source/_javascript_Core/b3/air/AirRegLiveness.cpp (0 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirRegLiveness.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirRegLiveness.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2017 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 "AirRegLiveness.h"
+
+#if ENABLE(B3_JIT)
+
+#include "AirArgInlines.h"
+#include "AirInstInlines.h"
+
+namespace JSC { namespace B3 { namespace Air {
+
+RegLiveness::RegLiveness(Code& code)
+    : m_liveAtHead(code.size())
+    , m_liveAtTail(code.size())
+{
+    // The liveAtTail of each block automatically contains the LateUse's of the terminal.
+    for (BasicBlock* block : code) {
+        RegisterSet& liveAtTail = m_liveAtTail[block];
+            
+        block->last().forEach<Reg>(
+            [&] (Reg& reg, Arg::Role role, Bank, Width) {
+                if (Arg::isLateUse(role))
+                    liveAtTail.add(reg);
+            });
+    }
+        
+    BitVector dirtyBlocks;
+    for (size_t blockIndex = code.size(); blockIndex--;)
+        dirtyBlocks.set(blockIndex);
+        
+    bool changed;
+    do {
+        changed = false;
+            
+        for (size_t blockIndex = code.size(); blockIndex--;) {
+            BasicBlock* block = code[blockIndex];
+            if (!block)
+                continue;
+                
+            if (!dirtyBlocks.quickClear(blockIndex))
+                continue;
+                
+            LocalCalc localCalc(*this, block);
+            for (size_t instIndex = block->size(); instIndex--;)
+                localCalc.execute(instIndex);
+                
+            // Handle the early def's of the first instruction.
+            block->at(0).forEach<Reg>(
+                [&] (Reg& reg, Arg::Role role, Bank, Width) {
+                    if (Arg::isEarlyDef(role))
+                        localCalc.m_workset.remove(reg);
+                });
+                
+            RegisterSet& liveAtHead = m_liveAtHead[block];
+            if (liveAtHead.subsumes(localCalc.m_workset))
+                continue;
+                
+            liveAtHead.merge(localCalc.m_workset);
+                
+            for (BasicBlock* predecessor : block->predecessors()) {
+                RegisterSet& liveAtTail = m_liveAtTail[predecessor];
+                if (liveAtTail.subsumes(localCalc.m_workset))
+                    continue;
+                    
+                liveAtTail.merge(localCalc.m_workset);
+                dirtyBlocks.quickSet(predecessor->index());
+                changed = true;
+            }
+        }
+    } while (changed);
+}
+
+RegLiveness::~RegLiveness()
+{
+}
+
+void RegLiveness::LocalCalc::execute(unsigned instIndex)
+{
+    Inst& inst = m_block->at(instIndex);
+            
+    // First handle the early def's of the next instruction.
+    if (instIndex + 1 < m_block->size()) {
+        Inst& nextInst = m_block->at(instIndex + 1);
+        nextInst.forEach<Reg>(
+            [&] (Reg& reg, Arg::Role role, Bank, Width) {
+                if (Arg::isEarlyDef(role))
+                    m_workset.remove(reg);
+            });
+    }
+            
+    // Then handle def's.
+    inst.forEach<Reg>(
+        [&] (Reg& reg, Arg::Role role, Bank, Width) {
+            if (Arg::isLateDef(role))
+                m_workset.remove(reg);
+        });
+            
+    // Then handle use's.
+    inst.forEach<Reg>(
+        [&] (Reg& reg, Arg::Role role, Bank, Width) {
+            if (Arg::isEarlyUse(role))
+                m_workset.add(reg);
+        });
+            
+    // And finally, handle the late use's of the previous instruction.
+    if (instIndex) {
+        Inst& prevInst = m_block->at(instIndex - 1);
+        prevInst.forEach<Reg>(
+            [&] (Reg& reg, Arg::Role role, Bank, Width) {
+                if (Arg::isLateUse(role))
+                    m_workset.add(reg);
+            });
+    }
+}
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+

Added: trunk/Source/_javascript_Core/b3/air/AirRegLiveness.h (0 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirRegLiveness.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/b3/air/AirRegLiveness.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#pragma once
+
+#if ENABLE(B3_JIT)
+
+#include "AirBasicBlock.h"
+#include "AirCode.h"
+#include "AirInst.h"
+#include "RegisterSet.h"
+
+namespace JSC { namespace B3 { namespace Air {
+
+// Although we could trivially adapt Air::Liveness<> to work with Reg, this would not be so
+// efficient. There is a small number of registers, so it's much better to use bitvectors for
+// register liveness. This is a specialization of Liveness<> that uses bitvectors directly.
+// This makes the code sufficiently different that it didn't make sense to try to share code.
+class RegLiveness {
+public:
+    typedef Reg Thing;
+    
+    RegLiveness(Code& code);
+    ~RegLiveness();
+    
+    // This calculator has to be run in reverse.
+    class LocalCalc {
+    public:
+        LocalCalc(RegLiveness& liveness, BasicBlock* block)
+            : m_block(block)
+            , m_workset(liveness.m_liveAtTail[block])
+        {
+        }
+        
+        const RegisterSet& live() const
+        {
+            return m_workset;
+        }
+        
+        bool isLive(Reg reg) const
+        {
+            return m_workset.contains(reg);
+        }
+        
+        void execute(unsigned instIndex);
+        
+    private:
+        friend class RegLiveness;
+        
+        BasicBlock* m_block;
+        RegisterSet m_workset;
+    };
+    
+    const RegisterSet& liveAtHead(BasicBlock* block) const
+    {
+        return m_liveAtHead[block];
+    }
+    
+    const RegisterSet& liveAtTail(BasicBlock* block) const
+    {
+        return m_liveAtTail[block];
+    }
+    
+private:
+    IndexMap<BasicBlock, RegisterSet> m_liveAtHead;
+    IndexMap<BasicBlock, RegisterSet> m_liveAtTail;
+};
+
+} } } // namespace JSC::B3::Air
+
+#endif // ENABLE(B3_JIT)
+

Modified: trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp (214407 => 214408)


--- trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/b3/air/AirReportUsedRegisters.cpp	2017-03-26 21:39:27 UTC (rev 214408)
@@ -31,7 +31,7 @@
 #include "AirArgInlines.h"
 #include "AirCode.h"
 #include "AirInstInlines.h"
-#include "AirLiveness.h"
+#include "AirRegLiveness.h"
 #include "AirPhaseScope.h"
 
 namespace JSC { namespace B3 { namespace Air {

Modified: trunk/Source/_javascript_Core/jit/RegisterSet.h (214407 => 214408)


--- trunk/Source/_javascript_Core/jit/RegisterSet.h	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/_javascript_Core/jit/RegisterSet.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,6 +36,8 @@
 
 namespace JSC {
 
+typedef Bitmap<MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1> RegisterBitmap;
+
 class RegisterSet {
 public:
     template<typename... Regs>
@@ -99,10 +101,17 @@
             set(reg);
     }
     
+    // Also allow add/remove/contains terminology, which means the same thing as set/clear/get.
+    void add(Reg reg) { set(reg); }
+    void remove(Reg reg) { clear(reg); }
+    bool contains(Reg reg) const { return get(reg); }
+    
     void merge(const RegisterSet& other) { m_bits.merge(other.m_bits); }
     void filter(const RegisterSet& other) { m_bits.filter(other.m_bits); }
     void exclude(const RegisterSet& other) { m_bits.exclude(other.m_bits); }
     
+    bool subsumes(const RegisterSet& other) const { return m_bits.subsumes(other.m_bits); }
+    
     size_t numberOfSetGPRs() const;
     size_t numberOfSetFPRs() const;
     size_t numberOfSetRegisters() const { return m_bits.count(); }
@@ -149,6 +158,42 @@
             });
     }
     
+    class iterator {
+    public:
+        iterator()
+        {
+        }
+        
+        iterator(const RegisterBitmap::iterator& iter)
+            : m_iter(iter)
+        {
+        }
+        
+        Reg operator*() const { return Reg::fromIndex(*m_iter); }
+        
+        iterator& operator++()
+        {
+            ++m_iter;
+            return *this;
+        }
+        
+        bool operator==(const iterator& other)
+        {
+            return m_iter == other.m_iter;
+        }
+        
+        bool operator!=(const iterator& other)
+        {
+            return !(*this == other);
+        }
+        
+    private:
+        RegisterBitmap::iterator m_iter;
+    };
+    
+    iterator begin() const { return iterator(m_bits.begin()); }
+    iterator end() const { return iterator(m_bits.end()); }
+    
 private:
     void setAny(Reg reg) { set(reg); }
     void setAny(const RegisterSet& set) { merge(set); }
@@ -166,7 +211,7 @@
     static const unsigned hashSpecialBitIndex = fprOffset + MacroAssembler::numFPRs;
     static const unsigned deletedBitIndex = 0;
     
-    Bitmap<MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1> m_bits;
+    RegisterBitmap m_bits;
 };
 
 struct RegisterSetHash {

Modified: trunk/Source/WTF/ChangeLog (214407 => 214408)


--- trunk/Source/WTF/ChangeLog	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/ChangeLog	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,3 +1,23 @@
+2017-03-26  Filip Pizlo  <[email protected]>
+
+        Air should use RegisterSet for RegLiveness
+        https://bugs.webkit.org/show_bug.cgi?id=170108
+
+        Reviewed by Yusuke Suzuki.
+
+        * wtf/Atomics.h:
+        (WTF::ensurePointer): This is a useful replacement for std::once, which requires less fencing.
+        * wtf/Bitmap.h: Add more utilities.
+        (WTF::Bitmap::iterator::iterator): An iterator for set bits.
+        (WTF::Bitmap::iterator::operator*):
+        (WTF::Bitmap::iterator::operator++):
+        (WTF::Bitmap::iterator::operator==):
+        (WTF::Bitmap::iterator::operator!=):
+        (WTF::Bitmap::begin):
+        (WTF::Bitmap::end):
+        (WTF::WordType>::subsumes): a.subsumes(b) if all of b's set bits are set in a.
+        (WTF::WordType>::findBit): find next set or clear bit.
+
 2017-03-24  JF Bastien  <[email protected]>
 
         WebAssembly: store state in TLS instead of on VM

Modified: trunk/Source/WTF/wtf/Atomics.h (214407 => 214408)


--- trunk/Source/WTF/wtf/Atomics.h	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/wtf/Atomics.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -519,6 +519,23 @@
 #endif
 }
 
+template<typename T, typename Func>
+ALWAYS_INLINE T& ensurePointer(Atomic<T*>& pointer, const Func& func)
+{
+    for (;;) {
+        T* oldValue = pointer.load(std::memory_order_relaxed);
+        if (oldValue) {
+            // On all sensible CPUs, we get an implicit dependency-based load-load barrier when
+            // loading this.
+            return *oldValue;
+        }
+        T* newValue = func();
+        if (pointer.compareExchangeWeak(oldValue, newValue))
+            return *newValue;
+        delete newValue;
+    }
+}
+
 } // namespace WTF
 
 using WTF::Atomic;
@@ -528,6 +545,7 @@
 using WTF::consume;
 using WTF::dependency;
 using WTF::dependencyWith;
+using WTF::ensurePointer;
 using WTF::nullDependency;
 
 #endif // Atomics_h

Modified: trunk/Source/WTF/wtf/Bitmap.h (214407 => 214408)


--- trunk/Source/WTF/wtf/Bitmap.h	2017-03-26 03:52:40 UTC (rev 214407)
+++ trunk/Source/WTF/wtf/Bitmap.h	2017-03-26 21:39:27 UTC (rev 214408)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2010, 2016 Apple Inc. All rights reserved.
+ *  Copyright (C) 2010-2017 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -59,9 +59,54 @@
     void filter(const Bitmap&);
     void exclude(const Bitmap&);
     
+    bool subsumes(const Bitmap&) const;
+    
     template<typename Func>
     void forEachSetBit(const Func&) const;
     
+    size_t findBit(size_t startIndex, bool value) const;
+    
+    class iterator {
+    public:
+        iterator()
+            : m_bitmap(nullptr)
+            , m_index(0)
+        {
+        }
+        
+        iterator(const Bitmap& bitmap, size_t index)
+            : m_bitmap(&bitmap)
+            , m_index(index)
+        {
+        }
+        
+        size_t operator*() const { return m_index; }
+        
+        iterator& operator++()
+        {
+            m_index = m_bitmap->findBit(m_index + 1, true);
+            return *this;
+        }
+        
+        bool operator==(const iterator& other) const
+        {
+            return m_index == other.m_index;
+        }
+        
+        bool operator!=(const iterator& other) const
+        {
+            return !(*this == other);
+        }
+
+    private:
+        const Bitmap* m_bitmap;
+        size_t m_index;
+    };
+    
+    // Use this to iterate over set bits.
+    iterator begin() const { return iterator(*this, findBit(0, true)); }
+    iterator end() const { return iterator(*this, bitmapSize); }
+    
     void mergeAndClear(Bitmap&);
     void setAndClear(Bitmap&);
     
@@ -258,6 +303,18 @@
 }
 
 template<size_t bitmapSize, typename WordType>
+inline bool Bitmap<bitmapSize, WordType>::subsumes(const Bitmap& other) const
+{
+    for (size_t i = 0; i < words; ++i) {
+        WordType myBits = bits[i];
+        WordType otherBits = other.bits[i];
+        if ((myBits | otherBits) != myBits)
+            return false;
+    }
+    return true;
+}
+
+template<size_t bitmapSize, typename WordType>
 template<typename Func>
 inline void Bitmap<bitmapSize, WordType>::forEachSetBit(const Func& func) const
 {
@@ -275,6 +332,28 @@
 }
 
 template<size_t bitmapSize, typename WordType>
+inline size_t Bitmap<bitmapSize, WordType>::findBit(size_t startIndex, bool value) const
+{
+    WordType skipValue = -(static_cast<WordType>(value) ^ 1);
+    size_t wordIndex = startIndex / wordSize;
+    size_t startIndexInWord = startIndex - wordIndex * wordSize;
+    
+    while (wordIndex < words) {
+        WordType word = bits[wordIndex];
+        if (word != skipValue) {
+            size_t index = startIndexInWord;
+            if (findBitInWord(word, index, wordSize, value))
+                return wordIndex * wordSize + index;
+        }
+        
+        wordIndex++;
+        startIndexInWord = 0;
+    }
+    
+    return bitmapSize;
+}
+
+template<size_t bitmapSize, typename WordType>
 inline void Bitmap<bitmapSize, WordType>::mergeAndClear(Bitmap& other)
 {
     for (size_t i = 0; i < words; ++i) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to