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