Title: [192183] trunk/Source/_javascript_Core
Revision
192183
Author
fpi...@apple.com
Date
2015-11-09 16:01:24 -0800 (Mon, 09 Nov 2015)

Log Message

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):

Modified Paths

Added Paths

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();
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to