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