Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (192182 => 192183)
--- trunk/Source/_javascript_Core/ChangeLog 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-11-10 00:01:24 UTC (rev 192183)
@@ -1,3 +1,147 @@
+2015-11-08 Filip Pizlo <fpi...@apple.com>
+
+ B3 should be able to compile a program with a double constant
+ https://bugs.webkit.org/show_bug.cgi?id=151002
+
+ Reviewed by Benjamin Poulain.
+
+ This implements a bunch of annoying stuff that is necessary to support constants that need a
+ data section, such as double constants on X86_64:
+
+ - B3::Procedure can now tell you what to keep alive in addition to the MacroAssemblerCodeRef.
+ We call this the B3::OpaqueByproducts. It's the client's responsibility to keep this alive
+ after calling B3::generate().
+
+ - Added a new helper for compiling B3 code, called B3::Compilation. Constructing a
+ Compilation runs the compiler. Then you can pass around a Compilation the way you would
+ have passed around a MacroAssemblerCodeRef.
+
+ - Added a constant motion phase, called moveConstants(). This does very simple constant
+ hoisting/sinking: it makes sure that each constant is only materialized in one place in
+ each basic block. It uses a DataSection, which is a kind of OpaqueByproduct, to store
+ double constants.
+
+ - The way I wanted to do constant motion is to basically track what constants are of interest
+ and then recreate them as needed, so the original Values become irrelevant in the process.
+ To do that, I needed an abstraction that is almost identical to the DFG PureValue
+ abstraction that we use for CSE. So, I created such a thing, and called it ValueKey. It
+ can be used to compare and hash pure Values, and to recreate them as needed.
+
+ - Fixed the lowering's handling of constants so that we don't perturb the placement of the
+ constant materializations.
+
+ * _javascript_Core.xcodeproj/project.pbxproj:
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::branchConvertDoubleToInt32):
+ (JSC::MacroAssemblerX86Common::moveZeroToDouble):
+ (JSC::MacroAssemblerX86Common::branchDoubleNonZero):
+ * b3/B3Common.h:
+ (JSC::B3::isIdentical):
+ (JSC::B3::isRepresentableAsImpl):
+ * b3/B3Compilation.cpp: Added.
+ (JSC::B3::Compilation::Compilation):
+ (JSC::B3::Compilation::~Compilation):
+ * b3/B3Compilation.h: Added.
+ (JSC::B3::Compilation::code):
+ * b3/B3ConstDoubleValue.h:
+ (JSC::B3::ConstDoubleValue::accepts): Deleted.
+ * b3/B3DataSection.cpp: Added.
+ (JSC::B3::DataSection::DataSection):
+ (JSC::B3::DataSection::~DataSection):
+ (JSC::B3::DataSection::dump):
+ * b3/B3DataSection.h: Added.
+ (JSC::B3::DataSection::data):
+ (JSC::B3::DataSection::size):
+ * b3/B3Generate.cpp:
+ (JSC::B3::generate):
+ (JSC::B3::generateToAir):
+ * b3/B3LowerToAir.cpp:
+ (JSC::B3::Air::LowerToAir::imm):
+ (JSC::B3::Air::LowerToAir::immOrTmp):
+ (JSC::B3::Air::LowerToAir::fillStackmap):
+ (JSC::B3::Air::LowerToAir::lower):
+ (JSC::B3::Air::LowerToAir::immForMove): Deleted.
+ (JSC::B3::Air::LowerToAir::immOrTmpForMove): Deleted.
+ * b3/B3MoveConstants.cpp: Added.
+ (JSC::B3::moveConstants):
+ * b3/B3MoveConstants.h: Added.
+ * b3/B3OpaqueByproduct.h: Added.
+ (JSC::B3::OpaqueByproduct::OpaqueByproduct):
+ (JSC::B3::OpaqueByproduct::~OpaqueByproduct):
+ * b3/B3OpaqueByproducts.cpp: Added.
+ (JSC::B3::OpaqueByproducts::OpaqueByproducts):
+ (JSC::B3::OpaqueByproducts::~OpaqueByproducts):
+ (JSC::B3::OpaqueByproducts::add):
+ (JSC::B3::OpaqueByproducts::dump):
+ * b3/B3OpaqueByproducts.h: Added.
+ (JSC::B3::OpaqueByproducts::count):
+ * b3/B3Opcode.h:
+ (JSC::B3::constPtrOpcode):
+ * b3/B3Procedure.cpp:
+ (JSC::B3::Procedure::Procedure):
+ (JSC::B3::Procedure::dump):
+ (JSC::B3::Procedure::blocksInPreOrder):
+ (JSC::B3::Procedure::deleteValue):
+ (JSC::B3::Procedure::addDataSection):
+ (JSC::B3::Procedure::addValueIndex):
+ * b3/B3Procedure.h:
+ (JSC::B3::Procedure::lastPhaseName):
+ (JSC::B3::Procedure::byproducts):
+ (JSC::B3::Procedure::takeByproducts):
+ * b3/B3Type.h:
+ * b3/B3Value.cpp:
+ (JSC::B3::Value::effects):
+ (JSC::B3::Value::key):
+ (JSC::B3::Value::performSubstitution):
+ * b3/B3Value.h:
+ * b3/B3ValueKey.cpp: Added.
+ (JSC::B3::ValueKey::dump):
+ (JSC::B3::ValueKey::materialize):
+ * b3/B3ValueKey.h: Added.
+ (JSC::B3::ValueKey::ValueKey):
+ (JSC::B3::ValueKey::opcode):
+ (JSC::B3::ValueKey::type):
+ (JSC::B3::ValueKey::childIndex):
+ (JSC::B3::ValueKey::value):
+ (JSC::B3::ValueKey::doubleValue):
+ (JSC::B3::ValueKey::operator==):
+ (JSC::B3::ValueKey::operator!=):
+ (JSC::B3::ValueKey::hash):
+ (JSC::B3::ValueKey::operator bool):
+ (JSC::B3::ValueKey::canMaterialize):
+ (JSC::B3::ValueKey::isHashTableDeletedValue):
+ (JSC::B3::ValueKeyHash::hash):
+ (JSC::B3::ValueKeyHash::equal):
+ * b3/B3ValueKeyInlines.h: Added.
+ (JSC::B3::ValueKey::ValueKey):
+ (JSC::B3::ValueKey::child):
+ * b3/air/AirCode.cpp:
+ (JSC::B3::Air::Code::Code):
+ * b3/air/AirCode.h:
+ (JSC::B3::Air::Code::proc):
+ (JSC::B3::Air::Code::lastPhaseName):
+ * b3/air/AirOpcode.opcodes:
+ * b3/testb3.cpp:
+ (JSC::B3::compile):
+ (JSC::B3::invoke):
+ (JSC::B3::compileAndRun):
+ (JSC::B3::test42):
+ (JSC::B3::testBranch):
+ (JSC::B3::testBranchPtr):
+ (JSC::B3::testDiamond):
+ (JSC::B3::testBranchNotEqual):
+ (JSC::B3::testBranchNotEqualCommute):
+ (JSC::B3::testBranchNotEqualNotEqual):
+ (JSC::B3::testBranchEqual):
+ (JSC::B3::testBranchEqualEqual):
+ (JSC::B3::testBranchEqualCommute):
+ (JSC::B3::testBranchEqualEqual1):
+ (JSC::B3::testBranchFold):
+ (JSC::B3::testSimpleCheck):
+ (JSC::B3::testCompare):
+ (JSC::B3::testReturnDouble):
+ (JSC::B3::run):
+
2015-11-09 Michael Saboff <msab...@apple.com>
Need a function that will provide Nth argument register
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (192182 => 192183)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2015-11-10 00:01:24 UTC (rev 192183)
@@ -288,6 +288,18 @@
0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DF81BE96AA80013C88F /* B3CCallValue.h */; };
0F338DFD1BED51270013C88F /* AirSimplifyCFG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */; };
0F338DFE1BED51270013C88F /* AirSimplifyCFG.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */; };
+ 0F338E0B1BF0276C0013C88F /* B3Compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338DFF1BF0276C0013C88F /* B3Compilation.cpp */; };
+ 0F338E0C1BF0276C0013C88F /* B3Compilation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E001BF0276C0013C88F /* B3Compilation.h */; };
+ 0F338E0D1BF0276C0013C88F /* B3DataSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338E011BF0276C0013C88F /* B3DataSection.cpp */; };
+ 0F338E0E1BF0276C0013C88F /* B3DataSection.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E021BF0276C0013C88F /* B3DataSection.h */; };
+ 0F338E0F1BF0276C0013C88F /* B3MoveConstants.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338E031BF0276C0013C88F /* B3MoveConstants.cpp */; };
+ 0F338E101BF0276C0013C88F /* B3MoveConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E041BF0276C0013C88F /* B3MoveConstants.h */; };
+ 0F338E111BF0276C0013C88F /* B3OpaqueByproduct.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E051BF0276C0013C88F /* B3OpaqueByproduct.h */; };
+ 0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338E061BF0276C0013C88F /* B3OpaqueByproducts.cpp */; };
+ 0F338E131BF0276C0013C88F /* B3OpaqueByproducts.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E071BF0276C0013C88F /* B3OpaqueByproducts.h */; };
+ 0F338E141BF0276C0013C88F /* B3ValueKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F338E081BF0276C0013C88F /* B3ValueKey.cpp */; };
+ 0F338E151BF0276C0013C88F /* B3ValueKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E091BF0276C0013C88F /* B3ValueKey.h */; };
+ 0F338E161BF0276C0013C88F /* B3ValueKeyInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F338E0A1BF0276C0013C88F /* B3ValueKeyInlines.h */; };
0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; };
0F38B01117CF078000B144D3 /* LLIntEntrypoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */; };
@@ -2313,6 +2325,18 @@
0F338DF81BE96AA80013C88F /* B3CCallValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3CCallValue.h; path = b3/B3CCallValue.h; sourceTree = "<group>"; };
0F338DFB1BED51270013C88F /* AirSimplifyCFG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirSimplifyCFG.cpp; path = b3/air/AirSimplifyCFG.cpp; sourceTree = "<group>"; };
0F338DFC1BED51270013C88F /* AirSimplifyCFG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirSimplifyCFG.h; path = b3/air/AirSimplifyCFG.h; sourceTree = "<group>"; };
+ 0F338DFF1BF0276C0013C88F /* B3Compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Compilation.cpp; path = b3/B3Compilation.cpp; sourceTree = "<group>"; };
+ 0F338E001BF0276C0013C88F /* B3Compilation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Compilation.h; path = b3/B3Compilation.h; sourceTree = "<group>"; };
+ 0F338E011BF0276C0013C88F /* B3DataSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3DataSection.cpp; path = b3/B3DataSection.cpp; sourceTree = "<group>"; };
+ 0F338E021BF0276C0013C88F /* B3DataSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3DataSection.h; path = b3/B3DataSection.h; sourceTree = "<group>"; };
+ 0F338E031BF0276C0013C88F /* B3MoveConstants.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3MoveConstants.cpp; path = b3/B3MoveConstants.cpp; sourceTree = "<group>"; };
+ 0F338E041BF0276C0013C88F /* B3MoveConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3MoveConstants.h; path = b3/B3MoveConstants.h; sourceTree = "<group>"; };
+ 0F338E051BF0276C0013C88F /* B3OpaqueByproduct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3OpaqueByproduct.h; path = b3/B3OpaqueByproduct.h; sourceTree = "<group>"; };
+ 0F338E061BF0276C0013C88F /* B3OpaqueByproducts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3OpaqueByproducts.cpp; path = b3/B3OpaqueByproducts.cpp; sourceTree = "<group>"; };
+ 0F338E071BF0276C0013C88F /* B3OpaqueByproducts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3OpaqueByproducts.h; path = b3/B3OpaqueByproducts.h; sourceTree = "<group>"; };
+ 0F338E081BF0276C0013C88F /* B3ValueKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3ValueKey.cpp; path = b3/B3ValueKey.cpp; sourceTree = "<group>"; };
+ 0F338E091BF0276C0013C88F /* B3ValueKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ValueKey.h; path = b3/B3ValueKey.h; sourceTree = "<group>"; };
+ 0F338E0A1BF0276C0013C88F /* B3ValueKeyInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3ValueKeyInlines.h; path = b3/B3ValueKeyInlines.h; sourceTree = "<group>"; };
0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; };
0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; };
0F38B00F17CF077F00B144D3 /* LLIntEntrypoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoint.cpp; path = llint/LLIntEntrypoint.cpp; sourceTree = "<group>"; };
@@ -4415,6 +4439,8 @@
0FEC84C01BDACDAC0080FF74 /* B3Common.h */,
0FEC84C11BDACDAC0080FF74 /* B3Commutativity.cpp */,
0FEC84C21BDACDAC0080FF74 /* B3Commutativity.h */,
+ 0F338DFF1BF0276C0013C88F /* B3Compilation.cpp */,
+ 0F338E001BF0276C0013C88F /* B3Compilation.h */,
0FEC84C31BDACDAC0080FF74 /* B3Const32Value.cpp */,
0FEC84C41BDACDAC0080FF74 /* B3Const32Value.h */,
0FEC84C51BDACDAC0080FF74 /* B3Const64Value.cpp */,
@@ -4426,6 +4452,8 @@
0F338DF41BE93D550013C88F /* B3ConstrainedValue.h */,
0FEC84C91BDACDAC0080FF74 /* B3ControlValue.cpp */,
0FEC84CA1BDACDAC0080FF74 /* B3ControlValue.h */,
+ 0F338E011BF0276C0013C88F /* B3DataSection.cpp */,
+ 0F338E021BF0276C0013C88F /* B3DataSection.h */,
0FEC85C41BE16F5A0080FF74 /* B3Effects.cpp */,
0FEC85BE1BE167A00080FF74 /* B3Effects.h */,
0FEC84CB1BDACDAC0080FF74 /* B3FrequencyClass.cpp */,
@@ -4445,6 +4473,11 @@
0FEC84D41BDACDAC0080FF74 /* B3LowerToAir.h */,
0FEC84D51BDACDAC0080FF74 /* B3MemoryValue.cpp */,
0FEC84D61BDACDAC0080FF74 /* B3MemoryValue.h */,
+ 0F338E031BF0276C0013C88F /* B3MoveConstants.cpp */,
+ 0F338E041BF0276C0013C88F /* B3MoveConstants.h */,
+ 0F338E051BF0276C0013C88F /* B3OpaqueByproduct.h */,
+ 0F338E061BF0276C0013C88F /* B3OpaqueByproducts.cpp */,
+ 0F338E071BF0276C0013C88F /* B3OpaqueByproducts.h */,
0FEC84D71BDACDAC0080FF74 /* B3Opcode.cpp */,
0FEC84D81BDACDAC0080FF74 /* B3Opcode.h */,
0FEC84D91BDACDAC0080FF74 /* B3Origin.cpp */,
@@ -4486,6 +4519,9 @@
0FEC84F91BDACDAC0080FF74 /* B3Value.cpp */,
0FEC84FA1BDACDAC0080FF74 /* B3Value.h */,
0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */,
+ 0F338E081BF0276C0013C88F /* B3ValueKey.cpp */,
+ 0F338E091BF0276C0013C88F /* B3ValueKey.h */,
+ 0F338E0A1BF0276C0013C88F /* B3ValueKeyInlines.h */,
0FEC84FC1BDACDAC0080FF74 /* B3ValueRep.cpp */,
0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */,
0FEC85AE1BDB5D5E0080FF74 /* testb3.cpp */,
@@ -6534,6 +6570,7 @@
0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */,
0FEC85721BDACDC70080FF74 /* AirBasicBlock.h in Headers */,
0F338DFA1BE96AA80013C88F /* B3CCallValue.h in Headers */,
+ 0F338E161BF0276C0013C88F /* B3ValueKeyInlines.h in Headers */,
0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
0FEC85761BDACDC70080FF74 /* AirCode.h in Headers */,
0F4570391BE44C910062A629 /* AirEliminateDeadCode.h in Headers */,
@@ -6631,6 +6668,7 @@
0FEC85451BDACDAC0080FF74 /* B3ValueInlines.h in Headers */,
0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */,
52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
+ 0F338E151BF0276C0013C88F /* B3ValueKey.h in Headers */,
147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */,
866739D213BFDE710023D87C /* BigInteger.h in Headers */,
0F64B2721A784BAF006E4E66 /* BinarySwitch.h in Headers */,
@@ -6643,6 +6681,7 @@
99DA00A71BD5993100F4575C /* builtins_generate_combined_header.py in Headers */,
99DA00A81BD5993100F4575C /* builtins_generate_combined_implementation.py in Headers */,
99DA00A91BD5993100F4575C /* builtins_generate_separate_header.py in Headers */,
+ 0F338E111BF0276C0013C88F /* B3OpaqueByproduct.h in Headers */,
99DA00AA1BD5993100F4575C /* builtins_generate_separate_implementation.py in Headers */,
99DA00A31BD5993100F4575C /* builtins_generator.py in Headers */,
99DA00A41BD5993100F4575C /* builtins_model.py in Headers */,
@@ -6959,6 +6998,7 @@
2AC922BC18A16182003CE0FB /* FTLDWARFDebugLineInfo.h in Headers */,
0F9C5E5F18E35F5E00D431C3 /* FTLDWARFRegister.h in Headers */,
0F235BD417178E1C00690C7F /* FTLExitArgument.h in Headers */,
+ 0F338E0C1BF0276C0013C88F /* B3Compilation.h in Headers */,
0F235BD617178E1C00690C7F /* FTLExitArgumentForOperand.h in Headers */,
0F235BD717178E1C00690C7F /* FTLExitArgumentList.h in Headers */,
0F2B9CF519D0BAC100B1D1B5 /* FTLExitPropertyValue.h in Headers */,
@@ -6985,6 +7025,7 @@
0FEA0A10170513DB00BB722C /* FTLLowerDFGToLLVM.h in Headers */,
A7D89D0217A0B90400773AD8 /* FTLLoweredNodeValue.h in Headers */,
0F2B9CF919D0BAC100B1D1B5 /* FTLOperations.h in Headers */,
+ 0F338E101BF0276C0013C88F /* B3MoveConstants.h in Headers */,
0FD8A31C17D51F2200CA2C40 /* FTLOSREntry.h in Headers */,
0F235BDD17178E1C00690C7F /* FTLOSRExit.h in Headers */,
0F235BDE17178E1C00690C7F /* FTLOSRExitCompilationInfo.h in Headers */,
@@ -7348,6 +7389,7 @@
86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */,
863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */,
86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */,
+ 0F338E0E1BF0276C0013C88F /* B3DataSection.h in Headers */,
FE68C6371B90DE040042BCB3 /* MacroAssemblerPrinter.h in Headers */,
86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */,
860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */,
@@ -7552,6 +7594,7 @@
5D53726F0E1C54880021E549 /* Tracing.h in Headers */,
0F952ABD1B487A7700C367C5 /* TrackedReferences.h in Headers */,
0F2B670617B6B5AB00A7AE3F /* TypedArrayAdaptors.h in Headers */,
+ 0F338E131BF0276C0013C88F /* B3OpaqueByproducts.h in Headers */,
0F2B670817B6B5AB00A7AE3F /* TypedArrayController.h in Headers */,
0F4B94DC17B9F07500DD03A4 /* TypedArrayInlines.h in Headers */,
0F2B670917B6B5AB00A7AE3F /* TypedArrays.h in Headers */,
@@ -8209,6 +8252,7 @@
148F21AA107EC53A0042EC2C /* BytecodeGenerator.cpp in Sources */,
7094C4DE1AE439530041A2EE /* BytecodeIntrinsicRegistry.cpp in Sources */,
C2FCAE1217A9C24E0034C735 /* BytecodeLivenessAnalysis.cpp in Sources */,
+ 0F338E0D1BF0276C0013C88F /* B3DataSection.cpp in Sources */,
65B8392F1BACAD6A0044E824 /* CachedRecovery.cpp in Sources */,
1428082D107EC0570013E7B2 /* CallData.cpp in Sources */,
0F64B2791A7957B2006E4E66 /* CallEdge.cpp in Sources */,
@@ -8225,6 +8269,7 @@
969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */,
0F8F94401667633000D61971 /* CodeBlockHash.cpp in Sources */,
0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */,
+ 0F338E0F1BF0276C0013C88F /* B3MoveConstants.cpp in Sources */,
0FD8A31317D4326C00CA2C40 /* CodeBlockSet.cpp in Sources */,
A77F1821164088B200640A47 /* CodeCache.cpp in Sources */,
0F8F9446166764F100D61971 /* CodeOrigin.cpp in Sources */,
@@ -8297,6 +8342,7 @@
A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */,
0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
+ 0F338E121BF0276C0013C88F /* B3OpaqueByproducts.cpp in Sources */,
0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
@@ -8694,6 +8740,7 @@
0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */,
E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */,
E355F3521B7DC85300C50DC5 /* ModuleLoaderObject.cpp in Sources */,
+ 0F338E0B1BF0276C0013C88F /* B3Compilation.cpp in Sources */,
14469DE0107EC7E700650446 /* NativeErrorConstructor.cpp in Sources */,
14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */,
E33E8D201B9013DE00346B52 /* NativeStdFunctionCell.cpp in Sources */,
@@ -8718,6 +8765,7 @@
93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */,
0FF9CE731B9CD6D0004EDCA6 /* PolymorphicAccess.cpp in Sources */,
0FE834171A6EF97B00D04847 /* PolymorphicCallStubRoutine.cpp in Sources */,
+ 0F338E141BF0276C0013C88F /* B3ValueKey.cpp in Sources */,
0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */,
95742F650DD11F5A000917FB /* Profile.cpp in Sources */,
95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */,
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (192182 => 192183)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -940,6 +940,11 @@
failureCases.append(m_assembler.jne());
}
+ void moveZeroToDouble(FPRegisterID reg)
+ {
+ m_assembler.xorpd_rr(reg, reg);
+ }
+
Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
{
ASSERT(isSSE2Present());
Modified: trunk/Source/_javascript_Core/b3/B3Common.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Common.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Common.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -40,12 +40,32 @@
bool shouldSaveIRBeforePhase();
bool shouldMeasurePhaseTiming();
+template<typename BitsType, typename InputType>
+inline bool isIdentical(InputType left, InputType right)
+{
+ BitsType leftBits = bitwise_cast<BitsType>(left);
+ BitsType rightBits = bitwise_cast<BitsType>(right);
+ return leftBits == rightBits;
+}
+
+inline bool isIdentical(int32_t left, int32_t right)
+{
+ return isIdentical<int32_t>(left, right);
+}
+
+inline bool isIdentical(int64_t left, int64_t right)
+{
+ return isIdentical<int64_t>(left, right);
+}
+
+inline bool isIdentical(double left, double right)
+{
+ return isIdentical<int64_t>(left, right);
+}
+
template<typename ResultType, typename InputType, typename BitsType>
inline bool isRepresentableAsImpl(InputType originalValue)
{
- // Get the raw bits of the original value.
- BitsType originalBits = bitwise_cast<BitsType>(originalValue);
-
// Convert the original value to the desired result type.
ResultType result = static_cast<ResultType>(originalValue);
@@ -53,10 +73,7 @@
// using the new type if such round-tripping doesn't lose bits.
InputType newValue = static_cast<InputType>(result);
- // Get the raw bits of the round-tripped value.
- BitsType newBits = bitwise_cast<BitsType>(newValue);
-
- return originalBits == newBits;
+ return isIdentical<BitsType>(originalValue, newValue);
}
template<typename ResultType>
Added: trunk/Source/_javascript_Core/b3/B3Compilation.cpp (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Compilation.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3Compilation.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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 "B3Compilation.h"
+
+#if ENABLE(B3_JIT)
+
+#include "B3Generate.h"
+#include "B3OpaqueByproducts.h"
+#include "B3Procedure.h"
+#include "CCallHelpers.h"
+#include "JSCInlines.h"
+#include "LinkBuffer.h"
+
+namespace JSC { namespace B3 {
+
+Compilation::Compilation(VM& vm, Procedure& proc)
+{
+ CCallHelpers jit(&vm);
+ generate(proc, jit);
+ LinkBuffer linkBuffer(vm, jit, nullptr);
+
+ m_codeRef = FINALIZE_CODE(linkBuffer, ("B3::Compilation"));
+ m_byproducts = proc.takeByproducts();
+}
+
+Compilation::~Compilation()
+{
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/B3Compilation.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Compilation.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3Compilation.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 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 B3Compilation_h
+#define B3Compilation_h
+
+#if ENABLE(B3_JIT)
+
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+class VM;
+
+namespace B3 {
+
+class OpaqueByproducts;
+class Procedure;
+
+// This is a fool-proof API for compiling a Procedure to code and then running that code. You compile
+// a Procedure using this API by doing:
+//
+// std::unique_ptr<Compilation> compilation = std::make_unique<Compilation>(vm, proc);
+//
+// Then you keep the Compilation object alive for as long as you want to be able to run the code. If
+// this API feels too high-level, you can use B3::generate() directly.
+
+class Compilation {
+ WTF_MAKE_NONCOPYABLE(Compilation);
+ WTF_MAKE_FAST_ALLOCATED;
+
+public:
+ JS_EXPORT_PRIVATE Compilation(VM&, Procedure&);
+ JS_EXPORT_PRIVATE ~Compilation();
+
+ MacroAssemblerCodePtr code() const { return m_codeRef.code(); }
+
+private:
+ MacroAssemblerCodeRef m_codeRef;
+ std::unique_ptr<OpaqueByproducts> m_byproducts;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3Compilation_h
+
Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -32,7 +32,7 @@
namespace JSC { namespace B3 {
-class ConstDoubleValue : public Value {
+class JS_EXPORT_PRIVATE ConstDoubleValue : public Value {
public:
static bool accepts(Opcode opcode) { return opcode == ConstDouble; }
Added: trunk/Source/_javascript_Core/b3/B3DataSection.cpp (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3DataSection.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3DataSection.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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 "B3DataSection.h"
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+DataSection::DataSection(size_t size)
+ : m_data(fastMalloc(size))
+ , m_size(size)
+{
+}
+
+DataSection::~DataSection()
+{
+ fastFree(m_data);
+}
+
+void DataSection::dump(PrintStream& out) const
+{
+ out.print("DataSection at ", RawPointer(m_data), " with ", m_size, " bytes.");
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/B3DataSection.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3DataSection.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3DataSection.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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 B3DataSection_h
+#define B3DataSection_h
+
+#if ENABLE(B3_JIT)
+
+#include "B3OpaqueByproduct.h"
+
+namespace JSC { namespace B3 {
+
+class DataSection : public OpaqueByproduct {
+public:
+ DataSection(size_t size);
+ virtual ~DataSection();
+
+ void* data() const { return m_data; }
+ size_t size() const { return m_size; }
+
+ void dump(PrintStream&) const override;
+
+private:
+ void* m_data;
+ size_t m_size;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3DataSection_h
+
Modified: trunk/Source/_javascript_Core/b3/B3Generate.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Generate.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Generate.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -33,6 +33,7 @@
#include "AirInstInlines.h"
#include "B3Common.h"
#include "B3LowerToAir.h"
+#include "B3MoveConstants.h"
#include "B3Procedure.h"
#include "B3ReduceStrength.h"
#include "B3TimingScope.h"
@@ -44,7 +45,7 @@
{
TimingScope timingScope("generate");
- Air::Code code;
+ Air::Code code(procedure);
generateToAir(procedure, code);
Air::generate(code, jit);
}
@@ -70,6 +71,8 @@
// FIXME: Add more optimizations here.
// https://bugs.webkit.org/show_bug.cgi?id=150507
+ moveConstants(procedure);
+
if (shouldValidateIR())
validate(procedure);
Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -440,23 +440,15 @@
Arg imm(Value* value)
{
- if (value->representableAs<int32_t>())
+ if (value->hasInt() && value->representableAs<int32_t>())
return Arg::imm(value->asNumber<int32_t>());
return Arg();
}
- Arg immForMove(Value* value) {
+ Arg immOrTmp(Value* value)
+ {
if (Arg result = imm(value))
return result;
- if (value->hasInt64())
- return Arg::imm64(value->asInt64());
- return Arg();
- }
-
- Arg immOrTmpForMove(Value* value)
- {
- if (Arg result = immForMove(value))
- return result;
return tmp(value);
}
@@ -731,14 +723,21 @@
Arg arg;
switch (value.rep().kind()) {
case ValueRep::Any:
- arg = immOrTmpForMove(value.value());
+ if (imm(value.value()))
+ arg = imm(value.value());
+ else if (value.value()->hasInt64())
+ arg = Arg::imm64(value.value()->asInt64());
+ else if (value.value()->hasDouble())
+ arg = Arg::imm64(bitwise_cast<int64_t>(value.value()->asDouble()));
+ else
+ arg = tmp(value.value());
break;
case ValueRep::SomeRegister:
arg = tmp(value.value());
break;
case ValueRep::Register:
arg = Tmp(value.rep().reg());
- append(Move, immOrTmpForMove(value.value()), arg);
+ append(Move, immOrTmp(value.value()), arg);
break;
case ValueRep::StackArgument:
arg = Arg::callArg(value.rep().offsetFromSP());
@@ -1152,7 +1151,13 @@
void lower()
{
switch (m_value->opcode()) {
- case Load:{
+ case B3::Nop: {
+ // Yes, we will totally see Nop's because some phases will replaceWithNop() instead of
+ // properly removing things.
+ return;
+ }
+
+ case Load: {
append(
moveForType(m_value->type()),
addr(m_value), tmp(m_value));
@@ -1285,12 +1290,25 @@
return;
}
- case Const32:
+ case Const32: {
+ append(Move, imm(m_value), tmp(m_value));
+ return;
+ }
case Const64: {
- append(Move, immForMove(m_value), tmp(m_value));
+ if (imm(m_value))
+ append(Move, imm(m_value), tmp(m_value));
+ else
+ append(Move, Arg::imm64(m_value->asInt64()), tmp(m_value));
return;
}
+ case ConstDouble: {
+ // We expect that the moveConstants() phase has run.
+ RELEASE_ASSERT(isIdentical(m_value->asDouble(), 0.0));
+ append(MoveZeroToDouble, tmp(m_value));
+ return;
+ }
+
case FramePointer: {
append(Move, Tmp(GPRInfo::callFrameRegister), tmp(m_value));
return;
@@ -1354,7 +1372,7 @@
case Upsilon: {
Value* value = m_value->child(0);
append(
- relaxedMoveForType(value->type()), immOrTmpForMove(value),
+ relaxedMoveForType(value->type()), immOrTmp(value),
tmp(m_value->as<UpsilonValue>()->phi()));
return;
}
@@ -1381,9 +1399,16 @@
case Return: {
Value* value = m_value->child(0);
- append(
- relaxedMoveForType(value->type()), immOrTmpForMove(value),
- Tmp(GPRInfo::returnValueGPR));
+ Air::Opcode move;
+ Tmp dest;
+ if (isInt(value->type())) {
+ move = Move;
+ dest = Tmp(GPRInfo::returnValueGPR);
+ } else {
+ move = MoveDouble;
+ dest = Tmp(FPRInfo::returnValueFPR);
+ }
+ append(move, immOrTmp(value), dest);
append(Ret);
return;
}
Added: trunk/Source/_javascript_Core/b3/B3MoveConstants.cpp (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3MoveConstants.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3MoveConstants.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2015 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 "B3MoveConstants.h"
+
+#if ENABLE(B3_JIT)
+
+#include "B3BasicBlockInlines.h"
+#include "B3InsertionSetInlines.h"
+#include "B3MemoryValue.h"
+#include "B3PhaseScope.h"
+#include "B3ProcedureInlines.h"
+#include "B3ValueInlines.h"
+#include "B3ValueKeyInlines.h"
+
+namespace JSC { namespace B3 {
+
+namespace {
+
+class MoveConstants {
+public:
+ MoveConstants(Procedure& proc)
+ : m_proc(proc)
+ , m_insertionSet(proc)
+ {
+ }
+
+ void run()
+ {
+ // Eventually this phase will do smart things. For now, it uses a super simple heuristic: it
+ // places large constants in the block that uses them, and makes sure that each block has
+ // only one materialization for each large constant.
+
+ // FIXME: Implement a better story for constants. At a minimum this should allow the B3
+ // client to specify important constants that always get hoisted. Also, the table used to
+ // hold double constants should have a pointer to it that is hoisted. If we wanted to be more
+ // aggressive, we could make constant materialization be a feature of Air: we could label
+ // some Tmps as being unmaterialized constants and have a late Air phase - post register
+ // allocation - that creates materializations of those constant Tmps by scavenging leftover
+ // registers.
+
+ // First we need to figure out which constants go into the data section. These are non-zero
+ // double constants.
+ for (Value* value : m_proc.values()) {
+ if (!needsMotion(value))
+ continue;
+ m_toRemove.append(value);
+ ValueKey key = value->key();
+ if (goesInTable(key))
+ m_constTable.add(key, m_constTable.size());
+ }
+
+ m_dataSection = static_cast<int64_t*>(m_proc.addDataSection(m_constTable.size() * sizeof(int64_t)));
+ for (auto& entry : m_constTable)
+ m_dataSection[entry.value] = entry.key.value();
+
+ for (BasicBlock* block : m_proc) {
+ m_constants.clear();
+
+ for (unsigned valueIndex = 0; valueIndex < block->size(); ++valueIndex) {
+ Value* value = block->at(valueIndex);
+ for (Value*& child : value->children()) {
+ if (!needsMotion(child))
+ continue;
+
+ child = materialize(valueIndex, child->key(), value->origin());
+ }
+ }
+
+ m_insertionSet.execute(block);
+ }
+
+ for (Value* toRemove : m_toRemove)
+ toRemove->replaceWithNop();
+ }
+
+private:
+ Value* materialize(unsigned valueIndex, const ValueKey& key, const Origin& origin)
+ {
+ if (Value* result = m_constants.get(key))
+ return result;
+
+ // Note that we deliberately don't do this in one add() because this is a recursive function
+ // that may rehash the map.
+
+ Value* result;
+ if (goesInTable(key)) {
+ Value* tableBase = materialize(
+ valueIndex,
+ ValueKey(
+ constPtrOpcode(), pointerType(),
+ static_cast<int64_t>(bitwise_cast<intptr_t>(m_dataSection))),
+ origin);
+ result = m_insertionSet.insert<MemoryValue>(
+ valueIndex, Load, key.type(), origin, tableBase,
+ sizeof(intptr_t) * m_constTable.get(key));
+ } else
+ result = m_insertionSet.insertValue(valueIndex, key.materialize(m_proc, origin));
+ m_constants.add(key, result);
+ return result;
+ }
+
+ bool goesInTable(const ValueKey& key)
+ {
+ return key.opcode() == ConstDouble && key != doubleZero();
+ }
+
+ bool needsMotion(const Value* value)
+ {
+ if (!value->isConstant())
+ return false;
+
+ // We currently assume that 32-bit int constants are always cheap to materialize.
+ // This is wrong for ARM. We need some abstract query like "isImmediate(int64_t)". On
+ // ARM64 this would take into account the way that ARM64 can encode large constants.
+ if (value->hasInt() && value->representableAs<int32_t>())
+ return false;
+
+ return true;
+ }
+
+ static ValueKey doubleZero()
+ {
+ return ValueKey(ConstDouble, Double, 0.0);
+ }
+
+ Procedure& m_proc;
+ Vector<Value*> m_toRemove;
+ HashMap<ValueKey, unsigned> m_constTable;
+ int64_t* m_dataSection;
+ HashMap<ValueKey, Value*> m_constants;
+ InsertionSet m_insertionSet;
+};
+
+} // anonymous namespace
+
+void moveConstants(Procedure& proc)
+{
+ PhaseScope phaseScope(proc, "moveConstants");
+ MoveConstants moveConstants(proc);
+ moveConstants.run();
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/B3MoveConstants.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3MoveConstants.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3MoveConstants.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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 B3MoveConstants_h
+#define B3MoveConstants_h
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+class Procedure;
+
+// Moves large constants around, with the goal of placing them in the optimal points in the program.
+
+void moveConstants(Procedure&);
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3MoveConstants_h
+
Added: trunk/Source/_javascript_Core/b3/B3OpaqueByproduct.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3OpaqueByproduct.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3OpaqueByproduct.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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 B3OpaqueByproduct_h
+#define B3OpaqueByproduct_h
+
+#if ENABLE(B3_JIT)
+
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace B3 {
+
+class OpaqueByproduct {
+ WTF_MAKE_NONCOPYABLE(OpaqueByproduct);
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ OpaqueByproduct() { }
+ virtual ~OpaqueByproduct() { }
+
+ virtual void dump(PrintStream&) const = 0;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3OpaqueByproduct_h
+
Added: trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.cpp (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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 "B3OpaqueByproducts.h"
+
+#if ENABLE(B3_JIT)
+
+namespace JSC { namespace B3 {
+
+OpaqueByproducts::OpaqueByproducts()
+{
+}
+
+OpaqueByproducts::~OpaqueByproducts()
+{
+}
+
+void OpaqueByproducts::add(std::unique_ptr<OpaqueByproduct> byproduct)
+{
+ m_byproducts.append(WTF::move(byproduct));
+}
+
+void OpaqueByproducts::dump(PrintStream& out) const
+{
+ out.print("Byproducts:\n");
+ if (m_byproducts.isEmpty()) {
+ out.print(" <empty>\n");
+ return;
+ }
+ for (auto& byproduct : m_byproducts)
+ out.print(" ", *byproduct, "\n");
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3OpaqueByproducts.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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 B3OpaqueByproducts_h
+#define B3OpaqueByproducts_h
+
+#if ENABLE(B3_JIT)
+
+#include "B3OpaqueByproduct.h"
+#include <memory>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace B3 {
+
+class OpaqueByproducts {
+ WTF_MAKE_NONCOPYABLE(OpaqueByproducts)
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ OpaqueByproducts();
+ ~OpaqueByproducts();
+
+ size_t count() const { return m_byproducts.size(); }
+
+ void add(std::unique_ptr<OpaqueByproduct>);
+
+ void dump(PrintStream&) const;
+
+private:
+ Vector<std::unique_ptr<OpaqueByproduct>> m_byproducts;
+};
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3OpaqueByproducts_h
+
Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Opcode.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -209,6 +209,13 @@
Optional<Opcode> invertedCompare(Opcode, Type);
+inline Opcode constPtrOpcode()
+{
+ if (is64Bit())
+ return Const64;
+ return Const32;
+}
+
} } // namespace JSC::B3
namespace WTF {
Modified: trunk/Source/_javascript_Core/b3/B3Procedure.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Procedure.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Procedure.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -31,12 +31,15 @@
#include "B3BasicBlockInlines.h"
#include "B3BasicBlockUtils.h"
#include "B3BlockWorklist.h"
+#include "B3DataSection.h"
+#include "B3OpaqueByproducts.h"
#include "B3ValueInlines.h"
namespace JSC { namespace B3 {
Procedure::Procedure()
: m_lastPhaseName("initial")
+ , m_byproducts(std::make_unique<OpaqueByproducts>())
{
}
@@ -107,6 +110,8 @@
{
for (BasicBlock* block : *this)
out.print(deepDump(block));
+ if (m_byproducts->count())
+ out.print(*m_byproducts);
}
Vector<BasicBlock*> Procedure::blocksInPreOrder()
@@ -126,6 +131,16 @@
m_values[value->index()] = nullptr;
}
+void* Procedure::addDataSection(size_t size)
+{
+ if (!size)
+ return nullptr;
+ std::unique_ptr<DataSection> dataSection = std::make_unique<DataSection>(size);
+ void* result = dataSection->data();
+ m_byproducts->add(WTF::move(dataSection));
+ return result;
+}
+
size_t Procedure::addValueIndex()
{
if (m_valueIndexFreeList.isEmpty()) {
Modified: trunk/Source/_javascript_Core/b3/B3Procedure.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Procedure.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Procedure.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -40,6 +40,7 @@
namespace JSC { namespace B3 {
class BasicBlock;
+class OpaqueByproducts;
class Value;
class Procedure {
@@ -201,6 +202,19 @@
const char* lastPhaseName() const { return m_lastPhaseName; }
+ void* addDataSection(size_t size);
+
+ OpaqueByproducts& byproducts() { return *m_byproducts; }
+
+ // Below are methods that make sense to call after you have generated code for the procedure.
+
+ // You have to call this method after calling generate(). The code generated by B3::generate()
+ // will require you to keep this object alive for as long as that code is runnable. Usually, this
+ // just keeps alive things like the double constant pool and switch lookup tables. If this sounds
+ // confusing, you should probably be using the B3::Compilation API to compile code. If you use
+ // that API, then you don't have to worry about this.
+ std::unique_ptr<OpaqueByproducts> takeByproducts() { return WTF::move(m_byproducts); }
+
private:
JS_EXPORT_PRIVATE size_t addValueIndex();
@@ -208,6 +222,7 @@
Vector<std::unique_ptr<Value>> m_values;
Vector<size_t> m_valueIndexFreeList;
const char* m_lastPhaseName;
+ std::unique_ptr<OpaqueByproducts> m_byproducts;
};
} } // namespace JSC::B3
Modified: trunk/Source/_javascript_Core/b3/B3Type.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Type.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Type.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -33,7 +33,7 @@
namespace JSC { namespace B3 {
-enum Type {
+enum Type : int8_t {
Void,
Int32,
Int64,
Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Value.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -36,6 +36,7 @@
#include "B3StackSlotValue.h"
#include "B3UpsilonValue.h"
#include "B3ValueInlines.h"
+#include "B3ValueKeyInlines.h"
#include <wtf/CommaPrinter.h>
#include <wtf/StringPrintStream.h>
@@ -356,6 +357,61 @@
return result;
}
+ValueKey Value::key() const
+{
+ switch (opcode()) {
+ case FramePointer:
+ return ValueKey(opcode(), type());
+ case Identity:
+ case SExt8:
+ case SExt16:
+ case SExt32:
+ case ZExt32:
+ case Trunc:
+ case FRound:
+ case IToD:
+ case DToI32:
+ case Check:
+ return ValueKey(opcode(), type(), child(0));
+ case Add:
+ case Sub:
+ case Mul:
+ case ChillDiv:
+ case Mod:
+ case BitAnd:
+ case BitOr:
+ case BitXor:
+ case Shl:
+ case SShr:
+ case ZShr:
+ case Equal:
+ case NotEqual:
+ case LessThan:
+ case GreaterThan:
+ case Above:
+ case Below:
+ case AboveEqual:
+ case BelowEqual:
+ case Div:
+ case CheckAdd:
+ case CheckSub:
+ case CheckMul:
+ return ValueKey(opcode(), type(), child(0), child(1));
+ case Const32:
+ return ValueKey(Const32, type(), static_cast<int64_t>(asInt32()));
+ case Const64:
+ return ValueKey(Const64, type(), asInt64());
+ case ConstDouble:
+ return ValueKey(ConstDouble, type(), asDouble());
+ case ArgumentReg:
+ return ValueKey(
+ ArgumentReg, type(),
+ static_cast<int64_t>(as<ArgumentRegValue>()->argumentReg().index()));
+ default:
+ return ValueKey();
+ }
+}
+
void Value::performSubstitution()
{
for (Value*& child : children()) {
Modified: trunk/Source/_javascript_Core/b3/B3Value.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/B3Value.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/B3Value.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -33,6 +33,7 @@
#include "B3Opcode.h"
#include "B3Origin.h"
#include "B3Type.h"
+#include "B3ValueKey.h"
#include <wtf/CommaPrinter.h>
#include <wtf/FastMalloc.h>
#include <wtf/Noncopyable.h>
@@ -167,9 +168,14 @@
TriState asTriState() const;
bool isLikeZero() const { return asTriState() == FalseTriState; }
bool isLikeNonZero() const { return asTriState() == TrueTriState; }
-
+
Effects effects() const;
+ // This returns a ValueKey that describes that this Value returns when it executes. Returns an
+ // empty ValueKey if this Value is impure. Note that an operation that returns Void could still
+ // have a non-empty ValueKey. This happens for example with Check operations.
+ ValueKey key() const;
+
// Makes sure that none of the children are Identity's. If a child points to Identity, this will
// repoint it at the Identity's child. For simplicity, this will follow arbitrarily long chains
// of Identity's.
Added: trunk/Source/_javascript_Core/b3/B3ValueKey.cpp (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3ValueKey.cpp (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 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 "B3ValueKey.h"
+
+#if ENABLE(B3_JIT)
+
+#include "B3ArgumentRegValue.h"
+#include "B3ProcedureInlines.h"
+#include "B3ValueInlines.h"
+#include "B3ValueKeyInlines.h"
+
+namespace JSC { namespace B3 {
+
+void ValueKey::dump(PrintStream& out) const
+{
+ out.print(m_type, " ", m_opcode, "(", u.indices[0], ", ", u.indices[1], ")");
+}
+
+Value* ValueKey::materialize(Procedure& proc, Origin origin) const
+{
+ switch (opcode()) {
+ case FramePointer:
+ return proc.add<Value>(opcode(), type(), origin);
+ case Identity:
+ case SExt8:
+ case SExt16:
+ case SExt32:
+ case ZExt32:
+ case Trunc:
+ case FRound:
+ case IToD:
+ case DToI32:
+ case Check:
+ return proc.add<Value>(opcode(), type(), origin, child(proc, 0));
+ case Add:
+ case Sub:
+ case Mul:
+ case ChillDiv:
+ case Mod:
+ case BitAnd:
+ case BitOr:
+ case BitXor:
+ case Shl:
+ case SShr:
+ case ZShr:
+ case Equal:
+ case NotEqual:
+ case LessThan:
+ case GreaterThan:
+ case Above:
+ case Below:
+ case AboveEqual:
+ case BelowEqual:
+ case Div:
+ return proc.add<Value>(opcode(), type(), origin, child(proc, 0), child(proc, 1));
+ case Const32:
+ return proc.add<Const32Value>(origin, static_cast<int32_t>(value()));
+ case Const64:
+ return proc.add<Const64Value>(origin, value());
+ case ConstDouble:
+ return proc.add<ConstDoubleValue>(origin, doubleValue());
+ case ArgumentReg:
+ return proc.add<ArgumentRegValue>(origin, Reg::fromIndex(static_cast<unsigned>(value())));
+ default:
+ return nullptr;
+ }
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
Added: trunk/Source/_javascript_Core/b3/B3ValueKey.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3ValueKey.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 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 B3ValueKey_h
+#define B3ValueKey_h
+
+#if ENABLE(B3_JIT)
+
+#include "B3HeapRange.h"
+#include "B3Opcode.h"
+#include "B3Origin.h"
+#include "B3Type.h"
+#include <wtf/HashTable.h>
+#include <wtf/Vector.h>
+
+namespace JSC { namespace B3 {
+
+class Procedure;
+class Value;
+
+// ValueKeys are useful for CSE. They abstractly describe the value that a Value returns when it
+// executes. Any Value that has the same ValueKey is guaranteed to return the same value, provided
+// that they return a non-empty ValueKey. Operations that have effects, or that can have their
+// behavior affected by other operations' effects, will return an empty ValueKey. You have to use
+// other mechanisms for doing CSE for impure operations.
+
+class ValueKey {
+public:
+ ValueKey()
+ {
+ }
+
+ ValueKey(Opcode opcode, Type type)
+ : m_opcode(opcode)
+ , m_type(type)
+ {
+ }
+
+ ValueKey(Opcode, Type, Value* child);
+
+ ValueKey(Opcode, Type, Value* left, Value* right);
+
+ ValueKey(Opcode opcode, Type type, int64_t value)
+ : m_opcode(opcode)
+ , m_type(type)
+ {
+ u.value = value;
+ }
+
+ ValueKey(Opcode opcode, Type type, double value)
+ : m_opcode(opcode)
+ , m_type(type)
+ {
+ u.doubleValue = value;
+ }
+
+ Opcode opcode() const { return m_opcode; }
+ Type type() const { return m_type; }
+ unsigned childIndex(unsigned index) const { return u.indices[index]; }
+ Value* child(Procedure&, unsigned index) const;
+ int64_t value() const { return u.value; }
+ double doubleValue() const { return u.doubleValue; }
+
+ bool operator==(const ValueKey& other) const
+ {
+ return m_opcode == other.m_opcode
+ && m_type == other.m_type
+ && u == other.u;
+ }
+
+ bool operator!=(const ValueKey& other) const
+ {
+ return !(*this == other);
+ }
+
+ unsigned hash() const
+ {
+ return m_opcode + m_type + WTF::IntHash<int64_t>::hash(u.value);
+ }
+
+ explicit operator bool() const { return *this != ValueKey(); }
+
+ void dump(PrintStream&) const;
+
+ bool canMaterialize() const
+ {
+ if (!*this)
+ return false;
+ switch (opcode()) {
+ case CheckAdd:
+ case CheckSub:
+ case CheckMul:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ // Attempts to materialize the Value for this ValueKey. May return nullptr if the value cannot
+ // be materialized. This happens for CheckAdd and friends. You can use canMaterialize() to check
+ // if your key is materializable.
+ Value* materialize(Procedure&, Origin) const;
+
+ ValueKey(WTF::HashTableDeletedValueType)
+ : m_type { Int32 }
+ {
+ }
+
+ bool isHashTableDeletedValue() const
+ {
+ return *this == ValueKey(WTF::HashTableDeletedValue);
+ }
+
+private:
+ Opcode m_opcode { Oops };
+ Type m_type { Void };
+ union U {
+ unsigned indices[2];
+ int64_t value;
+ double doubleValue;
+
+ U()
+ {
+ value = 0;
+ }
+
+ bool operator==(const U& other) const
+ {
+ return value == other.value;
+ }
+ } u;
+};
+
+struct ValueKeyHash {
+ static unsigned hash(const ValueKey& key) { return key.hash(); }
+ static bool equal(const ValueKey& a, const ValueKey& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::B3
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::B3::ValueKey> {
+ typedef JSC::B3::ValueKeyHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::B3::ValueKey> : public SimpleClassHashTraits<JSC::B3::ValueKey> {
+ static const bool emptyValueIsZero = false;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3ValueKey_h
+
Added: trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h (0 => 192183)
--- trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h (rev 0)
+++ trunk/Source/_javascript_Core/b3/B3ValueKeyInlines.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 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 B3ValueKeyInlines_h
+#define B3ValueKeyInlines_h
+
+#if ENABLE(B3_JIT)
+
+#include "B3Procedure.h"
+#include "B3Value.h"
+#include "B3ValueKey.h"
+
+namespace JSC { namespace B3 {
+
+inline ValueKey::ValueKey(Opcode opcode, Type type, Value* child)
+ : m_opcode(opcode)
+ , m_type(type)
+{
+ u.indices[0] = child->index();
+}
+
+inline ValueKey::ValueKey(Opcode opcode, Type type, Value* left, Value* right)
+ : m_opcode(opcode)
+ , m_type(type)
+{
+ u.indices[0] = left->index();
+ u.indices[1] = right->index();
+}
+
+inline Value* ValueKey::child(Procedure& proc, unsigned index) const
+{
+ return proc.values()[index];
+}
+
+} } // namespace JSC::B3
+
+#endif // ENABLE(B3_JIT)
+
+#endif // B3ValueKeyInlines_h
+
Modified: trunk/Source/_javascript_Core/b3/air/AirCode.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/air/AirCode.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/air/AirCode.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -34,8 +34,9 @@
namespace JSC { namespace B3 { namespace Air {
-Code::Code()
- : m_lastPhaseName("initial")
+Code::Code(Procedure& proc)
+ : m_proc(proc)
+ , m_lastPhaseName("initial")
{
}
Modified: trunk/Source/_javascript_Core/b3/air/AirCode.h (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/air/AirCode.h 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/air/AirCode.h 2015-11-10 00:01:24 UTC (rev 192183)
@@ -50,9 +50,11 @@
WTF_MAKE_NONCOPYABLE(Code);
WTF_MAKE_FAST_ALLOCATED;
public:
- Code();
+ Code(Procedure&);
~Code();
+ Procedure& proc() { return m_proc; }
+
BasicBlock* addBlock(double frequency = PNaN);
StackSlot* addStackSlot(unsigned byteSize, StackSlotKind, StackSlotValue* = nullptr);
@@ -293,6 +295,7 @@
const char* lastPhaseName() const { return m_lastPhaseName; }
private:
+ Procedure& m_proc; // Some meta-data, like byproducts, is stored in the Procedure.
Vector<std::unique_ptr<StackSlot>> m_stackSlots;
Vector<std::unique_ptr<BasicBlock>> m_blocks;
Vector<std::unique_ptr<Special>> m_specials;
Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes 2015-11-10 00:01:24 UTC (rev 192183)
@@ -191,6 +191,9 @@
Tmp, Addr as storeDouble
Tmp, Index as storeDouble
+MoveZeroToDouble D:F
+ Tmp
+
Move64ToDouble U:G, D:F
Tmp, Tmp
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (192182 => 192183)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2015-11-09 22:47:12 UTC (rev 192182)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2015-11-10 00:01:24 UTC (rev 192183)
@@ -27,10 +27,10 @@
#include "B3ArgumentRegValue.h"
#include "B3BasicBlockInlines.h"
+#include "B3Compilation.h"
#include "B3Const32Value.h"
#include "B3ConstPtrValue.h"
#include "B3ControlValue.h"
-#include "B3Generate.h"
#include "B3MemoryValue.h"
#include "B3Procedure.h"
#include "B3StackSlotValue.h"
@@ -67,16 +67,13 @@
VM* vm;
-MacroAssemblerCodeRef compile(Procedure& procedure)
+std::unique_ptr<Compilation> compile(Procedure& procedure)
{
- CCallHelpers jit(vm);
- generate(procedure, jit);
- LinkBuffer linkBuffer(*vm, jit, nullptr);
- return FINALIZE_CODE(linkBuffer, ("testb3"));
+ return std::make_unique<Compilation>(*vm, procedure);
}
template<typename T, typename... Arguments>
-T invoke(const MacroAssemblerCodeRef& code, Arguments... arguments)
+T invoke(const Compilation& code, Arguments... arguments)
{
T (*function)(Arguments...) = bitwise_cast<T(*)(Arguments...)>(code.code().executableAddress());
return function(arguments...);
@@ -85,7 +82,7 @@
template<typename T, typename... Arguments>
T compileAndRun(Procedure& procedure, Arguments... arguments)
{
- return invoke<T>(compile(procedure), arguments...);
+ return invoke<T>(*compile(procedure), arguments...);
}
void test42()
@@ -1833,8 +1830,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchPtr()
@@ -1858,8 +1855,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, static_cast<intptr_t>(42)) == 1);
- CHECK(invoke<int>(code, static_cast<intptr_t>(0)) == 0);
+ CHECK(invoke<int>(*code, static_cast<intptr_t>(42)) == 1);
+ CHECK(invoke<int>(*code, static_cast<intptr_t>(0)) == 0);
}
void testDiamond()
@@ -1891,8 +1888,8 @@
done->appendNew<ControlValue>(proc, Return, Origin(), phi);
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchNotEqual()
@@ -1921,8 +1918,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchNotEqualCommute()
@@ -1951,8 +1948,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchNotEqualNotEqual()
@@ -1984,8 +1981,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchEqual()
@@ -2014,8 +2011,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 1));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchEqualEqual()
@@ -2047,8 +2044,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 0));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchEqualCommute()
@@ -2077,8 +2074,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 1));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchEqualEqual1()
@@ -2110,8 +2107,8 @@
elseCase->appendNew<Const32Value>(proc, Origin(), 1));
auto code = compile(proc);
- CHECK(invoke<int>(code, 42) == 1);
- CHECK(invoke<int>(code, 0) == 0);
+ CHECK(invoke<int>(*code, 42) == 1);
+ CHECK(invoke<int>(*code, 0) == 0);
}
void testBranchFold(int value)
@@ -2397,10 +2394,10 @@
root->appendNew<ControlValue>(
proc, Return, Origin(), root->appendNew<Const32Value>(proc, Origin(), 0));
- MacroAssemblerCodeRef code = compile(proc);
+ auto code = compile(proc);
- CHECK(invoke<int>(code, 0) == 0);
- CHECK(invoke<int>(code, 1) == 42);
+ CHECK(invoke<int>(*code, 0) == 0);
+ CHECK(invoke<int>(*code, 1) == 42);
}
template<typename LeftFunctor, typename RightFunctor>
@@ -2650,6 +2647,17 @@
variants(-left, -right);
}
+void testReturnDouble(double value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<ConstDoubleValue>(proc, Origin(), value));
+
+ CHECK(isIdentical(compileAndRun<double>(proc), value));
+}
+
#define RUN(test) do { \
if (!shouldRun(#test)) \
break; \
@@ -3114,6 +3122,10 @@
RUN(testLoad<uint16_t>(Load16Z, 1000000000));
RUN(testLoad<uint16_t>(Load16Z, -1000000000));
+ RUN(testReturnDouble(0.0));
+ RUN(testReturnDouble(-0.0));
+ RUN(testReturnDouble(42.5));
+
if (tasks.isEmpty())
usage();