<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[244309] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/244309">244309</a></dd>
<dt>Author</dt> <dd>rmorisset@apple.com</dd>
<dt>Date</dt> <dd>2019-04-15 16:53:23 -0700 (Mon, 15 Apr 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>B3::Value should have different kinds of adjacency lists
https://bugs.webkit.org/show_bug.cgi?id=196091

Reviewed by Filip Pizlo.

The key idea of this optimization is to replace the Vector<Value*, 3> m_children in B3::Value (40 bytes on 64-bits platform) by one of the following:
- Nothing (0 bytes)
- 1 Value* (8 bytes)
- 2 Value* (16 bytes)
- 3 Value* (24 bytes)
- A Vector<Value*, 3>
after the end of the Value object, depending on the kind of the Value.
So for example, when allocating an Add, we would allocate an extra 16 bytes into which to store 2 Values.
This would halve the memory consumption of Const64/Const32/Nop/Identity and a bunch more kinds of values, and reduce by a more moderate amount the memory consumption of the rest of non-varargs values (e.g. Add would go from 72 to 48 bytes).

A few implementation points:
- Even if there is no children, we must remember to allocate at least enough space for replaceWithIdentity to work later. It needs sizeof(Value) (for the object itself) + sizeof(Value*) (for the pointer to its child)
- We must make sure to destroy the vector whenever we destroy a Value which is VarArgs
- We must remember how many elements there are in the case where we did not allocate a Vector. We cannot do it purely by relying on the kind, both for speed reasons and because Return can have either 0 or 1 argument in B3
  Thankfully, we have an extra byte of padding to use in the middle of B3::Value
- In order to support clone(), we must have a separate version of allocate, which extracts the opcode from the to-be-cloned object instead of from the call to the constructor
- Speaking of which, we need a special templated function opcodeFromConstructor, because some of the constructors of subclasses of Value don't take an explicit Opcode as argument, typically because they match a single one.
- To maximize performance, we provide specialized versions of child/lastChild/numChildren/children in the subclasses of Value, skipping checks when the actual type of the Value is already known.
  This is done through the B3_SPECIALIZE_VALUE_FOR_... defined at the bottom of B3Value.h
- In the constructors of Value, we convert all extra children arguments to Value* eagerly. It is not required for correctness (they will be converted when put into a Vector<Value*> or a Value* in the end), but it helps limit an explosion in the number of template instantiations.
- I moved DeepValueDump::dump from the .h to the .cpp, as there is no good reason to inline it, and recompiling JSC is already slow enough

* JavaScriptCore.xcodeproj/project.pbxproj:
* b3/B3ArgumentRegValue.cpp:
(JSC::B3::ArgumentRegValue::cloneImpl const): Deleted.
* b3/B3ArgumentRegValue.h:
* b3/B3AtomicValue.cpp:
(JSC::B3::AtomicValue::AtomicValue):
(JSC::B3::AtomicValue::cloneImpl const): Deleted.
* b3/B3AtomicValue.h:
* b3/B3BasicBlock.h:
* b3/B3BasicBlockInlines.h:
(JSC::B3::BasicBlock::appendNewNonTerminal): Deleted.
* b3/B3CCallValue.cpp:
(JSC::B3::CCallValue::appendArgs):
(JSC::B3::CCallValue::cloneImpl const): Deleted.
* b3/B3CCallValue.h:
* b3/B3CheckValue.cpp:
(JSC::B3::CheckValue::cloneImpl const): Deleted.
* b3/B3CheckValue.h:
* b3/B3Const32Value.cpp:
(JSC::B3::Const32Value::cloneImpl const): Deleted.
* b3/B3Const32Value.h:
* b3/B3Const64Value.cpp:
(JSC::B3::Const64Value::cloneImpl const): Deleted.
* b3/B3Const64Value.h:
* b3/B3ConstDoubleValue.cpp:
(JSC::B3::ConstDoubleValue::cloneImpl const): Deleted.
* b3/B3ConstDoubleValue.h:
* b3/B3ConstFloatValue.cpp:
(JSC::B3::ConstFloatValue::cloneImpl const): Deleted.
* b3/B3ConstFloatValue.h:
* b3/B3ConstPtrValue.h:
(JSC::B3::ConstPtrValue::opcodeFromConstructor):
* b3/B3FenceValue.cpp:
(JSC::B3::FenceValue::FenceValue):
(JSC::B3::FenceValue::cloneImpl const): Deleted.
* b3/B3FenceValue.h:
* b3/B3MemoryValue.cpp:
(JSC::B3::MemoryValue::MemoryValue):
(JSC::B3::MemoryValue::cloneImpl const): Deleted.
* b3/B3MemoryValue.h:
* b3/B3MoveConstants.cpp:
* b3/B3PatchpointValue.cpp:
(JSC::B3::PatchpointValue::cloneImpl const): Deleted.
* b3/B3PatchpointValue.h:
(JSC::B3::PatchpointValue::opcodeFromConstructor):
* b3/B3Procedure.cpp:
* b3/B3Procedure.h:
* b3/B3ProcedureInlines.h:
(JSC::B3::Procedure::add):
* b3/B3SlotBaseValue.cpp:
(JSC::B3::SlotBaseValue::cloneImpl const): Deleted.
* b3/B3SlotBaseValue.h:
* b3/B3StackmapSpecial.cpp:
(JSC::B3::StackmapSpecial::forEachArgImpl):
(JSC::B3::StackmapSpecial::isValidImpl):
* b3/B3StackmapValue.cpp:
(JSC::B3::StackmapValue::append):
(JSC::B3::StackmapValue::StackmapValue):
* b3/B3StackmapValue.h:
* b3/B3SwitchValue.cpp:
(JSC::B3::SwitchValue::SwitchValue):
(JSC::B3::SwitchValue::cloneImpl const): Deleted.
* b3/B3SwitchValue.h:
(JSC::B3::SwitchValue::opcodeFromConstructor):
* b3/B3UpsilonValue.cpp:
(JSC::B3::UpsilonValue::cloneImpl const): Deleted.
* b3/B3UpsilonValue.h:
* b3/B3Value.cpp:
(JSC::B3::DeepValueDump::dump const):
(JSC::B3::Value::~Value):
(JSC::B3::Value::replaceWithIdentity):
(JSC::B3::Value::replaceWithNopIgnoringType):
(JSC::B3::Value::replaceWithPhi):
(JSC::B3::Value::replaceWithJump):
(JSC::B3::Value::replaceWithOops):
(JSC::B3::Value::replaceWith):
(JSC::B3::Value::invertedCompare const):
(JSC::B3::Value::returnsBool const):
(JSC::B3::Value::cloneImpl const): Deleted.
* b3/B3Value.h:
(JSC::B3::DeepValueDump::dump const): Deleted.
* b3/B3ValueInlines.h:
(JSC::B3::Value::adjacencyListOffset const):
(JSC::B3::Value::cloneImpl const):
* b3/B3VariableValue.cpp:
(JSC::B3::VariableValue::VariableValue):
(JSC::B3::VariableValue::cloneImpl const): Deleted.
* b3/B3VariableValue.h:
* b3/B3WasmAddressValue.cpp:
(JSC::B3::WasmAddressValue::WasmAddressValue):
(JSC::B3::WasmAddressValue::cloneImpl const): Deleted.
* b3/B3WasmAddressValue.h:
* b3/B3WasmBoundsCheckValue.cpp:
(JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
(JSC::B3::WasmBoundsCheckValue::cloneImpl const): Deleted.
* b3/B3WasmBoundsCheckValue.h:
(JSC::B3::WasmBoundsCheckValue::accepts):
(JSC::B3::WasmBoundsCheckValue::opcodeFromConstructor):
* b3/testb3.cpp:
(JSC::B3::testCallFunctionWithHellaArguments):
(JSC::B3::testCallFunctionWithHellaArguments2):
(JSC::B3::testCallFunctionWithHellaArguments3):
(JSC::B3::testCallFunctionWithHellaDoubleArguments):
(JSC::B3::testCallFunctionWithHellaFloatArguments):
* ftl/FTLOutput.h:
(JSC::FTL::Output::call):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ArgumentRegValuecpp">trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ArgumentRegValueh">trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3AtomicValuecpp">trunk/Source/JavaScriptCore/b3/B3AtomicValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3AtomicValueh">trunk/Source/JavaScriptCore/b3/B3AtomicValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockh">trunk/Source/JavaScriptCore/b3/B3BasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3BasicBlockInlinesh">trunk/Source/JavaScriptCore/b3/B3BasicBlockInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CCallValuecpp">trunk/Source/JavaScriptCore/b3/B3CCallValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CCallValueh">trunk/Source/JavaScriptCore/b3/B3CCallValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CheckValuecpp">trunk/Source/JavaScriptCore/b3/B3CheckValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3CheckValueh">trunk/Source/JavaScriptCore/b3/B3CheckValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valuecpp">trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const32Valueh">trunk/Source/JavaScriptCore/b3/B3Const32Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const64Valuecpp">trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Const64Valueh">trunk/Source/JavaScriptCore/b3/B3Const64Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstDoubleValueh">trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstFloatValueh">trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ConstPtrValueh">trunk/Source/JavaScriptCore/b3/B3ConstPtrValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3FenceValuecpp">trunk/Source/JavaScriptCore/b3/B3FenceValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3FenceValueh">trunk/Source/JavaScriptCore/b3/B3FenceValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MemoryValuecpp">trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MemoryValueh">trunk/Source/JavaScriptCore/b3/B3MemoryValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3MoveConstantscpp">trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3PatchpointValuecpp">trunk/Source/JavaScriptCore/b3/B3PatchpointValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3PatchpointValueh">trunk/Source/JavaScriptCore/b3/B3PatchpointValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedurecpp">trunk/Source/JavaScriptCore/b3/B3Procedure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Procedureh">trunk/Source/JavaScriptCore/b3/B3Procedure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ProcedureInlinesh">trunk/Source/JavaScriptCore/b3/B3ProcedureInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3SlotBaseValuecpp">trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3SlotBaseValueh">trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3StackmapSpecialcpp">trunk/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3StackmapValuecpp">trunk/Source/JavaScriptCore/b3/B3StackmapValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3StackmapValueh">trunk/Source/JavaScriptCore/b3/B3StackmapValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3SwitchValuecpp">trunk/Source/JavaScriptCore/b3/B3SwitchValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3SwitchValueh">trunk/Source/JavaScriptCore/b3/B3SwitchValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3UpsilonValuecpp">trunk/Source/JavaScriptCore/b3/B3UpsilonValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3UpsilonValueh">trunk/Source/JavaScriptCore/b3/B3UpsilonValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Valuecpp">trunk/Source/JavaScriptCore/b3/B3Value.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3Valueh">trunk/Source/JavaScriptCore/b3/B3Value.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3ValueInlinesh">trunk/Source/JavaScriptCore/b3/B3ValueInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3VariableValuecpp">trunk/Source/JavaScriptCore/b3/B3VariableValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3VariableValueh">trunk/Source/JavaScriptCore/b3/B3VariableValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3WasmAddressValuecpp">trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3WasmAddressValueh">trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3WasmBoundsCheckValuecpp">trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3B3WasmBoundsCheckValueh">trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreb3testb3cpp">trunk/Source/JavaScriptCore/b3/testb3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOutputh">trunk/Source/JavaScriptCore/ftl/FTLOutput.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/ChangeLog       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -1,3 +1,139 @@
</span><ins>+2019-04-15  Robin Morisset  <rmorisset@apple.com>
+
+        B3::Value should have different kinds of adjacency lists
+        https://bugs.webkit.org/show_bug.cgi?id=196091
+
+        Reviewed by Filip Pizlo.
+
+        The key idea of this optimization is to replace the Vector<Value*, 3> m_children in B3::Value (40 bytes on 64-bits platform) by one of the following:
+        - Nothing (0 bytes)
+        - 1 Value* (8 bytes)
+        - 2 Value* (16 bytes)
+        - 3 Value* (24 bytes)
+        - A Vector<Value*, 3>
+        after the end of the Value object, depending on the kind of the Value.
+        So for example, when allocating an Add, we would allocate an extra 16 bytes into which to store 2 Values.
+        This would halve the memory consumption of Const64/Const32/Nop/Identity and a bunch more kinds of values, and reduce by a more moderate amount the memory consumption of the rest of non-varargs values (e.g. Add would go from 72 to 48 bytes).
+
+        A few implementation points:
+        - Even if there is no children, we must remember to allocate at least enough space for replaceWithIdentity to work later. It needs sizeof(Value) (for the object itself) + sizeof(Value*) (for the pointer to its child)
+        - We must make sure to destroy the vector whenever we destroy a Value which is VarArgs
+        - We must remember how many elements there are in the case where we did not allocate a Vector. We cannot do it purely by relying on the kind, both for speed reasons and because Return can have either 0 or 1 argument in B3
+          Thankfully, we have an extra byte of padding to use in the middle of B3::Value
+        - In order to support clone(), we must have a separate version of allocate, which extracts the opcode from the to-be-cloned object instead of from the call to the constructor
+        - Speaking of which, we need a special templated function opcodeFromConstructor, because some of the constructors of subclasses of Value don't take an explicit Opcode as argument, typically because they match a single one.
+        - To maximize performance, we provide specialized versions of child/lastChild/numChildren/children in the subclasses of Value, skipping checks when the actual type of the Value is already known.
+          This is done through the B3_SPECIALIZE_VALUE_FOR_... defined at the bottom of B3Value.h
+        - In the constructors of Value, we convert all extra children arguments to Value* eagerly. It is not required for correctness (they will be converted when put into a Vector<Value*> or a Value* in the end), but it helps limit an explosion in the number of template instantiations.
+        - I moved DeepValueDump::dump from the .h to the .cpp, as there is no good reason to inline it, and recompiling JSC is already slow enough
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * b3/B3ArgumentRegValue.cpp:
+        (JSC::B3::ArgumentRegValue::cloneImpl const): Deleted.
+        * b3/B3ArgumentRegValue.h:
+        * b3/B3AtomicValue.cpp:
+        (JSC::B3::AtomicValue::AtomicValue):
+        (JSC::B3::AtomicValue::cloneImpl const): Deleted.
+        * b3/B3AtomicValue.h:
+        * b3/B3BasicBlock.h:
+        * b3/B3BasicBlockInlines.h:
+        (JSC::B3::BasicBlock::appendNewNonTerminal): Deleted.
+        * b3/B3CCallValue.cpp:
+        (JSC::B3::CCallValue::appendArgs):
+        (JSC::B3::CCallValue::cloneImpl const): Deleted.
+        * b3/B3CCallValue.h:
+        * b3/B3CheckValue.cpp:
+        (JSC::B3::CheckValue::cloneImpl const): Deleted.
+        * b3/B3CheckValue.h:
+        * b3/B3Const32Value.cpp:
+        (JSC::B3::Const32Value::cloneImpl const): Deleted.
+        * b3/B3Const32Value.h:
+        * b3/B3Const64Value.cpp:
+        (JSC::B3::Const64Value::cloneImpl const): Deleted.
+        * b3/B3Const64Value.h:
+        * b3/B3ConstDoubleValue.cpp:
+        (JSC::B3::ConstDoubleValue::cloneImpl const): Deleted.
+        * b3/B3ConstDoubleValue.h:
+        * b3/B3ConstFloatValue.cpp:
+        (JSC::B3::ConstFloatValue::cloneImpl const): Deleted.
+        * b3/B3ConstFloatValue.h:
+        * b3/B3ConstPtrValue.h:
+        (JSC::B3::ConstPtrValue::opcodeFromConstructor):
+        * b3/B3FenceValue.cpp:
+        (JSC::B3::FenceValue::FenceValue):
+        (JSC::B3::FenceValue::cloneImpl const): Deleted.
+        * b3/B3FenceValue.h:
+        * b3/B3MemoryValue.cpp:
+        (JSC::B3::MemoryValue::MemoryValue):
+        (JSC::B3::MemoryValue::cloneImpl const): Deleted.
+        * b3/B3MemoryValue.h:
+        * b3/B3MoveConstants.cpp:
+        * b3/B3PatchpointValue.cpp:
+        (JSC::B3::PatchpointValue::cloneImpl const): Deleted.
+        * b3/B3PatchpointValue.h:
+        (JSC::B3::PatchpointValue::opcodeFromConstructor):
+        * b3/B3Procedure.cpp:
+        * b3/B3Procedure.h:
+        * b3/B3ProcedureInlines.h:
+        (JSC::B3::Procedure::add):
+        * b3/B3SlotBaseValue.cpp:
+        (JSC::B3::SlotBaseValue::cloneImpl const): Deleted.
+        * b3/B3SlotBaseValue.h:
+        * b3/B3StackmapSpecial.cpp:
+        (JSC::B3::StackmapSpecial::forEachArgImpl):
+        (JSC::B3::StackmapSpecial::isValidImpl):
+        * b3/B3StackmapValue.cpp:
+        (JSC::B3::StackmapValue::append):
+        (JSC::B3::StackmapValue::StackmapValue):
+        * b3/B3StackmapValue.h:
+        * b3/B3SwitchValue.cpp:
+        (JSC::B3::SwitchValue::SwitchValue):
+        (JSC::B3::SwitchValue::cloneImpl const): Deleted.
+        * b3/B3SwitchValue.h:
+        (JSC::B3::SwitchValue::opcodeFromConstructor):
+        * b3/B3UpsilonValue.cpp:
+        (JSC::B3::UpsilonValue::cloneImpl const): Deleted.
+        * b3/B3UpsilonValue.h:
+        * b3/B3Value.cpp:
+        (JSC::B3::DeepValueDump::dump const):
+        (JSC::B3::Value::~Value):
+        (JSC::B3::Value::replaceWithIdentity):
+        (JSC::B3::Value::replaceWithNopIgnoringType):
+        (JSC::B3::Value::replaceWithPhi):
+        (JSC::B3::Value::replaceWithJump):
+        (JSC::B3::Value::replaceWithOops):
+        (JSC::B3::Value::replaceWith):
+        (JSC::B3::Value::invertedCompare const):
+        (JSC::B3::Value::returnsBool const):
+        (JSC::B3::Value::cloneImpl const): Deleted.
+        * b3/B3Value.h:
+        (JSC::B3::DeepValueDump::dump const): Deleted.
+        * b3/B3ValueInlines.h:
+        (JSC::B3::Value::adjacencyListOffset const):
+        (JSC::B3::Value::cloneImpl const):
+        * b3/B3VariableValue.cpp:
+        (JSC::B3::VariableValue::VariableValue):
+        (JSC::B3::VariableValue::cloneImpl const): Deleted.
+        * b3/B3VariableValue.h:
+        * b3/B3WasmAddressValue.cpp:
+        (JSC::B3::WasmAddressValue::WasmAddressValue):
+        (JSC::B3::WasmAddressValue::cloneImpl const): Deleted.
+        * b3/B3WasmAddressValue.h:
+        * b3/B3WasmBoundsCheckValue.cpp:
+        (JSC::B3::WasmBoundsCheckValue::WasmBoundsCheckValue):
+        (JSC::B3::WasmBoundsCheckValue::cloneImpl const): Deleted.
+        * b3/B3WasmBoundsCheckValue.h:
+        (JSC::B3::WasmBoundsCheckValue::accepts):
+        (JSC::B3::WasmBoundsCheckValue::opcodeFromConstructor):
+        * b3/testb3.cpp:
+        (JSC::B3::testCallFunctionWithHellaArguments):
+        (JSC::B3::testCallFunctionWithHellaArguments2):
+        (JSC::B3::testCallFunctionWithHellaArguments3):
+        (JSC::B3::testCallFunctionWithHellaDoubleArguments):
+        (JSC::B3::testCallFunctionWithHellaFloatArguments):
+        * ftl/FTLOutput.h:
+        (JSC::FTL::Output::call):
+
</ins><span class="cx"> 2019-04-15  Tadeu Zagallo  <tzagallo@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Bytecode cache should not encode the SourceProvider for UnlinkedFunctionExecutable's classSource
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -669,7 +669,6 @@
</span><span class="cx">          0FEC85401BDACDAC0080FF74 /* B3UseCounts.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84F61BDACDAC0080FF74 /* B3UseCounts.h */; };
</span><span class="cx">          0FEC85421BDACDAC0080FF74 /* B3Validate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84F81BDACDAC0080FF74 /* B3Validate.h */; };
</span><span class="cx">          0FEC85441BDACDAC0080FF74 /* B3Value.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FA1BDACDAC0080FF74 /* B3Value.h */; };
</span><del>-               0FEC85451BDACDAC0080FF74 /* B3ValueInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */; };
</del><span class="cx">           0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FD1BDACDAC0080FF74 /* B3ValueRep.h */; };
</span><span class="cx">          0FEC856E1BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC85491BDACDC70080FF74 /* AirAllocateStackByGraphColoring.h */; };
</span><span class="cx">          0FEC85701BDACDC70080FF74 /* AirArg.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC854B1BDACDC70080FF74 /* AirArg.h */; };
</span><span class="lines">@@ -857,6 +856,8 @@
</span><span class="cx">          2AF7382D18BBBF92008A5A37 /* StructureIDTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AF7382B18BBBF92008A5A37 /* StructureIDTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          2D342F36F7244096804ADB24 /* SourceOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 425BA1337E4344E1B269A671 /* SourceOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          3395C70722555F6D00BDBFAD /* B3EliminateDeadCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 3395C70522555F6D00BDBFAD /* B3EliminateDeadCode.h */; };
</span><ins>+               33B2A54722653481005A0F79 /* B3ValueInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEC84FB1BDACDAC0080FF74 /* B3ValueInlines.h */; };
+               33B2A548226543BF005A0F79 /* FTLLowerDFGToB3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEA0A04170513DB00BB722C /* FTLLowerDFGToB3.cpp */; };
</ins><span class="cx">           371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; };
</span><span class="cx">          37C738D21EDB56E4003F2B0B /* ParseInt.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C738D11EDB5672003F2B0B /* ParseInt.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          412952771D2CF6BC00E78B89 /* builtins_generate_internals_wrapper_header.py in Headers */ = {isa = PBXBuildFile; fileRef = 412952731D2CF6AC00E78B89 /* builtins_generate_internals_wrapper_header.py */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -918,7 +919,6 @@
</span><span class="cx">          5333BBDB2110F7D2007618EC /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; };
</span><span class="cx">          5333BBDC2110F7D9007618EC /* DFGSpeculativeJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86EC9DC21328DF82002B2AD7 /* DFGSpeculativeJIT.cpp */; };
</span><span class="cx">          5333BBDD2110F7E1007618EC /* DFGSpeculativeJIT64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */; };
</span><del>-               5333BBDE2110FA3E007618EC /* FTLLowerDFGToB3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FEA0A04170513DB00BB722C /* FTLLowerDFGToB3.cpp */; };
</del><span class="cx">           5341FC721DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5341FC711DAC343C00E7E4D7 /* B3WasmBoundsCheckValue.h */; };
</span><span class="cx">          534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638701E70CF3D00F12AC1 /* JSRunLoopTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          534638751E70DDEC00F12AC1 /* PromiseDeferredTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 534638741E70DDEC00F12AC1 /* PromiseDeferredTimer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -8506,6 +8506,7 @@
</span><span class="cx">                          0F2C63BC1E63440C00C13839 /* AirBlockInsertionSet.h in Headers */,
</span><span class="cx">                          0FB3878E1BFBC44D00E3AB1E /* AirBlockWorklist.h in Headers */,
</span><span class="cx">                          0F79C7CA1E74C93B00EB34D1 /* AirBreakCriticalEdges.h in Headers */,
</span><ins>+                               33B2A54722653481005A0F79 /* B3ValueInlines.h in Headers */,
</ins><span class="cx">                           0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
</span><span class="cx">                          0FEC85741BDACDC70080FF74 /* AirCCallSpecial.h in Headers */,
</span><span class="cx">                          0FF4B4C71E8893C500DBBE86 /* AirCFG.h in Headers */,
</span><span class="lines">@@ -8698,7 +8699,6 @@
</span><span class="cx">                          0FEC85401BDACDAC0080FF74 /* B3UseCounts.h in Headers */,
</span><span class="cx">                          0FEC85421BDACDAC0080FF74 /* B3Validate.h in Headers */,
</span><span class="cx">                          0FEC85441BDACDAC0080FF74 /* B3Value.h in Headers */,
</span><del>-                               0FEC85451BDACDAC0080FF74 /* B3ValueInlines.h in Headers */,
</del><span class="cx">                           0F338E151BF0276C0013C88F /* B3ValueKey.h in Headers */,
</span><span class="cx">                          0F338E161BF0276C0013C88F /* B3ValueKeyInlines.h in Headers */,
</span><span class="cx">                          0FEC85471BDACDAC0080FF74 /* B3ValueRep.h in Headers */,
</span><span class="lines">@@ -10703,7 +10703,6 @@
</span><span class="cx">                          5333BBDC2110F7D9007618EC /* DFGSpeculativeJIT.cpp in Sources */,
</span><span class="cx">                          5333BBDB2110F7D2007618EC /* DFGSpeculativeJIT32_64.cpp in Sources */,
</span><span class="cx">                          5333BBDD2110F7E1007618EC /* DFGSpeculativeJIT64.cpp in Sources */,
</span><del>-                               5333BBDE2110FA3E007618EC /* FTLLowerDFGToB3.cpp in Sources */,
</del><span class="cx">                           536B319E1F735F160037FC33 /* LowLevelInterpreter.cpp in Sources */,
</span><span class="cx">                          0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
</span><span class="cx">                          0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,
</span><span class="lines">@@ -10837,6 +10836,7 @@
</span><span class="cx">                          536B310C1F71C5990037FC33 /* UnifiedSource119.cpp in Sources */,
</span><span class="cx">                          536B31261F71C5990037FC33 /* UnifiedSource120.cpp in Sources */,
</span><span class="cx">                          536B312D1F71C5990037FC33 /* UnifiedSource121.cpp in Sources */,
</span><ins>+                               33B2A548226543BF005A0F79 /* FTLLowerDFGToB3.cpp in Sources */,
</ins><span class="cx">                           536B31251F71C5990037FC33 /* UnifiedSource122.cpp in Sources */,
</span><span class="cx">                          536B311E1F71C5990037FC33 /* UnifiedSource123.cpp in Sources */,
</span><span class="cx">                          536B31141F71C5990037FC33 /* UnifiedSource124.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ArgumentRegValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.cpp    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.cpp       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -39,11 +39,6 @@
</span><span class="cx">     out.print(comma, m_reg);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* ArgumentRegValue::cloneImpl() const
-{
-    return new ArgumentRegValue(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ArgumentRegValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h      2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ArgumentRegValue.h 2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -40,16 +40,19 @@
</span><span class="cx"> 
</span><span class="cx">     Reg argumentReg() const { return m_reg; }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
+    
+    static Opcode opcodeFromConstructor(Origin, Reg) { return ArgumentReg; }
</ins><span class="cx"> 
</span><span class="cx">     ArgumentRegValue(Origin origin, Reg reg)
</span><del>-        : Value(CheckedOpcode, ArgumentReg, reg.isGPR() ? pointerType() : Double, origin)
</del><ins>+        : Value(CheckedOpcode, ArgumentReg, reg.isGPR() ? pointerType() : Double, Zero, origin)
</ins><span class="cx">         , m_reg(reg)
</span><span class="cx">     {
</span><span class="cx">         ASSERT(reg.isSet());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3AtomicValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3AtomicValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3AtomicValue.cpp 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3AtomicValue.cpp    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -41,13 +41,8 @@
</span><span class="cx">     MemoryValue::dumpMeta(comma, out);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* AtomicValue::cloneImpl() const
-{
-    return new AtomicValue(*this);
-}
-
</del><span class="cx"> AtomicValue::AtomicValue(AtomicValue::AtomicValueRMW, Kind kind, Origin origin, Width width, Value* operand, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
</span><del>-    : MemoryValue(CheckedOpcode, kind, operand->type(), origin, offset, range, fenceRange, operand, pointer)
</del><ins>+    : MemoryValue(CheckedOpcode, kind, operand->type(), Two, origin, offset, range, fenceRange, operand, pointer)
</ins><span class="cx">     , m_width(width)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(bestType(GP, accessWidth()) == accessType());
</span><span class="lines">@@ -66,7 +61,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> AtomicValue::AtomicValue(AtomicValue::AtomicValueCAS, Kind kind, Origin origin, Width width, Value* expectedValue, Value* newValue, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
</span><del>-    : MemoryValue(CheckedOpcode, kind, kind.opcode() == AtomicWeakCAS ? Int32 : expectedValue->type(), origin, offset, range, fenceRange, expectedValue, newValue, pointer)
</del><ins>+    : MemoryValue(CheckedOpcode, kind, kind.opcode() == AtomicWeakCAS ? Int32 : expectedValue->type(), Three, origin, offset, range, fenceRange, expectedValue, newValue, pointer)
</ins><span class="cx">     , m_width(width)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(bestType(GP, accessWidth()) == accessType());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3AtomicValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3AtomicValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3AtomicValue.h   2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3AtomicValue.h      2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -44,14 +44,15 @@
</span><span class="cx">     Type accessType() const { return child(0)->type(); }
</span><span class="cx">     
</span><span class="cx">     Width accessWidth() const { return m_width; }
</span><ins>+
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
</ins><span class="cx">     
</span><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><del>-    
-    Value* cloneImpl() const override;
-    
</del><ins>+
</ins><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     enum AtomicValueRMW { AtomicValueRMWTag };
</span><span class="cx">     enum AtomicValueCAS { AtomicValueCASTag };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlock.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlock.h    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlock.h       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -84,8 +84,6 @@
</span><span class="cx"> 
</span><span class="cx">     template<typename ValueType, typename... Arguments>
</span><span class="cx">     ValueType* appendNew(Procedure&, Arguments...);
</span><del>-    template<typename ValueType, typename... Arguments>
-    ValueType* appendNewNonTerminal(Procedure&, Arguments...);
</del><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE Value* appendIntConstant(Procedure&, Origin, Type, int64_t value);
</span><span class="cx">     Value* appendIntConstant(Procedure&, Value* likeValue, int64_t value);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3BasicBlockInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3BasicBlockInlines.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3BasicBlockInlines.h     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3BasicBlockInlines.h        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -42,14 +42,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename ValueType, typename... Arguments>
</span><del>-ValueType* BasicBlock::appendNewNonTerminal(Procedure& procedure, Arguments... arguments)
-{
-    ValueType* result = procedure.add<ValueType>(arguments...);
-    appendNonTerminal(result);
-    return result;
-}
-
-template<typename ValueType, typename... Arguments>
</del><span class="cx"> ValueType* BasicBlock::replaceLastWithNew(Procedure& procedure, Arguments... arguments)
</span><span class="cx"> {
</span><span class="cx">     ValueType* result = procedure.add<ValueType>(arguments...);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CCallValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CCallValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CCallValue.cpp  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3CCallValue.cpp     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -34,9 +34,9 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* CCallValue::cloneImpl() const
</del><ins>+void CCallValue::appendArgs(const Vector<Value*>& args)
</ins><span class="cx"> {
</span><del>-    return new CCallValue(*this);
</del><ins>+    childrenVector().appendVector(args);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CCallValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CCallValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CCallValue.h    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3CCallValue.h       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -38,17 +38,23 @@
</span><span class="cx"> 
</span><span class="cx">     ~CCallValue();
</span><span class="cx"> 
</span><ins>+    void appendArgs(const Vector<Value*>&);
+    
</ins><span class="cx">     Effects effects;
</span><span class="cx"> 
</span><del>-protected:
-    Value* cloneImpl() const override;
-    
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_VARARGS_CHILDREN
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_VARARGS_CHILDREN
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     template<typename... Arguments>
</span><ins>+    static Opcode opcodeFromConstructor(Arguments...) { return CCall; }
+
+    template<typename... Arguments>
</ins><span class="cx">     CCallValue(Type type, Origin origin, Arguments... arguments)
</span><del>-        : Value(CheckedOpcode, CCall, type, origin, arguments...)
</del><ins>+        : Value(CheckedOpcode, CCall, type, VarArgs, origin, static_cast<Value*>(arguments)...)
</ins><span class="cx">         , effects(Effects::forCall())
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(numChildren() >= 1);
</span><span class="lines">@@ -56,7 +62,7 @@
</span><span class="cx"> 
</span><span class="cx">     template<typename... Arguments>
</span><span class="cx">     CCallValue(Type type, Origin origin, const Effects& effects, Arguments... arguments)
</span><del>-        : Value(CheckedOpcode, CCall, type, origin, arguments...)
</del><ins>+        : Value(CheckedOpcode, CCall, type, VarArgs, origin, static_cast<Value*>(arguments)...)
</ins><span class="cx">         , effects(effects)
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(numChildren() >= 1);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CheckValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CheckValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CheckValue.cpp  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3CheckValue.cpp     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -40,11 +40,6 @@
</span><span class="cx">     m_kind = CheckAdd;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* CheckValue::cloneImpl() const
-{
-    return new CheckValue(*this);
-}
-
</del><span class="cx"> // Use this form for CheckAdd, CheckSub, and CheckMul.
</span><span class="cx"> CheckValue::CheckValue(Kind kind, Origin origin, Value* left, Value* right)
</span><span class="cx">     : StackmapValue(CheckedOpcode, kind, left->type(), origin)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3CheckValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3CheckValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3CheckValue.h    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3CheckValue.h       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -50,11 +50,11 @@
</span><span class="cx"> 
</span><span class="cx">     void convertToAdd();
</span><span class="cx"> 
</span><del>-protected:
-    Value* cloneImpl() const override;
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_VARARGS_CHILDREN
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     // Use this form for CheckAdd, CheckSub, and CheckMul.
</span><span class="cx">     JS_EXPORT_PRIVATE CheckValue(Kind, Origin, Value* left, Value* right);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp        2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.cpp   2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -303,11 +303,6 @@
</span><span class="cx">     out.print(comma, m_value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* Const32Value::cloneImpl() const
-{
-    return new Const32Value(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const32Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const32Value.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const32Value.h  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Const32Value.h     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -75,20 +75,24 @@
</span><span class="cx">     TriState aboveEqualConstant(const Value* other) const override;
</span><span class="cx">     TriState belowEqualConstant(const Value* other) const override;
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
</del><ins>+    // Protected because of ConstPtrValue
+    static Opcode opcodeFromConstructor(Origin = Origin(), int32_t = 0) { return Const32; }
</ins><span class="cx"> 
</span><del>-    friend class Procedure;
-
</del><span class="cx">     Const32Value(Origin origin, int32_t value)
</span><del>-        : Value(CheckedOpcode, Const32, Int32, origin)
</del><ins>+        : Value(CheckedOpcode, Const32, Int32, Zero, origin)
</ins><span class="cx">         , m_value(value)
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    friend class Procedure;
+    friend class Value;
+
</ins><span class="cx">     int32_t m_value;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const64Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp        2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Const64Value.cpp   2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -303,11 +303,6 @@
</span><span class="cx">     out.print(comma, m_value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* Const64Value::cloneImpl() const
-{
-    return new Const64Value(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Const64Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Const64Value.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Const64Value.h  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Const64Value.h     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -75,20 +75,24 @@
</span><span class="cx">     TriState aboveEqualConstant(const Value* other) const override;
</span><span class="cx">     TriState belowEqualConstant(const Value* other) const override;
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
</del><ins>+    // Protected because of ConstPtrValue
+    static Opcode opcodeFromConstructor(Origin = Origin(), int64_t = 0) { return Const64; }
</ins><span class="cx"> 
</span><del>-    friend class Procedure;
-
</del><span class="cx">     Const64Value(Origin origin, int64_t value)
</span><del>-        : Value(CheckedOpcode, Const64, Int64, origin)
</del><ins>+        : Value(CheckedOpcode, Const64, Int64, Zero, origin)
</ins><span class="cx">         , m_value(value)
</span><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx"> private:
</span><ins>+    friend class Procedure;
+    friend class Value;
+
</ins><span class="cx">     int64_t m_value;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -197,11 +197,6 @@
</span><span class="cx">     out.printf("%le", m_value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* ConstDoubleValue::cloneImpl() const
-{
-    return new ConstDoubleValue(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstDoubleValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h      2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h 2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -64,16 +64,18 @@
</span><span class="cx">     TriState greaterEqualConstant(const Value* other) const override;
</span><span class="cx">     TriState equalOrUnorderedConstant(const Value* other) const override;
</span><span class="cx"> 
</span><del>-protected:
-    void dumpMeta(CommaPrinter&, PrintStream&) const override;
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
</ins><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    void dumpMeta(CommaPrinter&, PrintStream&) const override;
+
+    static Opcode opcodeFromConstructor(Origin, double) { return ConstDouble; }
+
</ins><span class="cx">     ConstDoubleValue(Origin origin, double value)
</span><del>-        : Value(CheckedOpcode, ConstDouble, Double, origin)
</del><ins>+        : Value(CheckedOpcode, ConstDouble, Double, Zero, origin)
</ins><span class="cx">         , m_value(value)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -189,11 +189,6 @@
</span><span class="cx">     out.printf("%le", m_value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* ConstFloatValue::cloneImpl() const
-{
-    return new ConstFloatValue(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstFloatValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -63,16 +63,18 @@
</span><span class="cx">     TriState greaterEqualConstant(const Value* other) const override;
</span><span class="cx">     TriState equalOrUnorderedConstant(const Value* other) const override;
</span><span class="cx"> 
</span><del>-protected:
-    void dumpMeta(CommaPrinter&, PrintStream&) const override;
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
</ins><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    void dumpMeta(CommaPrinter&, PrintStream&) const override;
+
+    static Opcode opcodeFromConstructor(Origin, float) { return ConstFloat; }
+
</ins><span class="cx">     ConstFloatValue(Origin origin, float value)
</span><del>-        : Value(CheckedOpcode, ConstFloat, Float, origin)
</del><ins>+        : Value(CheckedOpcode, ConstFloat, Float, Zero, origin)
</ins><span class="cx">         , m_value(value)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ConstPtrValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ConstPtrValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ConstPtrValue.h 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ConstPtrValue.h    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -51,13 +51,18 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     template<typename T>
</span><ins>+    static Opcode opcodeFromConstructor(Origin, T*) { return ConstPtrValueBase::opcodeFromConstructor(); }
+    template<typename T>
</ins><span class="cx">     ConstPtrValue(Origin origin, T* pointer)
</span><span class="cx">         : ConstPtrValueBase(origin, bitwise_cast<intptr_t>(pointer))
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     template<typename T>
</span><ins>+    static Opcode opcodeFromConstructor(Origin, T) { return ConstPtrValueBase::opcodeFromConstructor(); }
+    template<typename T>
</ins><span class="cx">     ConstPtrValue(Origin origin, T pointer)
</span><span class="cx">         : ConstPtrValueBase(origin, static_cast<intptr_t>(pointer))
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3FenceValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3FenceValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3FenceValue.cpp  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3FenceValue.cpp     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -34,13 +34,8 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* FenceValue::cloneImpl() const
-{
-    return new FenceValue(*this);
-}
-
</del><span class="cx"> FenceValue::FenceValue(Origin origin, HeapRange read, HeapRange write)
</span><del>-    : Value(CheckedOpcode, Fence, Void, origin)
</del><ins>+    : Value(CheckedOpcode, Fence, Void, Zero, origin)
</ins><span class="cx">     , read(read)
</span><span class="cx">     , write(write)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3FenceValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3FenceValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3FenceValue.h    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3FenceValue.h       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -72,14 +72,14 @@
</span><span class="cx">     HeapRange read { HeapRange::top() };
</span><span class="cx">     HeapRange write { HeapRange::top() };
</span><span class="cx"> 
</span><del>-protected:
-    Value* cloneImpl() const override;
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx">     
</span><ins>+    static Opcode opcodeFromConstructor(Origin, HeapRange = HeapRange(), HeapRange = HeapRange()) { return Fence; }
</ins><span class="cx">     FenceValue(Origin origin, HeapRange read, HeapRange write);
</span><del>-    
</del><span class="cx">     FenceValue(Origin origin);
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MemoryValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3MemoryValue.cpp    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -73,15 +73,10 @@
</span><span class="cx">         out.print(comma, "fenceRange = ", fenceRange());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* MemoryValue::cloneImpl() const
-{
-    return new MemoryValue(*this);
-}
-
</del><span class="cx"> // Use this form for Load (but not Load8Z, Load8S, or any of the Loads that have a suffix that
</span><span class="cx"> // describes the returned type).
</span><span class="cx"> MemoryValue::MemoryValue(MemoryValue::MemoryValueLoad, Kind kind, Type type, Origin origin, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
</span><del>-    : Value(CheckedOpcode, kind, type, origin, pointer)
</del><ins>+    : Value(CheckedOpcode, kind, type, One, origin, pointer)
</ins><span class="cx">     , m_offset(offset)
</span><span class="cx">     , m_range(range)
</span><span class="cx">     , m_fenceRange(fenceRange)
</span><span class="lines">@@ -126,7 +121,7 @@
</span><span class="cx"> 
</span><span class="cx"> // Use this form for stores.
</span><span class="cx"> MemoryValue::MemoryValue(MemoryValue::MemoryValueStore, Kind kind, Origin origin, Value* value, Value* pointer, MemoryValue::OffsetType offset, HeapRange range, HeapRange fenceRange)
</span><del>-    : Value(CheckedOpcode, kind, Void, origin, value, pointer)
</del><ins>+    : Value(CheckedOpcode, kind, Void, Two, origin, value, pointer)
</ins><span class="cx">     , m_offset(offset)
</span><span class="cx">     , m_range(range)
</span><span class="cx">     , m_fenceRange(fenceRange)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MemoryValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MemoryValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MemoryValue.h   2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3MemoryValue.h      2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -84,14 +84,14 @@
</span><span class="cx"> 
</span><span class="cx">     bool isCanonicalWidth() const { return B3::isCanonicalWidth(accessWidth()); }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_NON_VARARGS_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><del>-
-    Value* cloneImpl() const override;
-
</del><ins>+    
</ins><span class="cx">     template<typename Int, typename = IsLegalOffset<Int>, typename... Arguments>
</span><del>-    MemoryValue(CheckedOpcodeTag, Kind kind, Type type, Origin origin, Int offset, HeapRange range, HeapRange fenceRange, Arguments... arguments)
-        : Value(CheckedOpcode, kind, type, origin, arguments...)
</del><ins>+    MemoryValue(CheckedOpcodeTag, Kind kind, Type type, NumChildren numChildren, Origin origin, Int offset, HeapRange range, HeapRange fenceRange, Arguments... arguments)
+        : Value(CheckedOpcode, kind, type, numChildren, origin, static_cast<Value*>(arguments)...)
</ins><span class="cx">         , m_offset(offset)
</span><span class="cx">         , m_range(range)
</span><span class="cx">         , m_fenceRange(fenceRange)
</span><span class="lines">@@ -100,6 +100,7 @@
</span><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     bool isLegalOffsetImpl(int32_t offset) const;
</span><span class="cx">     bool isLegalOffsetImpl(int64_t offset) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3MoveConstantscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3MoveConstants.cpp  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -58,7 +58,7 @@
</span><span class="cx">             [&] (const ValueKey& key) -> bool {
</span><span class="cx">                 return key.opcode() == ConstFloat || key.opcode() == ConstDouble;
</span><span class="cx">             });
</span><del>-        
</del><ins>+
</ins><span class="cx">         lowerFPConstants();
</span><span class="cx">         
</span><span class="cx">         hoistConstants(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PatchpointValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3PatchpointValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PatchpointValue.cpp     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3PatchpointValue.cpp        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -44,11 +44,6 @@
</span><span class="cx">         out.print(comma, "numFPScratchRegisters = ", numFPScratchRegisters);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* PatchpointValue::cloneImpl() const
-{
-    return new PatchpointValue(*this);
-}
-
</del><span class="cx"> PatchpointValue::PatchpointValue(Type type, Origin origin)
</span><span class="cx">     : Base(CheckedOpcode, Patchpoint, type, origin)
</span><span class="cx">     , effects(Effects::forCall())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3PatchpointValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3PatchpointValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3PatchpointValue.h       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3PatchpointValue.h  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -61,14 +61,16 @@
</span><span class="cx">     uint8_t numGPScratchRegisters { 0 };
</span><span class="cx">     uint8_t numFPScratchRegisters { 0 };
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_VARARGS_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    static Opcode opcodeFromConstructor(Type, Origin) { return Patchpoint; }
</ins><span class="cx">     JS_EXPORT_PRIVATE PatchpointValue(Type, Origin);
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.cpp   2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.cpp      2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -93,7 +93,6 @@
</span><span class="cx">     return m_values.add(WTFMove(clone));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> Value* Procedure::addIntConstant(Origin origin, Type type, int64_t value)
</span><span class="cx"> {
</span><span class="cx">     switch (type) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Procedureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Procedure.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Procedure.h     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Procedure.h        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -292,7 +292,7 @@
</span><span class="cx">     bool m_needsUsedRegisters { true };
</span><span class="cx">     bool m_hasQuirks { false };
</span><span class="cx"> };
</span><del>-
</del><ins>+    
</ins><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ProcedureInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ProcedureInlines.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ProcedureInlines.h      2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ProcedureInlines.h 2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -29,13 +29,14 @@
</span><span class="cx"> 
</span><span class="cx"> #include "B3BasicBlock.h"
</span><span class="cx"> #include "B3Procedure.h"
</span><ins>+#include "B3Value.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><del>-
</del><ins>+    
</ins><span class="cx"> template<typename ValueType, typename... Arguments>
</span><span class="cx"> ValueType* Procedure::add(Arguments... arguments)
</span><span class="cx"> {
</span><del>-    return static_cast<ValueType*>(addValueImpl(new ValueType(arguments...)));
</del><ins>+    return static_cast<ValueType*>(addValueImpl(Value::allocate<ValueType>(arguments...)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::B3
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3SlotBaseValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.cpp       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.cpp  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -41,11 +41,6 @@
</span><span class="cx">     out.print(comma, pointerDump(m_slot));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* SlotBaseValue::cloneImpl() const
-{
-    return new SlotBaseValue(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3SlotBaseValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.h 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3SlotBaseValue.h    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -41,16 +41,17 @@
</span><span class="cx"> 
</span><span class="cx">     StackSlot* slot() const { return m_slot; }
</span><span class="cx"> 
</span><del>-protected:
-    void dumpMeta(CommaPrinter&, PrintStream&) const override;
</del><ins>+    B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN
</ins><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    void dumpMeta(CommaPrinter&, PrintStream&) const override;
+
+    static Opcode opcodeFromConstructor(Origin, StackSlot*) { return SlotBase; }
</ins><span class="cx">     SlotBaseValue(Origin origin, StackSlot* slot)
</span><del>-        : Value(CheckedOpcode, SlotBase, pointerType(), origin)
</del><ins>+        : Value(CheckedOpcode, SlotBase, pointerType(), Zero, origin)
</ins><span class="cx">         , m_slot(slot)
</span><span class="cx">     {
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3StackmapSpecialcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp     2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3StackmapSpecial.cpp        2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -83,11 +83,11 @@
</span><span class="cx"> 
</span><span class="cx">     // Check that insane things have not happened.
</span><span class="cx">     ASSERT(inst.args.size() >= numIgnoredAirArgs);
</span><del>-    ASSERT(value->children().size() >= numIgnoredB3Args);
-    ASSERT(inst.args.size() - numIgnoredAirArgs >= value->children().size() - numIgnoredB3Args);
</del><ins>+    ASSERT(value->numChildren() >= numIgnoredB3Args);
+    ASSERT(inst.args.size() - numIgnoredAirArgs >= value->numChildren() - numIgnoredB3Args);
</ins><span class="cx">     ASSERT(inst.args[0].kind() == Arg::Kind::Special);
</span><span class="cx"> 
</span><del>-    for (unsigned i = 0; i < value->children().size() - numIgnoredB3Args; ++i) {
</del><ins>+    for (unsigned i = 0; i < value->numChildren() - numIgnoredB3Args; ++i) {
</ins><span class="cx">         Arg& arg = inst.args[i + numIgnoredAirArgs];
</span><span class="cx">         ConstrainedValue child = value->constrainedChild(i + numIgnoredB3Args);
</span><span class="cx"> 
</span><span class="lines">@@ -160,16 +160,16 @@
</span><span class="cx"> 
</span><span class="cx">     // Check that insane things have not happened.
</span><span class="cx">     ASSERT(inst.args.size() >= numIgnoredAirArgs);
</span><del>-    ASSERT(value->children().size() >= numIgnoredB3Args);
</del><ins>+    ASSERT(value->numChildren() >= numIgnoredB3Args);
</ins><span class="cx"> 
</span><span class="cx">     // For the Inst to be valid, it needs to have the right number of arguments.
</span><del>-    if (inst.args.size() - numIgnoredAirArgs < value->children().size() - numIgnoredB3Args)
</del><ins>+    if (inst.args.size() - numIgnoredAirArgs < value->numChildren() - numIgnoredB3Args)
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     // Regardless of constraints, stackmaps have some basic requirements for their arguments. For
</span><span class="cx">     // example, you can't have a non-FP-offset address. This verifies those conditions as well as the
</span><span class="cx">     // argument types.
</span><del>-    for (unsigned i = 0; i < value->children().size() - numIgnoredB3Args; ++i) {
</del><ins>+    for (unsigned i = 0; i < value->numChildren() - numIgnoredB3Args; ++i) {
</ins><span class="cx">         Value* child = value->child(i + numIgnoredB3Args);
</span><span class="cx">         Arg& arg = inst.args[i + numIgnoredAirArgs];
</span><span class="cx"> 
</span><span class="lines">@@ -178,7 +178,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // The number of constraints has to be no greater than the number of B3 children.
</span><del>-    ASSERT(value->m_reps.size() <= value->children().size());
</del><ins>+    ASSERT(value->m_reps.size() <= value->numChildren());
</ins><span class="cx"> 
</span><span class="cx">     // Verify any explicitly supplied constraints.
</span><span class="cx">     for (unsigned i = numIgnoredB3Args; i < value->m_reps.size(); ++i) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3StackmapValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3StackmapValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3StackmapValue.cpp       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3StackmapValue.cpp  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx"> void StackmapValue::append(Value* value, const ValueRep& rep)
</span><span class="cx"> {
</span><span class="cx">     if (rep == ValueRep::ColdAny) {
</span><del>-        children().append(value);
</del><ins>+        childrenVector().append(value);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     while (m_reps.size() < numChildren())
</span><span class="cx">         m_reps.append(ValueRep::ColdAny);
</span><span class="cx"> 
</span><del>-    children().append(value);
</del><ins>+    childrenVector().append(value);
</ins><span class="cx">     m_reps.append(rep);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> StackmapValue::StackmapValue(CheckedOpcodeTag, Kind kind, Type type, Origin origin)
</span><del>-    : Value(CheckedOpcode, kind, type, origin)
</del><ins>+    : Value(CheckedOpcode, kind, type, VarArgs, origin)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(accepts(kind));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3StackmapValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3StackmapValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3StackmapValue.h 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3StackmapValue.h    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -60,8 +60,7 @@
</span><span class="cx"> 
</span><span class="cx">     ~StackmapValue();
</span><span class="cx"> 
</span><del>-    // Use this to add children. Note that you could also add children by doing
-    // children().append(). That will work fine, but it's not recommended.
</del><ins>+    // Use this to add children.
</ins><span class="cx">     void append(const ConstrainedValue& value)
</span><span class="cx">     {
</span><span class="cx">         append(value.value(), value.rep());
</span><span class="lines">@@ -285,6 +284,8 @@
</span><span class="cx">         return ConstrainedValueCollection(*this);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_VARARGS_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpChildren(CommaPrinter&, PrintStream&) const override;
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3SwitchValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3SwitchValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3SwitchValue.cpp 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3SwitchValue.cpp    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -106,13 +106,8 @@
</span><span class="cx">     out.print(comma, "cases = [", listDump(m_values), "]");
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* SwitchValue::cloneImpl() const
-{
-    return new SwitchValue(*this);
-}
-
</del><span class="cx"> SwitchValue::SwitchValue(Origin origin, Value* child)
</span><del>-    : Value(CheckedOpcode, Switch, Void, origin, child)
</del><ins>+    : Value(CheckedOpcode, Switch, Void, One, origin, child)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3SwitchValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3SwitchValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3SwitchValue.h   2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3SwitchValue.h      2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -64,14 +64,17 @@
</span><span class="cx"> 
</span><span class="cx">     void dumpSuccessors(const BasicBlock*, PrintStream&) const override;
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(1)
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    static Opcode opcodeFromConstructor(Origin, Value*) { return Switch; }
</ins><span class="cx">     JS_EXPORT_PRIVATE SwitchValue(Origin, Value* child);
</span><span class="cx"> 
</span><span class="cx">     Vector<int64_t> m_values;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3UpsilonValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3UpsilonValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3UpsilonValue.cpp        2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3UpsilonValue.cpp   2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -45,11 +45,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* UpsilonValue::cloneImpl() const
-{
-    return new UpsilonValue(*this);
-}
-
</del><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3UpsilonValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3UpsilonValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3UpsilonValue.h  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3UpsilonValue.h     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -45,19 +45,22 @@
</span><span class="cx">         m_phi = phi;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(1)
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    static Opcode opcodeFromConstructor(Origin, Value*, Value* = nullptr) { return Upsilon; }
</ins><span class="cx">     // Note that passing the Phi during construction is optional. A valid pattern is to first create
</span><span class="cx">     // the Upsilons without the Phi, then create the Phi, then go back and tell the Upsilons about
</span><span class="cx">     // the Phi. This allows you to emit code in its natural order.
</span><span class="cx">     UpsilonValue(Origin origin, Value* value, Value* phi = nullptr)
</span><del>-        : Value(CheckedOpcode, Upsilon, Void, origin, value)
</del><ins>+        : Value(CheckedOpcode, Upsilon, Void, One, origin, value)
</ins><span class="cx">         , m_phi(phi)
</span><span class="cx">     {
</span><span class="cx">         if (phi)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.cpp       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Value.cpp  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -47,13 +47,23 @@
</span><span class="cx"> #include <wtf/CommaPrinter.h>
</span><span class="cx"> #include <wtf/ListDump.h>
</span><span class="cx"> #include <wtf/StringPrintStream.h>
</span><ins>+#include <wtf/Vector.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><span class="cx"> const char* const Value::dumpPrefix = "@";
</span><ins>+void DeepValueDump::dump(PrintStream& out) const
+{
+    if (m_value)
+        m_value->deepDump(m_proc, out);
+    else
+        out.print("<null>");
+}
</ins><span class="cx"> 
</span><span class="cx"> Value::~Value()
</span><span class="cx"> {
</span><ins>+    if (m_numChildren == VarArgs)
+        bitwise_cast<Vector<Value*, 3> *>(childrenAlloc())->Vector<Value*, 3>::~Vector();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Value::replaceWithIdentity(Value* value)
</span><span class="lines">@@ -62,27 +72,13 @@
</span><span class="cx">     // a plain Identity Value. We first collect all of the information we need, then we destruct the
</span><span class="cx">     // previous value in place, and then we construct the Identity Value in place.
</span><span class="cx"> 
</span><del>-    ASSERT(m_type == value->m_type);
</del><ins>+    RELEASE_ASSERT(m_type == value->m_type);
</ins><span class="cx">     ASSERT(value != this);
</span><span class="cx"> 
</span><del>-    if (m_type == Void) {
</del><ins>+    if (m_type == Void)
</ins><span class="cx">         replaceWithNopIgnoringType();
</span><del>-        return;
-    }
-
-    unsigned index = m_index;
-    Type type = m_type;
-    Origin origin = m_origin;
-    BasicBlock* owner = this->owner;
-
-    RELEASE_ASSERT(type == value->type());
-
-    this->~Value();
-
-    new (this) Value(Identity, type, origin, value);
-
-    this->owner = owner;
-    this->m_index = index;
</del><ins>+    else
+        replaceWith(Identity, m_type, this->owner, value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Value::replaceWithBottom(InsertionSet& insertionSet, size_t index)
</span><span class="lines">@@ -98,16 +94,7 @@
</span><span class="cx"> 
</span><span class="cx"> void Value::replaceWithNopIgnoringType()
</span><span class="cx"> {
</span><del>-    unsigned index = m_index;
-    Origin origin = m_origin;
-    BasicBlock* owner = this->owner;
-
-    this->~Value();
-
-    new (this) Value(Nop, Void, origin);
-
-    this->owner = owner;
-    this->m_index = index;
</del><ins>+    replaceWith(Nop, Void, this->owner);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Value::replaceWithPhi()
</span><span class="lines">@@ -116,34 +103,14 @@
</span><span class="cx">         replaceWithNop();
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    
-    unsigned index = m_index;
-    Origin origin = m_origin;
-    BasicBlock* owner = this->owner;
-    Type type = m_type;
</del><span class="cx"> 
</span><del>-    this->~Value();
-
-    new (this) Value(Phi, type, origin);
-
-    this->owner = owner;
-    this->m_index = index;
</del><ins>+    replaceWith(Phi, m_type, this->owner);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Value::replaceWithJump(BasicBlock* owner, FrequentedBlock target)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(owner->last() == this);
</span><del>-    
-    unsigned index = m_index;
-    Origin origin = m_origin;
-    
-    this->~Value();
-    
-    new (this) Value(Jump, Void, origin);
-    
-    this->owner = owner;
-    this->m_index = index;
-    
</del><ins>+    replaceWith(Jump, Void, this->owner);
</ins><span class="cx">     owner->setSuccessors(target);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -150,17 +117,7 @@
</span><span class="cx"> void Value::replaceWithOops(BasicBlock* owner)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(owner->last() == this);
</span><del>-    
-    unsigned index = m_index;
-    Origin origin = m_origin;
-    
-    this->~Value();
-    
-    new (this) Value(Oops, Void, origin);
-    
-    this->owner = owner;
-    this->m_index = index;
-    
</del><ins>+    replaceWith(Oops, Void, this->owner);
</ins><span class="cx">     owner->clearSuccessors();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -174,6 +131,30 @@
</span><span class="cx">     replaceWithOops(owner);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Value::replaceWith(Kind kind, Type type, BasicBlock* owner)
+{
+    unsigned index = m_index;
+
+    this->~Value();
+
+    new (this) Value(kind, type, m_origin);
+
+    this->m_index = index;
+    this->owner = owner;
+}
+
+void Value::replaceWith(Kind kind, Type type, BasicBlock* owner, Value* value)
+{
+    unsigned index = m_index;
+
+    this->~Value();
+
+    new (this) Value(kind, type, m_origin, value);
+
+    this->m_index = index;
+    this->owner = owner;
+}
+
</ins><span class="cx"> void Value::dump(PrintStream& out) const
</span><span class="cx"> {
</span><span class="cx">     bool isConstant = false;
</span><span class="lines">@@ -205,11 +186,6 @@
</span><span class="cx">         out.print(")");
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* Value::cloneImpl() const
-{
-    return new Value(*this);
-}
-
</del><span class="cx"> void Value::dumpChildren(CommaPrinter& comma, PrintStream& out) const
</span><span class="cx"> {
</span><span class="cx">     for (Value* child : children())
</span><span class="lines">@@ -458,11 +434,11 @@
</span><span class="cx"> 
</span><span class="cx"> Value* Value::invertedCompare(Procedure& proc) const
</span><span class="cx"> {
</span><del>-    if (!numChildren())
</del><ins>+    if (numChildren() != 2)
</ins><span class="cx">         return nullptr;
</span><span class="cx">     if (Optional<Opcode> invertedOpcode = B3::invertedCompare(opcode(), child(0)->type())) {
</span><span class="cx">         ASSERT(!kind().hasExtraBits());
</span><del>-        return proc.add<Value>(*invertedOpcode, type(), origin(), children());
</del><ins>+        return proc.add<Value>(*invertedOpcode, type(), origin(), child(0), child(1));
</ins><span class="cx">     }
</span><span class="cx">     return nullptr;
</span><span class="cx"> }
</span><span class="lines">@@ -496,6 +472,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (type() != Int32)
</span><span class="cx">         return false;
</span><ins>+
</ins><span class="cx">     switch (opcode()) {
</span><span class="cx">     case Const32:
</span><span class="cx">         return asInt32() == 0 || asInt32() == 1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3Valueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3Value.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3Value.h 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3Value.h    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx"> #include "B3Width.h"
</span><span class="cx"> #include <wtf/CommaPrinter.h>
</span><span class="cx"> #include <wtf/FastMalloc.h>
</span><del>-#include <wtf/Noncopyable.h>
</del><ins>+#include <wtf/IteratorRange.h>
</ins><span class="cx"> #include <wtf/StdLibExtras.h>
</span><span class="cx"> #include <wtf/TriState.h>
</span><span class="cx"> 
</span><span class="lines">@@ -53,8 +53,6 @@
</span><span class="cx"> class JS_EXPORT_PRIVATE Value {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    typedef Vector<Value*, 3> AdjacencyList;
-
</del><span class="cx">     static const char* const dumpPrefix;
</span><span class="cx"> 
</span><span class="cx">     static bool accepts(Kind) { return true; }
</span><span class="lines">@@ -82,14 +80,6 @@
</span><span class="cx">     Origin origin() const { return m_origin; }
</span><span class="cx">     void setOrigin(Origin origin) { m_origin = origin; }
</span><span class="cx">     
</span><del>-    Value*& child(unsigned index) { return m_children[index]; }
-    Value* child(unsigned index) const { return m_children[index]; }
-
-    Value*& lastChild() { return m_children.last(); }
-    Value* lastChild() const { return m_children.last(); }
-
-    unsigned numChildren() const { return m_children.size(); }
-
</del><span class="cx">     Type type() const { return m_type; }
</span><span class="cx">     void setType(Type type) { m_type = type; }
</span><span class="cx"> 
</span><span class="lines">@@ -97,9 +87,58 @@
</span><span class="cx">     Bank resultBank() const { return bankForType(type()); }
</span><span class="cx">     Width resultWidth() const { return widthForType(type()); }
</span><span class="cx"> 
</span><del>-    AdjacencyList& children() { return m_children; } 
-    const AdjacencyList& children() const { return m_children; }
</del><ins>+    unsigned numChildren() const
+    {
+        if (m_numChildren == VarArgs)
+            return childrenVector().size();
+        return m_numChildren;
+    }
+    
+    Value*& child(unsigned index)
+    {
+        ASSERT(index < numChildren());
+        return m_numChildren == VarArgs ? childrenVector()[index] : childrenArray()[index];
+    }
+    Value* child(unsigned index) const
+    {
+        ASSERT(index < numChildren());
+        return m_numChildren == VarArgs ? childrenVector()[index] : childrenArray()[index];
+    }
+    
+    Value*& lastChild()
+    {
+        if (m_numChildren == VarArgs)
+            return childrenVector().last();
+        ASSERT(m_numChildren >= 1);
+        return childrenArray()[m_numChildren - 1];
+    }
+    Value* lastChild() const
+    {
+        if (m_numChildren == VarArgs)
+            return childrenVector().last();
+        ASSERT(m_numChildren >= 1);
+        return childrenArray()[m_numChildren - 1];
+    }
</ins><span class="cx"> 
</span><ins>+    WTF::IteratorRange<Value**> children()
+    {
+        if (m_numChildren == VarArgs) {
+            Vector<Value*, 3>& vec = childrenVector();
+            return WTF::makeIteratorRange(&*vec.begin(), &*vec.end());
+        }
+        Value** buffer = childrenArray();
+        return {buffer, buffer + m_numChildren };
+    }
+    WTF::IteratorRange<Value* const*> children() const
+    {
+        if (m_numChildren == VarArgs) {
+            const Vector<Value*, 3>& vec = childrenVector();
+            return WTF::makeIteratorRange(&*vec.begin(), &*vec.end());
+        }
+        Value* const* buffer = childrenArray();
+        return {buffer, buffer + m_numChildren };
+    }
+
</ins><span class="cx">     // If you want to replace all uses of this value with a different value, then replace this
</span><span class="cx">     // value with Identity. Then do a pass of performSubstitution() on all of the values that use
</span><span class="cx">     // this one. Usually we do all of this in one pass in pre-order, which ensures that the
</span><span class="lines">@@ -301,19 +340,218 @@
</span><span class="cx">         typename std::enable_if<sizeof(Int) <= sizeof(OffsetType)>::type
</span><span class="cx">     > { };
</span><span class="cx"> 
</span><ins>+protected:
+    Value* cloneImpl() const;
</ins><span class="cx"> 
</span><del>-protected:
-    virtual Value* cloneImpl() const;
-    
</del><ins>+    void replaceWith(Kind, Type, BasicBlock*);
+    void replaceWith(Kind, Type, BasicBlock*, Value*);
+
</ins><span class="cx">     virtual void dumpChildren(CommaPrinter&, PrintStream&) const;
</span><span class="cx">     virtual void dumpMeta(CommaPrinter&, PrintStream&) const;
</span><span class="cx"> 
</span><ins>+    // The specific value of VarArgs does not matter, but the value of the others is assumed to match their meaning.
+    enum NumChildren : uint8_t { Zero = 0, One = 1, Two = 2, Three = 3, VarArgs = 4};
+
+    char* childrenAlloc() { return bitwise_cast<char*>(this) + adjacencyListOffset(); }
+    const char* childrenAlloc() const { return bitwise_cast<const char*>(this) + adjacencyListOffset(); }
+    Vector<Value*, 3>& childrenVector()
+    {
+        ASSERT(m_numChildren == VarArgs);
+        return *bitwise_cast<Vector<Value*, 3>*>(childrenAlloc());
+    }
+    const Vector<Value*, 3>& childrenVector() const
+    {
+        ASSERT(m_numChildren == VarArgs);
+        return *bitwise_cast<Vector<Value*, 3> const*>(childrenAlloc());
+    }
+    Value** childrenArray()
+    {
+        ASSERT(m_numChildren != VarArgs);
+        return bitwise_cast<Value**>(childrenAlloc());
+    }
+    Value* const* childrenArray() const
+    {
+        ASSERT(m_numChildren != VarArgs);
+        return bitwise_cast<Value* const*>(childrenAlloc());
+    }
+
+    template<typename... Arguments>
+    static Opcode opcodeFromConstructor(Kind kind, Arguments...) { return kind.opcode(); }
+    ALWAYS_INLINE static size_t adjacencyListSpace(Kind kind)
+    {
+        switch (kind.opcode()) {
+        case FramePointer:
+        case Nop:
+        case Phi:
+        case Jump:
+        case Oops:
+        case EntrySwitch:
+        case ArgumentReg:
+        case Const32:
+        case Const64:
+        case ConstFloat:
+        case ConstDouble:
+        case Fence:
+        case SlotBase:
+        case Get:
+            return 0;
+        case Return:
+        case Identity:
+        case Opaque:
+        case Neg:
+        case Clz:
+        case Abs:
+        case Ceil:
+        case Floor:
+        case Sqrt:
+        case SExt8:
+        case SExt16:
+        case Trunc:
+        case SExt32:
+        case ZExt32:
+        case FloatToDouble:
+        case IToD:
+        case DoubleToFloat:
+        case IToF:
+        case BitwiseCast:
+        case Branch:
+        case Depend:
+        case Load8Z:
+        case Load8S:
+        case Load16Z:
+        case Load16S:
+        case Load:
+        case Switch:
+        case Upsilon:
+        case Set:
+        case WasmAddress:
+        case WasmBoundsCheck:
+            return sizeof(Value*);
+        case Add:
+        case Sub:
+        case Mul:
+        case Div:
+        case UDiv:
+        case Mod:
+        case UMod:
+        case BitAnd:
+        case BitOr:
+        case BitXor:
+        case Shl:
+        case SShr:
+        case ZShr:
+        case RotR:
+        case RotL:
+        case Equal:
+        case NotEqual:
+        case LessThan:
+        case GreaterThan:
+        case LessEqual:
+        case GreaterEqual:
+        case Above:
+        case Below:
+        case AboveEqual:
+        case BelowEqual:
+        case EqualOrUnordered:
+        case AtomicXchgAdd:
+        case AtomicXchgAnd:
+        case AtomicXchgOr:
+        case AtomicXchgSub:
+        case AtomicXchgXor:
+        case AtomicXchg:
+        case Store8:
+        case Store16:
+        case Store:
+            return 2 * sizeof(Value*);
+        case Select:
+        case AtomicWeakCAS:
+        case AtomicStrongCAS:
+            return 3 * sizeof(Value*);
+        case CCall:
+        case Check:
+        case CheckAdd:
+        case CheckSub:
+        case CheckMul:
+        case Patchpoint:
+            return sizeof(Vector<Value*, 3>);
+        default:
+            break;
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+
</ins><span class="cx"> private:
</span><ins>+    static char* allocateSpace(Opcode opcode, size_t size)
+    {
+        size_t adjacencyListSpace = Value::adjacencyListSpace(opcode);
+        // We must allocate enough space that replaceWithIdentity can work without buffer overflow.
+        size_t allocIdentitySize = sizeof(Value) + sizeof(Value*);
+        size_t allocSize = std::max(size + adjacencyListSpace, allocIdentitySize);
+        return static_cast<char*>(WTF::fastMalloc(allocSize));
+    }
+
+protected:
+    template<typename ValueType, typename... Arguments>
+    static ValueType* allocate(Arguments... arguments)
+    {
+        char* alloc = allocateSpace(ValueType::opcodeFromConstructor(arguments...), sizeof(ValueType));
+        return new (alloc) ValueType(arguments...);
+    }
+    template<typename ValueType>
+    static ValueType* allocate(const ValueType& valueToClone)
+    {
+        char* alloc = allocateSpace(valueToClone.opcode(), sizeof(ValueType));
+        ValueType* result = new (alloc) ValueType(valueToClone);
+        result->buildAdjacencyList(sizeof(ValueType), valueToClone);
+        return result;
+    }
+
+    // Protected so it will only be called from allocate above, possibly through the subclasses'copy constructors
+    Value(const Value&) = default;
+
+    Value(Value&&) = delete;
+    Value& operator=(const Value&) = delete;
+    Value& operator=(Value&&) = delete;
+    
+    size_t adjacencyListOffset() const;
+
</ins><span class="cx">     friend class Procedure;
</span><span class="cx">     friend class SparseCollection<Value>;
</span><span class="cx"> 
</span><ins>+private:
+    template<typename... Arguments>
+    void buildAdjacencyList(NumChildren numChildren, Arguments... arguments)
+    {
+        if (numChildren == VarArgs) {
+            new (childrenAlloc()) Vector<Value*, 3> { arguments... };
+            return;
+        }
+        ASSERT(numChildren == sizeof...(arguments));
+        new (childrenAlloc()) Value*[sizeof...(arguments)] { arguments... };
+    }
+    void buildAdjacencyList(size_t offset, const Value& valueToClone)
+    {
+        switch (valueToClone.m_numChildren) {
+        case VarArgs:
+            new (bitwise_cast<char*>(this) + offset) Vector<Value*, 3> (valueToClone.childrenVector());
+            break;
+        case Three:
+            bitwise_cast<Value**>(bitwise_cast<char*>(this) + offset)[2] = valueToClone.childrenArray()[2];
+            FALLTHROUGH;
+        case Two:
+            bitwise_cast<Value**>(bitwise_cast<char*>(this) + offset)[1] = valueToClone.childrenArray()[1];
+            FALLTHROUGH;
+        case One:
+            bitwise_cast<Value**>(bitwise_cast<char*>(this) + offset)[0] = valueToClone.childrenArray()[0];
+            break;
+        case Zero:
+            break;
+        }
+    }
+    
</ins><span class="cx">     // Checks that this kind is valid for use with B3::Value.
</span><del>-    ALWAYS_INLINE static void checkKind(Kind kind, unsigned numArgs)
</del><ins>+    ALWAYS_INLINE static NumChildren numChildrenForKind(Kind kind, unsigned numArgs)
</ins><span class="cx">     {
</span><span class="cx">         switch (kind.opcode()) {
</span><span class="cx">         case FramePointer:
</span><span class="lines">@@ -324,11 +562,11 @@
</span><span class="cx">         case EntrySwitch:
</span><span class="cx">             if (UNLIKELY(numArgs))
</span><span class="cx">                 badKind(kind, numArgs);
</span><del>-            break;
</del><ins>+            return Zero;
</ins><span class="cx">         case Return:
</span><span class="cx">             if (UNLIKELY(numArgs > 1))
</span><span class="cx">                 badKind(kind, numArgs);
</span><del>-            break;
</del><ins>+            return numArgs ? One : Zero;
</ins><span class="cx">         case Identity:
</span><span class="cx">         case Opaque:
</span><span class="cx">         case Neg:
</span><span class="lines">@@ -351,7 +589,7 @@
</span><span class="cx">         case Depend:
</span><span class="cx">             if (UNLIKELY(numArgs != 1))
</span><span class="cx">                 badKind(kind, numArgs);
</span><del>-            break;
</del><ins>+            return One;
</ins><span class="cx">         case Add:
</span><span class="cx">         case Sub:
</span><span class="cx">         case Mul:
</span><span class="lines">@@ -380,129 +618,105 @@
</span><span class="cx">         case EqualOrUnordered:
</span><span class="cx">             if (UNLIKELY(numArgs != 2))
</span><span class="cx">                 badKind(kind, numArgs);
</span><del>-            break;
</del><ins>+            return Two;
</ins><span class="cx">         case Select:
</span><span class="cx">             if (UNLIKELY(numArgs != 3))
</span><span class="cx">                 badKind(kind, numArgs);
</span><del>-            break;
</del><ins>+            return Three;
</ins><span class="cx">         default:
</span><span class="cx">             badKind(kind, numArgs);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        return VarArgs;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="cx">     enum CheckedOpcodeTag { CheckedOpcode };
</span><del>-
-    Value(const Value&) = default;
-    Value& operator=(const Value&) = default;
</del><span class="cx">     
</span><span class="cx">     // Instantiate values via Procedure.
</span><span class="cx">     // This form requires specifying the type explicitly:
</span><span class="cx">     template<typename... Arguments>
</span><del>-    explicit Value(CheckedOpcodeTag, Kind kind, Type type, Origin origin, Value* firstChild, Arguments... arguments)
</del><ins>+    explicit Value(CheckedOpcodeTag, Kind kind, Type type, NumChildren numChildren, Origin origin, Value* firstChild, Arguments... arguments)
</ins><span class="cx">         : m_kind(kind)
</span><span class="cx">         , m_type(type)
</span><ins>+        , m_numChildren(numChildren)
</ins><span class="cx">         , m_origin(origin)
</span><del>-        , m_children{ firstChild, arguments... }
</del><span class="cx">     {
</span><ins>+        buildAdjacencyList(numChildren, firstChild, arguments...);
</ins><span class="cx">     }
</span><span class="cx">     // This form is for specifying the type explicitly when the opcode has no children:
</span><del>-    explicit Value(CheckedOpcodeTag, Kind kind, Type type, Origin origin)
</del><ins>+    explicit Value(CheckedOpcodeTag, Kind kind, Type type, NumChildren numChildren, Origin origin)
</ins><span class="cx">         : m_kind(kind)
</span><span class="cx">         , m_type(type)
</span><ins>+        , m_numChildren(numChildren)
</ins><span class="cx">         , m_origin(origin)
</span><span class="cx">     {
</span><ins>+        buildAdjacencyList(numChildren);
</ins><span class="cx">     }
</span><del>-    // This form is for those opcodes that can infer their type from the opcode and first child:
-    template<typename... Arguments>
-    explicit Value(CheckedOpcodeTag, Kind kind, Origin origin, Value* firstChild)
-        : m_kind(kind)
-        , m_type(typeFor(kind, firstChild))
-        , m_origin(origin)
-        , m_children{ firstChild }
-    {
-    }
-    // This form is for those opcodes that can infer their type from the opcode and first and second child:
-    template<typename... Arguments>
-    explicit Value(CheckedOpcodeTag, Kind kind, Origin origin, Value* firstChild, Value* secondChild, Arguments... arguments)
-        : m_kind(kind)
-        , m_type(typeFor(kind, firstChild, secondChild))
-        , m_origin(origin)
-        , m_children{ firstChild, secondChild, arguments... }
-    {
-    }
</del><span class="cx">     // This form is for those opcodes that can infer their type from the opcode alone, and that don't
</span><span class="cx">     // take any arguments:
</span><del>-    explicit Value(CheckedOpcodeTag, Kind kind, Origin origin)
</del><ins>+    explicit Value(CheckedOpcodeTag, Kind kind, NumChildren numChildren, Origin origin)
</ins><span class="cx">         : m_kind(kind)
</span><span class="cx">         , m_type(typeFor(kind, nullptr))
</span><ins>+        , m_numChildren(numChildren)
</ins><span class="cx">         , m_origin(origin)
</span><span class="cx">     {
</span><ins>+        buildAdjacencyList(numChildren);
</ins><span class="cx">     }
</span><del>-    // Use this form for varargs.
-    explicit Value(CheckedOpcodeTag, Kind kind, Type type, Origin origin, const AdjacencyList& children)
</del><ins>+    // This form is for those opcodes that can infer their type from the opcode and first child:
+    explicit Value(CheckedOpcodeTag, Kind kind, NumChildren numChildren, Origin origin, Value* firstChild)
</ins><span class="cx">         : m_kind(kind)
</span><del>-        , m_type(type)
</del><ins>+        , m_type(typeFor(kind, firstChild))
+        , m_numChildren(numChildren)
</ins><span class="cx">         , m_origin(origin)
</span><del>-        , m_children(children)
</del><span class="cx">     {
</span><ins>+        buildAdjacencyList(numChildren, firstChild);
</ins><span class="cx">     }
</span><del>-    explicit Value(CheckedOpcodeTag, Kind kind, Type type, Origin origin, AdjacencyList&& children)
</del><ins>+    // This form is for those opcodes that can infer their type from the opcode and first and second child:
+    template<typename... Arguments>
+    explicit Value(CheckedOpcodeTag, Kind kind, NumChildren numChildren, Origin origin, Value* firstChild, Value* secondChild, Arguments... arguments)
</ins><span class="cx">         : m_kind(kind)
</span><del>-        , m_type(type)
</del><ins>+        , m_type(typeFor(kind, firstChild, secondChild))
+        , m_numChildren(numChildren)
</ins><span class="cx">         , m_origin(origin)
</span><del>-        , m_children(WTFMove(children))
</del><span class="cx">     {
</span><ins>+        buildAdjacencyList(numChildren, firstChild, secondChild, arguments...);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // This is the constructor you end up actually calling, if you're instantiating Value
</span><span class="cx">     // directly.
</span><del>-    template<typename... Arguments>
-        explicit Value(Kind kind, Type type, Origin origin)
-        : Value(CheckedOpcode, kind, type, origin)
</del><ins>+    explicit Value(Kind kind, Type type, Origin origin)
+        : Value(CheckedOpcode, kind, type, Zero, origin)
</ins><span class="cx">     {
</span><del>-        checkKind(kind, 0);
</del><ins>+        RELEASE_ASSERT(numChildrenForKind(kind, 0) == Zero);
</ins><span class="cx">     }
</span><ins>+    // We explicitly convert the extra arguments to Value* (they may be pointers to some subclasses of Value) to limit template explosion
</ins><span class="cx">     template<typename... Arguments>
</span><del>-        explicit Value(Kind kind, Type type, Origin origin, Value* firstChild, Arguments&&... arguments)
-        : Value(CheckedOpcode, kind, type, origin, firstChild, std::forward<Arguments>(arguments)...)
</del><ins>+    explicit Value(Kind kind, Origin origin, Arguments... arguments)
+        : Value(CheckedOpcode, kind, numChildrenForKind(kind, sizeof...(arguments)), origin, static_cast<Value*>(arguments)...)
</ins><span class="cx">     {
</span><del>-        checkKind(kind, 1 + sizeof...(arguments));
</del><span class="cx">     }
</span><span class="cx">     template<typename... Arguments>
</span><del>-        explicit Value(Kind kind, Type type, Origin origin, const AdjacencyList& children)
-        : Value(CheckedOpcode, kind, type, origin, children)
</del><ins>+    explicit Value(Kind kind, Type type, Origin origin, Value* firstChild, Arguments... arguments)
+        : Value(CheckedOpcode, kind, type, numChildrenForKind(kind, 1 + sizeof...(arguments)), origin, firstChild, static_cast<Value*>(arguments)...)
</ins><span class="cx">     {
</span><del>-        checkKind(kind, children.size());
</del><span class="cx">     }
</span><del>-    template<typename... Arguments>
-        explicit Value(Kind kind, Type type, Origin origin, AdjacencyList&& children)
-        : Value(CheckedOpcode, kind, type, origin, WTFMove(children))
-    {
-        checkKind(kind, m_children.size());
-    }
-    template<typename... Arguments>
-        explicit Value(Kind kind, Origin origin, Arguments&&... arguments)
-        : Value(CheckedOpcode, kind, origin, std::forward<Arguments>(arguments)...)
-    {
-        checkKind(kind, sizeof...(arguments));
-    }
</del><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class CheckValue; // CheckValue::convertToAdd() modifies m_kind.
</span><del>-    
</del><ins>+
</ins><span class="cx">     static Type typeFor(Kind, Value* firstChild, Value* secondChild = nullptr);
</span><span class="cx"> 
</span><del>-    // This group of fields is arranged to fit in 64 bits.
</del><ins>+    // m_index to m_numChildren are arranged to fit in 64 bits.
</ins><span class="cx"> protected:
</span><span class="cx">     unsigned m_index { UINT_MAX };
</span><span class="cx"> private:
</span><span class="cx">     Kind m_kind;
</span><span class="cx">     Type m_type;
</span><del>-    
</del><ins>+protected:
+    NumChildren m_numChildren;
+private:
</ins><span class="cx">     Origin m_origin;
</span><del>-    AdjacencyList m_children;
</del><span class="cx"> 
</span><span class="cx">     NO_RETURN_DUE_TO_CRASH static void badKind(Kind, unsigned);
</span><span class="cx"> 
</span><span class="lines">@@ -518,13 +732,7 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void dump(PrintStream& out) const
-    {
-        if (m_value)
-            m_value->deepDump(m_proc, out);
-        else
-            out.print("<null>");
-    }
</del><ins>+    void dump(PrintStream& out) const;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     const Procedure* m_proc;
</span><span class="lines">@@ -540,6 +748,116 @@
</span><span class="cx">     return DeepValueDump(nullptr, value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// The following macros are designed for subclasses of B3::Value to use.
+// They are never required for correctness, but can improve the performance of child/lastChild/numChildren/children methods,
+// for users that already know the specific subclass of Value they are manipulating.
+// The first set is to be used when you know something about the number of children of all values of a class, including its subclasses:
+// - B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN: always 0 children (e.g. Const32Value)
+// - B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(n): always n children, with n in {1, 2, 3} (e.g. UpsilonValue, with n = 1)
+// - B3_SPECIALIZE_VALUE_FOR_NON_VARARGS_CHILDREN: different numbers of children, but never a variable number at runtime (e.g. MemoryValue, that can have between 1 and 3 children)
+// - B3_SPECIALIZE_VALUE_FOR_VARARGS_CHILDREN: always a varargs (e.g. CCallValue)
+// The second set is only to be used by classes that we know are not further subclassed by anyone adding fields,
+// as they hardcode the offset of the children array/vector (which is equal to the size of the object).
+// - B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+// - B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_VARARGS_CHILDREN
+#define B3_SPECIALIZE_VALUE_FOR_NO_CHILDREN \
+    unsigned numChildren() const { return 0; } \
+    WTF::IteratorRange<Value**> children() { return {nullptr, nullptr}; } \
+    WTF::IteratorRange<Value* const*> children() const { return { nullptr, nullptr}; }
+
+#define B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(n) \
+public: \
+    unsigned numChildren() const { return n; } \
+    Value*& child(unsigned index) \
+    { \
+        ASSERT(index <= n); \
+        return childrenArray()[index]; \
+    } \
+    Value* child(unsigned index) const \
+    { \
+        ASSERT(index <= n); \
+        return childrenArray()[index]; \
+    } \
+    Value*& lastChild() \
+    { \
+        return childrenArray()[n - 1]; \
+    } \
+    Value* lastChild() const \
+    { \
+        return childrenArray()[n - 1]; \
+    } \
+    WTF::IteratorRange<Value**> children() \
+    { \
+        Value** buffer = childrenArray(); \
+        return {buffer, buffer + n }; \
+    } \
+    WTF::IteratorRange<Value* const*> children() const \
+    { \
+        Value* const* buffer = childrenArray(); \
+        return {buffer, buffer + n }; \
+    } \
+
+#define B3_SPECIALIZE_VALUE_FOR_NON_VARARGS_CHILDREN \
+public: \
+    unsigned numChildren() const { return m_numChildren; } \
+    Value*& child(unsigned index) { return childrenArray()[index]; } \
+    Value* child(unsigned index) const { return childrenArray()[index]; } \
+    Value*& lastChild() { return childrenArray()[numChildren() - 1]; } \
+    Value* lastChild() const { return childrenArray()[numChildren() - 1]; } \
+    WTF::IteratorRange<Value**> children() \
+    { \
+        Value** buffer = childrenArray(); \
+        return {buffer, buffer + numChildren() }; \
+    } \
+    WTF::IteratorRange<Value* const*> children() const \
+    { \
+        Value* const* buffer = childrenArray(); \
+        return {buffer, buffer + numChildren() }; \
+    } \
+
+#define B3_SPECIALIZE_VALUE_FOR_VARARGS_CHILDREN \
+public: \
+    unsigned numChildren() const { return childrenVector().size(); } \
+    Value*& child(unsigned index) { return childrenVector()[index]; } \
+    Value* child(unsigned index) const { return childrenVector()[index]; } \
+    Value*& lastChild() { return childrenVector().last(); } \
+    Value* lastChild() const { return childrenVector().last(); } \
+    WTF::IteratorRange<Value**> children() \
+    { \
+        Vector<Value*, 3>& vec = childrenVector(); \
+        return WTF::makeIteratorRange(&*vec.begin(), &*vec.end()); \
+    } \
+    WTF::IteratorRange<Value* const*> children() const \
+    { \
+        const Vector<Value*, 3>& vec = childrenVector(); \
+        return WTF::makeIteratorRange(&*vec.begin(), &*vec.end()); \
+    } \
+
+// Only use this for classes with no subclass that add new fields (as it uses sizeof(*this))
+// Also there is no point in applying this to classes with no children, as they don't have a children array to access.
+#define B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN \
+private: \
+    Value** childrenArray() \
+    { \
+        return bitwise_cast<Value**>(bitwise_cast<char*>(this) + sizeof(*this)); \
+    } \
+    Value* const* childrenArray() const \
+    { \
+        return bitwise_cast<Value* const*>(bitwise_cast<char const*>(this) + sizeof(*this)); \
+    }
+
+// Only use this for classes with no subclass that add new fields (as it uses sizeof(*this))
+#define B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_VARARGS_CHILDREN \
+private: \
+    Vector<Value*, 3>& childrenVector() \
+    { \
+        return *bitwise_cast<Vector<Value*, 3>*>(bitwise_cast<char*>(this) + sizeof(*this)); \
+    } \
+    const Vector<Value*, 3>& childrenVector() const \
+    { \
+        return *bitwise_cast<Vector<Value*, 3> const*>(bitwise_cast<char const*>(this) + sizeof(*this)); \
+    } \
+
</ins><span class="cx"> } } // namespace JSC::B3
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(B3_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3ValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3ValueInlines.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3ValueInlines.h  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3ValueInlines.h     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -27,19 +27,157 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(B3_JIT)
</span><span class="cx"> 
</span><ins>+#include "B3ArgumentRegValue.h"
+#include "B3AtomicValue.h"
+#include "B3CCallValue.h"
</ins><span class="cx"> #include "B3CheckValue.h"
</span><span class="cx"> #include "B3Const32Value.h"
</span><span class="cx"> #include "B3Const64Value.h"
</span><span class="cx"> #include "B3ConstDoubleValue.h"
</span><span class="cx"> #include "B3ConstFloatValue.h"
</span><ins>+#include "B3FenceValue.h"
+#include "B3MemoryValue.h"
</ins><span class="cx"> #include "B3PatchpointValue.h"
</span><span class="cx"> #include "B3PhiChildren.h"
</span><span class="cx"> #include "B3Procedure.h"
</span><ins>+#include "B3SlotBaseValue.h"
+#include "B3SwitchValue.h"
+#include "B3UpsilonValue.h"
</ins><span class="cx"> #include "B3Value.h"
</span><ins>+#include "B3VariableValue.h"
+#include "B3WasmAddressValue.h"
+#include "B3WasmBoundsCheckValue.h"
</ins><span class="cx"> #include <wtf/GraphNodeWorklist.h>
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace B3 {
</span><span class="cx"> 
</span><ins>+#define DISPATCH_ON_KIND(MACRO) \
+    switch (kind().opcode()) { \
+    case FramePointer: \
+    case Nop: \
+    case Phi: \
+    case Jump: \
+    case Oops: \
+    case EntrySwitch: \
+    case Return: \
+    case Identity: \
+    case Opaque: \
+    case Neg: \
+    case Clz: \
+    case Abs: \
+    case Ceil: \
+    case Floor: \
+    case Sqrt: \
+    case SExt8: \
+    case SExt16: \
+    case Trunc: \
+    case SExt32: \
+    case ZExt32: \
+    case FloatToDouble: \
+    case IToD: \
+    case DoubleToFloat: \
+    case IToF: \
+    case BitwiseCast: \
+    case Branch: \
+    case Depend: \
+    case Add: \
+    case Sub: \
+    case Mul: \
+    case Div: \
+    case UDiv: \
+    case Mod: \
+    case UMod: \
+    case BitAnd: \
+    case BitOr: \
+    case BitXor: \
+    case Shl: \
+    case SShr: \
+    case ZShr: \
+    case RotR: \
+    case RotL: \
+    case Equal: \
+    case NotEqual: \
+    case LessThan: \
+    case GreaterThan: \
+    case LessEqual: \
+    case GreaterEqual: \
+    case Above: \
+    case Below: \
+    case AboveEqual: \
+    case BelowEqual: \
+    case EqualOrUnordered: \
+    case Select: \
+        return MACRO(Value); \
+    case ArgumentReg: \
+        return MACRO(ArgumentRegValue); \
+    case Const32: \
+        return MACRO(Const32Value); \
+    case Const64: \
+        return MACRO(Const64Value); \
+    case ConstFloat: \
+        return MACRO(ConstFloatValue); \
+    case ConstDouble: \
+        return MACRO(ConstDoubleValue); \
+    case Fence: \
+        return MACRO(FenceValue); \
+    case SlotBase: \
+        return MACRO(SlotBaseValue); \
+    case Get: \
+    case Set: \
+        return MACRO(VariableValue); \
+    case Load8Z: \
+    case Load8S: \
+    case Load16Z: \
+    case Load16S: \
+    case Load: \
+    case Store8: \
+    case Store16: \
+    case Store: \
+        return MACRO(MemoryValue); \
+    case Switch: \
+        return MACRO(SwitchValue); \
+    case Upsilon: \
+        return MACRO(UpsilonValue); \
+    case WasmAddress: \
+        return MACRO(WasmAddressValue); \
+    case WasmBoundsCheck: \
+        return MACRO(WasmBoundsCheckValue); \
+    case AtomicXchgAdd: \
+    case AtomicXchgAnd: \
+    case AtomicXchgOr: \
+    case AtomicXchgSub: \
+    case AtomicXchgXor: \
+    case AtomicXchg: \
+    case AtomicWeakCAS: \
+    case AtomicStrongCAS: \
+        return MACRO(AtomicValue); \
+    case CCall: \
+        return MACRO(CCallValue); \
+    case Check: \
+    case CheckAdd: \
+    case CheckSub: \
+    case CheckMul: \
+        return MACRO(CheckValue); \
+    case Patchpoint: \
+        return MACRO(PatchpointValue); \
+    default: \
+        RELEASE_ASSERT_NOT_REACHED(); \
+    }
+
+ALWAYS_INLINE size_t Value::adjacencyListOffset() const
+{
+#define VALUE_TYPE_SIZE(ValueType) sizeof(ValueType)
+    DISPATCH_ON_KIND(VALUE_TYPE_SIZE);
+#undef VALUE_TYPE_SIZE
+}
+
+ALWAYS_INLINE Value* Value::cloneImpl() const
+{
+#define VALUE_TYPE_CLONE(ValueType) allocate<ValueType>(*static_cast<const ValueType*>(this))
+    DISPATCH_ON_KIND(VALUE_TYPE_CLONE);
+#undef VALUE_TYPE_CLONE
+}
+
</ins><span class="cx"> template<typename BottomProvider>
</span><span class="cx"> void Value::replaceWithBottom(const BottomProvider& bottomProvider)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3VariableValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3VariableValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3VariableValue.cpp       2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3VariableValue.cpp  2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -41,13 +41,8 @@
</span><span class="cx">     out.print(comma, pointerDump(m_variable));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* VariableValue::cloneImpl() const
-{
-    return new VariableValue(*this);
-}
-
</del><span class="cx"> VariableValue::VariableValue(Kind kind, Origin origin, Variable* variable, Value* value)
</span><del>-    : Value(CheckedOpcode, kind, Void, origin, value)
</del><ins>+    : Value(CheckedOpcode, kind, Void, One, origin, value)
</ins><span class="cx">     , m_variable(variable)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(kind == Set);
</span><span class="lines">@@ -54,7 +49,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> VariableValue::VariableValue(Kind kind, Origin origin, Variable* variable)
</span><del>-    : Value(CheckedOpcode, kind, variable->type(), origin)
</del><ins>+    : Value(CheckedOpcode, kind, variable->type(), Zero, origin)
</ins><span class="cx">     , m_variable(variable)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(kind == Get);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3VariableValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3VariableValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3VariableValue.h 2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3VariableValue.h    2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -41,13 +41,15 @@
</span><span class="cx"> 
</span><span class="cx">     Variable* variable() const { return m_variable; }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_NON_VARARGS_CHILDREN
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><span class="cx">     // Use this for Set.
</span><span class="cx">     VariableValue(Kind, Origin, Variable*, Value*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3WasmAddressValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.cpp    2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.cpp       2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -39,13 +39,8 @@
</span><span class="cx">     out.print(comma, m_pinnedGPR);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* WasmAddressValue::cloneImpl() const
-{
-    return new WasmAddressValue(*this);
-}
-
</del><span class="cx"> WasmAddressValue::WasmAddressValue(Origin origin, Value* value, GPRReg pinnedGPR)
</span><del>-    : Value(CheckedOpcode, WasmAddress, Int64, origin, value)
</del><ins>+    : Value(CheckedOpcode, WasmAddress, Int64, One, origin, value)
</ins><span class="cx">     , m_pinnedGPR(pinnedGPR)
</span><span class="cx"> {
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3WasmAddressValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.h      2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3WasmAddressValue.h 2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -40,14 +40,17 @@
</span><span class="cx"> 
</span><span class="cx">     GPRReg pinnedGPR() const { return m_pinnedGPR; }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(1)
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    static Opcode opcodeFromConstructor(Origin, Value*, GPRReg) { return WasmAddress; }
</ins><span class="cx">     WasmAddressValue(Origin, Value*, GPRReg);
</span><span class="cx"> 
</span><span class="cx">     GPRReg m_pinnedGPR;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3WasmBoundsCheckValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.cpp        2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.cpp   2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WasmBoundsCheckValue::WasmBoundsCheckValue(Origin origin, GPRReg pinnedSize, Value* ptr, unsigned offset)
</span><del>-    : Value(CheckedOpcode, WasmBoundsCheck, origin, ptr)
</del><ins>+    : Value(CheckedOpcode, WasmBoundsCheck, One, origin, ptr)
</ins><span class="cx">     , m_offset(offset)
</span><span class="cx">     , m_boundsType(Type::Pinned)
</span><span class="cx"> {
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WasmBoundsCheckValue::WasmBoundsCheckValue(Origin origin, Value* ptr, unsigned offset, size_t maximum)
</span><del>-    : Value(CheckedOpcode, WasmBoundsCheck, origin, ptr)
</del><ins>+    : Value(CheckedOpcode, WasmBoundsCheck, One, origin, ptr)
</ins><span class="cx">     , m_offset(offset)
</span><span class="cx">     , m_boundsType(Type::Maximum)
</span><span class="cx"> {
</span><span class="lines">@@ -55,11 +55,6 @@
</span><span class="cx">     m_bounds.maximum = maximum;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Value* WasmBoundsCheckValue::cloneImpl() const
-{
-    return new WasmBoundsCheckValue(*this);
-}
-
</del><span class="cx"> void WasmBoundsCheckValue::dumpMeta(CommaPrinter& comma, PrintStream& out) const
</span><span class="cx"> {
</span><span class="cx">     switch (m_boundsType) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3B3WasmBoundsCheckValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.h  2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/B3WasmBoundsCheckValue.h     2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -34,15 +34,7 @@
</span><span class="cx"> 
</span><span class="cx"> class WasmBoundsCheckValue : public Value {
</span><span class="cx"> public:
</span><del>-    static bool accepts(Kind kind)
-    {
-        switch (kind.opcode()) {
-        case WasmBoundsCheck:
-            return true;
-        default:
-            return false;
-        }
-    }
</del><ins>+    static bool accepts(Kind kind) { return kind == WasmBoundsCheck; }
</ins><span class="cx">     
</span><span class="cx">     ~WasmBoundsCheckValue();
</span><span class="cx"> 
</span><span class="lines">@@ -60,15 +52,20 @@
</span><span class="cx">     Type boundsType() const { return m_boundsType; }
</span><span class="cx">     Bounds bounds() const { return m_bounds; }
</span><span class="cx"> 
</span><ins>+    B3_SPECIALIZE_VALUE_FOR_FIXED_CHILDREN(1)
+    B3_SPECIALIZE_VALUE_FOR_FINAL_SIZE_FIXED_CHILDREN
+
</ins><span class="cx"> protected:
</span><span class="cx">     void dumpMeta(CommaPrinter&, PrintStream&) const override;
</span><span class="cx"> 
</span><del>-    Value* cloneImpl() const override;
-
</del><span class="cx"> private:
</span><span class="cx">     friend class Procedure;
</span><ins>+    friend class Value;
</ins><span class="cx"> 
</span><ins>+    static Opcode opcodeFromConstructor(Origin, GPRReg, Value*, unsigned) { return WasmBoundsCheck; }
</ins><span class="cx">     JS_EXPORT_PRIVATE WasmBoundsCheckValue(Origin, GPRReg pinnedGPR, Value* ptr, unsigned offset);
</span><ins>+
+    static Opcode opcodeFromConstructor(Origin, Value*, unsigned, size_t) { return WasmBoundsCheck; }
</ins><span class="cx">     JS_EXPORT_PRIVATE WasmBoundsCheckValue(Origin, Value* ptr, unsigned offset, size_t maximum);
</span><span class="cx"> 
</span><span class="cx">     unsigned m_offset;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreb3testb3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/b3/testb3.cpp (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/b3/testb3.cpp        2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/b3/testb3.cpp   2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -10960,7 +10960,7 @@
</span><span class="cx">     CCallValue* call = root->appendNew<CCallValue>(
</span><span class="cx">         proc, Int32, Origin(),
</span><span class="cx">         root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments, B3CCallPtrTag)));
</span><del>-    call->children().appendVector(args);
</del><ins>+    call->appendArgs(args);
</ins><span class="cx">     
</span><span class="cx">     root->appendNewControlValue(proc, Return, Origin(), call);
</span><span class="cx"> 
</span><span class="lines">@@ -10986,7 +10986,7 @@
</span><span class="cx">     CCallValue* call = root->appendNew<CCallValue>(
</span><span class="cx">         proc, Int64, Origin(),
</span><span class="cx">         root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments2, B3CCallPtrTag)));
</span><del>-    call->children().appendVector(args);
</del><ins>+    call->appendArgs(args);
</ins><span class="cx">     
</span><span class="cx">     root->appendNewControlValue(proc, Return, Origin(), call);
</span><span class="cx"> 
</span><span class="lines">@@ -11008,7 +11008,7 @@
</span><span class="cx">     CCallValue* call = root->appendNew<CCallValue>(
</span><span class="cx">         proc, Int32, Origin(),
</span><span class="cx">         root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaArguments3, B3CCallPtrTag)));
</span><del>-    call->children().appendVector(args);
</del><ins>+    call->appendArgs(args);
</ins><span class="cx">     
</span><span class="cx">     root->appendNewControlValue(proc, Return, Origin(), call);
</span><span class="cx"> 
</span><span class="lines">@@ -11108,7 +11108,7 @@
</span><span class="cx">     CCallValue* call = root->appendNew<CCallValue>(
</span><span class="cx">         proc, Double, Origin(),
</span><span class="cx">         root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaDoubleArguments, B3CCallPtrTag)));
</span><del>-    call->children().appendVector(args);
</del><ins>+    call->appendArgs(args);
</ins><span class="cx">     
</span><span class="cx">     root->appendNewControlValue(proc, Return, Origin(), call);
</span><span class="cx"> 
</span><span class="lines">@@ -11132,7 +11132,7 @@
</span><span class="cx">     CCallValue* call = root->appendNew<CCallValue>(
</span><span class="cx">         proc, Float, Origin(),
</span><span class="cx">         root->appendNew<ConstPtrValue>(proc, Origin(), tagCFunctionPtr<void*>(functionWithHellaFloatArguments, B3CCallPtrTag)));
</span><del>-    call->children().appendVector(args);
</del><ins>+    call->appendArgs(args);
</ins><span class="cx">     
</span><span class="cx">     root->appendNewControlValue(proc, Return, Origin(), call);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOutputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOutput.h (244308 => 244309)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOutput.h      2019-04-15 23:48:57 UTC (rev 244308)
+++ trunk/Source/JavaScriptCore/ftl/FTLOutput.h 2019-04-15 23:53:23 UTC (rev 244309)
</span><span class="lines">@@ -380,7 +380,7 @@
</span><span class="cx">     LValue call(LType type, LValue function, const VectorType& vector)
</span><span class="cx">     {
</span><span class="cx">         B3::CCallValue* result = m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function);
</span><del>-        result->children().appendVector(vector);
</del><ins>+        result->appendArgs(vector);
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     LValue call(LType type, LValue function) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function); }
</span></span></pre>
</div>
</div>

</body>
</html>