[BigInt] Add ValueSub into DFG
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGByteCodeParser.cpp
1 /*
2  * Copyright (C) 2011-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGByteCodeParser.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "ArithProfile.h"
32 #include "ArrayConstructor.h"
33 #include "BasicBlockLocation.h"
34 #include "BuiltinNames.h"
35 #include "BytecodeStructs.h"
36 #include "CallLinkStatus.h"
37 #include "CodeBlock.h"
38 #include "CodeBlockWithJITType.h"
39 #include "CommonSlowPaths.h"
40 #include "DFGAbstractHeap.h"
41 #include "DFGArrayMode.h"
42 #include "DFGCFG.h"
43 #include "DFGCapabilities.h"
44 #include "DFGClobberize.h"
45 #include "DFGClobbersExitState.h"
46 #include "DFGGraph.h"
47 #include "DFGJITCode.h"
48 #include "FunctionCodeBlock.h"
49 #include "GetByIdStatus.h"
50 #include "Heap.h"
51 #include "InByIdStatus.h"
52 #include "InstanceOfStatus.h"
53 #include "JSCInlines.h"
54 #include "JSFixedArray.h"
55 #include "JSImmutableButterfly.h"
56 #include "JSModuleEnvironment.h"
57 #include "JSModuleNamespaceObject.h"
58 #include "NumberConstructor.h"
59 #include "ObjectConstructor.h"
60 #include "OpcodeInlines.h"
61 #include "PreciseJumpTargets.h"
62 #include "PutByIdFlags.h"
63 #include "PutByIdStatus.h"
64 #include "RegExpPrototype.h"
65 #include "StackAlignment.h"
66 #include "StringConstructor.h"
67 #include "StructureStubInfo.h"
68 #include "Watchdog.h"
69 #include <wtf/CommaPrinter.h>
70 #include <wtf/HashMap.h>
71 #include <wtf/MathExtras.h>
72 #include <wtf/SetForScope.h>
73 #include <wtf/StdLibExtras.h>
74
75 namespace JSC { namespace DFG {
76
77 namespace DFGByteCodeParserInternal {
78 #ifdef NDEBUG
79 static const bool verbose = false;
80 #else
81 static const bool verbose = true;
82 #endif
83 } // namespace DFGByteCodeParserInternal
84
85 #define VERBOSE_LOG(...) do { \
86 if (DFGByteCodeParserInternal::verbose && Options::verboseDFGBytecodeParsing()) \
87 dataLog(__VA_ARGS__); \
88 } while (false)
89
90 // === ByteCodeParser ===
91 //
92 // This class is used to compile the dataflow graph from a CodeBlock.
93 class ByteCodeParser {
94 public:
95     ByteCodeParser(Graph& graph)
96         : m_vm(&graph.m_vm)
97         , m_codeBlock(graph.m_codeBlock)
98         , m_profiledBlock(graph.m_profiledBlock)
99         , m_graph(graph)
100         , m_currentBlock(0)
101         , m_currentIndex(0)
102         , m_constantUndefined(graph.freeze(jsUndefined()))
103         , m_constantNull(graph.freeze(jsNull()))
104         , m_constantNaN(graph.freeze(jsNumber(PNaN)))
105         , m_constantOne(graph.freeze(jsNumber(1)))
106         , m_numArguments(m_codeBlock->numParameters())
107         , m_numLocals(m_codeBlock->numCalleeLocals())
108         , m_parameterSlots(0)
109         , m_numPassedVarArgs(0)
110         , m_inlineStackTop(0)
111         , m_currentInstruction(0)
112         , m_hasDebuggerEnabled(graph.hasDebuggerEnabled())
113     {
114         ASSERT(m_profiledBlock);
115     }
116     
117     // Parse a full CodeBlock of bytecode.
118     void parse();
119     
120 private:
121     struct InlineStackEntry;
122
123     // Just parse from m_currentIndex to the end of the current CodeBlock.
124     void parseCodeBlock();
125     
126     void ensureLocals(unsigned newNumLocals)
127     {
128         VERBOSE_LOG("   ensureLocals: trying to raise m_numLocals from ", m_numLocals, " to ", newNumLocals, "\n");
129         if (newNumLocals <= m_numLocals)
130             return;
131         m_numLocals = newNumLocals;
132         for (size_t i = 0; i < m_graph.numBlocks(); ++i)
133             m_graph.block(i)->ensureLocals(newNumLocals);
134     }
135
136     // Helper for min and max.
137     template<typename ChecksFunctor>
138     bool handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks);
139     
140     void refineStatically(CallLinkStatus&, Node* callTarget);
141     // Blocks can either be targetable (i.e. in the m_blockLinkingTargets of one InlineStackEntry) with a well-defined bytecodeBegin,
142     // or they can be untargetable, with bytecodeBegin==UINT_MAX, to be managed manually and not by the linkBlock machinery.
143     // This is used most notably when doing polyvariant inlining (it requires a fair bit of control-flow with no bytecode analog).
144     // It is also used when doing an early return from an inlined callee: it is easier to fix the bytecode index later on if needed
145     // than to move the right index all the way to the treatment of op_ret.
146     BasicBlock* allocateTargetableBlock(unsigned bytecodeIndex);
147     BasicBlock* allocateUntargetableBlock();
148     // An untargetable block can be given a bytecodeIndex to be later managed by linkBlock, but only once, and it can never go in the other direction
149     void makeBlockTargetable(BasicBlock*, unsigned bytecodeIndex);
150     void addJumpTo(BasicBlock*);
151     void addJumpTo(unsigned bytecodeIndex);
152     // Handle calls. This resolves issues surrounding inlining and intrinsics.
153     enum Terminality { Terminal, NonTerminal };
154     Terminality handleCall(
155         int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
156         Node* callTarget, int argumentCountIncludingThis, int registerOffset, CallLinkStatus,
157         SpeculatedType prediction);
158     Terminality handleCall(Instruction* pc, NodeType op, CallMode);
159     Terminality handleVarargsCall(Instruction* pc, NodeType op, CallMode);
160     void emitFunctionChecks(CallVariant, Node* callTarget, VirtualRegister thisArgumnt);
161     void emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis);
162     Node* getArgumentCount();
163     template<typename ChecksFunctor>
164     bool handleRecursiveTailCall(Node* callTargetNode, CallVariant, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& emitFunctionCheckIfNeeded);
165     unsigned inliningCost(CallVariant, int argumentCountIncludingThis, InlineCallFrame::Kind); // Return UINT_MAX if it's not an inlining candidate. By convention, intrinsics have a cost of 1.
166     // Handle inlining. Return true if it succeeded, false if we need to plant a call.
167     bool handleVarargsInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, VirtualRegister argumentsArgument, unsigned argumentsOffset, NodeType callOp, InlineCallFrame::Kind);
168     unsigned getInliningBalance(const CallLinkStatus&, CodeSpecializationKind);
169     enum class CallOptimizationResult { OptimizedToJump, Inlined, DidNothing };
170     CallOptimizationResult handleCallVariant(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, VirtualRegister thisArgument, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, bool needsToCheckCallee);
171     CallOptimizationResult handleInlining(Node* callTargetNode, int resultOperand, const CallLinkStatus&, int registerOffset, VirtualRegister thisArgument, int argumentCountIncludingThis, unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind, SpeculatedType prediction);
172     template<typename ChecksFunctor>
173     void inlineCall(Node* callTargetNode, int resultOperand, CallVariant, int registerOffset, int argumentCountIncludingThis, InlineCallFrame::Kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks);
174     // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call.
175     template<typename ChecksFunctor>
176     bool handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
177     template<typename ChecksFunctor>
178     bool handleDOMJITCall(Node* callee, int resultOperand, const DOMJIT::Signature*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks);
179     template<typename ChecksFunctor>
180     bool handleIntrinsicGetter(int resultOperand, SpeculatedType prediction, const GetByIdVariant& intrinsicVariant, Node* thisNode, const ChecksFunctor& insertChecks);
181     template<typename ChecksFunctor>
182     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor& insertChecks);
183     template<typename ChecksFunctor>
184     bool handleConstantInternalFunction(Node* callTargetNode, int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, SpeculatedType, const ChecksFunctor& insertChecks);
185     Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value);
186     Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset);
187     bool handleDOMJITGetter(int resultOperand, const GetByIdVariant&, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction);
188     bool handleModuleNamespaceLoad(int resultOperand, SpeculatedType, Node* base, GetByIdStatus);
189
190     // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
191     // check the validity of the condition, but it may return a null one if it encounters a contradiction.
192     ObjectPropertyCondition presenceLike(
193         JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
194     
195     // Attempt to watch the presence of a property. It will watch that the property is present in the same
196     // way as in all of the structures in the set. It may emit code instead of just setting a watchpoint.
197     // Returns true if this all works out.
198     bool checkPresenceLike(JSObject* knownBase, UniquedStringImpl*, PropertyOffset, const StructureSet&);
199     void checkPresenceLike(Node* base, UniquedStringImpl*, PropertyOffset, const StructureSet&);
200     
201     // Works with both GetByIdVariant and the setter form of PutByIdVariant.
202     template<typename VariantType>
203     Node* load(SpeculatedType, Node* base, unsigned identifierNumber, const VariantType&);
204
205     Node* store(Node* base, unsigned identifier, const PutByIdVariant&, Node* value);
206
207     void handleGetById(
208         int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber, GetByIdStatus, AccessType, unsigned instructionSize);
209     void emitPutById(
210         Node* base, unsigned identifierNumber, Node* value,  const PutByIdStatus&, bool isDirect);
211     void handlePutById(
212         Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
213         bool isDirect);
214     
215     // Either register a watchpoint or emit a check for this condition. Returns false if the
216     // condition no longer holds, and therefore no reasonable check can be emitted.
217     bool check(const ObjectPropertyCondition&);
218     
219     GetByOffsetMethod promoteToConstant(GetByOffsetMethod);
220     
221     // Either register a watchpoint or emit a check for this condition. It must be a Presence
222     // condition. It will attempt to promote a Presence condition to an Equivalence condition.
223     // Emits code for the loaded value that the condition guards, and returns a node containing
224     // the loaded value. Returns null if the condition no longer holds.
225     GetByOffsetMethod planLoad(const ObjectPropertyCondition&);
226     Node* load(SpeculatedType, unsigned identifierNumber, const GetByOffsetMethod&, NodeType = GetByOffset);
227     Node* load(SpeculatedType, const ObjectPropertyCondition&, NodeType = GetByOffset);
228     
229     // Calls check() for each condition in the set: that is, it either emits checks or registers
230     // watchpoints (or a combination of the two) to make the conditions hold. If any of those
231     // conditions are no longer checkable, returns false.
232     bool check(const ObjectPropertyConditionSet&);
233     
234     // Calls check() for those conditions that aren't the slot base, and calls load() for the slot
235     // base. Does a combination of watchpoint registration and check emission to guard the
236     // conditions, and emits code to load the value from the slot base. Returns a node containing
237     // the loaded value. Returns null if any of the conditions were no longer checkable.
238     GetByOffsetMethod planLoad(const ObjectPropertyConditionSet&);
239     Node* load(SpeculatedType, const ObjectPropertyConditionSet&, NodeType = GetByOffset);
240
241     void prepareToParseBlock();
242     void clearCaches();
243
244     // Parse a single basic block of bytecode instructions.
245     void parseBlock(unsigned limit);
246     // Link block successors.
247     void linkBlock(BasicBlock*, Vector<BasicBlock*>& possibleTargets);
248     void linkBlocks(Vector<BasicBlock*>& unlinkedBlocks, Vector<BasicBlock*>& possibleTargets);
249     
250     VariableAccessData* newVariableAccessData(VirtualRegister operand)
251     {
252         ASSERT(!operand.isConstant());
253         
254         m_graph.m_variableAccessData.append(VariableAccessData(operand));
255         return &m_graph.m_variableAccessData.last();
256     }
257     
258     // Get/Set the operands/result of a bytecode instruction.
259     Node* getDirect(VirtualRegister operand)
260     {
261         ASSERT(!operand.isConstant());
262
263         // Is this an argument?
264         if (operand.isArgument())
265             return getArgument(operand);
266
267         // Must be a local.
268         return getLocal(operand);
269     }
270
271     Node* get(VirtualRegister operand)
272     {
273         if (operand.isConstant()) {
274             unsigned constantIndex = operand.toConstantIndex();
275             unsigned oldSize = m_constants.size();
276             if (constantIndex >= oldSize || !m_constants[constantIndex]) {
277                 const CodeBlock& codeBlock = *m_inlineStackTop->m_codeBlock;
278                 JSValue value = codeBlock.getConstant(operand.offset());
279                 SourceCodeRepresentation sourceCodeRepresentation = codeBlock.constantSourceCodeRepresentation(operand.offset());
280                 if (constantIndex >= oldSize) {
281                     m_constants.grow(constantIndex + 1);
282                     for (unsigned i = oldSize; i < m_constants.size(); ++i)
283                         m_constants[i] = nullptr;
284                 }
285
286                 Node* constantNode = nullptr;
287                 if (sourceCodeRepresentation == SourceCodeRepresentation::Double)
288                     constantNode = addToGraph(DoubleConstant, OpInfo(m_graph.freezeStrong(jsDoubleNumber(value.asNumber()))));
289                 else
290                     constantNode = addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(value)));
291                 m_constants[constantIndex] = constantNode;
292             }
293             ASSERT(m_constants[constantIndex]);
294             return m_constants[constantIndex];
295         }
296         
297         if (inlineCallFrame()) {
298             if (!inlineCallFrame()->isClosureCall) {
299                 JSFunction* callee = inlineCallFrame()->calleeConstant();
300                 if (operand.offset() == CallFrameSlot::callee)
301                     return weakJSConstant(callee);
302             }
303         } else if (operand.offset() == CallFrameSlot::callee) {
304             // We have to do some constant-folding here because this enables CreateThis folding. Note
305             // that we don't have such watchpoint-based folding for inlined uses of Callee, since in that
306             // case if the function is a singleton then we already know it.
307             if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(*m_vm, m_codeBlock->ownerExecutable())) {
308                 InferredValue* singleton = executable->singletonFunction();
309                 if (JSValue value = singleton->inferredValue()) {
310                     m_graph.watchpoints().addLazily(singleton);
311                     JSFunction* function = jsCast<JSFunction*>(value);
312                     return weakJSConstant(function);
313                 }
314             }
315             return addToGraph(GetCallee);
316         }
317         
318         return getDirect(m_inlineStackTop->remapOperand(operand));
319     }
320     
321     enum SetMode {
322         // A normal set which follows a two-phase commit that spans code origins. During
323         // the current code origin it issues a MovHint, and at the start of the next
324         // code origin there will be a SetLocal. If the local needs flushing, the second
325         // SetLocal will be preceded with a Flush.
326         NormalSet,
327         
328         // A set where the SetLocal happens immediately and there is still a Flush. This
329         // is relevant when assigning to a local in tricky situations for the delayed
330         // SetLocal logic but where we know that we have not performed any side effects
331         // within this code origin. This is a safe replacement for NormalSet anytime we
332         // know that we have not yet performed side effects in this code origin.
333         ImmediateSetWithFlush,
334         
335         // A set where the SetLocal happens immediately and we do not Flush it even if
336         // this is a local that is marked as needing it. This is relevant when
337         // initializing locals at the top of a function.
338         ImmediateNakedSet
339     };
340     Node* setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
341     {
342         addToGraph(MovHint, OpInfo(operand.offset()), value);
343
344         // We can't exit anymore because our OSR exit state has changed.
345         m_exitOK = false;
346
347         DelayedSetLocal delayed(currentCodeOrigin(), operand, value, setMode);
348         
349         if (setMode == NormalSet) {
350             m_setLocalQueue.append(delayed);
351             return nullptr;
352         }
353         
354         return delayed.execute(this);
355     }
356     
357     void processSetLocalQueue()
358     {
359         for (unsigned i = 0; i < m_setLocalQueue.size(); ++i)
360             m_setLocalQueue[i].execute(this);
361         m_setLocalQueue.shrink(0);
362     }
363
364     Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
365     {
366         return setDirect(m_inlineStackTop->remapOperand(operand), value, setMode);
367     }
368     
369     Node* injectLazyOperandSpeculation(Node* node)
370     {
371         ASSERT(node->op() == GetLocal);
372         ASSERT(node->origin.semantic.bytecodeIndex == m_currentIndex);
373         ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
374         LazyOperandValueProfileKey key(m_currentIndex, node->local());
375         SpeculatedType prediction = m_inlineStackTop->m_lazyOperands.prediction(locker, key);
376         node->variableAccessData()->predict(prediction);
377         return node;
378     }
379
380     // Used in implementing get/set, above, where the operand is a local variable.
381     Node* getLocal(VirtualRegister operand)
382     {
383         unsigned local = operand.toLocal();
384
385         Node* node = m_currentBlock->variablesAtTail.local(local);
386         
387         // This has two goals: 1) link together variable access datas, and 2)
388         // try to avoid creating redundant GetLocals. (1) is required for
389         // correctness - no other phase will ensure that block-local variable
390         // access data unification is done correctly. (2) is purely opportunistic
391         // and is meant as an compile-time optimization only.
392         
393         VariableAccessData* variable;
394         
395         if (node) {
396             variable = node->variableAccessData();
397             
398             switch (node->op()) {
399             case GetLocal:
400                 return node;
401             case SetLocal:
402                 return node->child1().node();
403             default:
404                 break;
405             }
406         } else
407             variable = newVariableAccessData(operand);
408         
409         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
410         m_currentBlock->variablesAtTail.local(local) = node;
411         return node;
412     }
413     Node* setLocal(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
414     {
415         SetForScope<CodeOrigin> originChange(m_currentSemanticOrigin, semanticOrigin);
416
417         unsigned local = operand.toLocal();
418         
419         if (setMode != ImmediateNakedSet) {
420             ArgumentPosition* argumentPosition = findArgumentPositionForLocal(operand);
421             if (argumentPosition)
422                 flushDirect(operand, argumentPosition);
423             else if (m_graph.needsScopeRegister() && operand == m_codeBlock->scopeRegister())
424                 flush(operand);
425         }
426
427         VariableAccessData* variableAccessData = newVariableAccessData(operand);
428         variableAccessData->mergeStructureCheckHoistingFailed(
429             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
430         variableAccessData->mergeCheckArrayHoistingFailed(
431             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
432         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
433         m_currentBlock->variablesAtTail.local(local) = node;
434         return node;
435     }
436
437     // Used in implementing get/set, above, where the operand is an argument.
438     Node* getArgument(VirtualRegister operand)
439     {
440         unsigned argument = operand.toArgument();
441         ASSERT(argument < m_numArguments);
442         
443         Node* node = m_currentBlock->variablesAtTail.argument(argument);
444
445         VariableAccessData* variable;
446         
447         if (node) {
448             variable = node->variableAccessData();
449             
450             switch (node->op()) {
451             case GetLocal:
452                 return node;
453             case SetLocal:
454                 return node->child1().node();
455             default:
456                 break;
457             }
458         } else
459             variable = newVariableAccessData(operand);
460         
461         node = injectLazyOperandSpeculation(addToGraph(GetLocal, OpInfo(variable)));
462         m_currentBlock->variablesAtTail.argument(argument) = node;
463         return node;
464     }
465     Node* setArgument(const CodeOrigin& semanticOrigin, VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
466     {
467         SetForScope<CodeOrigin> originChange(m_currentSemanticOrigin, semanticOrigin);
468
469         unsigned argument = operand.toArgument();
470         ASSERT(argument < m_numArguments);
471         
472         VariableAccessData* variableAccessData = newVariableAccessData(operand);
473
474         // Always flush arguments, except for 'this'. If 'this' is created by us,
475         // then make sure that it's never unboxed.
476         if (argument || m_graph.needsFlushedThis()) {
477             if (setMode != ImmediateNakedSet)
478                 flushDirect(operand);
479         }
480         
481         if (!argument && m_codeBlock->specializationKind() == CodeForConstruct)
482             variableAccessData->mergeShouldNeverUnbox(true);
483         
484         variableAccessData->mergeStructureCheckHoistingFailed(
485             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadCache));
486         variableAccessData->mergeCheckArrayHoistingFailed(
487             m_inlineStackTop->m_exitProfile.hasExitSite(semanticOrigin.bytecodeIndex, BadIndexingType));
488         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
489         m_currentBlock->variablesAtTail.argument(argument) = node;
490         return node;
491     }
492     
493     ArgumentPosition* findArgumentPositionForArgument(int argument)
494     {
495         InlineStackEntry* stack = m_inlineStackTop;
496         while (stack->m_inlineCallFrame)
497             stack = stack->m_caller;
498         return stack->m_argumentPositions[argument];
499     }
500     
501     ArgumentPosition* findArgumentPositionForLocal(VirtualRegister operand)
502     {
503         for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) {
504             InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame;
505             if (!inlineCallFrame)
506                 break;
507             if (operand.offset() < static_cast<int>(inlineCallFrame->stackOffset + CallFrame::headerSizeInRegisters))
508                 continue;
509             if (operand.offset() >= static_cast<int>(inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset() + inlineCallFrame->argumentsWithFixup.size()))
510                 continue;
511             int argument = VirtualRegister(operand.offset() - inlineCallFrame->stackOffset).toArgument();
512             return stack->m_argumentPositions[argument];
513         }
514         return 0;
515     }
516     
517     ArgumentPosition* findArgumentPosition(VirtualRegister operand)
518     {
519         if (operand.isArgument())
520             return findArgumentPositionForArgument(operand.toArgument());
521         return findArgumentPositionForLocal(operand);
522     }
523
524     template<typename AddFlushDirectFunc>
525     void flushImpl(InlineCallFrame* inlineCallFrame, const AddFlushDirectFunc& addFlushDirect)
526     {
527         int numArguments;
528         if (inlineCallFrame) {
529             ASSERT(!m_graph.hasDebuggerEnabled());
530             numArguments = inlineCallFrame->argumentsWithFixup.size();
531             if (inlineCallFrame->isClosureCall)
532                 addFlushDirect(inlineCallFrame, remapOperand(inlineCallFrame, VirtualRegister(CallFrameSlot::callee)));
533             if (inlineCallFrame->isVarargs())
534                 addFlushDirect(inlineCallFrame, remapOperand(inlineCallFrame, VirtualRegister(CallFrameSlot::argumentCount)));
535         } else
536             numArguments = m_graph.baselineCodeBlockFor(inlineCallFrame)->numParameters();
537
538         for (unsigned argument = numArguments; argument--;)
539             addFlushDirect(inlineCallFrame, remapOperand(inlineCallFrame, virtualRegisterForArgument(argument)));
540
541         if (m_graph.needsScopeRegister())
542             addFlushDirect(nullptr, m_graph.m_codeBlock->scopeRegister());
543     }
544
545     template<typename AddFlushDirectFunc, typename AddPhantomLocalDirectFunc>
546     void flushForTerminalImpl(CodeOrigin origin, const AddFlushDirectFunc& addFlushDirect, const AddPhantomLocalDirectFunc& addPhantomLocalDirect)
547     {
548         origin.walkUpInlineStack(
549             [&] (CodeOrigin origin) {
550                 unsigned bytecodeIndex = origin.bytecodeIndex;
551                 InlineCallFrame* inlineCallFrame = origin.inlineCallFrame;
552                 flushImpl(inlineCallFrame, addFlushDirect);
553
554                 CodeBlock* codeBlock = m_graph.baselineCodeBlockFor(inlineCallFrame);
555                 FullBytecodeLiveness& fullLiveness = m_graph.livenessFor(codeBlock);
556                 const FastBitVector& livenessAtBytecode = fullLiveness.getLiveness(bytecodeIndex);
557
558                 for (unsigned local = codeBlock->numCalleeLocals(); local--;) {
559                     if (livenessAtBytecode[local])
560                         addPhantomLocalDirect(inlineCallFrame, remapOperand(inlineCallFrame, virtualRegisterForLocal(local)));
561                 }
562             });
563     }
564
565     void flush(VirtualRegister operand)
566     {
567         flushDirect(m_inlineStackTop->remapOperand(operand));
568     }
569     
570     void flushDirect(VirtualRegister operand)
571     {
572         flushDirect(operand, findArgumentPosition(operand));
573     }
574
575     void flushDirect(VirtualRegister operand, ArgumentPosition* argumentPosition)
576     {
577         addFlushOrPhantomLocal<Flush>(operand, argumentPosition);
578     }
579
580     template<NodeType nodeType>
581     void addFlushOrPhantomLocal(VirtualRegister operand, ArgumentPosition* argumentPosition)
582     {
583         ASSERT(!operand.isConstant());
584         
585         Node* node = m_currentBlock->variablesAtTail.operand(operand);
586         
587         VariableAccessData* variable;
588         
589         if (node)
590             variable = node->variableAccessData();
591         else
592             variable = newVariableAccessData(operand);
593         
594         node = addToGraph(nodeType, OpInfo(variable));
595         m_currentBlock->variablesAtTail.operand(operand) = node;
596         if (argumentPosition)
597             argumentPosition->addVariable(variable);
598     }
599
600     void phantomLocalDirect(VirtualRegister operand)
601     {
602         addFlushOrPhantomLocal<PhantomLocal>(operand, findArgumentPosition(operand));
603     }
604
605     void flush(InlineStackEntry* inlineStackEntry)
606     {
607         auto addFlushDirect = [&] (InlineCallFrame*, VirtualRegister reg) { flushDirect(reg); };
608         flushImpl(inlineStackEntry->m_inlineCallFrame, addFlushDirect);
609     }
610
611     void flushForTerminal()
612     {
613         auto addFlushDirect = [&] (InlineCallFrame*, VirtualRegister reg) { flushDirect(reg); };
614         auto addPhantomLocalDirect = [&] (InlineCallFrame*, VirtualRegister reg) { phantomLocalDirect(reg); };
615         flushForTerminalImpl(currentCodeOrigin(), addFlushDirect, addPhantomLocalDirect);
616     }
617
618     void flushForReturn()
619     {
620         flush(m_inlineStackTop);
621     }
622     
623     void flushIfTerminal(SwitchData& data)
624     {
625         if (data.fallThrough.bytecodeIndex() > m_currentIndex)
626             return;
627         
628         for (unsigned i = data.cases.size(); i--;) {
629             if (data.cases[i].target.bytecodeIndex() > m_currentIndex)
630                 return;
631         }
632         
633         flushForTerminal();
634     }
635
636     // Assumes that the constant should be strongly marked.
637     Node* jsConstant(JSValue constantValue)
638     {
639         return addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(constantValue)));
640     }
641
642     Node* weakJSConstant(JSValue constantValue)
643     {
644         return addToGraph(JSConstant, OpInfo(m_graph.freeze(constantValue)));
645     }
646
647     // Helper functions to get/set the this value.
648     Node* getThis()
649     {
650         return get(m_inlineStackTop->m_codeBlock->thisRegister());
651     }
652
653     void setThis(Node* value)
654     {
655         set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
656     }
657
658     InlineCallFrame* inlineCallFrame()
659     {
660         return m_inlineStackTop->m_inlineCallFrame;
661     }
662
663     bool allInlineFramesAreTailCalls()
664     {
665         return !inlineCallFrame() || !inlineCallFrame()->getCallerSkippingTailCalls();
666     }
667
668     CodeOrigin currentCodeOrigin()
669     {
670         return CodeOrigin(m_currentIndex, inlineCallFrame());
671     }
672
673     NodeOrigin currentNodeOrigin()
674     {
675         CodeOrigin semantic;
676         CodeOrigin forExit;
677
678         if (m_currentSemanticOrigin.isSet())
679             semantic = m_currentSemanticOrigin;
680         else
681             semantic = currentCodeOrigin();
682
683         forExit = currentCodeOrigin();
684
685         return NodeOrigin(semantic, forExit, m_exitOK);
686     }
687     
688     BranchData* branchData(unsigned taken, unsigned notTaken)
689     {
690         // We assume that branches originating from bytecode always have a fall-through. We
691         // use this assumption to avoid checking for the creation of terminal blocks.
692         ASSERT((taken > m_currentIndex) || (notTaken > m_currentIndex));
693         BranchData* data = m_graph.m_branchData.add();
694         *data = BranchData::withBytecodeIndices(taken, notTaken);
695         return data;
696     }
697     
698     Node* addToGraph(Node* node)
699     {
700         VERBOSE_LOG("        appended ", node, " ", Graph::opName(node->op()), "\n");
701
702         m_hasAnyForceOSRExits |= (node->op() == ForceOSRExit);
703
704         m_currentBlock->append(node);
705         if (clobbersExitState(m_graph, node))
706             m_exitOK = false;
707         return node;
708     }
709     
710     Node* addToGraph(NodeType op, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
711     {
712         Node* result = m_graph.addNode(
713             op, currentNodeOrigin(), Edge(child1), Edge(child2),
714             Edge(child3));
715         return addToGraph(result);
716     }
717     Node* addToGraph(NodeType op, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
718     {
719         Node* result = m_graph.addNode(
720             op, currentNodeOrigin(), child1, child2, child3);
721         return addToGraph(result);
722     }
723     Node* addToGraph(NodeType op, OpInfo info, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
724     {
725         Node* result = m_graph.addNode(
726             op, currentNodeOrigin(), info, Edge(child1), Edge(child2),
727             Edge(child3));
728         return addToGraph(result);
729     }
730     Node* addToGraph(NodeType op, OpInfo info, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
731     {
732         Node* result = m_graph.addNode(op, currentNodeOrigin(), info, child1, child2, child3);
733         return addToGraph(result);
734     }
735     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
736     {
737         Node* result = m_graph.addNode(
738             op, currentNodeOrigin(), info1, info2,
739             Edge(child1), Edge(child2), Edge(child3));
740         return addToGraph(result);
741     }
742     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
743     {
744         Node* result = m_graph.addNode(
745             op, currentNodeOrigin(), info1, info2, child1, child2, child3);
746         return addToGraph(result);
747     }
748     
749     Node* addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2 = OpInfo())
750     {
751         Node* result = m_graph.addNode(
752             Node::VarArg, op, currentNodeOrigin(), info1, info2,
753             m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs);
754         addToGraph(result);
755         
756         m_numPassedVarArgs = 0;
757         
758         return result;
759     }
760     
761     void addVarArgChild(Node* child)
762     {
763         m_graph.m_varArgChildren.append(Edge(child));
764         m_numPassedVarArgs++;
765     }
766
767     void addVarArgChild(Edge child)
768     {
769         m_graph.m_varArgChildren.append(child);
770         m_numPassedVarArgs++;
771     }
772     
773     Node* addCallWithoutSettingResult(
774         NodeType op, OpInfo opInfo, Node* callee, int argCount, int registerOffset,
775         OpInfo prediction)
776     {
777         addVarArgChild(callee);
778         size_t parameterSlots = Graph::parameterSlotsForArgCount(argCount);
779
780         if (parameterSlots > m_parameterSlots)
781             m_parameterSlots = parameterSlots;
782
783         for (int i = 0; i < argCount; ++i)
784             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
785
786         return addToGraph(Node::VarArg, op, opInfo, prediction);
787     }
788     
789     Node* addCall(
790         int result, NodeType op, const DOMJIT::Signature* signature, Node* callee, int argCount, int registerOffset,
791         SpeculatedType prediction)
792     {
793         if (op == TailCall) {
794             if (allInlineFramesAreTailCalls())
795                 return addCallWithoutSettingResult(op, OpInfo(signature), callee, argCount, registerOffset, OpInfo());
796             op = TailCallInlinedCaller;
797         }
798
799
800         Node* call = addCallWithoutSettingResult(
801             op, OpInfo(signature), callee, argCount, registerOffset, OpInfo(prediction));
802         VirtualRegister resultReg(result);
803         if (resultReg.isValid())
804             set(resultReg, call);
805         return call;
806     }
807     
808     Node* cellConstantWithStructureCheck(JSCell* object, Structure* structure)
809     {
810         // FIXME: This should route to emitPropertyCheck, not the other way around. But currently,
811         // this gets no profit from using emitPropertyCheck() since we'll non-adaptively watch the
812         // object's structure as soon as we make it a weakJSCosntant.
813         Node* objectNode = weakJSConstant(object);
814         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectNode);
815         return objectNode;
816     }
817     
818     SpeculatedType getPredictionWithoutOSRExit(unsigned bytecodeIndex)
819     {
820         SpeculatedType prediction;
821         {
822             ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
823             prediction = m_inlineStackTop->m_profiledBlock->valueProfilePredictionForBytecodeOffset(locker, bytecodeIndex);
824         }
825
826         if (prediction != SpecNone)
827             return prediction;
828
829         // If we have no information about the values this
830         // node generates, we check if by any chance it is
831         // a tail call opcode. In that case, we walk up the
832         // inline frames to find a call higher in the call
833         // chain and use its prediction. If we only have
834         // inlined tail call frames, we use SpecFullTop
835         // to avoid a spurious OSR exit.
836         Instruction* instruction = &m_inlineStackTop->m_profiledBlock->instructions()[bytecodeIndex];
837         OpcodeID opcodeID = Interpreter::getOpcodeID(instruction->u.opcode);
838
839         switch (opcodeID) {
840         case op_tail_call:
841         case op_tail_call_varargs:
842         case op_tail_call_forward_arguments: {
843             // Things should be more permissive to us returning BOTTOM instead of TOP here.
844             // Currently, this will cause us to Force OSR exit. This is bad because returning
845             // TOP will cause anything that transitively touches this speculated type to
846             // also become TOP during prediction propagation.
847             // https://bugs.webkit.org/show_bug.cgi?id=164337
848             if (!inlineCallFrame())
849                 return SpecFullTop;
850
851             CodeOrigin* codeOrigin = inlineCallFrame()->getCallerSkippingTailCalls();
852             if (!codeOrigin)
853                 return SpecFullTop;
854
855             InlineStackEntry* stack = m_inlineStackTop;
856             while (stack->m_inlineCallFrame != codeOrigin->inlineCallFrame)
857                 stack = stack->m_caller;
858
859             bytecodeIndex = codeOrigin->bytecodeIndex;
860             CodeBlock* profiledBlock = stack->m_profiledBlock;
861             ConcurrentJSLocker locker(profiledBlock->m_lock);
862             return profiledBlock->valueProfilePredictionForBytecodeOffset(locker, bytecodeIndex);
863         }
864
865         default:
866             return SpecNone;
867         }
868
869         RELEASE_ASSERT_NOT_REACHED();
870         return SpecNone;
871     }
872
873     SpeculatedType getPrediction(unsigned bytecodeIndex)
874     {
875         SpeculatedType prediction = getPredictionWithoutOSRExit(bytecodeIndex);
876
877         if (prediction == SpecNone) {
878             // We have no information about what values this node generates. Give up
879             // on executing this code, since we're likely to do more damage than good.
880             addToGraph(ForceOSRExit);
881         }
882         
883         return prediction;
884     }
885     
886     SpeculatedType getPredictionWithoutOSRExit()
887     {
888         return getPredictionWithoutOSRExit(m_currentIndex);
889     }
890     
891     SpeculatedType getPrediction()
892     {
893         return getPrediction(m_currentIndex);
894     }
895     
896     ArrayMode getArrayMode(ArrayProfile* profile, Array::Action action)
897     {
898         ConcurrentJSLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
899         profile->computeUpdatedPrediction(locker, m_inlineStackTop->m_profiledBlock);
900         bool makeSafe = profile->outOfBounds(locker);
901         return ArrayMode::fromObserved(locker, profile, action, makeSafe);
902     }
903
904     Node* makeSafe(Node* node)
905     {
906         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
907             node->mergeFlags(NodeMayOverflowInt32InDFG);
908         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
909             node->mergeFlags(NodeMayNegZeroInDFG);
910         
911         if (!isX86() && node->op() == ArithMod)
912             return node;
913
914         {
915             ArithProfile* arithProfile = m_inlineStackTop->m_profiledBlock->arithProfileForBytecodeOffset(m_currentIndex);
916             if (arithProfile) {
917                 switch (node->op()) {
918                 case ArithAdd:
919                 case ArithSub:
920                 case ValueAdd:
921                     if (arithProfile->didObserveDouble())
922                         node->mergeFlags(NodeMayHaveDoubleResult);
923                     if (arithProfile->didObserveNonNumber())
924                         node->mergeFlags(NodeMayHaveNonNumberResult);
925                     break;
926                 
927                 case ArithMul: {
928                     if (arithProfile->didObserveInt52Overflow())
929                         node->mergeFlags(NodeMayOverflowInt52);
930                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
931                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
932                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
933                         node->mergeFlags(NodeMayNegZeroInBaseline);
934                     if (arithProfile->didObserveDouble())
935                         node->mergeFlags(NodeMayHaveDoubleResult);
936                     if (arithProfile->didObserveNonNumber())
937                         node->mergeFlags(NodeMayHaveNonNumberResult);
938                     break;
939                 }
940                 case ValueNegate:
941                 case ArithNegate: {
942                     if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble())
943                         node->mergeFlags(NodeMayHaveDoubleResult);
944                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
945                         node->mergeFlags(NodeMayNegZeroInBaseline);
946                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
947                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
948                     if (arithProfile->didObserveNonNumber()) {
949                         // FIXME: We should add support to BigInt into speculation
950                         // https://bugs.webkit.org/show_bug.cgi?id=182470
951                         node->mergeFlags(NodeMayHaveNonNumberResult);
952                     }
953                     break;
954                 }
955                 
956                 default:
957                     break;
958                 }
959             }
960         }
961         
962         if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
963             switch (node->op()) {
964             case UInt32ToNumber:
965             case ArithAdd:
966             case ArithSub:
967             case ValueAdd:
968             case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
969                 node->mergeFlags(NodeMayOverflowInt32InBaseline);
970                 break;
971                 
972             default:
973                 break;
974             }
975         }
976         
977         return node;
978     }
979     
980     Node* makeDivSafe(Node* node)
981     {
982         ASSERT(node->op() == ArithDiv);
983         
984         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
985             node->mergeFlags(NodeMayOverflowInt32InDFG);
986         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
987             node->mergeFlags(NodeMayNegZeroInDFG);
988         
989         // The main slow case counter for op_div in the old JIT counts only when
990         // the operands are not numbers. We don't care about that since we already
991         // have speculations in place that take care of that separately. We only
992         // care about when the outcome of the division is not an integer, which
993         // is what the special fast case counter tells us.
994         
995         if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex))
996             return node;
997         
998         // FIXME: It might be possible to make this more granular.
999         node->mergeFlags(NodeMayOverflowInt32InBaseline | NodeMayNegZeroInBaseline);
1000         
1001         return node;
1002     }
1003     
1004     void noticeArgumentsUse()
1005     {
1006         // All of the arguments in this function need to be formatted as JSValues because we will
1007         // load from them in a random-access fashion and we don't want to have to switch on
1008         // format.
1009         
1010         for (ArgumentPosition* argument : m_inlineStackTop->m_argumentPositions)
1011             argument->mergeShouldNeverUnbox(true);
1012     }
1013
1014     bool needsDynamicLookup(ResolveType, OpcodeID);
1015
1016     VM* m_vm;
1017     CodeBlock* m_codeBlock;
1018     CodeBlock* m_profiledBlock;
1019     Graph& m_graph;
1020
1021     // The current block being generated.
1022     BasicBlock* m_currentBlock;
1023     // The bytecode index of the current instruction being generated.
1024     unsigned m_currentIndex;
1025     // The semantic origin of the current node if different from the current Index.
1026     CodeOrigin m_currentSemanticOrigin;
1027     // True if it's OK to OSR exit right now.
1028     bool m_exitOK { false };
1029
1030     FrozenValue* m_constantUndefined;
1031     FrozenValue* m_constantNull;
1032     FrozenValue* m_constantNaN;
1033     FrozenValue* m_constantOne;
1034     Vector<Node*, 16> m_constants;
1035
1036     HashMap<InlineCallFrame*, Vector<ArgumentPosition*>, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>> m_inlineCallFrameToArgumentPositions;
1037
1038     // The number of arguments passed to the function.
1039     unsigned m_numArguments;
1040     // The number of locals (vars + temporaries) used in the function.
1041     unsigned m_numLocals;
1042     // The number of slots (in units of sizeof(Register)) that we need to
1043     // preallocate for arguments to outgoing calls from this frame. This
1044     // number includes the CallFrame slots that we initialize for the callee
1045     // (but not the callee-initialized CallerFrame and ReturnPC slots).
1046     // This number is 0 if and only if this function is a leaf.
1047     unsigned m_parameterSlots;
1048     // The number of var args passed to the next var arg node.
1049     unsigned m_numPassedVarArgs;
1050
1051     struct InlineStackEntry {
1052         ByteCodeParser* m_byteCodeParser;
1053         
1054         CodeBlock* m_codeBlock;
1055         CodeBlock* m_profiledBlock;
1056         InlineCallFrame* m_inlineCallFrame;
1057         
1058         ScriptExecutable* executable() { return m_codeBlock->ownerScriptExecutable(); }
1059         
1060         QueryableExitProfile m_exitProfile;
1061         
1062         // Remapping of identifier and constant numbers from the code block being
1063         // inlined (inline callee) to the code block that we're inlining into
1064         // (the machine code block, which is the transitive, though not necessarily
1065         // direct, caller).
1066         Vector<unsigned> m_identifierRemap;
1067         Vector<unsigned> m_switchRemap;
1068         
1069         // These are blocks whose terminal is a Jump, Branch or Switch, and whose target has not yet been linked.
1070         // Their terminal instead refers to a bytecode index, and the right BB can be found in m_blockLinkingTargets.
1071         Vector<BasicBlock*> m_unlinkedBlocks;
1072         
1073         // Potential block linking targets. Must be sorted by bytecodeBegin, and
1074         // cannot have two blocks that have the same bytecodeBegin.
1075         Vector<BasicBlock*> m_blockLinkingTargets;
1076
1077         // Optional: a continuation block for returns to jump to. It is set by early returns if it does not exist.
1078         BasicBlock* m_continuationBlock;
1079
1080         VirtualRegister m_returnValue;
1081         
1082         // Speculations about variable types collected from the profiled code block,
1083         // which are based on OSR exit profiles that past DFG compilations of this
1084         // code block had gathered.
1085         LazyOperandValueProfileParser m_lazyOperands;
1086         
1087         ICStatusMap m_baselineMap;
1088         ICStatusContext m_optimizedContext;
1089         
1090         // Pointers to the argument position trackers for this slice of code.
1091         Vector<ArgumentPosition*> m_argumentPositions;
1092         
1093         InlineStackEntry* m_caller;
1094         
1095         InlineStackEntry(
1096             ByteCodeParser*,
1097             CodeBlock*,
1098             CodeBlock* profiledBlock,
1099             JSFunction* callee, // Null if this is a closure call.
1100             VirtualRegister returnValueVR,
1101             VirtualRegister inlineCallFrameStart,
1102             int argumentCountIncludingThis,
1103             InlineCallFrame::Kind,
1104             BasicBlock* continuationBlock);
1105         
1106         ~InlineStackEntry();
1107         
1108         VirtualRegister remapOperand(VirtualRegister operand) const
1109         {
1110             if (!m_inlineCallFrame)
1111                 return operand;
1112             
1113             ASSERT(!operand.isConstant());
1114
1115             return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
1116         }
1117     };
1118     
1119     InlineStackEntry* m_inlineStackTop;
1120     
1121     ICStatusContextStack m_icContextStack;
1122     
1123     struct DelayedSetLocal {
1124         CodeOrigin m_origin;
1125         VirtualRegister m_operand;
1126         Node* m_value;
1127         SetMode m_setMode;
1128         
1129         DelayedSetLocal() { }
1130         DelayedSetLocal(const CodeOrigin& origin, VirtualRegister operand, Node* value, SetMode setMode)
1131             : m_origin(origin)
1132             , m_operand(operand)
1133             , m_value(value)
1134             , m_setMode(setMode)
1135         {
1136             RELEASE_ASSERT(operand.isValid());
1137         }
1138         
1139         Node* execute(ByteCodeParser* parser)
1140         {
1141             if (m_operand.isArgument())
1142                 return parser->setArgument(m_origin, m_operand, m_value, m_setMode);
1143             return parser->setLocal(m_origin, m_operand, m_value, m_setMode);
1144         }
1145     };
1146     
1147     Vector<DelayedSetLocal, 2> m_setLocalQueue;
1148
1149     Instruction* m_currentInstruction;
1150     bool m_hasDebuggerEnabled;
1151     bool m_hasAnyForceOSRExits { false };
1152 };
1153
1154 BasicBlock* ByteCodeParser::allocateTargetableBlock(unsigned bytecodeIndex)
1155 {
1156     ASSERT(bytecodeIndex != UINT_MAX);
1157     Ref<BasicBlock> block = adoptRef(*new BasicBlock(bytecodeIndex, m_numArguments, m_numLocals, 1));
1158     BasicBlock* blockPtr = block.ptr();
1159     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1160     if (m_inlineStackTop->m_blockLinkingTargets.size())
1161         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1162     m_inlineStackTop->m_blockLinkingTargets.append(blockPtr);
1163     m_graph.appendBlock(WTFMove(block));
1164     return blockPtr;
1165 }
1166
1167 BasicBlock* ByteCodeParser::allocateUntargetableBlock()
1168 {
1169     Ref<BasicBlock> block = adoptRef(*new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
1170     BasicBlock* blockPtr = block.ptr();
1171     m_graph.appendBlock(WTFMove(block));
1172     return blockPtr;
1173 }
1174
1175 void ByteCodeParser::makeBlockTargetable(BasicBlock* block, unsigned bytecodeIndex)
1176 {
1177     RELEASE_ASSERT(block->bytecodeBegin == UINT_MAX);
1178     block->bytecodeBegin = bytecodeIndex;
1179     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1180     if (m_inlineStackTop->m_blockLinkingTargets.size())
1181         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1182     m_inlineStackTop->m_blockLinkingTargets.append(block);
1183 }
1184
1185 void ByteCodeParser::addJumpTo(BasicBlock* block)
1186 {
1187     ASSERT(!m_currentBlock->terminal());
1188     Node* jumpNode = addToGraph(Jump);
1189     jumpNode->targetBlock() = block;
1190     m_currentBlock->didLink();
1191 }
1192
1193 void ByteCodeParser::addJumpTo(unsigned bytecodeIndex)
1194 {
1195     ASSERT(!m_currentBlock->terminal());
1196     addToGraph(Jump, OpInfo(bytecodeIndex));
1197     m_inlineStackTop->m_unlinkedBlocks.append(m_currentBlock);
1198 }
1199
1200 ByteCodeParser::Terminality ByteCodeParser::handleCall(Instruction* pc, NodeType op, CallMode callMode)
1201 {
1202     static_assert(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct),
1203         "op_call, op_tail_call and op_construct should always have the same length");
1204     static_assert(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_tail_call),
1205         "op_call, op_tail_call and op_construct should always have the same length");
1206     
1207     int result = pc[1].u.operand;
1208     Node* callTarget = get(VirtualRegister(pc[2].u.operand));
1209     int argumentCountIncludingThis = pc[3].u.operand;
1210     int registerOffset = -pc[4].u.operand;
1211
1212     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1213         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1214         m_inlineStackTop->m_baselineMap, m_icContextStack);
1215
1216     InlineCallFrame::Kind kind = InlineCallFrame::kindFor(callMode);
1217
1218     return handleCall(result, op, kind, OPCODE_LENGTH(op_call), callTarget,
1219         argumentCountIncludingThis, registerOffset, callLinkStatus, getPrediction());
1220 }
1221
1222 void ByteCodeParser::refineStatically(CallLinkStatus& callLinkStatus, Node* callTarget)
1223 {
1224     if (callTarget->isCellConstant())
1225         callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell()));
1226 }
1227
1228 ByteCodeParser::Terminality ByteCodeParser::handleCall(
1229     int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
1230     Node* callTarget, int argumentCountIncludingThis, int registerOffset,
1231     CallLinkStatus callLinkStatus, SpeculatedType prediction)
1232 {
1233     ASSERT(registerOffset <= 0);
1234
1235     refineStatically(callLinkStatus, callTarget);
1236     
1237     VERBOSE_LOG("    Handling call at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1238     
1239     // If we have profiling information about this call, and it did not behave too polymorphically,
1240     // we may be able to inline it, or in the case of recursive tail calls turn it into a jump.
1241     if (callLinkStatus.canOptimize()) {
1242         addToGraph(FilterCallLinkStatus, OpInfo(m_graph.m_plan.recordedStatuses().addCallLinkStatus(currentCodeOrigin(), callLinkStatus)), callTarget);
1243
1244         VirtualRegister thisArgument = virtualRegisterForArgument(0, registerOffset);
1245         auto optimizationResult = handleInlining(callTarget, result, callLinkStatus, registerOffset, thisArgument,
1246             argumentCountIncludingThis, m_currentIndex + instructionSize, op, kind, prediction);
1247         if (optimizationResult == CallOptimizationResult::OptimizedToJump)
1248             return Terminal;
1249         if (optimizationResult == CallOptimizationResult::Inlined) {
1250             if (UNLIKELY(m_graph.compilation()))
1251                 m_graph.compilation()->noticeInlinedCall();
1252             return NonTerminal;
1253         }
1254     }
1255     
1256     Node* callNode = addCall(result, op, nullptr, callTarget, argumentCountIncludingThis, registerOffset, prediction);
1257     ASSERT(callNode->op() != TailCallVarargs && callNode->op() != TailCallForwardVarargs);
1258     return callNode->op() == TailCall ? Terminal : NonTerminal;
1259 }
1260
1261 ByteCodeParser::Terminality ByteCodeParser::handleVarargsCall(Instruction* pc, NodeType op, CallMode callMode)
1262 {
1263     static_assert(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_construct_varargs),
1264         "op_call_varargs, op_tail_call_varargs and op_construct_varargs should always have the same length");
1265     static_assert(OPCODE_LENGTH(op_call_varargs) == OPCODE_LENGTH(op_tail_call_varargs),
1266         "op_call_varargs, op_tail_call_varargs and op_construct_varargs should always have the same length");
1267
1268     int result = pc[1].u.operand;
1269     int callee = pc[2].u.operand;
1270     int thisReg = pc[3].u.operand;
1271     int arguments = pc[4].u.operand;
1272     int firstFreeReg = pc[5].u.operand;
1273     int firstVarArgOffset = pc[6].u.operand;
1274     
1275     SpeculatedType prediction = getPrediction();
1276     
1277     Node* callTarget = get(VirtualRegister(callee));
1278     
1279     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1280         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1281         m_inlineStackTop->m_baselineMap, m_icContextStack);
1282     refineStatically(callLinkStatus, callTarget);
1283     
1284     VERBOSE_LOG("    Varargs call link status at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1285     
1286     if (callLinkStatus.canOptimize()) {
1287         addToGraph(FilterCallLinkStatus, OpInfo(m_graph.m_plan.recordedStatuses().addCallLinkStatus(currentCodeOrigin(), callLinkStatus)), callTarget);
1288
1289         if (handleVarargsInlining(callTarget, result,
1290             callLinkStatus, firstFreeReg, VirtualRegister(thisReg), VirtualRegister(arguments),
1291             firstVarArgOffset, op,
1292             InlineCallFrame::varargsKindFor(callMode))) {
1293             if (UNLIKELY(m_graph.compilation()))
1294                 m_graph.compilation()->noticeInlinedCall();
1295             return NonTerminal;
1296         }
1297     }
1298     
1299     CallVarargsData* data = m_graph.m_callVarargsData.add();
1300     data->firstVarArgOffset = firstVarArgOffset;
1301     
1302     Node* thisChild = get(VirtualRegister(thisReg));
1303     Node* argumentsChild = nullptr;
1304     if (op != TailCallForwardVarargs)
1305         argumentsChild = get(VirtualRegister(arguments));
1306
1307     if (op == TailCallVarargs || op == TailCallForwardVarargs) {
1308         if (allInlineFramesAreTailCalls()) {
1309             addToGraph(op, OpInfo(data), OpInfo(), callTarget, thisChild, argumentsChild);
1310             return Terminal;
1311         }
1312         op = op == TailCallVarargs ? TailCallVarargsInlinedCaller : TailCallForwardVarargsInlinedCaller;
1313     }
1314
1315     Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, thisChild, argumentsChild);
1316     VirtualRegister resultReg(result);
1317     if (resultReg.isValid())
1318         set(resultReg, call);
1319     return NonTerminal;
1320 }
1321
1322 void ByteCodeParser::emitFunctionChecks(CallVariant callee, Node* callTarget, VirtualRegister thisArgumentReg)
1323 {
1324     Node* thisArgument;
1325     if (thisArgumentReg.isValid())
1326         thisArgument = get(thisArgumentReg);
1327     else
1328         thisArgument = nullptr;
1329
1330     JSCell* calleeCell;
1331     Node* callTargetForCheck;
1332     if (callee.isClosureCall()) {
1333         calleeCell = callee.executable();
1334         callTargetForCheck = addToGraph(GetExecutable, callTarget);
1335     } else {
1336         calleeCell = callee.nonExecutableCallee();
1337         callTargetForCheck = callTarget;
1338     }
1339     
1340     ASSERT(calleeCell);
1341     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck);
1342     if (thisArgument)
1343         addToGraph(Phantom, thisArgument);
1344 }
1345
1346 Node* ByteCodeParser::getArgumentCount()
1347 {
1348     Node* argumentCount;
1349     if (m_inlineStackTop->m_inlineCallFrame && !m_inlineStackTop->m_inlineCallFrame->isVarargs())
1350         argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->argumentCountIncludingThis))->value());
1351     else
1352         argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(m_inlineStackTop->m_inlineCallFrame), OpInfo(SpecInt32Only));
1353     return argumentCount;
1354 }
1355
1356 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
1357 {
1358     for (int i = 0; i < argumentCountIncludingThis; ++i)
1359         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
1360 }
1361
1362 template<typename ChecksFunctor>
1363 bool ByteCodeParser::handleRecursiveTailCall(Node* callTargetNode, CallVariant callVariant, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& emitFunctionCheckIfNeeded)
1364 {
1365     if (UNLIKELY(!Options::optimizeRecursiveTailCalls()))
1366         return false;
1367
1368     auto targetExecutable = callVariant.executable();
1369     InlineStackEntry* stackEntry = m_inlineStackTop;
1370     do {
1371         if (targetExecutable != stackEntry->executable())
1372             continue;
1373         VERBOSE_LOG("   We found a recursive tail call, trying to optimize it into a jump.\n");
1374
1375         if (auto* callFrame = stackEntry->m_inlineCallFrame) {
1376             // Some code may statically use the argument count from the InlineCallFrame, so it would be invalid to loop back if it does not match.
1377             // We "continue" instead of returning false in case another stack entry further on the stack has the right number of arguments.
1378             if (argumentCountIncludingThis != static_cast<int>(callFrame->argumentCountIncludingThis))
1379                 continue;
1380         } else {
1381             // We are in the machine code entry (i.e. the original caller).
1382             // If we have more arguments than the number of parameters to the function, it is not clear where we could put them on the stack.
1383             if (argumentCountIncludingThis > m_codeBlock->numParameters())
1384                 return false;
1385         }
1386
1387         // If an InlineCallFrame is not a closure, it was optimized using a constant callee.
1388         // Check if this is the same callee that we try to inline here.
1389         if (stackEntry->m_inlineCallFrame && !stackEntry->m_inlineCallFrame->isClosureCall) {
1390             if (stackEntry->m_inlineCallFrame->calleeConstant() != callVariant.function())
1391                 continue;
1392         }
1393
1394         // We must add some check that the profiling information was correct and the target of this call is what we thought.
1395         emitFunctionCheckIfNeeded();
1396         // We flush everything, as if we were in the backedge of a loop (see treatment of op_jmp in parseBlock).
1397         flushForTerminal();
1398
1399         // We must set the callee to the right value
1400         if (stackEntry->m_inlineCallFrame) {
1401             if (stackEntry->m_inlineCallFrame->isClosureCall)
1402                 setDirect(stackEntry->remapOperand(VirtualRegister(CallFrameSlot::callee)), callTargetNode, NormalSet);
1403         } else
1404             addToGraph(SetCallee, callTargetNode);
1405
1406         // We must set the arguments to the right values
1407         if (!stackEntry->m_inlineCallFrame)
1408             addToGraph(SetArgumentCountIncludingThis, OpInfo(argumentCountIncludingThis));
1409         int argIndex = 0;
1410         for (; argIndex < argumentCountIncludingThis; ++argIndex) {
1411             Node* value = get(virtualRegisterForArgument(argIndex, registerOffset));
1412             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), value, NormalSet);
1413         }
1414         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1415         for (; argIndex < stackEntry->m_codeBlock->numParameters(); ++argIndex)
1416             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), undefined, NormalSet);
1417
1418         // We must repeat the work of op_enter here as we will jump right after it.
1419         // We jump right after it and not before it, because of some invariant saying that a CFG root cannot have predecessors in the IR.
1420         for (int i = 0; i < stackEntry->m_codeBlock->numVars(); ++i)
1421             setDirect(stackEntry->remapOperand(virtualRegisterForLocal(i)), undefined, NormalSet);
1422
1423         // We want to emit the SetLocals with an exit origin that points to the place we are jumping to.
1424         unsigned oldIndex = m_currentIndex;
1425         auto oldStackTop = m_inlineStackTop;
1426         m_inlineStackTop = stackEntry;
1427         m_currentIndex = OPCODE_LENGTH(op_enter);
1428         m_exitOK = true;
1429         processSetLocalQueue();
1430         m_currentIndex = oldIndex;
1431         m_inlineStackTop = oldStackTop;
1432         m_exitOK = false;
1433
1434         BasicBlock** entryBlockPtr = tryBinarySearch<BasicBlock*, unsigned>(stackEntry->m_blockLinkingTargets, stackEntry->m_blockLinkingTargets.size(), OPCODE_LENGTH(op_enter), getBytecodeBeginForBlock);
1435         RELEASE_ASSERT(entryBlockPtr);
1436         addJumpTo(*entryBlockPtr);
1437         return true;
1438         // It would be unsound to jump over a non-tail call: the "tail" call is not really a tail call in that case.
1439     } while (stackEntry->m_inlineCallFrame && stackEntry->m_inlineCallFrame->kind == InlineCallFrame::TailCall && (stackEntry = stackEntry->m_caller));
1440
1441     // The tail call was not recursive
1442     return false;
1443 }
1444
1445 unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, InlineCallFrame::Kind kind)
1446 {
1447     CallMode callMode = InlineCallFrame::callModeFor(kind);
1448     CodeSpecializationKind specializationKind = specializationKindFor(callMode);
1449     VERBOSE_LOG("Considering inlining ", callee, " into ", currentCodeOrigin(), "\n");
1450     
1451     if (m_hasDebuggerEnabled) {
1452         VERBOSE_LOG("    Failing because the debugger is in use.\n");
1453         return UINT_MAX;
1454     }
1455
1456     FunctionExecutable* executable = callee.functionExecutable();
1457     if (!executable) {
1458         VERBOSE_LOG("    Failing because there is no function executable.\n");
1459         return UINT_MAX;
1460     }
1461     
1462     // Do we have a code block, and does the code block's size match the heuristics/requirements for
1463     // being an inline candidate? We might not have a code block (1) if code was thrown away,
1464     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
1465     // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
1466     // to inline it if we had a static proof of what was being called; this might happen for example
1467     // if you call a global function, where watchpointing gives us static information. Overall,
1468     // it's a rare case because we expect that any hot callees would have already been compiled.
1469     CodeBlock* codeBlock = executable->baselineCodeBlockFor(specializationKind);
1470     if (!codeBlock) {
1471         VERBOSE_LOG("    Failing because no code block available.\n");
1472         return UINT_MAX;
1473     }
1474
1475     if (!Options::useArityFixupInlining()) {
1476         if (codeBlock->numParameters() > argumentCountIncludingThis) {
1477             VERBOSE_LOG("    Failing because of arity mismatch.\n");
1478             return UINT_MAX;
1479         }
1480     }
1481
1482     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
1483         codeBlock, specializationKind, callee.isClosureCall());
1484     VERBOSE_LOG("    Call mode: ", callMode, "\n");
1485     VERBOSE_LOG("    Is closure call: ", callee.isClosureCall(), "\n");
1486     VERBOSE_LOG("    Capability level: ", capabilityLevel, "\n");
1487     VERBOSE_LOG("    Might inline function: ", mightInlineFunctionFor(codeBlock, specializationKind), "\n");
1488     VERBOSE_LOG("    Might compile function: ", mightCompileFunctionFor(codeBlock, specializationKind), "\n");
1489     VERBOSE_LOG("    Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n");
1490     VERBOSE_LOG("    Is inlining candidate: ", codeBlock->ownerScriptExecutable()->isInliningCandidate(), "\n");
1491     if (!canInline(capabilityLevel)) {
1492         VERBOSE_LOG("    Failing because the function is not inlineable.\n");
1493         return UINT_MAX;
1494     }
1495     
1496     // Check if the caller is already too large. We do this check here because that's just
1497     // where we happen to also have the callee's code block, and we want that for the
1498     // purpose of unsetting SABI.
1499     if (!isSmallEnoughToInlineCodeInto(m_codeBlock)) {
1500         codeBlock->m_shouldAlwaysBeInlined = false;
1501         VERBOSE_LOG("    Failing because the caller is too large.\n");
1502         return UINT_MAX;
1503     }
1504     
1505     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
1506     // this function.
1507     // https://bugs.webkit.org/show_bug.cgi?id=127627
1508     
1509     // FIXME: We currently inline functions that have run in LLInt but not in Baseline. These
1510     // functions have very low fidelity profiling, and presumably they weren't very hot if they
1511     // haven't gotten to Baseline yet. Consider not inlining these functions.
1512     // https://bugs.webkit.org/show_bug.cgi?id=145503
1513     
1514     // Have we exceeded inline stack depth, or are we trying to inline a recursive call to
1515     // too many levels? If either of these are detected, then don't inline. We adjust our
1516     // heuristics if we are dealing with a function that cannot otherwise be compiled.
1517     
1518     unsigned depth = 0;
1519     unsigned recursion = 0;
1520     
1521     for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
1522         ++depth;
1523         if (depth >= Options::maximumInliningDepth()) {
1524             VERBOSE_LOG("    Failing because depth exceeded.\n");
1525             return UINT_MAX;
1526         }
1527         
1528         if (entry->executable() == executable) {
1529             ++recursion;
1530             if (recursion >= Options::maximumInliningRecursion()) {
1531                 VERBOSE_LOG("    Failing because recursion detected.\n");
1532                 return UINT_MAX;
1533             }
1534         }
1535     }
1536     
1537     VERBOSE_LOG("    Inlining should be possible.\n");
1538     
1539     // It might be possible to inline.
1540     return codeBlock->instructionCount();
1541 }
1542
1543 template<typename ChecksFunctor>
1544 void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, InlineCallFrame::Kind kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
1545 {
1546     Instruction* savedCurrentInstruction = m_currentInstruction;
1547     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1548     
1549     ASSERT(inliningCost(callee, argumentCountIncludingThis, kind) != UINT_MAX);
1550     
1551     CodeBlock* codeBlock = callee.functionExecutable()->baselineCodeBlockFor(specializationKind);
1552     insertChecks(codeBlock);
1553
1554     // FIXME: Don't flush constants!
1555
1556     // arityFixupCount and numberOfStackPaddingSlots are different. While arityFixupCount does not consider about stack alignment,
1557     // numberOfStackPaddingSlots consider alignment. Consider the following case,
1558     //
1559     // before: [ ... ][arg0][header]
1560     // after:  [ ... ][ext ][arg1][arg0][header]
1561     //
1562     // In the above case, arityFixupCount is 1. But numberOfStackPaddingSlots is 2 because the stack needs to be aligned.
1563     // We insert extra slots to align stack.
1564     int arityFixupCount = std::max<int>(codeBlock->numParameters() - argumentCountIncludingThis, 0);
1565     int numberOfStackPaddingSlots = CommonSlowPaths::numberOfStackPaddingSlots(codeBlock, argumentCountIncludingThis);
1566     ASSERT(!(numberOfStackPaddingSlots % stackAlignmentRegisters()));
1567     int registerOffsetAfterFixup = registerOffset - numberOfStackPaddingSlots;
1568     
1569     int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffsetAfterFixup)).offset() + CallFrame::headerSizeInRegisters;
1570     
1571     ensureLocals(
1572         VirtualRegister(inlineCallFrameStart).toLocal() + 1 +
1573         CallFrame::headerSizeInRegisters + codeBlock->numCalleeLocals());
1574     
1575     size_t argumentPositionStart = m_graph.m_argumentPositions.size();
1576
1577     VirtualRegister resultReg(resultOperand);
1578     if (resultReg.isValid())
1579         resultReg = m_inlineStackTop->remapOperand(resultReg);
1580
1581     VariableAccessData* calleeVariable = nullptr;
1582     if (callee.isClosureCall()) {
1583         Node* calleeSet = set(
1584             VirtualRegister(registerOffsetAfterFixup + CallFrameSlot::callee), callTargetNode, ImmediateNakedSet);
1585         
1586         calleeVariable = calleeSet->variableAccessData();
1587         calleeVariable->mergeShouldNeverUnbox(true);
1588     }
1589
1590     if (arityFixupCount) {
1591         // Note: we do arity fixup in two phases:
1592         // 1. We get all the values we need and MovHint them to the expected locals.
1593         // 2. We SetLocal them inside the callee's CodeOrigin. This way, if we exit, the callee's
1594         //    frame is already set up. If any SetLocal exits, we have a valid exit state.
1595         //    This is required because if we didn't do this in two phases, we may exit in
1596         //    the middle of arity fixup from the caller's CodeOrigin. This is unsound because if
1597         //    we did the SetLocals in the caller's frame, the memcpy may clobber needed parts
1598         //    of the frame right before exiting. For example, consider if we need to pad two args:
1599         //    [arg3][arg2][arg1][arg0]
1600         //    [fix ][fix ][arg3][arg2][arg1][arg0]
1601         //    We memcpy starting from arg0 in the direction of arg3. If we were to exit at a type check
1602         //    for arg3's SetLocal in the caller's CodeOrigin, we'd exit with a frame like so:
1603         //    [arg3][arg2][arg1][arg2][arg1][arg0]
1604         //    And the caller would then just end up thinking its argument are:
1605         //    [arg3][arg2][arg1][arg2]
1606         //    which is incorrect.
1607
1608         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1609         // The stack needs to be aligned due to the JS calling convention. Thus, we have a hole if the count of arguments is not aligned.
1610         // We call this hole "extra slot". Consider the following case, the number of arguments is 2. If this argument
1611         // count does not fulfill the stack alignment requirement, we already inserted extra slots.
1612         //
1613         // before: [ ... ][ext ][arg1][arg0][header]
1614         //
1615         // In the above case, one extra slot is inserted. If the code's parameter count is 3, we will fixup arguments.
1616         // At that time, we can simply use this extra slots. So the fixuped stack is the following.
1617         //
1618         // before: [ ... ][ext ][arg1][arg0][header]
1619         // after:  [ ... ][arg2][arg1][arg0][header]
1620         //
1621         // In such cases, we do not need to move frames.
1622         if (registerOffsetAfterFixup != registerOffset) {
1623             for (int index = 0; index < argumentCountIncludingThis; ++index) {
1624                 Node* value = get(virtualRegisterForArgument(index, registerOffset));
1625                 VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(index, registerOffsetAfterFixup));
1626                 addToGraph(MovHint, OpInfo(argumentToSet.offset()), value);
1627                 m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, value, ImmediateNakedSet });
1628             }
1629         }
1630         for (int index = 0; index < arityFixupCount; ++index) {
1631             VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(argumentCountIncludingThis + index, registerOffsetAfterFixup));
1632             addToGraph(MovHint, OpInfo(argumentToSet.offset()), undefined);
1633             m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, undefined, ImmediateNakedSet });
1634         }
1635
1636         // At this point, it's OK to OSR exit because we finished setting up
1637         // our callee's frame. We emit an ExitOK below from the callee's CodeOrigin.
1638     }
1639
1640     InlineStackEntry inlineStackEntry(this, codeBlock, codeBlock, callee.function(), resultReg,
1641         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind, continuationBlock);
1642
1643     // This is where the actual inlining really happens.
1644     unsigned oldIndex = m_currentIndex;
1645     m_currentIndex = 0;
1646
1647     // At this point, it's again OK to OSR exit.
1648     m_exitOK = true;
1649     addToGraph(ExitOK);
1650
1651     processSetLocalQueue();
1652
1653     InlineVariableData inlineVariableData;
1654     inlineVariableData.inlineCallFrame = m_inlineStackTop->m_inlineCallFrame;
1655     inlineVariableData.argumentPositionStart = argumentPositionStart;
1656     inlineVariableData.calleeVariable = 0;
1657     
1658     RELEASE_ASSERT(
1659         m_inlineStackTop->m_inlineCallFrame->isClosureCall
1660         == callee.isClosureCall());
1661     if (callee.isClosureCall()) {
1662         RELEASE_ASSERT(calleeVariable);
1663         inlineVariableData.calleeVariable = calleeVariable;
1664     }
1665     
1666     m_graph.m_inlineVariableData.append(inlineVariableData);
1667
1668     parseCodeBlock();
1669     clearCaches(); // Reset our state now that we're back to the outer code.
1670     
1671     m_currentIndex = oldIndex;
1672     m_exitOK = false;
1673
1674     linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
1675     
1676     // Most functions have at least one op_ret and thus set up the continuation block.
1677     // In some rare cases, a function ends in op_unreachable, forcing us to allocate a new continuationBlock here.
1678     if (inlineStackEntry.m_continuationBlock)
1679         m_currentBlock = inlineStackEntry.m_continuationBlock;
1680     else
1681         m_currentBlock = allocateUntargetableBlock();
1682     ASSERT(!m_currentBlock->terminal());
1683
1684     prepareToParseBlock();
1685     m_currentInstruction = savedCurrentInstruction;
1686 }
1687
1688 ByteCodeParser::CallOptimizationResult ByteCodeParser::handleCallVariant(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, VirtualRegister thisArgument, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, SpeculatedType prediction, unsigned& inliningBalance, BasicBlock* continuationBlock, bool needsToCheckCallee)
1689 {
1690     VERBOSE_LOG("    Considering callee ", callee, "\n");
1691
1692     bool didInsertChecks = false;
1693     auto insertChecksWithAccounting = [&] () {
1694         if (needsToCheckCallee)
1695             emitFunctionChecks(callee, callTargetNode, thisArgument);
1696         didInsertChecks = true;
1697     };
1698
1699     if (kind == InlineCallFrame::TailCall && ByteCodeParser::handleRecursiveTailCall(callTargetNode, callee, registerOffset, argumentCountIncludingThis, insertChecksWithAccounting)) {
1700         RELEASE_ASSERT(didInsertChecks);
1701         return CallOptimizationResult::OptimizedToJump;
1702     }
1703     RELEASE_ASSERT(!didInsertChecks);
1704
1705     if (!inliningBalance)
1706         return CallOptimizationResult::DidNothing;
1707
1708     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1709
1710     auto endSpecialCase = [&] () {
1711         RELEASE_ASSERT(didInsertChecks);
1712         addToGraph(Phantom, callTargetNode);
1713         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1714         inliningBalance--;
1715         if (continuationBlock) {
1716             m_currentIndex = nextOffset;
1717             m_exitOK = true;
1718             processSetLocalQueue();
1719             addJumpTo(continuationBlock);
1720         }
1721     };
1722
1723     if (InternalFunction* function = callee.internalFunction()) {
1724         if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) {
1725             endSpecialCase();
1726             return CallOptimizationResult::Inlined;
1727         }
1728         RELEASE_ASSERT(!didInsertChecks);
1729         return CallOptimizationResult::DidNothing;
1730     }
1731
1732     Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
1733     if (intrinsic != NoIntrinsic) {
1734         if (handleIntrinsicCall(callTargetNode, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1735             endSpecialCase();
1736             return CallOptimizationResult::Inlined;
1737         }
1738         RELEASE_ASSERT(!didInsertChecks);
1739         // We might still try to inline the Intrinsic because it might be a builtin JS function.
1740     }
1741
1742     if (Options::useDOMJIT()) {
1743         if (const DOMJIT::Signature* signature = callee.signatureFor(specializationKind)) {
1744             if (handleDOMJITCall(callTargetNode, resultOperand, signature, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1745                 endSpecialCase();
1746                 return CallOptimizationResult::Inlined;
1747             }
1748             RELEASE_ASSERT(!didInsertChecks);
1749         }
1750     }
1751     
1752     unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, kind);
1753     if (myInliningCost > inliningBalance)
1754         return CallOptimizationResult::DidNothing;
1755
1756     auto insertCheck = [&] (CodeBlock*) {
1757         if (needsToCheckCallee)
1758             emitFunctionChecks(callee, callTargetNode, thisArgument);
1759     };
1760     inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, kind, continuationBlock, insertCheck);
1761     inliningBalance -= myInliningCost;
1762     return CallOptimizationResult::Inlined;
1763 }
1764
1765 bool ByteCodeParser::handleVarargsInlining(Node* callTargetNode, int resultOperand,
1766     const CallLinkStatus& callLinkStatus, int firstFreeReg, VirtualRegister thisArgument,
1767     VirtualRegister argumentsArgument, unsigned argumentsOffset,
1768     NodeType callOp, InlineCallFrame::Kind kind)
1769 {
1770     VERBOSE_LOG("Handling inlining (Varargs)...\nStack: ", currentCodeOrigin(), "\n");
1771     if (callLinkStatus.maxNumArguments() > Options::maximumVarargsForInlining()) {
1772         VERBOSE_LOG("Bailing inlining: too many arguments for varargs inlining.\n");
1773         return false;
1774     }
1775     if (callLinkStatus.couldTakeSlowPath() || callLinkStatus.size() != 1) {
1776         VERBOSE_LOG("Bailing inlining: polymorphic inlining is not yet supported for varargs.\n");
1777         return false;
1778     }
1779
1780     CallVariant callVariant = callLinkStatus[0];
1781
1782     unsigned mandatoryMinimum;
1783     if (FunctionExecutable* functionExecutable = callVariant.functionExecutable())
1784         mandatoryMinimum = functionExecutable->parameterCount();
1785     else
1786         mandatoryMinimum = 0;
1787     
1788     // includes "this"
1789     unsigned maxNumArguments = std::max(callLinkStatus.maxNumArguments(), mandatoryMinimum + 1);
1790
1791     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1792     if (inliningCost(callVariant, maxNumArguments, kind) > getInliningBalance(callLinkStatus, specializationKind)) {
1793         VERBOSE_LOG("Bailing inlining: inlining cost too high.\n");
1794         return false;
1795     }
1796     
1797     int registerOffset = firstFreeReg + 1;
1798     registerOffset -= maxNumArguments; // includes "this"
1799     registerOffset -= CallFrame::headerSizeInRegisters;
1800     registerOffset = -WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -registerOffset);
1801     
1802     auto insertChecks = [&] (CodeBlock* codeBlock) {
1803         emitFunctionChecks(callVariant, callTargetNode, thisArgument);
1804         
1805         int remappedRegisterOffset =
1806         m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset();
1807         
1808         ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal());
1809         
1810         int argumentStart = registerOffset + CallFrame::headerSizeInRegisters;
1811         int remappedArgumentStart =
1812         m_inlineStackTop->remapOperand(VirtualRegister(argumentStart)).offset();
1813         
1814         LoadVarargsData* data = m_graph.m_loadVarargsData.add();
1815         data->start = VirtualRegister(remappedArgumentStart + 1);
1816         data->count = VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount);
1817         data->offset = argumentsOffset;
1818         data->limit = maxNumArguments;
1819         data->mandatoryMinimum = mandatoryMinimum;
1820         
1821         if (callOp == TailCallForwardVarargs)
1822             addToGraph(ForwardVarargs, OpInfo(data));
1823         else
1824             addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
1825         
1826         // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
1827         // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
1828         // callTargetNode because the other 2 are still in use and alive at this point.
1829         addToGraph(Phantom, callTargetNode);
1830         
1831         // In DFG IR before SSA, we cannot insert control flow between after the
1832         // LoadVarargs and the last SetArgument. This isn't a problem once we get to DFG
1833         // SSA. Fortunately, we also have other reasons for not inserting control flow
1834         // before SSA.
1835         
1836         VariableAccessData* countVariable = newVariableAccessData(VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount));
1837         // This is pretty lame, but it will force the count to be flushed as an int. This doesn't
1838         // matter very much, since our use of a SetArgument and Flushes for this local slot is
1839         // mostly just a formality.
1840         countVariable->predict(SpecInt32Only);
1841         countVariable->mergeIsProfitableToUnbox(true);
1842         Node* setArgumentCount = addToGraph(SetArgument, OpInfo(countVariable));
1843         m_currentBlock->variablesAtTail.setOperand(countVariable->local(), setArgumentCount);
1844         
1845         set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
1846         for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
1847             VariableAccessData* variable = newVariableAccessData(VirtualRegister(remappedArgumentStart + argument));
1848             variable->mergeShouldNeverUnbox(true); // We currently have nowhere to put the type check on the LoadVarargs. LoadVarargs is effectful, so after it finishes, we cannot exit.
1849             
1850             // For a while it had been my intention to do things like this inside the
1851             // prediction injection phase. But in this case it's really best to do it here,
1852             // because it's here that we have access to the variable access datas for the
1853             // inlining we're about to do.
1854             //
1855             // Something else that's interesting here is that we'd really love to get
1856             // predictions from the arguments loaded at the callsite, rather than the
1857             // arguments received inside the callee. But that probably won't matter for most
1858             // calls.
1859             if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
1860                 ConcurrentJSLocker locker(codeBlock->m_lock);
1861                 ValueProfile& profile = codeBlock->valueProfileForArgument(argument);
1862                 variable->predict(profile.computeUpdatedPrediction(locker));
1863             }
1864             
1865             Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
1866             m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
1867         }
1868     };
1869
1870     // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because
1871     // we currently don't have any way of getting profiling information for arguments to non-JS varargs
1872     // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow,
1873     // and there are no callsite value profiles and native function won't have callee value profiles for
1874     // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to
1875     // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without
1876     // calling LoadVarargs twice.
1877     inlineCall(callTargetNode, resultOperand, callVariant, registerOffset, maxNumArguments, kind, nullptr, insertChecks);
1878
1879     VERBOSE_LOG("Successful inlining (varargs, monomorphic).\nStack: ", currentCodeOrigin(), "\n");
1880     return true;
1881 }
1882
1883 unsigned ByteCodeParser::getInliningBalance(const CallLinkStatus& callLinkStatus, CodeSpecializationKind specializationKind)
1884 {
1885     unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
1886     if (specializationKind == CodeForConstruct)
1887         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
1888     if (callLinkStatus.isClosureCall())
1889         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
1890     return inliningBalance;
1891 }
1892
1893 ByteCodeParser::CallOptimizationResult ByteCodeParser::handleInlining(
1894     Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus,
1895     int registerOffset, VirtualRegister thisArgument,
1896     int argumentCountIncludingThis,
1897     unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
1898 {
1899     VERBOSE_LOG("Handling inlining...\nStack: ", currentCodeOrigin(), "\n");
1900     
1901     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1902     unsigned inliningBalance = getInliningBalance(callLinkStatus, specializationKind);
1903
1904     // First check if we can avoid creating control flow. Our inliner does some CFG
1905     // simplification on the fly and this helps reduce compile times, but we can only leverage
1906     // this in cases where we don't need control flow diamonds to check the callee.
1907     if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
1908         return handleCallVariant(
1909             callTargetNode, resultOperand, callLinkStatus[0], registerOffset, thisArgument,
1910             argumentCountIncludingThis, nextOffset, kind, prediction, inliningBalance, nullptr, true);
1911     }
1912
1913     // We need to create some kind of switch over callee. For now we only do this if we believe that
1914     // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
1915     // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
1916     // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
1917     // we could improve that aspect of this by doing polymorphic inlining but having the profiling
1918     // also.
1919     if (!m_graph.m_plan.isFTL() || !Options::usePolymorphicCallInlining()) {
1920         VERBOSE_LOG("Bailing inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
1921         return CallOptimizationResult::DidNothing;
1922     }
1923     
1924     // If the claim is that this did not originate from a stub, then we don't want to emit a switch
1925     // statement. Whenever the non-stub profiling says that it could take slow path, it really means that
1926     // it has no idea.
1927     if (!Options::usePolymorphicCallInliningForNonStubStatus()
1928         && !callLinkStatus.isBasedOnStub()) {
1929         VERBOSE_LOG("Bailing inlining (non-stub polymorphism).\nStack: ", currentCodeOrigin(), "\n");
1930         return CallOptimizationResult::DidNothing;
1931     }
1932
1933     bool allAreClosureCalls = true;
1934     bool allAreDirectCalls = true;
1935     for (unsigned i = callLinkStatus.size(); i--;) {
1936         if (callLinkStatus[i].isClosureCall())
1937             allAreDirectCalls = false;
1938         else
1939             allAreClosureCalls = false;
1940     }
1941
1942     Node* thingToSwitchOn;
1943     if (allAreDirectCalls)
1944         thingToSwitchOn = callTargetNode;
1945     else if (allAreClosureCalls)
1946         thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
1947     else {
1948         // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
1949         // where it would be beneficial. It might be best to handle these cases as if all calls were
1950         // closure calls.
1951         // https://bugs.webkit.org/show_bug.cgi?id=136020
1952         VERBOSE_LOG("Bailing inlining (mix).\nStack: ", currentCodeOrigin(), "\n");
1953         return CallOptimizationResult::DidNothing;
1954     }
1955
1956     VERBOSE_LOG("Doing hard inlining...\nStack: ", currentCodeOrigin(), "\n");
1957
1958     // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
1959     // store the callee so that it will be accessible to all of the blocks we're about to create. We
1960     // get away with doing an immediate-set here because we wouldn't have performed any side effects
1961     // yet.
1962     VERBOSE_LOG("Register offset: ", registerOffset);
1963     VirtualRegister calleeReg(registerOffset + CallFrameSlot::callee);
1964     calleeReg = m_inlineStackTop->remapOperand(calleeReg);
1965     VERBOSE_LOG("Callee is going to be ", calleeReg, "\n");
1966     setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
1967
1968     // It's OK to exit right now, even though we set some locals. That's because those locals are not
1969     // user-visible.
1970     m_exitOK = true;
1971     addToGraph(ExitOK);
1972     
1973     SwitchData& data = *m_graph.m_switchData.add();
1974     data.kind = SwitchCell;
1975     addToGraph(Switch, OpInfo(&data), thingToSwitchOn);
1976     m_currentBlock->didLink();
1977     
1978     BasicBlock* continuationBlock = allocateUntargetableBlock();
1979     VERBOSE_LOG("Adding untargetable block ", RawPointer(continuationBlock), " (continuation)\n");
1980     
1981     // We may force this true if we give up on inlining any of the edges.
1982     bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
1983     
1984     VERBOSE_LOG("About to loop over functions at ", currentCodeOrigin(), ".\n");
1985
1986     unsigned oldOffset = m_currentIndex;
1987     for (unsigned i = 0; i < callLinkStatus.size(); ++i) {
1988         m_currentIndex = oldOffset;
1989         BasicBlock* calleeEntryBlock = allocateUntargetableBlock();
1990         m_currentBlock = calleeEntryBlock;
1991         prepareToParseBlock();
1992
1993         // At the top of each switch case, we can exit.
1994         m_exitOK = true;
1995         
1996         Node* myCallTargetNode = getDirect(calleeReg);
1997         
1998         auto inliningResult = handleCallVariant(
1999             myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
2000             thisArgument, argumentCountIncludingThis, nextOffset, kind, prediction,
2001             inliningBalance, continuationBlock, false);
2002         
2003         if (inliningResult == CallOptimizationResult::DidNothing) {
2004             // That failed so we let the block die. Nothing interesting should have been added to
2005             // the block. We also give up on inlining any of the (less frequent) callees.
2006             ASSERT(m_graph.m_blocks.last() == m_currentBlock);
2007             m_graph.killBlockAndItsContents(m_currentBlock);
2008             m_graph.m_blocks.removeLast();
2009             VERBOSE_LOG("Inlining of a poly call failed, we will have to go through a slow path\n");
2010
2011             // The fact that inlining failed means we need a slow path.
2012             couldTakeSlowPath = true;
2013             break;
2014         }
2015         
2016         JSCell* thingToCaseOn;
2017         if (allAreDirectCalls)
2018             thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
2019         else {
2020             ASSERT(allAreClosureCalls);
2021             thingToCaseOn = callLinkStatus[i].executable();
2022         }
2023         data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), calleeEntryBlock));
2024         VERBOSE_LOG("Finished optimizing ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
2025     }
2026
2027     // Slow path block
2028     m_currentBlock = allocateUntargetableBlock();
2029     m_currentIndex = oldOffset;
2030     m_exitOK = true;
2031     data.fallThrough = BranchTarget(m_currentBlock);
2032     prepareToParseBlock();
2033     Node* myCallTargetNode = getDirect(calleeReg);
2034     if (couldTakeSlowPath) {
2035         addCall(
2036             resultOperand, callOp, nullptr, myCallTargetNode, argumentCountIncludingThis,
2037             registerOffset, prediction);
2038         VERBOSE_LOG("We added a call in the slow path\n");
2039     } else {
2040         addToGraph(CheckBadCell);
2041         addToGraph(Phantom, myCallTargetNode);
2042         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
2043         
2044         set(VirtualRegister(resultOperand), addToGraph(BottomValue));
2045         VERBOSE_LOG("couldTakeSlowPath was false\n");
2046     }
2047
2048     m_currentIndex = nextOffset;
2049     m_exitOK = true; // Origin changed, so it's fine to exit again.
2050     processSetLocalQueue();
2051
2052     if (Node* terminal = m_currentBlock->terminal())
2053         ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
2054     else {
2055         addJumpTo(continuationBlock);
2056     }
2057
2058     prepareToParseBlock();
2059     
2060     m_currentIndex = oldOffset;
2061     m_currentBlock = continuationBlock;
2062     m_exitOK = true;
2063     
2064     VERBOSE_LOG("Done inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
2065     return CallOptimizationResult::Inlined;
2066 }
2067
2068 template<typename ChecksFunctor>
2069 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks)
2070 {
2071     ASSERT(op == ArithMin || op == ArithMax);
2072
2073     if (argumentCountIncludingThis == 1) {
2074         insertChecks();
2075         double result = op == ArithMax ? -std::numeric_limits<double>::infinity() : +std::numeric_limits<double>::infinity();
2076         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsDoubleNumber(result)))));
2077         return true;
2078     }
2079      
2080     if (argumentCountIncludingThis == 2) {
2081         insertChecks();
2082         Node* result = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
2083         addToGraph(Phantom, Edge(result, NumberUse));
2084         set(VirtualRegister(resultOperand), result);
2085         return true;
2086     }
2087     
2088     if (argumentCountIncludingThis == 3) {
2089         insertChecks();
2090         set(VirtualRegister(resultOperand), addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2091         return true;
2092     }
2093     
2094     // Don't handle >=3 arguments for now.
2095     return false;
2096 }
2097
2098 template<typename ChecksFunctor>
2099 bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2100 {
2101     VERBOSE_LOG("       The intrinsic is ", intrinsic, "\n");
2102
2103     if (!isOpcodeShape<OpCallShape>(m_currentInstruction))
2104         return false;
2105
2106     // It so happens that the code below doesn't handle the invalid result case. We could fix that, but
2107     // it would only benefit intrinsics called as setters, like if you do:
2108     //
2109     //     o.__defineSetter__("foo", Math.pow)
2110     //
2111     // Which is extremely amusing, but probably not worth optimizing.
2112     if (!VirtualRegister(resultOperand).isValid())
2113         return false;
2114     
2115     switch (intrinsic) {
2116
2117     // Intrinsic Functions:
2118
2119     case AbsIntrinsic: {
2120         if (argumentCountIncludingThis == 1) { // Math.abs()
2121             insertChecks();
2122             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2123             return true;
2124         }
2125
2126         if (!MacroAssembler::supportsFloatingPointAbs())
2127             return false;
2128
2129         insertChecks();
2130         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
2131         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
2132             node->mergeFlags(NodeMayOverflowInt32InDFG);
2133         set(VirtualRegister(resultOperand), node);
2134         return true;
2135     }
2136
2137     case MinIntrinsic:
2138         return handleMinMax(resultOperand, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
2139         
2140     case MaxIntrinsic:
2141         return handleMinMax(resultOperand, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
2142
2143 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2144     case capitalizedName##Intrinsic:
2145     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2146 #undef DFG_ARITH_UNARY
2147     {
2148         if (argumentCountIncludingThis == 1) {
2149             insertChecks();
2150             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2151             return true;
2152         }
2153         Arith::UnaryType type = Arith::UnaryType::Sin;
2154         switch (intrinsic) {
2155 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2156         case capitalizedName##Intrinsic: \
2157             type = Arith::UnaryType::capitalizedName; \
2158             break;
2159     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2160 #undef DFG_ARITH_UNARY
2161         default:
2162             RELEASE_ASSERT_NOT_REACHED();
2163         }
2164         insertChecks();
2165         set(VirtualRegister(resultOperand), addToGraph(ArithUnary, OpInfo(static_cast<std::underlying_type<Arith::UnaryType>::type>(type)), get(virtualRegisterForArgument(1, registerOffset))));
2166         return true;
2167     }
2168
2169     case FRoundIntrinsic:
2170     case SqrtIntrinsic: {
2171         if (argumentCountIncludingThis == 1) {
2172             insertChecks();
2173             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2174             return true;
2175         }
2176
2177         NodeType nodeType = Unreachable;
2178         switch (intrinsic) {
2179         case FRoundIntrinsic:
2180             nodeType = ArithFRound;
2181             break;
2182         case SqrtIntrinsic:
2183             nodeType = ArithSqrt;
2184             break;
2185         default:
2186             RELEASE_ASSERT_NOT_REACHED();
2187         }
2188         insertChecks();
2189         set(VirtualRegister(resultOperand), addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
2190         return true;
2191     }
2192
2193     case PowIntrinsic: {
2194         if (argumentCountIncludingThis < 3) {
2195             // Math.pow() and Math.pow(x) return NaN.
2196             insertChecks();
2197             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2198             return true;
2199         }
2200         insertChecks();
2201         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
2202         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
2203         set(VirtualRegister(resultOperand), addToGraph(ArithPow, get(xOperand), get(yOperand)));
2204         return true;
2205     }
2206         
2207     case ArrayPushIntrinsic: {
2208 #if USE(JSVALUE32_64)
2209         if (isX86()) {
2210             if (argumentCountIncludingThis > 2)
2211                 return false;
2212         }
2213 #endif
2214
2215         if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
2216             return false;
2217         ArrayMode arrayMode = getArrayMode(arrayProfileFor<OpCallShape>(m_currentInstruction), Array::Write);
2218         if (!arrayMode.isJSArray())
2219             return false;
2220         switch (arrayMode.type()) {
2221         case Array::Int32:
2222         case Array::Double:
2223         case Array::Contiguous:
2224         case Array::ArrayStorage: {
2225             insertChecks();
2226
2227             addVarArgChild(nullptr); // For storage.
2228             for (int i = 0; i < argumentCountIncludingThis; ++i)
2229                 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
2230             Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
2231             set(VirtualRegister(resultOperand), arrayPush);
2232             
2233             return true;
2234         }
2235             
2236         default:
2237             return false;
2238         }
2239     }
2240
2241     case ArraySliceIntrinsic: {
2242 #if USE(JSVALUE32_64)
2243         if (isX86()) {
2244             // There aren't enough registers for this to be done easily.
2245             return false;
2246         }
2247 #endif
2248         if (argumentCountIncludingThis < 1)
2249             return false;
2250
2251         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2252             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
2253             return false;
2254         ArrayMode arrayMode = getArrayMode(arrayProfileFor<OpCallShape>(m_currentInstruction), Array::Read);
2255         if (!arrayMode.isJSArray())
2256             return false;
2257
2258         if (!arrayMode.isJSArrayWithOriginalStructure())
2259             return false;
2260
2261         switch (arrayMode.type()) {
2262         case Array::Double:
2263         case Array::Int32:
2264         case Array::Contiguous: {
2265             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2266
2267             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
2268             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
2269
2270             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2271             // https://bugs.webkit.org/show_bug.cgi?id=173171
2272             if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
2273                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
2274                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2275                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2276                 && globalObject->arrayPrototypeChainIsSane()) {
2277
2278                 m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
2279                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2280                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2281                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2282
2283                 insertChecks();
2284
2285                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2286                 // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
2287                 // 1. We ensure that the "constructor" property hasn't been changed (because the observable
2288                 // effects of slice require that we perform a Get(array, "constructor") and we can skip
2289                 // that if we're an original array structure. (We can relax this in the future by using
2290                 // TryGetById and CheckCell).
2291                 //
2292                 // 2. We check that the array we're calling slice on has the same global object as the lexical
2293                 // global object that this code is running in. This requirement is necessary because we setup the
2294                 // watchpoints above on the lexical global object. This means that code that calls slice on
2295                 // arrays produced by other global objects won't get this optimization. We could relax this
2296                 // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
2297                 // we generate instead of registering it as a watchpoint that would invalidate the compilation.
2298                 //
2299                 // 3. By proving we're an original array structure, we guarantee that the incoming array
2300                 // isn't a subclass of Array.
2301
2302                 StructureSet structureSet;
2303                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
2304                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
2305                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
2306                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithInt32));
2307                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
2308                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithDouble));
2309                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
2310
2311                 addVarArgChild(array);
2312                 if (argumentCountIncludingThis >= 2)
2313                     addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
2314                 if (argumentCountIncludingThis >= 3)
2315                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
2316                 addVarArgChild(addToGraph(GetButterfly, array));
2317
2318                 Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
2319                 set(VirtualRegister(resultOperand), arraySlice);
2320                 return true;
2321             }
2322
2323             return false;
2324         }
2325         default:
2326             return false;
2327         }
2328
2329         RELEASE_ASSERT_NOT_REACHED();
2330         return false;
2331     }
2332
2333     case ArrayIndexOfIntrinsic: {
2334         if (argumentCountIncludingThis < 2)
2335             return false;
2336
2337         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
2338             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2339             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
2340             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2341             return false;
2342
2343         ArrayMode arrayMode = getArrayMode(arrayProfileFor<OpCallShape>(m_currentInstruction), Array::Read);
2344         if (!arrayMode.isJSArray())
2345             return false;
2346
2347         if (!arrayMode.isJSArrayWithOriginalStructure())
2348             return false;
2349
2350         // We do not want to convert arrays into one type just to perform indexOf.
2351         if (arrayMode.doesConversion())
2352             return false;
2353
2354         switch (arrayMode.type()) {
2355         case Array::Double:
2356         case Array::Int32:
2357         case Array::Contiguous: {
2358             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2359
2360             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
2361             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
2362
2363             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2364             // https://bugs.webkit.org/show_bug.cgi?id=173171
2365             if (globalObject->havingABadTimeWatchpoint()->isStillValid()
2366                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2367                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2368                 && globalObject->arrayPrototypeChainIsSane()) {
2369
2370                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2371                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2372                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2373
2374                 insertChecks();
2375
2376                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2377                 addVarArgChild(array);
2378                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element.
2379                 if (argumentCountIncludingThis >= 3)
2380                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index.
2381                 addVarArgChild(nullptr);
2382
2383                 Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo());
2384                 set(VirtualRegister(resultOperand), node);
2385                 return true;
2386             }
2387
2388             return false;
2389         }
2390         default:
2391             return false;
2392         }
2393
2394         RELEASE_ASSERT_NOT_REACHED();
2395         return false;
2396
2397     }
2398         
2399     case ArrayPopIntrinsic: {
2400         if (argumentCountIncludingThis != 1)
2401             return false;
2402         ArrayMode arrayMode = getArrayMode(arrayProfileFor<OpCallShape>(m_currentInstruction), Array::Write);
2403         if (!arrayMode.isJSArray())
2404             return false;
2405         switch (arrayMode.type()) {
2406         case Array::Int32:
2407         case Array::Double:
2408         case Array::Contiguous:
2409         case Array::ArrayStorage: {
2410             insertChecks();
2411             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
2412             set(VirtualRegister(resultOperand), arrayPop);
2413             return true;
2414         }
2415             
2416         default:
2417             return false;
2418         }
2419     }
2420         
2421     case AtomicsAddIntrinsic:
2422     case AtomicsAndIntrinsic:
2423     case AtomicsCompareExchangeIntrinsic:
2424     case AtomicsExchangeIntrinsic:
2425     case AtomicsIsLockFreeIntrinsic:
2426     case AtomicsLoadIntrinsic:
2427     case AtomicsOrIntrinsic:
2428     case AtomicsStoreIntrinsic:
2429     case AtomicsSubIntrinsic:
2430     case AtomicsXorIntrinsic: {
2431         if (!is64Bit())
2432             return false;
2433         
2434         NodeType op = LastNodeType;
2435         Array::Action action = Array::Write;
2436         unsigned numArgs = 0; // Number of actual args; we add one for the backing store pointer.
2437         switch (intrinsic) {
2438         case AtomicsAddIntrinsic:
2439             op = AtomicsAdd;
2440             numArgs = 3;
2441             break;
2442         case AtomicsAndIntrinsic:
2443             op = AtomicsAnd;
2444             numArgs = 3;
2445             break;
2446         case AtomicsCompareExchangeIntrinsic:
2447             op = AtomicsCompareExchange;
2448             numArgs = 4;
2449             break;
2450         case AtomicsExchangeIntrinsic:
2451             op = AtomicsExchange;
2452             numArgs = 3;
2453             break;
2454         case AtomicsIsLockFreeIntrinsic:
2455             // This gets no backing store, but we need no special logic for this since this also does
2456             // not need varargs.
2457             op = AtomicsIsLockFree;
2458             numArgs = 1;
2459             break;
2460         case AtomicsLoadIntrinsic:
2461             op = AtomicsLoad;
2462             numArgs = 2;
2463             action = Array::Read;
2464             break;
2465         case AtomicsOrIntrinsic:
2466             op = AtomicsOr;
2467             numArgs = 3;
2468             break;
2469         case AtomicsStoreIntrinsic:
2470             op = AtomicsStore;
2471             numArgs = 3;
2472             break;
2473         case AtomicsSubIntrinsic:
2474             op = AtomicsSub;
2475             numArgs = 3;
2476             break;
2477         case AtomicsXorIntrinsic:
2478             op = AtomicsXor;
2479             numArgs = 3;
2480             break;
2481         default:
2482             RELEASE_ASSERT_NOT_REACHED();
2483             break;
2484         }
2485         
2486         if (static_cast<unsigned>(argumentCountIncludingThis) < 1 + numArgs)
2487             return false;
2488         
2489         insertChecks();
2490         
2491         Vector<Node*, 3> args;
2492         for (unsigned i = 0; i < numArgs; ++i)
2493             args.append(get(virtualRegisterForArgument(1 + i, registerOffset)));
2494         
2495         Node* result;
2496         if (numArgs + 1 <= 3) {
2497             while (args.size() < 3)
2498                 args.append(nullptr);
2499             result = addToGraph(op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction), args[0], args[1], args[2]);
2500         } else {
2501             for (Node* node : args)
2502                 addVarArgChild(node);
2503             addVarArgChild(nullptr);
2504             result = addToGraph(Node::VarArg, op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction));
2505         }
2506         
2507         set(VirtualRegister(resultOperand), result);
2508         return true;
2509     }
2510
2511     case ParseIntIntrinsic: {
2512         if (argumentCountIncludingThis < 2)
2513             return false;
2514
2515         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2516             return false;
2517
2518         insertChecks();
2519         VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
2520         Node* parseInt;
2521         if (argumentCountIncludingThis == 2)
2522             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
2523         else {
2524             ASSERT(argumentCountIncludingThis > 2);
2525             VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
2526             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
2527         }
2528         set(VirtualRegister(resultOperand), parseInt);
2529         return true;
2530     }
2531
2532     case CharCodeAtIntrinsic: {
2533         if (argumentCountIncludingThis != 2)
2534             return false;
2535
2536         insertChecks();
2537         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2538         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2539         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
2540
2541         set(VirtualRegister(resultOperand), charCode);
2542         return true;
2543     }
2544
2545     case CharAtIntrinsic: {
2546         if (argumentCountIncludingThis != 2)
2547             return false;
2548
2549         insertChecks();
2550         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2551         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2552         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
2553
2554         set(VirtualRegister(resultOperand), charCode);
2555         return true;
2556     }
2557     case Clz32Intrinsic: {
2558         insertChecks();
2559         if (argumentCountIncludingThis == 1)
2560             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
2561         else {
2562             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2563             set(VirtualRegister(resultOperand), addToGraph(ArithClz32, operand));
2564         }
2565         return true;
2566     }
2567     case FromCharCodeIntrinsic: {
2568         if (argumentCountIncludingThis != 2)
2569             return false;
2570
2571         insertChecks();
2572         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2573         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
2574
2575         set(VirtualRegister(resultOperand), charCode);
2576
2577         return true;
2578     }
2579
2580     case RegExpExecIntrinsic: {
2581         if (argumentCountIncludingThis != 2)
2582             return false;
2583         
2584         insertChecks();
2585         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2586         set(VirtualRegister(resultOperand), regExpExec);
2587         
2588         return true;
2589     }
2590         
2591     case RegExpTestIntrinsic:
2592     case RegExpTestFastIntrinsic: {
2593         if (argumentCountIncludingThis != 2)
2594             return false;
2595
2596         if (intrinsic == RegExpTestIntrinsic) {
2597             // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2598             if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2599                 return false;
2600
2601             JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2602             Structure* regExpStructure = globalObject->regExpStructure();
2603             m_graph.registerStructure(regExpStructure);
2604             ASSERT(regExpStructure->storedPrototype().isObject());
2605             ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2606
2607             FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2608             Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2609
2610             auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2611                 JSValue currentProperty;
2612                 if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2613                     return false;
2614                 
2615                 return currentProperty == primordialProperty;
2616             };
2617
2618             // Check that RegExp.exec is still the primordial RegExp.prototype.exec
2619             if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2620                 return false;
2621
2622             // Check that regExpObject is actually a RegExp object.
2623             Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2624             addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
2625
2626             // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
2627             UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
2628             unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
2629             Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
2630             FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
2631             addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
2632         }
2633
2634         insertChecks();
2635         Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2636         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
2637         set(VirtualRegister(resultOperand), regExpExec);
2638         
2639         return true;
2640     }
2641
2642     case RegExpMatchFastIntrinsic: {
2643         RELEASE_ASSERT(argumentCountIncludingThis == 2);
2644
2645         insertChecks();
2646         Node* regExpMatch = addToGraph(RegExpMatchFast, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2647         set(VirtualRegister(resultOperand), regExpMatch);
2648         return true;
2649     }
2650
2651     case ObjectCreateIntrinsic: {
2652         if (argumentCountIncludingThis != 2)
2653             return false;
2654
2655         insertChecks();
2656         set(VirtualRegister(resultOperand), addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
2657         return true;
2658     }
2659
2660     case ObjectGetPrototypeOfIntrinsic: {
2661         if (argumentCountIncludingThis != 2)
2662             return false;
2663
2664         insertChecks();
2665         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2666         return true;
2667     }
2668
2669     case ObjectIsIntrinsic: {
2670         if (argumentCountIncludingThis < 3)
2671             return false;
2672
2673         insertChecks();
2674         set(VirtualRegister(resultOperand), addToGraph(SameValue, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2675         return true;
2676     }
2677
2678     case ReflectGetPrototypeOfIntrinsic: {
2679         if (argumentCountIncludingThis != 2)
2680             return false;
2681
2682         insertChecks();
2683         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), Edge(get(virtualRegisterForArgument(1, registerOffset)), ObjectUse)));
2684         return true;
2685     }
2686
2687     case IsTypedArrayViewIntrinsic: {
2688         ASSERT(argumentCountIncludingThis == 2);
2689
2690         insertChecks();
2691         set(VirtualRegister(resultOperand), addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2692         return true;
2693     }
2694
2695     case StringPrototypeValueOfIntrinsic: {
2696         insertChecks();
2697         Node* value = get(virtualRegisterForArgument(0, registerOffset));
2698         set(VirtualRegister(resultOperand), addToGraph(StringValueOf, value));
2699         return true;
2700     }
2701
2702     case StringPrototypeReplaceIntrinsic: {
2703         if (argumentCountIncludingThis != 3)
2704             return false;
2705
2706         // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
2707         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2708             return false;
2709
2710         // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2711         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2712             return false;
2713
2714         JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2715         Structure* regExpStructure = globalObject->regExpStructure();
2716         m_graph.registerStructure(regExpStructure);
2717         ASSERT(regExpStructure->storedPrototype().isObject());
2718         ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2719
2720         FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2721         Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2722
2723         auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2724             JSValue currentProperty;
2725             if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2726                 return false;
2727
2728             return currentProperty == primordialProperty;
2729         };
2730
2731         // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
2732         if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2733             return false;
2734
2735         // Check that searchRegExp.global is still the primordial RegExp.prototype.global
2736         if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
2737             return false;
2738
2739         // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
2740         if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
2741             return false;
2742
2743         // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
2744         if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
2745             return false;
2746
2747         insertChecks();
2748
2749         Node* result = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2750         set(VirtualRegister(resultOperand), result);
2751         return true;
2752     }
2753         
2754     case StringPrototypeReplaceRegExpIntrinsic: {
2755         if (argumentCountIncludingThis != 3)
2756             return false;
2757         
2758         insertChecks();
2759         Node* result = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2760         set(VirtualRegister(resultOperand), result);
2761         return true;
2762     }
2763         
2764     case RoundIntrinsic:
2765     case FloorIntrinsic:
2766     case CeilIntrinsic:
2767     case TruncIntrinsic: {
2768         if (argumentCountIncludingThis == 1) {
2769             insertChecks();
2770             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2771             return true;
2772         }
2773         insertChecks();
2774         Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2775         NodeType op;
2776         if (intrinsic == RoundIntrinsic)
2777             op = ArithRound;
2778         else if (intrinsic == FloorIntrinsic)
2779             op = ArithFloor;
2780         else if (intrinsic == CeilIntrinsic)
2781             op = ArithCeil;
2782         else {
2783             ASSERT(intrinsic == TruncIntrinsic);
2784             op = ArithTrunc;
2785         }
2786         Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
2787         set(VirtualRegister(resultOperand), roundNode);
2788         return true;
2789     }
2790     case IMulIntrinsic: {
2791         if (argumentCountIncludingThis != 3)
2792             return false;
2793         insertChecks();
2794         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
2795         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
2796         Node* left = get(leftOperand);
2797         Node* right = get(rightOperand);
2798         set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
2799         return true;
2800     }
2801
2802     case RandomIntrinsic: {
2803         if (argumentCountIncludingThis != 1)
2804             return false;
2805         insertChecks();
2806         set(VirtualRegister(resultOperand), addToGraph(ArithRandom));
2807         return true;
2808     }
2809         
2810     case DFGTrueIntrinsic: {
2811         insertChecks();
2812         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2813         return true;
2814     }
2815
2816     case FTLTrueIntrinsic: {
2817         insertChecks();
2818         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(m_graph.m_plan.isFTL())));
2819         return true;
2820     }
2821         
2822     case OSRExitIntrinsic: {
2823         insertChecks();
2824         addToGraph(ForceOSRExit);
2825         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2826         return true;
2827     }
2828         
2829     case IsFinalTierIntrinsic: {
2830         insertChecks();
2831         set(VirtualRegister(resultOperand),
2832             jsConstant(jsBoolean(Options::useFTLJIT() ? m_graph.m_plan.isFTL() : true)));
2833         return true;
2834     }
2835         
2836     case SetInt32HeapPredictionIntrinsic: {
2837         insertChecks();
2838         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2839             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2840             if (node->hasHeapPrediction())
2841                 node->setHeapPrediction(SpecInt32Only);
2842         }
2843         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2844         return true;
2845     }
2846         
2847     case CheckInt32Intrinsic: {
2848         insertChecks();
2849         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2850             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2851             addToGraph(Phantom, Edge(node, Int32Use));
2852         }
2853         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2854         return true;
2855     }
2856         
2857     case FiatInt52Intrinsic: {
2858         if (argumentCountIncludingThis != 2)
2859             return false;
2860         insertChecks();
2861         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2862         if (enableInt52())
2863             set(VirtualRegister(resultOperand), addToGraph(FiatInt52, get(operand)));
2864         else
2865             set(VirtualRegister(resultOperand), get(operand));
2866         return true;
2867     }
2868
2869     case JSMapGetIntrinsic: {
2870         if (argumentCountIncludingThis != 2)
2871             return false;
2872
2873         insertChecks();
2874         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2875         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2876         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2877         Node* hash = addToGraph(MapHash, normalizedKey);
2878         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(normalizedKey), Edge(hash));
2879         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2880         set(VirtualRegister(resultOperand), result);
2881         return true;
2882     }
2883
2884     case JSSetHasIntrinsic:
2885     case JSMapHasIntrinsic: {
2886         if (argumentCountIncludingThis != 2)
2887             return false;
2888
2889         insertChecks();
2890         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
2891         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2892         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2893         Node* hash = addToGraph(MapHash, normalizedKey);
2894         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
2895         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
2896         JSCell* sentinel = nullptr;
2897         if (intrinsic == JSMapHasIntrinsic)
2898             sentinel = m_vm->sentinelMapBucket.get();
2899         else
2900             sentinel = m_vm->sentinelSetBucket.get();
2901
2902         FrozenValue* frozenPointer = m_graph.freeze(sentinel);
2903         Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
2904         Node* result = addToGraph(LogicalNot, invertedResult);
2905         set(VirtualRegister(resultOperand), result);
2906         return true;
2907     }
2908
2909     case JSSetAddIntrinsic: {
2910         if (argumentCountIncludingThis != 2)
2911             return false;
2912
2913         insertChecks();
2914         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2915         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2916         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2917         Node* hash = addToGraph(MapHash, normalizedKey);
2918         addToGraph(SetAdd, base, normalizedKey, hash);
2919         set(VirtualRegister(resultOperand), base);
2920         return true;
2921     }
2922
2923     case JSMapSetIntrinsic: {
2924         if (argumentCountIncludingThis != 3)
2925             return false;
2926
2927         insertChecks();
2928         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2929         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2930         Node* value = get(virtualRegisterForArgument(2, registerOffset));
2931
2932         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2933         Node* hash = addToGraph(MapHash, normalizedKey);
2934
2935         addVarArgChild(base);
2936         addVarArgChild(normalizedKey);
2937         addVarArgChild(value);
2938         addVarArgChild(hash);
2939         addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
2940         set(VirtualRegister(resultOperand), base);
2941         return true;
2942     }
2943
2944     case JSSetBucketHeadIntrinsic:
2945     case JSMapBucketHeadIntrinsic: {
2946         ASSERT(argumentCountIncludingThis == 2);
2947
2948         insertChecks();
2949         Node* map = get(virtualRegisterForArgument(1, registerOffset));
2950         UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
2951         Node* result = addToGraph(GetMapBucketHead, Edge(map, useKind));
2952         set(VirtualRegister(resultOperand), result);
2953         return true;
2954     }
2955
2956     case JSSetBucketNextIntrinsic:
2957     case JSMapBucketNextIntrinsic: {
2958         ASSERT(argumentCountIncludingThis == 2);
2959
2960         insertChecks();
2961         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2962         BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2963         Node* result = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
2964         set(VirtualRegister(resultOperand), result);
2965         return true;
2966     }
2967
2968     case JSSetBucketKeyIntrinsic:
2969     case JSMapBucketKeyIntrinsic: {
2970         ASSERT(argumentCountIncludingThis == 2);
2971
2972         insertChecks();
2973         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2974         BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2975         Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
2976         set(VirtualRegister(resultOperand), result);
2977         return true;
2978     }
2979
2980     case JSMapBucketValueIntrinsic: {
2981         ASSERT(argumentCountIncludingThis == 2);
2982
2983         insertChecks();
2984         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2985         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2986         set(VirtualRegister(resultOperand), result);
2987         return true;
2988     }
2989
2990     case JSWeakMapGetIntrinsic: {
2991         if (argumentCountIncludingThis != 2)
2992             return false;
2993
2994         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2995             return false;
2996
2997         insertChecks();
2998         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2999         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3000         addToGraph(Check, Edge(key, ObjectUse));
3001         Node* hash = addToGraph(MapHash, key);
3002         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3003         Node* result = addToGraph(ExtractValueFromWeakMapGet, OpInfo(), OpInfo(prediction), holder);
3004
3005         set(VirtualRegister(resultOperand), result);
3006         return true;
3007     }
3008
3009     case JSWeakMapHasIntrinsic: {
3010         if (argumentCountIncludingThis != 2)
3011             return false;
3012
3013         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3014             return false;
3015
3016         insertChecks();
3017         Node* map = get(virtualRegisterForArgument(0, registerOffset));
3018         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3019         addToGraph(Check, Edge(key, ObjectUse));
3020         Node* hash = addToGraph(MapHash, key);
3021         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3022         Node* invertedResult = addToGraph(IsEmpty, holder);
3023         Node* result = addToGraph(LogicalNot, invertedResult);
3024
3025         set(VirtualRegister(resultOperand), result);
3026         return true;
3027     }
3028
3029     case JSWeakSetHasIntrinsic: {
3030         if (argumentCountIncludingThis != 2)
3031             return false;
3032
3033         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3034             return false;
3035
3036         insertChecks();
3037         Node* map = get(virtualRegisterForArgument(0, registerOffset));
3038         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3039         addToGraph(Check, Edge(key, ObjectUse));
3040         Node* hash = addToGraph(MapHash, key);
3041         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3042         Node* invertedResult = addToGraph(IsEmpty, holder);
3043         Node* result = addToGraph(LogicalNot, invertedResult);
3044
3045         set(VirtualRegister(resultOperand), result);
3046         return true;
3047     }
3048
3049     case JSWeakSetAddIntrinsic: {
3050         if (argumentCountIncludingThis != 2)
3051             return false;
3052
3053         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3054             return false;
3055
3056         insertChecks();
3057         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3058         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3059         addToGraph(Check, Edge(key, ObjectUse));
3060         Node* hash = addToGraph(MapHash, key);
3061         addToGraph(WeakSetAdd, Edge(base, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3062         set(VirtualRegister(resultOperand), base);
3063         return true;
3064     }
3065
3066     case JSWeakMapSetIntrinsic: {
3067         if (argumentCountIncludingThis != 3)
3068             return false;
3069
3070         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3071             return false;
3072
3073         insertChecks();
3074         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3075         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3076         Node* value = get(virtualRegisterForArgument(2, registerOffset));
3077
3078         addToGraph(Check, Edge(key, ObjectUse));
3079         Node* hash = addToGraph(MapHash, key);
3080
3081         addVarArgChild(Edge(base, WeakMapObjectUse));
3082         addVarArgChild(Edge(key, ObjectUse));
3083         addVarArgChild(Edge(value));
3084         addVarArgChild(Edge(hash, Int32Use));
3085         addToGraph(Node::VarArg, WeakMapSet, OpInfo(0), OpInfo(0));
3086         set(VirtualRegister(resultOperand), base);
3087         return true;
3088     }
3089
3090     case DataViewGetInt8:
3091     case DataViewGetUint8:
3092     case DataViewGetInt16:
3093     case DataViewGetUint16:
3094     case DataViewGetInt32:
3095     case DataViewGetUint32:
3096     case DataViewGetFloat32:
3097     case DataViewGetFloat64: {
3098         if (!is64Bit())
3099             return false;
3100
3101         // To inline data view accesses, we assume the architecture we're running on:
3102         // - Is little endian.
3103         // - Allows unaligned loads/stores without crashing. 
3104
3105         if (argumentCountIncludingThis < 2)
3106             return false;
3107         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3108             return false;
3109
3110         insertChecks();
3111
3112         uint8_t byteSize;
3113         NodeType op = DataViewGetInt;
3114         bool isSigned = false;
3115         switch (intrinsic) {
3116         case DataViewGetInt8:
3117             isSigned = true;
3118             FALLTHROUGH;
3119         case DataViewGetUint8:
3120             byteSize = 1;
3121             break;
3122
3123         case DataViewGetInt16:
3124             isSigned = true;
3125             FALLTHROUGH;
3126         case DataViewGetUint16:
3127             byteSize = 2;
3128             break;
3129
3130         case DataViewGetInt32:
3131             isSigned = true;
3132             FALLTHROUGH;
3133         case DataViewGetUint32:
3134             byteSize = 4;
3135             break;
3136
3137         case DataViewGetFloat32:
3138             byteSize = 4;
3139             op = DataViewGetFloat;
3140             break;
3141         case DataViewGetFloat64:
3142             byteSize = 8;
3143             op = DataViewGetFloat;
3144             break;
3145         default:
3146             RELEASE_ASSERT_NOT_REACHED();
3147         }
3148
3149         TriState isLittleEndian = MixedTriState;
3150         Node* littleEndianChild = nullptr;
3151         if (byteSize > 1) {
3152             if (argumentCountIncludingThis < 3)
3153                 isLittleEndian = FalseTriState;
3154             else {
3155                 littleEndianChild = get(virtualRegisterForArgument(2, registerOffset));
3156                 if (littleEndianChild->hasConstant()) {
3157                     JSValue constant = littleEndianChild->constant()->value();
3158                     isLittleEndian = constant.pureToBoolean();
3159                     if (isLittleEndian != MixedTriState)
3160                         littleEndianChild = nullptr;
3161                 } else
3162                     isLittleEndian = MixedTriState;
3163             }
3164         }
3165
3166         DataViewData data { };
3167         data.isLittleEndian = isLittleEndian;
3168         data.isSigned = isSigned;
3169         data.byteSize = byteSize;
3170
3171         set(VirtualRegister(resultOperand),
3172             addToGraph(op, OpInfo(data.asQuadWord), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), littleEndianChild));
3173         return true;
3174     }
3175
3176     case DataViewSetInt8:
3177     case DataViewSetUint8:
3178     case DataViewSetInt16:
3179     case DataViewSetUint16:
3180     case DataViewSetInt32:
3181     case DataViewSetUint32:
3182     case DataViewSetFloat32:
3183     case DataViewSetFloat64: {
3184         if (!is64Bit())
3185             return false;
3186
3187         if (argumentCountIncludingThis < 3)
3188             return false;
3189
3190         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3191             return false;
3192
3193         insertChecks();
3194
3195         uint8_t byteSize;
3196         bool isFloatingPoint = false;
3197         bool isSigned = false;
3198         switch (intrinsic) {
3199         case DataViewSetInt8:
3200             isSigned = true;
3201             FALLTHROUGH;
3202         case DataViewSetUint8:
3203             byteSize = 1;
3204             break;
3205
3206         case DataViewSetInt16:
3207             isSigned = true;
3208             FALLTHROUGH;
3209         case DataViewSetUint16:
3210             byteSize = 2;
3211             break;
3212
3213         case DataViewSetInt32:
3214             isSigned = true;
3215             FALLTHROUGH;
3216         case DataViewSetUint32:
3217             byteSize = 4;
3218             break;
3219
3220         case DataViewSetFloat32:
3221             isFloatingPoint = true;
3222             byteSize = 4;
3223             break;
3224         case DataViewSetFloat64:
3225             isFloatingPoint = true;
3226             byteSize = 8;
3227             break;
3228         default:
3229             RELEASE_ASSERT_NOT_REACHED();
3230         }
3231
3232         TriState isLittleEndian = MixedTriState;
3233         Node* littleEndianChild = nullptr;
3234         if (byteSize > 1) {
3235             if (argumentCountIncludingThis < 4)
3236                 isLittleEndian = FalseTriState;
3237             else {
3238                 littleEndianChild = get(virtualRegisterForArgument(3, registerOffset));
3239                 if (littleEndianChild->hasConstant()) {
3240                     JSValue constant = littleEndianChild->constant()->value();
3241                     isLittleEndian = constant.pureToBoolean();
3242                     if (isLittleEndian != MixedTriState)
3243                         littleEndianChild = nullptr;
3244                 } else
3245                     isLittleEndian = MixedTriState;
3246             }
3247         }
3248
3249         DataViewData data { };
3250         data.isLittleEndian = isLittleEndian;
3251         data.isSigned = isSigned;
3252         data.byteSize = byteSize;
3253         data.isFloatingPoint = isFloatingPoint;
3254
3255         addVarArgChild(get(virtualRegisterForArgument(0, registerOffset)));
3256         addVarArgChild(get(virtualRegisterForArgument(1, registerOffset)));
3257         addVarArgChild(get(virtualRegisterForArgument(2, registerOffset)));
3258         addVarArgChild(littleEndianChild);
3259
3260         addToGraph(Node::VarArg, DataViewSet, OpInfo(data.asQuadWord), OpInfo());
3261         return true;
3262     }
3263
3264     case HasOwnPropertyIntrinsic: {
3265         if (argumentCountIncludingThis != 2)
3266             return false;
3267
3268         // This can be racy, that's fine. We know that once we observe that this is created,
3269         // that it will never be destroyed until the VM is destroyed. It's unlikely that
3270         // we'd ever get to the point where we inline this as an intrinsic without the
3271         // cache being created, however, it's possible if we always throw exceptions inside
3272         // hasOwnProperty.
3273         if (!m_vm->hasOwnPropertyCache())
3274             return false;
3275
3276         insertChecks();
3277         Node* object = get(virtualRegisterForArgument(0, registerOffset));
3278         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3279         Node* result = addToGraph(HasOwnProperty, object, key);
3280         set(VirtualRegister(resultOperand), result);
3281         return true;
3282     }
3283
3284     case StringPrototypeSliceIntrinsic: {
3285         if (argumentCountIncludingThis < 2)
3286             return false;
3287
3288         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3289             return false;
3290
3291         insertChecks();
3292         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3293         Node* start = get(virtualRegisterForArgument(1, registerOffset));
3294         Node* end = nullptr;
3295         if (argumentCountIncludingThis > 2)
3296             end = get(virtualRegisterForArgument(2, registerOffset));
3297         Node* result = addToGraph(StringSlice, thisString, start, end);
3298         set(VirtualRegister(resultOperand), result);
3299         return true;
3300     }
3301
3302     case StringPrototypeToLowerCaseIntrinsic: {
3303         if (argumentCountIncludingThis != 1)
3304             return false;
3305
3306         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3307             return false;
3308
3309         insertChecks();
3310         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3311         Node* result = addToGraph(ToLowerCase, thisString);
3312         set(VirtualRegister(resultOperand), result);
3313         return true;
3314     }
3315
3316     case NumberPrototypeToStringIntrinsic: {
3317         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
3318             return false;
3319
3320         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3321             return false;
3322
3323         insertChecks();
3324         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
3325         if (argumentCountIncludingThis == 1) {
3326             Node* result = addToGraph(ToString, thisNumber);
3327             set(VirtualRegister(resultOperand), result);
3328         } else {
3329             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
3330             Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix);
3331             set(VirtualRegister(resultOperand), result);
3332         }
3333         return true;
3334     }
3335
3336     case NumberIsIntegerIntrinsic: {
3337         if (argumentCountIncludingThis < 2)
3338             return false;
3339
3340         insertChecks();
3341         Node* input = get(virtualRegisterForArgument(1, registerOffset));
3342         Node* result = addToGraph(NumberIsInteger, input);
3343         set(VirtualRegister(resultOperand), result);
3344         return true;
3345     }
3346
3347     case CPUMfenceIntrinsic:
3348     case CPURdtscIntrinsic:
3349     case CPUCpuidIntrinsic:
3350     case CPUPauseIntrinsic: {
3351 #if CPU(X86_64)
3352         if (!m_graph.m_plan.isFTL())
3353             return false;
3354         insertChecks();
3355         set(VirtualRegister(resultOperand),
3356             addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
3357         return true;
3358 #else
3359         return false;
3360 #endif
3361     }
3362
3363
3364     default:
3365         return false;
3366     }
3367 }
3368
3369 template<typename ChecksFunctor>
3370 bool ByteCodeParser::handleDOMJITCall(Node* callTarget, int resultOperand, const DOMJIT::Signature* signature, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3371 {
3372     if (argumentCountIncludingThis != static_cast<int>(1 + signature->argumentCount))
3373         return false;
3374     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3375         return false;
3376
3377     // FIXME: Currently, we only support functions which arguments are up to 2.
3378     // Eventually, we should extend this. But possibly, 2 or 3 can cover typical use cases.
3379     // https://bugs.webkit.org/show_bug.cgi?id=164346
3380     ASSERT_WITH_MESSAGE(argumentCountIncludingThis <= JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS, "Currently CallDOM does not support an arbitrary length arguments.");
3381
3382     insertChecks();
3383     addCall(resultOperand, Call, signature, callTarget, argumentCountIncludingThis, registerOffset, prediction);
3384     return true;
3385 }
3386
3387
3388 template<typename ChecksFunctor>
3389 bool ByteCodeParser::handleIntrinsicGetter(int resultOperand, SpeculatedType prediction, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
3390 {
3391     switch (variant.intrinsic()) {
3392     case TypedArrayByteLengthIntrinsic: {
3393         insertChecks();
3394
3395         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3396         Array::Type arrayType = toArrayType(type);
3397         size_t logSize = logElementSize(type);
3398
3399         variant.structureSet().forEach([&] (Structure* structure) {
3400             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3401             ASSERT(logSize == logElementSize(curType));
3402             arrayType = refineTypedArrayType(arrayType, curType);
3403             ASSERT(arrayType != Array::Generic);
3404         });
3405
3406         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
3407
3408         if (!logSize) {
3409             set(VirtualRegister(resultOperand), lengthNode);
3410             return true;
3411         }
3412
3413         // We can use a BitLShift here because typed arrays will never have a byteLength
3414         // that overflows int32.
3415         Node* shiftNode = jsConstant(jsNumber(logSize));
3416         set(VirtualRegister(resultOperand), addToGraph(BitLShift, lengthNode, shiftNode));
3417
3418         return true;
3419     }
3420
3421     case TypedArrayLengthIntrinsic: {
3422         insertChecks();
3423
3424         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3425         Array::Type arrayType = toArrayType(type);
3426
3427         variant.structureSet().forEach([&] (Structure* structure) {
3428             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3429             arrayType = refineTypedArrayType(arrayType, curType);
3430             ASSERT(arrayType != Array::Generic);
3431         });
3432
3433         set(VirtualRegister(resultOperand), addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
3434
3435         return true;
3436
3437     }
3438
3439     case TypedArrayByteOffsetIntrinsic: {
3440         insertChecks();
3441
3442         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3443         Array::Type arrayType = toArrayType(type);
3444
3445         variant.structureSet().forEach([&] (Structure* structure) {
3446             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3447             arrayType = refineTypedArrayType(arrayType, curType);
3448             ASSERT(arrayType != Array::Generic);
3449         });
3450
3451         set(VirtualRegister(resultOperand), addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
3452
3453         return true;
3454     }
3455
3456     case UnderscoreProtoIntrinsic: {
3457         insertChecks();
3458
3459         bool canFold = !variant.structureSet().isEmpty();
3460         JSValue prototype;
3461         variant.structureSet().forEach([&] (Structure* structure) {
3462             auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3463             MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3464             if (getPrototypeMethod != defaultGetPrototype) {
3465                 canFold = false;
3466                 return;
3467             }
3468
3469             if (structure->hasPolyProto()) {
3470                 canFold = false;
3471                 return;
3472             }
3473             if (!prototype)
3474                 prototype = structure->storedPrototype();
3475             else if (prototype != structure->storedPrototype())
3476                 canFold = false;
3477         });
3478
3479         // OK, only one prototype is found. We perform constant folding here.
3480         // This information is important for super's constructor call to get new.target constant.
3481         if (prototype && canFold) {
3482             set(VirtualRegister(resultOperand), weakJSConstant(prototype));
3483             return true;
3484         }
3485
3486         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), thisNode));
3487         return true;
3488     }
3489
3490     default:
3491         return false;
3492     }
3493     RELEASE_ASSERT_NOT_REACHED();
3494 }
3495
3496 static void blessCallDOMGetter(Node* node)
3497 {
3498     DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
3499     if (snippet && !snippet->effect.mustGenerate())
3500         node->clearFlags(NodeMustGenerate);
3501 }
3502
3503 bool ByteCodeParser::handleDOMJITGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction)
3504 {
3505     if (!variant.domAttribute())
3506         return false;
3507
3508     auto domAttribute = variant.domAttribute().value();
3509
3510     // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough,
3511     // since replacement of CustomGetterSetter always incurs Structure transition.
3512     if (!check(variant.conditionSet()))
3513         return false;
3514     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
3515     
3516     // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
3517     addToGraph(CheckSubClass, OpInfo(domAttribute.classInfo), thisNode);
3518     
3519     bool wasSeenInJIT = true;
3520     addToGraph(FilterGetByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByIdStatus(currentCodeOrigin(), GetByIdStatus(GetByIdStatus::Custom, wasSeenInJIT, variant))), thisNode);
3521
3522     CallDOMGetterData* callDOMGetterData = m_graph.m_callDOMGetterData.add();
3523     callDOMGetterData->customAccessorGetter = variant.customAccessorGetter();
3524     ASSERT(callDOMGetterData->customAccessorGetter);
3525
3526     if (const auto* domJIT = domAttribute.domJIT) {
3527         callDOMGetterData->domJIT = domJIT;
3528         Ref<DOMJIT::CallDOMGetterSnippet> snippet = domJIT->compiler()();
3529         callDOMGetterData->snippet = snippet.ptr();
3530         m_graph.m_domJITSnippets.append(WTFMove(snippet));
3531     }
3532     DOMJIT::CallDOMGetterSnippet* callDOMGetterSnippet = callDOMGetterData->snippet;
3533     callDOMGetterData->identifierNumber = identifierNumber;
3534
3535     Node* callDOMGetterNode = nullptr;
3536     // GlobalObject of thisNode is always used to create a DOMWrapper.
3537     if (callDOMGetterSnippet && callDOMGetterSnippet->requireGlobalObject) {
3538         Node* globalObject = addToGraph(GetGlobalObject, thisNode);
3539         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode, globalObject);
3540     } else
3541         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode);
3542     blessCallDOMGetter(callDOMGetterNode);
3543     set(VirtualRegister(resultOperand), callDOMGetterNode);
3544     return true;
3545 }
3546
3547 bool ByteCodeParser::handleModuleNamespaceLoad(int resultOperand, SpeculatedType prediction, Node* base, GetByIdStatus getById)
3548 {
3549     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
3550         return false;
3551     addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
3552
3553     addToGraph(FilterGetByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByIdStatus(currentCodeOrigin(), getById)), base);
3554
3555     // Ideally we wouldn't have to do this Phantom. But:
3556     //
3557     // For the constant case: we must do it because otherwise we would have no way of knowing
3558     // that the scope is live at OSR here.
3559     //
3560     // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
3561     // won't be able to handle an Undefined scope.
3562     addToGraph(Phantom, base);
3563
3564     // Constant folding in the bytecode parser is important for performance. This may not
3565     // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
3566     // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
3567     // would recompile. But if we can fold it here, we avoid the exit.
3568     m_graph.freeze(getById.moduleEnvironment());
3569     if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
3570         set(VirtualRegister(resultOperand), weakJSConstant(value));
3571         return true;
3572     }
3573     set(VirtualRegister(resultOperand), addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
3574     return true;
3575 }
3576
3577 template<typename ChecksFunctor>
3578 bool ByteCodeParser::handleTypedArrayConstructor(
3579     int resultOperand, InternalFunction* function, int registerOffset,
3580     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
3581 {
3582     if (!isTypedView(type))
3583         return false;
3584     
3585     if (function->classInfo() != constructorClassInfoForType(type))
3586         return false;
3587     
3588     if (function->globalObject(*m_vm) != m_inlineStackTop->m_codeBlock->globalObject())
3589         return false;
3590     
3591     // We only have an intrinsic for the case where you say:
3592     //
3593     // new FooArray(blah);
3594     //
3595     // Of course, 'blah' could be any of the following:
3596     //
3597     // - Integer, indicating that you want to allocate an array of that length.
3598     //   This is the thing we're hoping for, and what we can actually do meaningful
3599     //   optimizations for.
3600     //
3601     // - Array buffer, indicating that you want to create a view onto that _entire_
3602     //   buffer.
3603     //
3604     // - Non-buffer object, indicating that you want to create a copy of that
3605     //   object by pretending that it quacks like an array.
3606     //
3607     // - Anything else, indicating that you want to have an exception thrown at
3608     //   you.
3609     //
3610     // The intrinsic, NewTypedArray, will behave as if it could do any of these
3611     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
3612     // predicted Int32, then we lock it in as a normal typed array allocation.
3613     // Otherwise, NewTypedArray turns into a totally opaque function call that
3614     // may clobber the world - by virtue of it accessing properties on what could
3615     // be an object.
3616     //
3617     // Note that although the generic form of NewTypedArray sounds sort of awful,
3618     // it is actually quite likely to be more efficient than a fully generic
3619     // Construct. So, we might want to think about making NewTypedArray variadic,
3620     // or else making Construct not super slow.
3621     
3622     if (argumentCountIncludingThis != 2)
3623         return false;
3624     
3625     if (!function->globalObject(*m_vm)->typedArrayStructureConcurrently(type))
3626         return false;
3627
3628     insertChecks();
3629     set(VirtualRegister(resultOperand),
3630         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
3631     return true;
3632 }
3633
3634 template<typename ChecksFunctor>
3635 bool ByteCodeParser::handleConstantInternalFunction(
3636     Node* callTargetNode, int resultOperand, InternalFunction* function, int registerOffset,
3637     int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3638 {
3639     VERBOSE_LOG("    Handling constant internal function ", JSValue(function), "\n");
3640