Metadata should not be copyable
[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->didObserveNonNumber())
945                         node->mergeFlags(NodeMayHaveNonNumberResult);
946                     break;
947                 
948                 case ArithMul: {
949                     if (arithProfile->didObserveInt52Overflow())
950                         node->mergeFlags(NodeMayOverflowInt52);
951                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
952                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
953                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
954                         node->mergeFlags(NodeMayNegZeroInBaseline);
955                     if (arithProfile->didObserveDouble())
956                         node->mergeFlags(NodeMayHaveDoubleResult);
957                     if (arithProfile->didObserveNonNumber())
958                         node->mergeFlags(NodeMayHaveNonNumberResult);
959                     break;
960                 }
961                 case ValueNegate:
962                 case ArithNegate: {
963                     if (arithProfile->lhsObservedType().sawNumber() || arithProfile->didObserveDouble())
964                         node->mergeFlags(NodeMayHaveDoubleResult);
965                     if (arithProfile->didObserveNegZeroDouble() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
966                         node->mergeFlags(NodeMayNegZeroInBaseline);
967                     if (arithProfile->didObserveInt32Overflow() || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
968                         node->mergeFlags(NodeMayOverflowInt32InBaseline);
969                     if (arithProfile->didObserveNonNumber()) {
970                         // FIXME: We should add support to BigInt into speculation
971                         // https://bugs.webkit.org/show_bug.cgi?id=182470
972                         node->mergeFlags(NodeMayHaveNonNumberResult);
973                     }
974                     break;
975                 }
976                 
977                 default:
978                     break;
979                 }
980             }
981         }
982         
983         if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
984             switch (node->op()) {
985             case UInt32ToNumber:
986             case ArithAdd:
987             case ArithSub:
988             case ValueAdd:
989             case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
990                 node->mergeFlags(NodeMayOverflowInt32InBaseline);
991                 break;
992                 
993             default:
994                 break;
995             }
996         }
997         
998         return node;
999     }
1000     
1001     Node* makeDivSafe(Node* node)
1002     {
1003         ASSERT(node->op() == ArithDiv);
1004         
1005         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
1006             node->mergeFlags(NodeMayOverflowInt32InDFG);
1007         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
1008             node->mergeFlags(NodeMayNegZeroInDFG);
1009         
1010         // The main slow case counter for op_div in the old JIT counts only when
1011         // the operands are not numbers. We don't care about that since we already
1012         // have speculations in place that take care of that separately. We only
1013         // care about when the outcome of the division is not an integer, which
1014         // is what the special fast case counter tells us.
1015         
1016         if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex))
1017             return node;
1018         
1019         // FIXME: It might be possible to make this more granular.
1020         node->mergeFlags(NodeMayOverflowInt32InBaseline | NodeMayNegZeroInBaseline);
1021         
1022         return node;
1023     }
1024     
1025     void noticeArgumentsUse()
1026     {
1027         // All of the arguments in this function need to be formatted as JSValues because we will
1028         // load from them in a random-access fashion and we don't want to have to switch on
1029         // format.
1030         
1031         for (ArgumentPosition* argument : m_inlineStackTop->m_argumentPositions)
1032             argument->mergeShouldNeverUnbox(true);
1033     }
1034
1035     bool needsDynamicLookup(ResolveType, OpcodeID);
1036
1037     VM* m_vm;
1038     CodeBlock* m_codeBlock;
1039     CodeBlock* m_profiledBlock;
1040     Graph& m_graph;
1041
1042     // The current block being generated.
1043     BasicBlock* m_currentBlock;
1044     // The bytecode index of the current instruction being generated.
1045     unsigned m_currentIndex;
1046     // The semantic origin of the current node if different from the current Index.
1047     CodeOrigin m_currentSemanticOrigin;
1048     // True if it's OK to OSR exit right now.
1049     bool m_exitOK { false };
1050
1051     FrozenValue* m_constantUndefined;
1052     FrozenValue* m_constantNull;
1053     FrozenValue* m_constantNaN;
1054     FrozenValue* m_constantOne;
1055     Vector<Node*, 16> m_constants;
1056
1057     HashMap<InlineCallFrame*, Vector<ArgumentPosition*>, WTF::DefaultHash<InlineCallFrame*>::Hash, WTF::NullableHashTraits<InlineCallFrame*>> m_inlineCallFrameToArgumentPositions;
1058
1059     // The number of arguments passed to the function.
1060     unsigned m_numArguments;
1061     // The number of locals (vars + temporaries) used in the function.
1062     unsigned m_numLocals;
1063     // The number of slots (in units of sizeof(Register)) that we need to
1064     // preallocate for arguments to outgoing calls from this frame. This
1065     // number includes the CallFrame slots that we initialize for the callee
1066     // (but not the callee-initialized CallerFrame and ReturnPC slots).
1067     // This number is 0 if and only if this function is a leaf.
1068     unsigned m_parameterSlots;
1069     // The number of var args passed to the next var arg node.
1070     unsigned m_numPassedVarArgs;
1071
1072     struct InlineStackEntry {
1073         ByteCodeParser* m_byteCodeParser;
1074         
1075         CodeBlock* m_codeBlock;
1076         CodeBlock* m_profiledBlock;
1077         InlineCallFrame* m_inlineCallFrame;
1078         
1079         ScriptExecutable* executable() { return m_codeBlock->ownerScriptExecutable(); }
1080         
1081         QueryableExitProfile m_exitProfile;
1082         
1083         // Remapping of identifier and constant numbers from the code block being
1084         // inlined (inline callee) to the code block that we're inlining into
1085         // (the machine code block, which is the transitive, though not necessarily
1086         // direct, caller).
1087         Vector<unsigned> m_identifierRemap;
1088         Vector<unsigned> m_switchRemap;
1089         
1090         // These are blocks whose terminal is a Jump, Branch or Switch, and whose target has not yet been linked.
1091         // Their terminal instead refers to a bytecode index, and the right BB can be found in m_blockLinkingTargets.
1092         Vector<BasicBlock*> m_unlinkedBlocks;
1093         
1094         // Potential block linking targets. Must be sorted by bytecodeBegin, and
1095         // cannot have two blocks that have the same bytecodeBegin.
1096         Vector<BasicBlock*> m_blockLinkingTargets;
1097
1098         // Optional: a continuation block for returns to jump to. It is set by early returns if it does not exist.
1099         BasicBlock* m_continuationBlock;
1100
1101         VirtualRegister m_returnValue;
1102         
1103         // Speculations about variable types collected from the profiled code block,
1104         // which are based on OSR exit profiles that past DFG compilations of this
1105         // code block had gathered.
1106         LazyOperandValueProfileParser m_lazyOperands;
1107         
1108         ICStatusMap m_baselineMap;
1109         ICStatusContext m_optimizedContext;
1110         
1111         // Pointers to the argument position trackers for this slice of code.
1112         Vector<ArgumentPosition*> m_argumentPositions;
1113         
1114         InlineStackEntry* m_caller;
1115         
1116         InlineStackEntry(
1117             ByteCodeParser*,
1118             CodeBlock*,
1119             CodeBlock* profiledBlock,
1120             JSFunction* callee, // Null if this is a closure call.
1121             VirtualRegister returnValueVR,
1122             VirtualRegister inlineCallFrameStart,
1123             int argumentCountIncludingThis,
1124             InlineCallFrame::Kind,
1125             BasicBlock* continuationBlock);
1126         
1127         ~InlineStackEntry();
1128         
1129         VirtualRegister remapOperand(VirtualRegister operand) const
1130         {
1131             if (!m_inlineCallFrame)
1132                 return operand;
1133             
1134             ASSERT(!operand.isConstant());
1135
1136             return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
1137         }
1138     };
1139     
1140     InlineStackEntry* m_inlineStackTop;
1141     
1142     ICStatusContextStack m_icContextStack;
1143     
1144     struct DelayedSetLocal {
1145         CodeOrigin m_origin;
1146         VirtualRegister m_operand;
1147         Node* m_value;
1148         SetMode m_setMode;
1149         
1150         DelayedSetLocal() { }
1151         DelayedSetLocal(const CodeOrigin& origin, VirtualRegister operand, Node* value, SetMode setMode)
1152             : m_origin(origin)
1153             , m_operand(operand)
1154             , m_value(value)
1155             , m_setMode(setMode)
1156         {
1157             RELEASE_ASSERT(operand.isValid());
1158         }
1159         
1160         Node* execute(ByteCodeParser* parser)
1161         {
1162             if (m_operand.isArgument())
1163                 return parser->setArgument(m_origin, m_operand, m_value, m_setMode);
1164             return parser->setLocal(m_origin, m_operand, m_value, m_setMode);
1165         }
1166     };
1167     
1168     Vector<DelayedSetLocal, 2> m_setLocalQueue;
1169
1170     const Instruction* m_currentInstruction;
1171     bool m_hasDebuggerEnabled;
1172     bool m_hasAnyForceOSRExits { false };
1173 };
1174
1175 BasicBlock* ByteCodeParser::allocateTargetableBlock(unsigned bytecodeIndex)
1176 {
1177     ASSERT(bytecodeIndex != UINT_MAX);
1178     Ref<BasicBlock> block = adoptRef(*new BasicBlock(bytecodeIndex, m_numArguments, m_numLocals, 1));
1179     BasicBlock* blockPtr = block.ptr();
1180     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1181     if (m_inlineStackTop->m_blockLinkingTargets.size())
1182         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1183     m_inlineStackTop->m_blockLinkingTargets.append(blockPtr);
1184     m_graph.appendBlock(WTFMove(block));
1185     return blockPtr;
1186 }
1187
1188 BasicBlock* ByteCodeParser::allocateUntargetableBlock()
1189 {
1190     Ref<BasicBlock> block = adoptRef(*new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
1191     BasicBlock* blockPtr = block.ptr();
1192     m_graph.appendBlock(WTFMove(block));
1193     return blockPtr;
1194 }
1195
1196 void ByteCodeParser::makeBlockTargetable(BasicBlock* block, unsigned bytecodeIndex)
1197 {
1198     RELEASE_ASSERT(block->bytecodeBegin == UINT_MAX);
1199     block->bytecodeBegin = bytecodeIndex;
1200     // m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
1201     if (m_inlineStackTop->m_blockLinkingTargets.size())
1202         ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
1203     m_inlineStackTop->m_blockLinkingTargets.append(block);
1204 }
1205
1206 void ByteCodeParser::addJumpTo(BasicBlock* block)
1207 {
1208     ASSERT(!m_currentBlock->terminal());
1209     Node* jumpNode = addToGraph(Jump);
1210     jumpNode->targetBlock() = block;
1211     m_currentBlock->didLink();
1212 }
1213
1214 void ByteCodeParser::addJumpTo(unsigned bytecodeIndex)
1215 {
1216     ASSERT(!m_currentBlock->terminal());
1217     addToGraph(Jump, OpInfo(bytecodeIndex));
1218     m_inlineStackTop->m_unlinkedBlocks.append(m_currentBlock);
1219 }
1220
1221 template<typename CallOp>
1222 ByteCodeParser::Terminality ByteCodeParser::handleCall(const Instruction* pc, NodeType op, CallMode callMode)
1223 {
1224     auto bytecode = pc->as<CallOp>();
1225     Node* callTarget = get(bytecode.callee);
1226     int registerOffset = -static_cast<int>(bytecode.argv);
1227
1228     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1229         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1230         m_inlineStackTop->m_baselineMap, m_icContextStack);
1231
1232     InlineCallFrame::Kind kind = InlineCallFrame::kindFor(callMode);
1233
1234     return handleCall(bytecode.dst, op, kind, pc->size(), callTarget,
1235         bytecode.argc, registerOffset, callLinkStatus, getPrediction());
1236 }
1237
1238 void ByteCodeParser::refineStatically(CallLinkStatus& callLinkStatus, Node* callTarget)
1239 {
1240     if (callTarget->isCellConstant())
1241         callLinkStatus.setProvenConstantCallee(CallVariant(callTarget->asCell()));
1242 }
1243
1244 ByteCodeParser::Terminality ByteCodeParser::handleCall(
1245     VirtualRegister result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
1246     Node* callTarget, int argumentCountIncludingThis, int registerOffset,
1247     CallLinkStatus callLinkStatus, SpeculatedType prediction)
1248 {
1249     ASSERT(registerOffset <= 0);
1250
1251     refineStatically(callLinkStatus, callTarget);
1252     
1253     VERBOSE_LOG("    Handling call at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1254     
1255     // If we have profiling information about this call, and it did not behave too polymorphically,
1256     // we may be able to inline it, or in the case of recursive tail calls turn it into a jump.
1257     if (callLinkStatus.canOptimize()) {
1258         addToGraph(FilterCallLinkStatus, OpInfo(m_graph.m_plan.recordedStatuses().addCallLinkStatus(currentCodeOrigin(), callLinkStatus)), callTarget);
1259
1260         VirtualRegister thisArgument = virtualRegisterForArgument(0, registerOffset);
1261         auto optimizationResult = handleInlining(callTarget, result, callLinkStatus, registerOffset, thisArgument,
1262             argumentCountIncludingThis, m_currentIndex + instructionSize, op, kind, prediction);
1263         if (optimizationResult == CallOptimizationResult::OptimizedToJump)
1264             return Terminal;
1265         if (optimizationResult == CallOptimizationResult::Inlined) {
1266             if (UNLIKELY(m_graph.compilation()))
1267                 m_graph.compilation()->noticeInlinedCall();
1268             return NonTerminal;
1269         }
1270     }
1271     
1272     Node* callNode = addCall(result, op, nullptr, callTarget, argumentCountIncludingThis, registerOffset, prediction);
1273     ASSERT(callNode->op() != TailCallVarargs && callNode->op() != TailCallForwardVarargs);
1274     return callNode->op() == TailCall ? Terminal : NonTerminal;
1275 }
1276
1277 template<typename CallOp>
1278 ByteCodeParser::Terminality ByteCodeParser::handleVarargsCall(const Instruction* pc, NodeType op, CallMode callMode)
1279 {
1280     auto bytecode = pc->as<CallOp>();
1281     int firstFreeReg = bytecode.firstFree.offset();
1282     int firstVarArgOffset = bytecode.firstVarArg;
1283     
1284     SpeculatedType prediction = getPrediction();
1285     
1286     Node* callTarget = get(bytecode.callee);
1287     
1288     CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
1289         m_inlineStackTop->m_profiledBlock, currentCodeOrigin(),
1290         m_inlineStackTop->m_baselineMap, m_icContextStack);
1291     refineStatically(callLinkStatus, callTarget);
1292     
1293     VERBOSE_LOG("    Varargs call link status at ", currentCodeOrigin(), ": ", callLinkStatus, "\n");
1294     
1295     if (callLinkStatus.canOptimize()) {
1296         addToGraph(FilterCallLinkStatus, OpInfo(m_graph.m_plan.recordedStatuses().addCallLinkStatus(currentCodeOrigin(), callLinkStatus)), callTarget);
1297
1298         if (handleVarargsInlining(callTarget, bytecode.dst,
1299             callLinkStatus, firstFreeReg, bytecode.thisValue, bytecode.arguments,
1300             firstVarArgOffset, op,
1301             InlineCallFrame::varargsKindFor(callMode))) {
1302             if (UNLIKELY(m_graph.compilation()))
1303                 m_graph.compilation()->noticeInlinedCall();
1304             return NonTerminal;
1305         }
1306     }
1307     
1308     CallVarargsData* data = m_graph.m_callVarargsData.add();
1309     data->firstVarArgOffset = firstVarArgOffset;
1310     
1311     Node* thisChild = get(bytecode.thisValue);
1312     Node* argumentsChild = nullptr;
1313     if (op != TailCallForwardVarargs)
1314         argumentsChild = get(bytecode.arguments);
1315
1316     if (op == TailCallVarargs || op == TailCallForwardVarargs) {
1317         if (allInlineFramesAreTailCalls()) {
1318             addToGraph(op, OpInfo(data), OpInfo(), callTarget, thisChild, argumentsChild);
1319             return Terminal;
1320         }
1321         op = op == TailCallVarargs ? TailCallVarargsInlinedCaller : TailCallForwardVarargsInlinedCaller;
1322     }
1323
1324     Node* call = addToGraph(op, OpInfo(data), OpInfo(prediction), callTarget, thisChild, argumentsChild);
1325     if (bytecode.dst.isValid())
1326         set(bytecode.dst, call);
1327     return NonTerminal;
1328 }
1329
1330 void ByteCodeParser::emitFunctionChecks(CallVariant callee, Node* callTarget, VirtualRegister thisArgumentReg)
1331 {
1332     Node* thisArgument;
1333     if (thisArgumentReg.isValid())
1334         thisArgument = get(thisArgumentReg);
1335     else
1336         thisArgument = nullptr;
1337
1338     JSCell* calleeCell;
1339     Node* callTargetForCheck;
1340     if (callee.isClosureCall()) {
1341         calleeCell = callee.executable();
1342         callTargetForCheck = addToGraph(GetExecutable, callTarget);
1343     } else {
1344         calleeCell = callee.nonExecutableCallee();
1345         callTargetForCheck = callTarget;
1346     }
1347     
1348     ASSERT(calleeCell);
1349     addToGraph(CheckCell, OpInfo(m_graph.freeze(calleeCell)), callTargetForCheck);
1350     if (thisArgument)
1351         addToGraph(Phantom, thisArgument);
1352 }
1353
1354 Node* ByteCodeParser::getArgumentCount()
1355 {
1356     Node* argumentCount;
1357     if (m_inlineStackTop->m_inlineCallFrame && !m_inlineStackTop->m_inlineCallFrame->isVarargs())
1358         argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->argumentCountIncludingThis))->value());
1359     else
1360         argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(m_inlineStackTop->m_inlineCallFrame), OpInfo(SpecInt32Only));
1361     return argumentCount;
1362 }
1363
1364 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
1365 {
1366     for (int i = 0; i < argumentCountIncludingThis; ++i)
1367         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
1368 }
1369
1370 template<typename ChecksFunctor>
1371 bool ByteCodeParser::handleRecursiveTailCall(Node* callTargetNode, CallVariant callVariant, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& emitFunctionCheckIfNeeded)
1372 {
1373     if (UNLIKELY(!Options::optimizeRecursiveTailCalls()))
1374         return false;
1375
1376     auto targetExecutable = callVariant.executable();
1377     InlineStackEntry* stackEntry = m_inlineStackTop;
1378     do {
1379         if (targetExecutable != stackEntry->executable())
1380             continue;
1381         VERBOSE_LOG("   We found a recursive tail call, trying to optimize it into a jump.\n");
1382
1383         if (auto* callFrame = stackEntry->m_inlineCallFrame) {
1384             // Some code may statically use the argument count from the InlineCallFrame, so it would be invalid to loop back if it does not match.
1385             // We "continue" instead of returning false in case another stack entry further on the stack has the right number of arguments.
1386             if (argumentCountIncludingThis != static_cast<int>(callFrame->argumentCountIncludingThis))
1387                 continue;
1388         } else {
1389             // We are in the machine code entry (i.e. the original caller).
1390             // 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.
1391             if (argumentCountIncludingThis > m_codeBlock->numParameters())
1392                 return false;
1393         }
1394
1395         // If an InlineCallFrame is not a closure, it was optimized using a constant callee.
1396         // Check if this is the same callee that we try to inline here.
1397         if (stackEntry->m_inlineCallFrame && !stackEntry->m_inlineCallFrame->isClosureCall) {
1398             if (stackEntry->m_inlineCallFrame->calleeConstant() != callVariant.function())
1399                 continue;
1400         }
1401
1402         // We must add some check that the profiling information was correct and the target of this call is what we thought.
1403         emitFunctionCheckIfNeeded();
1404         // We flush everything, as if we were in the backedge of a loop (see treatment of op_jmp in parseBlock).
1405         flushForTerminal();
1406
1407         // We must set the callee to the right value
1408         if (stackEntry->m_inlineCallFrame) {
1409             if (stackEntry->m_inlineCallFrame->isClosureCall)
1410                 setDirect(stackEntry->remapOperand(VirtualRegister(CallFrameSlot::callee)), callTargetNode, NormalSet);
1411         } else
1412             addToGraph(SetCallee, callTargetNode);
1413
1414         // We must set the arguments to the right values
1415         if (!stackEntry->m_inlineCallFrame)
1416             addToGraph(SetArgumentCountIncludingThis, OpInfo(argumentCountIncludingThis));
1417         int argIndex = 0;
1418         for (; argIndex < argumentCountIncludingThis; ++argIndex) {
1419             Node* value = get(virtualRegisterForArgument(argIndex, registerOffset));
1420             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), value, NormalSet);
1421         }
1422         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1423         for (; argIndex < stackEntry->m_codeBlock->numParameters(); ++argIndex)
1424             setDirect(stackEntry->remapOperand(virtualRegisterForArgument(argIndex)), undefined, NormalSet);
1425
1426         // We must repeat the work of op_enter here as we will jump right after it.
1427         // We jump right after it and not before it, because of some invariant saying that a CFG root cannot have predecessors in the IR.
1428         for (int i = 0; i < stackEntry->m_codeBlock->numVars(); ++i)
1429             setDirect(stackEntry->remapOperand(virtualRegisterForLocal(i)), undefined, NormalSet);
1430
1431         // We want to emit the SetLocals with an exit origin that points to the place we are jumping to.
1432         unsigned oldIndex = m_currentIndex;
1433         auto oldStackTop = m_inlineStackTop;
1434         m_inlineStackTop = stackEntry;
1435         m_currentIndex = opcodeLengths[op_enter];
1436         m_exitOK = true;
1437         processSetLocalQueue();
1438         m_currentIndex = oldIndex;
1439         m_inlineStackTop = oldStackTop;
1440         m_exitOK = false;
1441
1442         BasicBlock** entryBlockPtr = tryBinarySearch<BasicBlock*, unsigned>(stackEntry->m_blockLinkingTargets, stackEntry->m_blockLinkingTargets.size(), opcodeLengths[op_enter], getBytecodeBeginForBlock);
1443         RELEASE_ASSERT(entryBlockPtr);
1444         addJumpTo(*entryBlockPtr);
1445         return true;
1446         // It would be unsound to jump over a non-tail call: the "tail" call is not really a tail call in that case.
1447     } while (stackEntry->m_inlineCallFrame && stackEntry->m_inlineCallFrame->kind == InlineCallFrame::TailCall && (stackEntry = stackEntry->m_caller));
1448
1449     // The tail call was not recursive
1450     return false;
1451 }
1452
1453 unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, InlineCallFrame::Kind kind)
1454 {
1455     CallMode callMode = InlineCallFrame::callModeFor(kind);
1456     CodeSpecializationKind specializationKind = specializationKindFor(callMode);
1457     VERBOSE_LOG("Considering inlining ", callee, " into ", currentCodeOrigin(), "\n");
1458     
1459     if (m_hasDebuggerEnabled) {
1460         VERBOSE_LOG("    Failing because the debugger is in use.\n");
1461         return UINT_MAX;
1462     }
1463
1464     FunctionExecutable* executable = callee.functionExecutable();
1465     if (!executable) {
1466         VERBOSE_LOG("    Failing because there is no function executable.\n");
1467         return UINT_MAX;
1468     }
1469     
1470     // Do we have a code block, and does the code block's size match the heuristics/requirements for
1471     // being an inline candidate? We might not have a code block (1) if code was thrown away,
1472     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
1473     // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
1474     // to inline it if we had a static proof of what was being called; this might happen for example
1475     // if you call a global function, where watchpointing gives us static information. Overall,
1476     // it's a rare case because we expect that any hot callees would have already been compiled.
1477     CodeBlock* codeBlock = executable->baselineCodeBlockFor(specializationKind);
1478     if (!codeBlock) {
1479         VERBOSE_LOG("    Failing because no code block available.\n");
1480         return UINT_MAX;
1481     }
1482
1483     if (!Options::useArityFixupInlining()) {
1484         if (codeBlock->numParameters() > argumentCountIncludingThis) {
1485             VERBOSE_LOG("    Failing because of arity mismatch.\n");
1486             return UINT_MAX;
1487         }
1488     }
1489
1490     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
1491         codeBlock, specializationKind, callee.isClosureCall());
1492     VERBOSE_LOG("    Call mode: ", callMode, "\n");
1493     VERBOSE_LOG("    Is closure call: ", callee.isClosureCall(), "\n");
1494     VERBOSE_LOG("    Capability level: ", capabilityLevel, "\n");
1495     VERBOSE_LOG("    Might inline function: ", mightInlineFunctionFor(codeBlock, specializationKind), "\n");
1496     VERBOSE_LOG("    Might compile function: ", mightCompileFunctionFor(codeBlock, specializationKind), "\n");
1497     VERBOSE_LOG("    Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n");
1498     VERBOSE_LOG("    Is inlining candidate: ", codeBlock->ownerScriptExecutable()->isInliningCandidate(), "\n");
1499     if (!canInline(capabilityLevel)) {
1500         VERBOSE_LOG("    Failing because the function is not inlineable.\n");
1501         return UINT_MAX;
1502     }
1503     
1504     // Check if the caller is already too large. We do this check here because that's just
1505     // where we happen to also have the callee's code block, and we want that for the
1506     // purpose of unsetting SABI.
1507     if (!isSmallEnoughToInlineCodeInto(m_codeBlock)) {
1508         codeBlock->m_shouldAlwaysBeInlined = false;
1509         VERBOSE_LOG("    Failing because the caller is too large.\n");
1510         return UINT_MAX;
1511     }
1512     
1513     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
1514     // this function.
1515     // https://bugs.webkit.org/show_bug.cgi?id=127627
1516     
1517     // FIXME: We currently inline functions that have run in LLInt but not in Baseline. These
1518     // functions have very low fidelity profiling, and presumably they weren't very hot if they
1519     // haven't gotten to Baseline yet. Consider not inlining these functions.
1520     // https://bugs.webkit.org/show_bug.cgi?id=145503
1521     
1522     // Have we exceeded inline stack depth, or are we trying to inline a recursive call to
1523     // too many levels? If either of these are detected, then don't inline. We adjust our
1524     // heuristics if we are dealing with a function that cannot otherwise be compiled.
1525     
1526     unsigned depth = 0;
1527     unsigned recursion = 0;
1528     
1529     for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
1530         ++depth;
1531         if (depth >= Options::maximumInliningDepth()) {
1532             VERBOSE_LOG("    Failing because depth exceeded.\n");
1533             return UINT_MAX;
1534         }
1535         
1536         if (entry->executable() == executable) {
1537             ++recursion;
1538             if (recursion >= Options::maximumInliningRecursion()) {
1539                 VERBOSE_LOG("    Failing because recursion detected.\n");
1540                 return UINT_MAX;
1541             }
1542         }
1543     }
1544     
1545     VERBOSE_LOG("    Inlining should be possible.\n");
1546     
1547     // It might be possible to inline.
1548     return codeBlock->instructionCount();
1549 }
1550
1551 template<typename ChecksFunctor>
1552 void ByteCodeParser::inlineCall(Node* callTargetNode, VirtualRegister result, CallVariant callee, int registerOffset, int argumentCountIncludingThis, InlineCallFrame::Kind kind, BasicBlock* continuationBlock, const ChecksFunctor& insertChecks)
1553 {
1554     const Instruction* savedCurrentInstruction = m_currentInstruction;
1555     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1556     
1557     ASSERT(inliningCost(callee, argumentCountIncludingThis, kind) != UINT_MAX);
1558     
1559     CodeBlock* codeBlock = callee.functionExecutable()->baselineCodeBlockFor(specializationKind);
1560     insertChecks(codeBlock);
1561
1562     // FIXME: Don't flush constants!
1563
1564     // arityFixupCount and numberOfStackPaddingSlots are different. While arityFixupCount does not consider about stack alignment,
1565     // numberOfStackPaddingSlots consider alignment. Consider the following case,
1566     //
1567     // before: [ ... ][arg0][header]
1568     // after:  [ ... ][ext ][arg1][arg0][header]
1569     //
1570     // In the above case, arityFixupCount is 1. But numberOfStackPaddingSlots is 2 because the stack needs to be aligned.
1571     // We insert extra slots to align stack.
1572     int arityFixupCount = std::max<int>(codeBlock->numParameters() - argumentCountIncludingThis, 0);
1573     int numberOfStackPaddingSlots = CommonSlowPaths::numberOfStackPaddingSlots(codeBlock, argumentCountIncludingThis);
1574     ASSERT(!(numberOfStackPaddingSlots % stackAlignmentRegisters()));
1575     int registerOffsetAfterFixup = registerOffset - numberOfStackPaddingSlots;
1576     
1577     int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffsetAfterFixup)).offset() + CallFrame::headerSizeInRegisters;
1578     
1579     ensureLocals(
1580         VirtualRegister(inlineCallFrameStart).toLocal() + 1 +
1581         CallFrame::headerSizeInRegisters + codeBlock->numCalleeLocals());
1582     
1583     size_t argumentPositionStart = m_graph.m_argumentPositions.size();
1584
1585     if (result.isValid())
1586         result = m_inlineStackTop->remapOperand(result);
1587
1588     VariableAccessData* calleeVariable = nullptr;
1589     if (callee.isClosureCall()) {
1590         Node* calleeSet = set(
1591             VirtualRegister(registerOffsetAfterFixup + CallFrameSlot::callee), callTargetNode, ImmediateNakedSet);
1592         
1593         calleeVariable = calleeSet->variableAccessData();
1594         calleeVariable->mergeShouldNeverUnbox(true);
1595     }
1596
1597     if (arityFixupCount) {
1598         // Note: we do arity fixup in two phases:
1599         // 1. We get all the values we need and MovHint them to the expected locals.
1600         // 2. We SetLocal them inside the callee's CodeOrigin. This way, if we exit, the callee's
1601         //    frame is already set up. If any SetLocal exits, we have a valid exit state.
1602         //    This is required because if we didn't do this in two phases, we may exit in
1603         //    the middle of arity fixup from the caller's CodeOrigin. This is unsound because if
1604         //    we did the SetLocals in the caller's frame, the memcpy may clobber needed parts
1605         //    of the frame right before exiting. For example, consider if we need to pad two args:
1606         //    [arg3][arg2][arg1][arg0]
1607         //    [fix ][fix ][arg3][arg2][arg1][arg0]
1608         //    We memcpy starting from arg0 in the direction of arg3. If we were to exit at a type check
1609         //    for arg3's SetLocal in the caller's CodeOrigin, we'd exit with a frame like so:
1610         //    [arg3][arg2][arg1][arg2][arg1][arg0]
1611         //    And the caller would then just end up thinking its argument are:
1612         //    [arg3][arg2][arg1][arg2]
1613         //    which is incorrect.
1614
1615         Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
1616         // 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.
1617         // We call this hole "extra slot". Consider the following case, the number of arguments is 2. If this argument
1618         // count does not fulfill the stack alignment requirement, we already inserted extra slots.
1619         //
1620         // before: [ ... ][ext ][arg1][arg0][header]
1621         //
1622         // In the above case, one extra slot is inserted. If the code's parameter count is 3, we will fixup arguments.
1623         // At that time, we can simply use this extra slots. So the fixuped stack is the following.
1624         //
1625         // before: [ ... ][ext ][arg1][arg0][header]
1626         // after:  [ ... ][arg2][arg1][arg0][header]
1627         //
1628         // In such cases, we do not need to move frames.
1629         if (registerOffsetAfterFixup != registerOffset) {
1630             for (int index = 0; index < argumentCountIncludingThis; ++index) {
1631                 Node* value = get(virtualRegisterForArgument(index, registerOffset));
1632                 VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(index, registerOffsetAfterFixup));
1633                 addToGraph(MovHint, OpInfo(argumentToSet.offset()), value);
1634                 m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, value, ImmediateNakedSet });
1635             }
1636         }
1637         for (int index = 0; index < arityFixupCount; ++index) {
1638             VirtualRegister argumentToSet = m_inlineStackTop->remapOperand(virtualRegisterForArgument(argumentCountIncludingThis + index, registerOffsetAfterFixup));
1639             addToGraph(MovHint, OpInfo(argumentToSet.offset()), undefined);
1640             m_setLocalQueue.append(DelayedSetLocal { currentCodeOrigin(), argumentToSet, undefined, ImmediateNakedSet });
1641         }
1642
1643         // At this point, it's OK to OSR exit because we finished setting up
1644         // our callee's frame. We emit an ExitOK below from the callee's CodeOrigin.
1645     }
1646
1647     InlineStackEntry inlineStackEntry(this, codeBlock, codeBlock, callee.function(), result,
1648         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind, continuationBlock);
1649
1650     // This is where the actual inlining really happens.
1651     unsigned oldIndex = m_currentIndex;
1652     m_currentIndex = 0;
1653
1654     // At this point, it's again OK to OSR exit.
1655     m_exitOK = true;
1656     addToGraph(ExitOK);
1657
1658     processSetLocalQueue();
1659
1660     InlineVariableData inlineVariableData;
1661     inlineVariableData.inlineCallFrame = m_inlineStackTop->m_inlineCallFrame;
1662     inlineVariableData.argumentPositionStart = argumentPositionStart;
1663     inlineVariableData.calleeVariable = 0;
1664     
1665     RELEASE_ASSERT(
1666         m_inlineStackTop->m_inlineCallFrame->isClosureCall
1667         == callee.isClosureCall());
1668     if (callee.isClosureCall()) {
1669         RELEASE_ASSERT(calleeVariable);
1670         inlineVariableData.calleeVariable = calleeVariable;
1671     }
1672     
1673     m_graph.m_inlineVariableData.append(inlineVariableData);
1674
1675     parseCodeBlock();
1676     clearCaches(); // Reset our state now that we're back to the outer code.
1677     
1678     m_currentIndex = oldIndex;
1679     m_exitOK = false;
1680
1681     linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
1682     
1683     // Most functions have at least one op_ret and thus set up the continuation block.
1684     // In some rare cases, a function ends in op_unreachable, forcing us to allocate a new continuationBlock here.
1685     if (inlineStackEntry.m_continuationBlock)
1686         m_currentBlock = inlineStackEntry.m_continuationBlock;
1687     else
1688         m_currentBlock = allocateUntargetableBlock();
1689     ASSERT(!m_currentBlock->terminal());
1690
1691     prepareToParseBlock();
1692     m_currentInstruction = savedCurrentInstruction;
1693 }
1694
1695 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)
1696 {
1697     VERBOSE_LOG("    Considering callee ", callee, "\n");
1698
1699     bool didInsertChecks = false;
1700     auto insertChecksWithAccounting = [&] () {
1701         if (needsToCheckCallee)
1702             emitFunctionChecks(callee, callTargetNode, thisArgument);
1703         didInsertChecks = true;
1704     };
1705
1706     if (kind == InlineCallFrame::TailCall && ByteCodeParser::handleRecursiveTailCall(callTargetNode, callee, registerOffset, argumentCountIncludingThis, insertChecksWithAccounting)) {
1707         RELEASE_ASSERT(didInsertChecks);
1708         return CallOptimizationResult::OptimizedToJump;
1709     }
1710     RELEASE_ASSERT(!didInsertChecks);
1711
1712     if (!inliningBalance)
1713         return CallOptimizationResult::DidNothing;
1714
1715     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1716
1717     auto endSpecialCase = [&] () {
1718         RELEASE_ASSERT(didInsertChecks);
1719         addToGraph(Phantom, callTargetNode);
1720         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1721         inliningBalance--;
1722         if (continuationBlock) {
1723             m_currentIndex = nextOffset;
1724             m_exitOK = true;
1725             processSetLocalQueue();
1726             addJumpTo(continuationBlock);
1727         }
1728     };
1729
1730     if (InternalFunction* function = callee.internalFunction()) {
1731         if (handleConstantInternalFunction(callTargetNode, result, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) {
1732             endSpecialCase();
1733             return CallOptimizationResult::Inlined;
1734         }
1735         RELEASE_ASSERT(!didInsertChecks);
1736         return CallOptimizationResult::DidNothing;
1737     }
1738
1739     Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
1740     if (intrinsic != NoIntrinsic) {
1741         if (handleIntrinsicCall(callTargetNode, result, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1742             endSpecialCase();
1743             return CallOptimizationResult::Inlined;
1744         }
1745         RELEASE_ASSERT(!didInsertChecks);
1746         // We might still try to inline the Intrinsic because it might be a builtin JS function.
1747     }
1748
1749     if (Options::useDOMJIT()) {
1750         if (const DOMJIT::Signature* signature = callee.signatureFor(specializationKind)) {
1751             if (handleDOMJITCall(callTargetNode, result, signature, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1752                 endSpecialCase();
1753                 return CallOptimizationResult::Inlined;
1754             }
1755             RELEASE_ASSERT(!didInsertChecks);
1756         }
1757     }
1758     
1759     unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, kind);
1760     if (myInliningCost > inliningBalance)
1761         return CallOptimizationResult::DidNothing;
1762
1763     auto insertCheck = [&] (CodeBlock*) {
1764         if (needsToCheckCallee)
1765             emitFunctionChecks(callee, callTargetNode, thisArgument);
1766     };
1767     inlineCall(callTargetNode, result, callee, registerOffset, argumentCountIncludingThis, kind, continuationBlock, insertCheck);
1768     inliningBalance -= myInliningCost;
1769     return CallOptimizationResult::Inlined;
1770 }
1771
1772 bool ByteCodeParser::handleVarargsInlining(Node* callTargetNode, VirtualRegister result,
1773     const CallLinkStatus& callLinkStatus, int firstFreeReg, VirtualRegister thisArgument,
1774     VirtualRegister argumentsArgument, unsigned argumentsOffset,
1775     NodeType callOp, InlineCallFrame::Kind kind)
1776 {
1777     VERBOSE_LOG("Handling inlining (Varargs)...\nStack: ", currentCodeOrigin(), "\n");
1778     if (callLinkStatus.maxNumArguments() > Options::maximumVarargsForInlining()) {
1779         VERBOSE_LOG("Bailing inlining: too many arguments for varargs inlining.\n");
1780         return false;
1781     }
1782     if (callLinkStatus.couldTakeSlowPath() || callLinkStatus.size() != 1) {
1783         VERBOSE_LOG("Bailing inlining: polymorphic inlining is not yet supported for varargs.\n");
1784         return false;
1785     }
1786
1787     CallVariant callVariant = callLinkStatus[0];
1788
1789     unsigned mandatoryMinimum;
1790     if (FunctionExecutable* functionExecutable = callVariant.functionExecutable())
1791         mandatoryMinimum = functionExecutable->parameterCount();
1792     else
1793         mandatoryMinimum = 0;
1794     
1795     // includes "this"
1796     unsigned maxNumArguments = std::max(callLinkStatus.maxNumArguments(), mandatoryMinimum + 1);
1797
1798     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1799     if (inliningCost(callVariant, maxNumArguments, kind) > getInliningBalance(callLinkStatus, specializationKind)) {
1800         VERBOSE_LOG("Bailing inlining: inlining cost too high.\n");
1801         return false;
1802     }
1803     
1804     int registerOffset = firstFreeReg + 1;
1805     registerOffset -= maxNumArguments; // includes "this"
1806     registerOffset -= CallFrame::headerSizeInRegisters;
1807     registerOffset = -WTF::roundUpToMultipleOf(stackAlignmentRegisters(), -registerOffset);
1808     
1809     auto insertChecks = [&] (CodeBlock* codeBlock) {
1810         emitFunctionChecks(callVariant, callTargetNode, thisArgument);
1811         
1812         int remappedRegisterOffset =
1813         m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset();
1814         
1815         ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal());
1816         
1817         int argumentStart = registerOffset + CallFrame::headerSizeInRegisters;
1818         int remappedArgumentStart =
1819         m_inlineStackTop->remapOperand(VirtualRegister(argumentStart)).offset();
1820         
1821         LoadVarargsData* data = m_graph.m_loadVarargsData.add();
1822         data->start = VirtualRegister(remappedArgumentStart + 1);
1823         data->count = VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount);
1824         data->offset = argumentsOffset;
1825         data->limit = maxNumArguments;
1826         data->mandatoryMinimum = mandatoryMinimum;
1827         
1828         if (callOp == TailCallForwardVarargs)
1829             addToGraph(ForwardVarargs, OpInfo(data));
1830         else
1831             addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
1832         
1833         // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
1834         // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
1835         // callTargetNode because the other 2 are still in use and alive at this point.
1836         addToGraph(Phantom, callTargetNode);
1837         
1838         // In DFG IR before SSA, we cannot insert control flow between after the
1839         // LoadVarargs and the last SetArgument. This isn't a problem once we get to DFG
1840         // SSA. Fortunately, we also have other reasons for not inserting control flow
1841         // before SSA.
1842         
1843         VariableAccessData* countVariable = newVariableAccessData(VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount));
1844         // This is pretty lame, but it will force the count to be flushed as an int. This doesn't
1845         // matter very much, since our use of a SetArgument and Flushes for this local slot is
1846         // mostly just a formality.
1847         countVariable->predict(SpecInt32Only);
1848         countVariable->mergeIsProfitableToUnbox(true);
1849         Node* setArgumentCount = addToGraph(SetArgument, OpInfo(countVariable));
1850         m_currentBlock->variablesAtTail.setOperand(countVariable->local(), setArgumentCount);
1851         
1852         set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
1853         for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
1854             VariableAccessData* variable = newVariableAccessData(VirtualRegister(remappedArgumentStart + argument));
1855             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.
1856             
1857             // For a while it had been my intention to do things like this inside the
1858             // prediction injection phase. But in this case it's really best to do it here,
1859             // because it's here that we have access to the variable access datas for the
1860             // inlining we're about to do.
1861             //
1862             // Something else that's interesting here is that we'd really love to get
1863             // predictions from the arguments loaded at the callsite, rather than the
1864             // arguments received inside the callee. But that probably won't matter for most
1865             // calls.
1866             if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
1867                 ConcurrentJSLocker locker(codeBlock->m_lock);
1868                 ValueProfile& profile = codeBlock->valueProfileForArgument(argument);
1869                 variable->predict(profile.computeUpdatedPrediction(locker));
1870             }
1871             
1872             Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
1873             m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
1874         }
1875     };
1876
1877     // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because
1878     // we currently don't have any way of getting profiling information for arguments to non-JS varargs
1879     // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow,
1880     // and there are no callsite value profiles and native function won't have callee value profiles for
1881     // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to
1882     // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without
1883     // calling LoadVarargs twice.
1884     inlineCall(callTargetNode, result, callVariant, registerOffset, maxNumArguments, kind, nullptr, insertChecks);
1885
1886     VERBOSE_LOG("Successful inlining (varargs, monomorphic).\nStack: ", currentCodeOrigin(), "\n");
1887     return true;
1888 }
1889
1890 unsigned ByteCodeParser::getInliningBalance(const CallLinkStatus& callLinkStatus, CodeSpecializationKind specializationKind)
1891 {
1892     unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
1893     if (specializationKind == CodeForConstruct)
1894         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
1895     if (callLinkStatus.isClosureCall())
1896         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
1897     return inliningBalance;
1898 }
1899
1900 ByteCodeParser::CallOptimizationResult ByteCodeParser::handleInlining(
1901     Node* callTargetNode, VirtualRegister result, const CallLinkStatus& callLinkStatus,
1902     int registerOffset, VirtualRegister thisArgument,
1903     int argumentCountIncludingThis,
1904     unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
1905 {
1906     VERBOSE_LOG("Handling inlining...\nStack: ", currentCodeOrigin(), "\n");
1907     
1908     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1909     unsigned inliningBalance = getInliningBalance(callLinkStatus, specializationKind);
1910
1911     // First check if we can avoid creating control flow. Our inliner does some CFG
1912     // simplification on the fly and this helps reduce compile times, but we can only leverage
1913     // this in cases where we don't need control flow diamonds to check the callee.
1914     if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
1915         return handleCallVariant(
1916             callTargetNode, result, callLinkStatus[0], registerOffset, thisArgument,
1917             argumentCountIncludingThis, nextOffset, kind, prediction, inliningBalance, nullptr, true);
1918     }
1919
1920     // We need to create some kind of switch over callee. For now we only do this if we believe that
1921     // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
1922     // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
1923     // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
1924     // we could improve that aspect of this by doing polymorphic inlining but having the profiling
1925     // also.
1926     if (!m_graph.m_plan.isFTL() || !Options::usePolymorphicCallInlining()) {
1927         VERBOSE_LOG("Bailing inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
1928         return CallOptimizationResult::DidNothing;
1929     }
1930     
1931     // If the claim is that this did not originate from a stub, then we don't want to emit a switch
1932     // statement. Whenever the non-stub profiling says that it could take slow path, it really means that
1933     // it has no idea.
1934     if (!Options::usePolymorphicCallInliningForNonStubStatus()
1935         && !callLinkStatus.isBasedOnStub()) {
1936         VERBOSE_LOG("Bailing inlining (non-stub polymorphism).\nStack: ", currentCodeOrigin(), "\n");
1937         return CallOptimizationResult::DidNothing;
1938     }
1939
1940     bool allAreClosureCalls = true;
1941     bool allAreDirectCalls = true;
1942     for (unsigned i = callLinkStatus.size(); i--;) {
1943         if (callLinkStatus[i].isClosureCall())
1944             allAreDirectCalls = false;
1945         else
1946             allAreClosureCalls = false;
1947     }
1948
1949     Node* thingToSwitchOn;
1950     if (allAreDirectCalls)
1951         thingToSwitchOn = callTargetNode;
1952     else if (allAreClosureCalls)
1953         thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
1954     else {
1955         // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
1956         // where it would be beneficial. It might be best to handle these cases as if all calls were
1957         // closure calls.
1958         // https://bugs.webkit.org/show_bug.cgi?id=136020
1959         VERBOSE_LOG("Bailing inlining (mix).\nStack: ", currentCodeOrigin(), "\n");
1960         return CallOptimizationResult::DidNothing;
1961     }
1962
1963     VERBOSE_LOG("Doing hard inlining...\nStack: ", currentCodeOrigin(), "\n");
1964
1965     // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
1966     // store the callee so that it will be accessible to all of the blocks we're about to create. We
1967     // get away with doing an immediate-set here because we wouldn't have performed any side effects
1968     // yet.
1969     VERBOSE_LOG("Register offset: ", registerOffset);
1970     VirtualRegister calleeReg(registerOffset + CallFrameSlot::callee);
1971     calleeReg = m_inlineStackTop->remapOperand(calleeReg);
1972     VERBOSE_LOG("Callee is going to be ", calleeReg, "\n");
1973     setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
1974
1975     // It's OK to exit right now, even though we set some locals. That's because those locals are not
1976     // user-visible.
1977     m_exitOK = true;
1978     addToGraph(ExitOK);
1979     
1980     SwitchData& data = *m_graph.m_switchData.add();
1981     data.kind = SwitchCell;
1982     addToGraph(Switch, OpInfo(&data), thingToSwitchOn);
1983     m_currentBlock->didLink();
1984     
1985     BasicBlock* continuationBlock = allocateUntargetableBlock();
1986     VERBOSE_LOG("Adding untargetable block ", RawPointer(continuationBlock), " (continuation)\n");
1987     
1988     // We may force this true if we give up on inlining any of the edges.
1989     bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
1990     
1991     VERBOSE_LOG("About to loop over functions at ", currentCodeOrigin(), ".\n");
1992
1993     unsigned oldOffset = m_currentIndex;
1994     for (unsigned i = 0; i < callLinkStatus.size(); ++i) {
1995         m_currentIndex = oldOffset;
1996         BasicBlock* calleeEntryBlock = allocateUntargetableBlock();
1997         m_currentBlock = calleeEntryBlock;
1998         prepareToParseBlock();
1999
2000         // At the top of each switch case, we can exit.
2001         m_exitOK = true;
2002         
2003         Node* myCallTargetNode = getDirect(calleeReg);
2004         
2005         auto inliningResult = handleCallVariant(
2006             myCallTargetNode, result, callLinkStatus[i], registerOffset,
2007             thisArgument, argumentCountIncludingThis, nextOffset, kind, prediction,
2008             inliningBalance, continuationBlock, false);
2009         
2010         if (inliningResult == CallOptimizationResult::DidNothing) {
2011             // That failed so we let the block die. Nothing interesting should have been added to
2012             // the block. We also give up on inlining any of the (less frequent) callees.
2013             ASSERT(m_graph.m_blocks.last() == m_currentBlock);
2014             m_graph.killBlockAndItsContents(m_currentBlock);
2015             m_graph.m_blocks.removeLast();
2016             VERBOSE_LOG("Inlining of a poly call failed, we will have to go through a slow path\n");
2017
2018             // The fact that inlining failed means we need a slow path.
2019             couldTakeSlowPath = true;
2020             break;
2021         }
2022         
2023         JSCell* thingToCaseOn;
2024         if (allAreDirectCalls)
2025             thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
2026         else {
2027             ASSERT(allAreClosureCalls);
2028             thingToCaseOn = callLinkStatus[i].executable();
2029         }
2030         data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), calleeEntryBlock));
2031         VERBOSE_LOG("Finished optimizing ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
2032     }
2033
2034     // Slow path block
2035     m_currentBlock = allocateUntargetableBlock();
2036     m_currentIndex = oldOffset;
2037     m_exitOK = true;
2038     data.fallThrough = BranchTarget(m_currentBlock);
2039     prepareToParseBlock();
2040     Node* myCallTargetNode = getDirect(calleeReg);
2041     if (couldTakeSlowPath) {
2042         addCall(
2043             result, callOp, nullptr, myCallTargetNode, argumentCountIncludingThis,
2044             registerOffset, prediction);
2045         VERBOSE_LOG("We added a call in the slow path\n");
2046     } else {
2047         addToGraph(CheckBadCell);
2048         addToGraph(Phantom, myCallTargetNode);
2049         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
2050         
2051         set(result, addToGraph(BottomValue));
2052         VERBOSE_LOG("couldTakeSlowPath was false\n");
2053     }
2054
2055     m_currentIndex = nextOffset;
2056     m_exitOK = true; // Origin changed, so it's fine to exit again.
2057     processSetLocalQueue();
2058
2059     if (Node* terminal = m_currentBlock->terminal())
2060         ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
2061     else {
2062         addJumpTo(continuationBlock);
2063     }
2064
2065     prepareToParseBlock();
2066     
2067     m_currentIndex = oldOffset;
2068     m_currentBlock = continuationBlock;
2069     m_exitOK = true;
2070     
2071     VERBOSE_LOG("Done inlining (hard).\nStack: ", currentCodeOrigin(), "\n");
2072     return CallOptimizationResult::Inlined;
2073 }
2074
2075 template<typename ChecksFunctor>
2076 bool ByteCodeParser::handleMinMax(VirtualRegister result, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks)
2077 {
2078     ASSERT(op == ArithMin || op == ArithMax);
2079
2080     if (argumentCountIncludingThis == 1) {
2081         insertChecks();
2082         double limit = op == ArithMax ? -std::numeric_limits<double>::infinity() : +std::numeric_limits<double>::infinity();
2083         set(result, addToGraph(JSConstant, OpInfo(m_graph.freeze(jsDoubleNumber(limit)))));
2084         return true;
2085     }
2086      
2087     if (argumentCountIncludingThis == 2) {
2088         insertChecks();
2089         Node* resultNode = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
2090         addToGraph(Phantom, Edge(resultNode, NumberUse));
2091         set(result, resultNode);
2092         return true;
2093     }
2094     
2095     if (argumentCountIncludingThis == 3) {
2096         insertChecks();
2097         set(result, addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2098         return true;
2099     }
2100     
2101     // Don't handle >=3 arguments for now.
2102     return false;
2103 }
2104
2105 template<typename ChecksFunctor>
2106 bool ByteCodeParser::handleIntrinsicCall(Node* callee, VirtualRegister result, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2107 {
2108     VERBOSE_LOG("       The intrinsic is ", intrinsic, "\n");
2109
2110     if (!isOpcodeShape<OpCallShape>(m_currentInstruction))
2111         return false;
2112
2113     // It so happens that the code below doesn't handle the invalid result case. We could fix that, but
2114     // it would only benefit intrinsics called as setters, like if you do:
2115     //
2116     //     o.__defineSetter__("foo", Math.pow)
2117     //
2118     // Which is extremely amusing, but probably not worth optimizing.
2119     if (!result.isValid())
2120         return false;
2121     
2122     switch (intrinsic) {
2123
2124     // Intrinsic Functions:
2125
2126     case AbsIntrinsic: {
2127         if (argumentCountIncludingThis == 1) { // Math.abs()
2128             insertChecks();
2129             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
2130             return true;
2131         }
2132
2133         if (!MacroAssembler::supportsFloatingPointAbs())
2134             return false;
2135
2136         insertChecks();
2137         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
2138         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
2139             node->mergeFlags(NodeMayOverflowInt32InDFG);
2140         set(result, node);
2141         return true;
2142     }
2143
2144     case MinIntrinsic:
2145         return handleMinMax(result, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
2146         
2147     case MaxIntrinsic:
2148         return handleMinMax(result, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
2149
2150 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2151     case capitalizedName##Intrinsic:
2152     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2153 #undef DFG_ARITH_UNARY
2154     {
2155         if (argumentCountIncludingThis == 1) {
2156             insertChecks();
2157             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
2158             return true;
2159         }
2160         Arith::UnaryType type = Arith::UnaryType::Sin;
2161         switch (intrinsic) {
2162 #define DFG_ARITH_UNARY(capitalizedName, lowerName) \
2163         case capitalizedName##Intrinsic: \
2164             type = Arith::UnaryType::capitalizedName; \
2165             break;
2166     FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY)
2167 #undef DFG_ARITH_UNARY
2168         default:
2169             RELEASE_ASSERT_NOT_REACHED();
2170         }
2171         insertChecks();
2172         set(result, addToGraph(ArithUnary, OpInfo(static_cast<std::underlying_type<Arith::UnaryType>::type>(type)), get(virtualRegisterForArgument(1, registerOffset))));
2173         return true;
2174     }
2175
2176     case FRoundIntrinsic:
2177     case SqrtIntrinsic: {
2178         if (argumentCountIncludingThis == 1) {
2179             insertChecks();
2180             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
2181             return true;
2182         }
2183
2184         NodeType nodeType = Unreachable;
2185         switch (intrinsic) {
2186         case FRoundIntrinsic:
2187             nodeType = ArithFRound;
2188             break;
2189         case SqrtIntrinsic:
2190             nodeType = ArithSqrt;
2191             break;
2192         default:
2193             RELEASE_ASSERT_NOT_REACHED();
2194         }
2195         insertChecks();
2196         set(result, addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
2197         return true;
2198     }
2199
2200     case PowIntrinsic: {
2201         if (argumentCountIncludingThis < 3) {
2202             // Math.pow() and Math.pow(x) return NaN.
2203             insertChecks();
2204             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
2205             return true;
2206         }
2207         insertChecks();
2208         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
2209         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
2210         set(result, addToGraph(ArithPow, get(xOperand), get(yOperand)));
2211         return true;
2212     }
2213         
2214     case ArrayPushIntrinsic: {
2215 #if USE(JSVALUE32_64)
2216         if (isX86()) {
2217             if (argumentCountIncludingThis > 2)
2218                 return false;
2219         }
2220 #endif
2221
2222         if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
2223             return false;
2224         
2225         ArrayMode arrayMode = getArrayMode(Array::Write);
2226         if (!arrayMode.isJSArray())
2227             return false;
2228         switch (arrayMode.type()) {
2229         case Array::Int32:
2230         case Array::Double:
2231         case Array::Contiguous:
2232         case Array::ArrayStorage: {
2233             insertChecks();
2234
2235             addVarArgChild(nullptr); // For storage.
2236             for (int i = 0; i < argumentCountIncludingThis; ++i)
2237                 addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
2238             Node* arrayPush = addToGraph(Node::VarArg, ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction));
2239             set(result, arrayPush);
2240             
2241             return true;
2242         }
2243             
2244         default:
2245             return false;
2246         }
2247     }
2248
2249     case ArraySliceIntrinsic: {
2250 #if USE(JSVALUE32_64)
2251         if (isX86()) {
2252             // There aren't enough registers for this to be done easily.
2253             return false;
2254         }
2255 #endif
2256         if (argumentCountIncludingThis < 1)
2257             return false;
2258
2259         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2260             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
2261             return false;
2262
2263         ArrayMode arrayMode = getArrayMode(Array::Read);
2264         if (!arrayMode.isJSArray())
2265             return false;
2266
2267         if (!arrayMode.isJSArrayWithOriginalStructure())
2268             return false;
2269
2270         switch (arrayMode.type()) {
2271         case Array::Double:
2272         case Array::Int32:
2273         case Array::Contiguous: {
2274             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2275
2276             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
2277             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
2278
2279             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2280             // https://bugs.webkit.org/show_bug.cgi?id=173171
2281             if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
2282                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
2283                 && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2284                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2285                 && globalObject->arrayPrototypeChainIsSane()) {
2286
2287                 m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
2288                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2289                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2290                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2291
2292                 insertChecks();
2293
2294                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2295                 // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
2296                 // 1. We ensure that the "constructor" property hasn't been changed (because the observable
2297                 // effects of slice require that we perform a Get(array, "constructor") and we can skip
2298                 // that if we're an original array structure. (We can relax this in the future by using
2299                 // TryGetById and CheckCell).
2300                 //
2301                 // 2. We check that the array we're calling slice on has the same global object as the lexical
2302                 // global object that this code is running in. This requirement is necessary because we setup the
2303                 // watchpoints above on the lexical global object. This means that code that calls slice on
2304                 // arrays produced by other global objects won't get this optimization. We could relax this
2305                 // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
2306                 // we generate instead of registering it as a watchpoint that would invalidate the compilation.
2307                 //
2308                 // 3. By proving we're an original array structure, we guarantee that the incoming array
2309                 // isn't a subclass of Array.
2310
2311                 StructureSet structureSet;
2312                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
2313                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
2314                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
2315                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithInt32));
2316                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
2317                 structureSet.add(globalObject->originalArrayStructureForIndexingType(CopyOnWriteArrayWithDouble));
2318                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
2319
2320                 addVarArgChild(array);
2321                 if (argumentCountIncludingThis >= 2)
2322                     addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
2323                 if (argumentCountIncludingThis >= 3)
2324                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
2325                 addVarArgChild(addToGraph(GetButterfly, array));
2326
2327                 Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
2328                 set(result, arraySlice);
2329                 return true;
2330             }
2331
2332             return false;
2333         }
2334         default:
2335             return false;
2336         }
2337
2338         RELEASE_ASSERT_NOT_REACHED();
2339         return false;
2340     }
2341
2342     case ArrayIndexOfIntrinsic: {
2343         if (argumentCountIncludingThis < 2)
2344             return false;
2345
2346         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
2347             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2348             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
2349             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2350             return false;
2351
2352         ArrayMode arrayMode = getArrayMode(Array::Read);
2353         if (!arrayMode.isJSArray())
2354             return false;
2355
2356         if (!arrayMode.isJSArrayWithOriginalStructure())
2357             return false;
2358
2359         // We do not want to convert arrays into one type just to perform indexOf.
2360         if (arrayMode.doesConversion())
2361             return false;
2362
2363         switch (arrayMode.type()) {
2364         case Array::Double:
2365         case Array::Int32:
2366         case Array::Contiguous: {
2367             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2368
2369             Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(*m_vm);
2370             Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(*m_vm);
2371
2372             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2373             // https://bugs.webkit.org/show_bug.cgi?id=173171
2374             if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
2375                 && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
2376                 && globalObject->arrayPrototypeChainIsSane()) {
2377
2378                 m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
2379                 m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
2380
2381                 insertChecks();
2382
2383                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2384                 addVarArgChild(array);
2385                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Search element.
2386                 if (argumentCountIncludingThis >= 3)
2387                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // Start index.
2388                 addVarArgChild(nullptr);
2389
2390                 Node* node = addToGraph(Node::VarArg, ArrayIndexOf, OpInfo(arrayMode.asWord()), OpInfo());
2391                 set(result, node);
2392                 return true;
2393             }
2394
2395             return false;
2396         }
2397         default:
2398             return false;
2399         }
2400
2401         RELEASE_ASSERT_NOT_REACHED();
2402         return false;
2403
2404     }
2405         
2406     case ArrayPopIntrinsic: {
2407         if (argumentCountIncludingThis != 1)
2408             return false;
2409         
2410         ArrayMode arrayMode = getArrayMode(Array::Write);
2411         if (!arrayMode.isJSArray())
2412             return false;
2413         switch (arrayMode.type()) {
2414         case Array::Int32:
2415         case Array::Double:
2416         case Array::Contiguous:
2417         case Array::ArrayStorage: {
2418             insertChecks();
2419             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
2420             set(result, arrayPop);
2421             return true;
2422         }
2423             
2424         default:
2425             return false;
2426         }
2427     }
2428         
2429     case AtomicsAddIntrinsic:
2430     case AtomicsAndIntrinsic:
2431     case AtomicsCompareExchangeIntrinsic:
2432     case AtomicsExchangeIntrinsic:
2433     case AtomicsIsLockFreeIntrinsic:
2434     case AtomicsLoadIntrinsic:
2435     case AtomicsOrIntrinsic:
2436     case AtomicsStoreIntrinsic:
2437     case AtomicsSubIntrinsic:
2438     case AtomicsXorIntrinsic: {
2439         if (!is64Bit())
2440             return false;
2441         
2442         NodeType op = LastNodeType;
2443         Array::Action action = Array::Write;
2444         unsigned numArgs = 0; // Number of actual args; we add one for the backing store pointer.
2445         switch (intrinsic) {
2446         case AtomicsAddIntrinsic:
2447             op = AtomicsAdd;
2448             numArgs = 3;
2449             break;
2450         case AtomicsAndIntrinsic:
2451             op = AtomicsAnd;
2452             numArgs = 3;
2453             break;
2454         case AtomicsCompareExchangeIntrinsic:
2455             op = AtomicsCompareExchange;
2456             numArgs = 4;
2457             break;
2458         case AtomicsExchangeIntrinsic:
2459             op = AtomicsExchange;
2460             numArgs = 3;
2461             break;
2462         case AtomicsIsLockFreeIntrinsic:
2463             // This gets no backing store, but we need no special logic for this since this also does
2464             // not need varargs.
2465             op = AtomicsIsLockFree;
2466             numArgs = 1;
2467             break;
2468         case AtomicsLoadIntrinsic:
2469             op = AtomicsLoad;
2470             numArgs = 2;
2471             action = Array::Read;
2472             break;
2473         case AtomicsOrIntrinsic:
2474             op = AtomicsOr;
2475             numArgs = 3;
2476             break;
2477         case AtomicsStoreIntrinsic:
2478             op = AtomicsStore;
2479             numArgs = 3;
2480             break;
2481         case AtomicsSubIntrinsic:
2482             op = AtomicsSub;
2483             numArgs = 3;
2484             break;
2485         case AtomicsXorIntrinsic:
2486             op = AtomicsXor;
2487             numArgs = 3;
2488             break;
2489         default:
2490             RELEASE_ASSERT_NOT_REACHED();
2491             break;
2492         }
2493         
2494         if (static_cast<unsigned>(argumentCountIncludingThis) < 1 + numArgs)
2495             return false;
2496         
2497         insertChecks();
2498         
2499         Vector<Node*, 3> args;
2500         for (unsigned i = 0; i < numArgs; ++i)
2501             args.append(get(virtualRegisterForArgument(1 + i, registerOffset)));
2502         
2503         Node* resultNode;
2504         if (numArgs + 1 <= 3) {
2505             while (args.size() < 3)
2506                 args.append(nullptr);
2507             resultNode = addToGraph(op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction), args[0], args[1], args[2]);
2508         } else {
2509             for (Node* node : args)
2510                 addVarArgChild(node);
2511             addVarArgChild(nullptr);
2512             resultNode = addToGraph(Node::VarArg, op, OpInfo(ArrayMode(Array::SelectUsingPredictions, action).asWord()), OpInfo(prediction));
2513         }
2514         
2515         set(result, resultNode);
2516         return true;
2517     }
2518
2519     case ParseIntIntrinsic: {
2520         if (argumentCountIncludingThis < 2)
2521             return false;
2522
2523         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2524             return false;
2525
2526         insertChecks();
2527         VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
2528         Node* parseInt;
2529         if (argumentCountIncludingThis == 2)
2530             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
2531         else {
2532             ASSERT(argumentCountIncludingThis > 2);
2533             VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
2534             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
2535         }
2536         set(result, parseInt);
2537         return true;
2538     }
2539
2540     case CharCodeAtIntrinsic: {
2541         if (argumentCountIncludingThis != 2)
2542             return false;
2543
2544         insertChecks();
2545         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2546         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2547         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
2548
2549         set(result, charCode);
2550         return true;
2551     }
2552
2553     case CharAtIntrinsic: {
2554         if (argumentCountIncludingThis != 2)
2555             return false;
2556
2557         insertChecks();
2558         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2559         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2560         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String, Array::Read).asWord()), get(thisOperand), get(indexOperand));
2561
2562         set(result, charCode);
2563         return true;
2564     }
2565     case Clz32Intrinsic: {
2566         insertChecks();
2567         if (argumentCountIncludingThis == 1)
2568             set(result, addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
2569         else {
2570             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2571             set(result, addToGraph(ArithClz32, operand));
2572         }
2573         return true;
2574     }
2575     case FromCharCodeIntrinsic: {
2576         if (argumentCountIncludingThis != 2)
2577             return false;
2578
2579         insertChecks();
2580         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2581         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
2582
2583         set(result, charCode);
2584
2585         return true;
2586     }
2587
2588     case RegExpExecIntrinsic: {
2589         if (argumentCountIncludingThis != 2)
2590             return false;
2591         
2592         insertChecks();
2593         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2594         set(result, regExpExec);
2595         
2596         return true;
2597     }
2598         
2599     case RegExpTestIntrinsic:
2600     case RegExpTestFastIntrinsic: {
2601         if (argumentCountIncludingThis != 2)
2602             return false;
2603
2604         if (intrinsic == RegExpTestIntrinsic) {
2605             // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2606             if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2607                 return false;
2608
2609             JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2610             Structure* regExpStructure = globalObject->regExpStructure();
2611             m_graph.registerStructure(regExpStructure);
2612             ASSERT(regExpStructure->storedPrototype().isObject());
2613             ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2614
2615             FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2616             Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2617
2618             auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2619                 JSValue currentProperty;
2620                 if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2621                     return false;
2622                 
2623                 return currentProperty == primordialProperty;
2624             };
2625
2626             // Check that RegExp.exec is still the primordial RegExp.prototype.exec
2627             if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2628                 return false;
2629
2630             // Check that regExpObject is actually a RegExp object.
2631             Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2632             addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
2633
2634             // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
2635             UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
2636             unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
2637             Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
2638             FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
2639             addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
2640         }
2641
2642         insertChecks();
2643         Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2644         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
2645         set(result, regExpExec);
2646         
2647         return true;
2648     }
2649
2650     case RegExpMatchFastIntrinsic: {
2651         RELEASE_ASSERT(argumentCountIncludingThis == 2);
2652
2653         insertChecks();
2654         Node* regExpMatch = addToGraph(RegExpMatchFast, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2655         set(result, regExpMatch);
2656         return true;
2657     }
2658
2659     case ObjectCreateIntrinsic: {
2660         if (argumentCountIncludingThis != 2)
2661             return false;
2662
2663         insertChecks();
2664         set(result, addToGraph(ObjectCreate, get(virtualRegisterForArgument(1, registerOffset))));
2665         return true;
2666     }
2667
2668     case ObjectGetPrototypeOfIntrinsic: {
2669         if (argumentCountIncludingThis != 2)
2670             return false;
2671
2672         insertChecks();
2673         set(result, addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2674         return true;
2675     }
2676
2677     case ObjectIsIntrinsic: {
2678         if (argumentCountIncludingThis < 3)
2679             return false;
2680
2681         insertChecks();
2682         set(result, addToGraph(SameValue, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2683         return true;
2684     }
2685
2686     case ReflectGetPrototypeOfIntrinsic: {
2687         if (argumentCountIncludingThis != 2)
2688             return false;
2689
2690         insertChecks();
2691         set(result, addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), Edge(get(virtualRegisterForArgument(1, registerOffset)), ObjectUse)));
2692         return true;
2693     }
2694
2695     case IsTypedArrayViewIntrinsic: {
2696         ASSERT(argumentCountIncludingThis == 2);
2697
2698         insertChecks();
2699         set(result, addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2700         return true;
2701     }
2702
2703     case StringPrototypeValueOfIntrinsic: {
2704         insertChecks();
2705         Node* value = get(virtualRegisterForArgument(0, registerOffset));
2706         set(result, addToGraph(StringValueOf, value));
2707         return true;
2708     }
2709
2710     case StringPrototypeReplaceIntrinsic: {
2711         if (argumentCountIncludingThis != 3)
2712             return false;
2713
2714         // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
2715         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2716             return false;
2717
2718         // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2719         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2720             return false;
2721
2722         JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2723         Structure* regExpStructure = globalObject->regExpStructure();
2724         m_graph.registerStructure(regExpStructure);
2725         ASSERT(regExpStructure->storedPrototype().isObject());
2726         ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2727
2728         FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2729         Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2730
2731         auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2732             JSValue currentProperty;
2733             if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2734                 return false;
2735
2736             return currentProperty == primordialProperty;
2737         };
2738
2739         // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
2740         if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2741             return false;
2742
2743         // Check that searchRegExp.global is still the primordial RegExp.prototype.global
2744         if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
2745             return false;
2746
2747         // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
2748         if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
2749             return false;
2750
2751         // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
2752         if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
2753             return false;
2754
2755         insertChecks();
2756
2757         Node* resultNode = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2758         set(result, resultNode);
2759         return true;
2760     }
2761         
2762     case StringPrototypeReplaceRegExpIntrinsic: {
2763         if (argumentCountIncludingThis != 3)
2764             return false;
2765         
2766         insertChecks();
2767         Node* resultNode = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2768         set(result, resultNode);
2769         return true;
2770     }
2771         
2772     case RoundIntrinsic:
2773     case FloorIntrinsic:
2774     case CeilIntrinsic:
2775     case TruncIntrinsic: {
2776         if (argumentCountIncludingThis == 1) {
2777             insertChecks();
2778             set(result, addToGraph(JSConstant, OpInfo(m_constantNaN)));
2779             return true;
2780         }
2781         insertChecks();
2782         Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2783         NodeType op;
2784         if (intrinsic == RoundIntrinsic)
2785             op = ArithRound;
2786         else if (intrinsic == FloorIntrinsic)
2787             op = ArithFloor;
2788         else if (intrinsic == CeilIntrinsic)
2789             op = ArithCeil;
2790         else {
2791             ASSERT(intrinsic == TruncIntrinsic);
2792             op = ArithTrunc;
2793         }
2794         Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
2795         set(result, roundNode);
2796         return true;
2797     }
2798     case IMulIntrinsic: {
2799         if (argumentCountIncludingThis != 3)
2800             return false;
2801         insertChecks();
2802         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
2803         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
2804         Node* left = get(leftOperand);
2805         Node* right = get(rightOperand);
2806         set(result, addToGraph(ArithIMul, left, right));
2807         return true;
2808     }
2809
2810     case RandomIntrinsic: {
2811         if (argumentCountIncludingThis != 1)
2812             return false;
2813         insertChecks();
2814         set(result, addToGraph(ArithRandom));
2815         return true;
2816     }
2817         
2818     case DFGTrueIntrinsic: {
2819         insertChecks();
2820         set(result, jsConstant(jsBoolean(true)));
2821         return true;
2822     }
2823
2824     case FTLTrueIntrinsic: {
2825         insertChecks();
2826         set(result, jsConstant(jsBoolean(m_graph.m_plan.isFTL())));
2827         return true;
2828     }
2829         
2830     case OSRExitIntrinsic: {
2831         insertChecks();
2832         addToGraph(ForceOSRExit);
2833         set(result, addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2834         return true;
2835     }
2836         
2837     case IsFinalTierIntrinsic: {
2838         insertChecks();
2839         set(result,
2840             jsConstant(jsBoolean(Options::useFTLJIT() ? m_graph.m_plan.isFTL() : true)));
2841         return true;
2842     }
2843         
2844     case SetInt32HeapPredictionIntrinsic: {
2845         insertChecks();
2846         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2847             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2848             if (node->hasHeapPrediction())
2849                 node->setHeapPrediction(SpecInt32Only);
2850         }
2851         set(result, addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2852         return true;
2853     }
2854         
2855     case CheckInt32Intrinsic: {
2856         insertChecks();
2857         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2858             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2859             addToGraph(Phantom, Edge(node, Int32Use));
2860         }
2861         set(result, jsConstant(jsBoolean(true)));
2862         return true;
2863     }
2864         
2865     case FiatInt52Intrinsic: {
2866         if (argumentCountIncludingThis != 2)
2867             return false;
2868         insertChecks();
2869         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2870         if (enableInt52())
2871             set(result, addToGraph(FiatInt52, get(operand)));
2872         else
2873             set(result, get(operand));
2874         return true;
2875     }
2876
2877     case JSMapGetIntrinsic: {
2878         if (argumentCountIncludingThis != 2)
2879             return false;
2880
2881         insertChecks();
2882         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2883         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2884         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2885         Node* hash = addToGraph(MapHash, normalizedKey);
2886         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(normalizedKey), Edge(hash));
2887         Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2888         set(result, resultNode);
2889         return true;
2890     }
2891
2892     case JSSetHasIntrinsic:
2893     case JSMapHasIntrinsic: {
2894         if (argumentCountIncludingThis != 2)
2895             return false;
2896
2897         insertChecks();
2898         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
2899         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2900         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2901         Node* hash = addToGraph(MapHash, normalizedKey);
2902         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
2903         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
2904         JSCell* sentinel = nullptr;
2905         if (intrinsic == JSMapHasIntrinsic)
2906             sentinel = m_vm->sentinelMapBucket.get();
2907         else
2908             sentinel = m_vm->sentinelSetBucket.get();
2909
2910         FrozenValue* frozenPointer = m_graph.freeze(sentinel);
2911         Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
2912         Node* resultNode = addToGraph(LogicalNot, invertedResult);
2913         set(result, resultNode);
2914         return true;
2915     }
2916
2917     case JSSetAddIntrinsic: {
2918         if (argumentCountIncludingThis != 2)
2919             return false;
2920
2921         insertChecks();
2922         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2923         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2924         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2925         Node* hash = addToGraph(MapHash, normalizedKey);
2926         addToGraph(SetAdd, base, normalizedKey, hash);
2927         set(result, base);
2928         return true;
2929     }
2930
2931     case JSMapSetIntrinsic: {
2932         if (argumentCountIncludingThis != 3)
2933             return false;
2934
2935         insertChecks();
2936         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2937         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2938         Node* value = get(virtualRegisterForArgument(2, registerOffset));
2939
2940         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2941         Node* hash = addToGraph(MapHash, normalizedKey);
2942
2943         addVarArgChild(base);
2944         addVarArgChild(normalizedKey);
2945         addVarArgChild(value);
2946         addVarArgChild(hash);
2947         addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
2948         set(result, base);
2949         return true;
2950     }
2951
2952     case JSSetBucketHeadIntrinsic:
2953     case JSMapBucketHeadIntrinsic: {
2954         ASSERT(argumentCountIncludingThis == 2);
2955
2956         insertChecks();
2957         Node* map = get(virtualRegisterForArgument(1, registerOffset));
2958         UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
2959         Node* resultNode = addToGraph(GetMapBucketHead, Edge(map, useKind));
2960         set(result, resultNode);
2961         return true;
2962     }
2963
2964     case JSSetBucketNextIntrinsic:
2965     case JSMapBucketNextIntrinsic: {
2966         ASSERT(argumentCountIncludingThis == 2);
2967
2968         insertChecks();
2969         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2970         BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2971         Node* resultNode = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
2972         set(result, resultNode);
2973         return true;
2974     }
2975
2976     case JSSetBucketKeyIntrinsic:
2977     case JSMapBucketKeyIntrinsic: {
2978         ASSERT(argumentCountIncludingThis == 2);
2979
2980         insertChecks();
2981         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2982         BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2983         Node* resultNode = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
2984         set(result, resultNode);
2985         return true;
2986     }
2987
2988     case JSMapBucketValueIntrinsic: {
2989         ASSERT(argumentCountIncludingThis == 2);
2990
2991         insertChecks();
2992         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2993         Node* resultNode = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2994         set(result, resultNode);
2995         return true;
2996     }
2997
2998     case JSWeakMapGetIntrinsic: {
2999         if (argumentCountIncludingThis != 2)
3000             return false;
3001
3002         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3003             return false;
3004
3005         insertChecks();
3006         Node* map = get(virtualRegisterForArgument(0, registerOffset));
3007         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3008         addToGraph(Check, Edge(key, ObjectUse));
3009         Node* hash = addToGraph(MapHash, key);
3010         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3011         Node* resultNode = addToGraph(ExtractValueFromWeakMapGet, OpInfo(), OpInfo(prediction), holder);
3012
3013         set(result, resultNode);
3014         return true;
3015     }
3016
3017     case JSWeakMapHasIntrinsic: {
3018         if (argumentCountIncludingThis != 2)
3019             return false;
3020
3021         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3022             return false;
3023
3024         insertChecks();
3025         Node* map = get(virtualRegisterForArgument(0, registerOffset));
3026         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3027         addToGraph(Check, Edge(key, ObjectUse));
3028         Node* hash = addToGraph(MapHash, key);
3029         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3030         Node* invertedResult = addToGraph(IsEmpty, holder);
3031         Node* resultNode = addToGraph(LogicalNot, invertedResult);
3032
3033         set(result, resultNode);
3034         return true;
3035     }
3036
3037     case JSWeakSetHasIntrinsic: {
3038         if (argumentCountIncludingThis != 2)
3039             return false;
3040
3041         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3042             return false;
3043
3044         insertChecks();
3045         Node* map = get(virtualRegisterForArgument(0, registerOffset));
3046         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3047         addToGraph(Check, Edge(key, ObjectUse));
3048         Node* hash = addToGraph(MapHash, key);
3049         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3050         Node* invertedResult = addToGraph(IsEmpty, holder);
3051         Node* resultNode = addToGraph(LogicalNot, invertedResult);
3052
3053         set(result, resultNode);
3054         return true;
3055     }
3056
3057     case JSWeakSetAddIntrinsic: {
3058         if (argumentCountIncludingThis != 2)
3059             return false;
3060
3061         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3062             return false;
3063
3064         insertChecks();
3065         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3066         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3067         addToGraph(Check, Edge(key, ObjectUse));
3068         Node* hash = addToGraph(MapHash, key);
3069         addToGraph(WeakSetAdd, Edge(base, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3070         set(result, base);
3071         return true;
3072     }
3073
3074     case JSWeakMapSetIntrinsic: {
3075         if (argumentCountIncludingThis != 3)
3076             return false;
3077
3078         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3079             return false;
3080
3081         insertChecks();
3082         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3083         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3084         Node* value = get(virtualRegisterForArgument(2, registerOffset));
3085
3086         addToGraph(Check, Edge(key, ObjectUse));
3087         Node* hash = addToGraph(MapHash, key);
3088
3089         addVarArgChild(Edge(base, WeakMapObjectUse));
3090         addVarArgChild(Edge(key, ObjectUse));
3091         addVarArgChild(Edge(value));
3092         addVarArgChild(Edge(hash, Int32Use));
3093         addToGraph(Node::VarArg, WeakMapSet, OpInfo(0), OpInfo(0));
3094         set(result, base);
3095         return true;
3096     }
3097
3098     case DataViewGetInt8:
3099     case DataViewGetUint8:
3100     case DataViewGetInt16:
3101     case DataViewGetUint16:
3102     case DataViewGetInt32:
3103     case DataViewGetUint32:
3104     case DataViewGetFloat32:
3105     case DataViewGetFloat64: {
3106         if (!is64Bit())
3107             return false;
3108
3109         // To inline data view accesses, we assume the architecture we're running on:
3110         // - Is little endian.
3111         // - Allows unaligned loads/stores without crashing. 
3112
3113         if (argumentCountIncludingThis < 2)
3114             return false;
3115         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3116             return false;
3117
3118         insertChecks();
3119
3120         uint8_t byteSize;
3121         NodeType op = DataViewGetInt;
3122         bool isSigned = false;
3123         switch (intrinsic) {
3124         case DataViewGetInt8:
3125             isSigned = true;
3126             FALLTHROUGH;
3127         case DataViewGetUint8:
3128             byteSize = 1;
3129             break;
3130
3131         case DataViewGetInt16:
3132             isSigned = true;
3133             FALLTHROUGH;
3134         case DataViewGetUint16:
3135             byteSize = 2;
3136             break;
3137
3138         case DataViewGetInt32:
3139             isSigned = true;
3140             FALLTHROUGH;
3141         case DataViewGetUint32:
3142             byteSize = 4;
3143             break;
3144
3145         case DataViewGetFloat32:
3146             byteSize = 4;
3147             op = DataViewGetFloat;
3148             break;
3149         case DataViewGetFloat64:
3150             byteSize = 8;
3151             op = DataViewGetFloat;
3152             break;
3153         default:
3154             RELEASE_ASSERT_NOT_REACHED();
3155         }
3156
3157         TriState isLittleEndian = MixedTriState;
3158         Node* littleEndianChild = nullptr;
3159         if (byteSize > 1) {
3160             if (argumentCountIncludingThis < 3)
3161                 isLittleEndian = FalseTriState;
3162             else {
3163                 littleEndianChild = get(virtualRegisterForArgument(2, registerOffset));
3164                 if (littleEndianChild->hasConstant()) {
3165                     JSValue constant = littleEndianChild->constant()->value();
3166                     isLittleEndian = constant.pureToBoolean();
3167                     if (isLittleEndian != MixedTriState)
3168                         littleEndianChild = nullptr;
3169                 } else
3170                     isLittleEndian = MixedTriState;
3171             }
3172         }
3173
3174         DataViewData data { };
3175         data.isLittleEndian = isLittleEndian;
3176         data.isSigned = isSigned;
3177         data.byteSize = byteSize;
3178
3179         set(VirtualRegister(result),
3180             addToGraph(op, OpInfo(data.asQuadWord), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), littleEndianChild));
3181         return true;
3182     }
3183
3184     case DataViewSetInt8:
3185     case DataViewSetUint8:
3186     case DataViewSetInt16:
3187     case DataViewSetUint16:
3188     case DataViewSetInt32:
3189     case DataViewSetUint32:
3190     case DataViewSetFloat32:
3191     case DataViewSetFloat64: {
3192         if (!is64Bit())
3193             return false;
3194
3195         if (argumentCountIncludingThis < 3)
3196             return false;
3197
3198         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3199             return false;
3200
3201         insertChecks();
3202
3203         uint8_t byteSize;
3204         bool isFloatingPoint = false;
3205         bool isSigned = false;
3206         switch (intrinsic) {
3207         case DataViewSetInt8:
3208             isSigned = true;
3209             FALLTHROUGH;
3210         case DataViewSetUint8:
3211             byteSize = 1;
3212             break;
3213
3214         case DataViewSetInt16:
3215             isSigned = true;
3216             FALLTHROUGH;
3217         case DataViewSetUint16:
3218             byteSize = 2;
3219             break;
3220
3221         case DataViewSetInt32:
3222             isSigned = true;
3223             FALLTHROUGH;
3224         case DataViewSetUint32:
3225             byteSize = 4;
3226             break;
3227
3228         case DataViewSetFloat32:
3229             isFloatingPoint = true;
3230             byteSize = 4;
3231             break;
3232         case DataViewSetFloat64:
3233             isFloatingPoint = true;
3234             byteSize = 8;
3235             break;
3236         default:
3237             RELEASE_ASSERT_NOT_REACHED();
3238         }
3239
3240         TriState isLittleEndian = MixedTriState;
3241         Node* littleEndianChild = nullptr;
3242         if (byteSize > 1) {
3243             if (argumentCountIncludingThis < 4)
3244                 isLittleEndian = FalseTriState;
3245             else {
3246                 littleEndianChild = get(virtualRegisterForArgument(3, registerOffset));
3247                 if (littleEndianChild->hasConstant()) {
3248                     JSValue constant = littleEndianChild->constant()->value();
3249                     isLittleEndian = constant.pureToBoolean();
3250                     if (isLittleEndian != MixedTriState)
3251                         littleEndianChild = nullptr;
3252                 } else
3253                     isLittleEndian = MixedTriState;
3254             }
3255         }
3256
3257         DataViewData data { };
3258         data.isLittleEndian = isLittleEndian;
3259         data.isSigned = isSigned;
3260         data.byteSize = byteSize;
3261         data.isFloatingPoint = isFloatingPoint;
3262
3263         addVarArgChild(get(virtualRegisterForArgument(0, registerOffset)));
3264         addVarArgChild(get(virtualRegisterForArgument(1, registerOffset)));
3265         addVarArgChild(get(virtualRegisterForArgument(2, registerOffset)));
3266         addVarArgChild(littleEndianChild);
3267
3268         addToGraph(Node::VarArg, DataViewSet, OpInfo(data.asQuadWord), OpInfo());
3269         return true;
3270     }
3271
3272     case HasOwnPropertyIntrinsic: {
3273         if (argumentCountIncludingThis != 2)
3274             return false;
3275
3276         // This can be racy, that's fine. We know that once we observe that this is created,
3277         // that it will never be destroyed until the VM is destroyed. It's unlikely that
3278         // we'd ever get to the point where we inline this as an intrinsic without the
3279         // cache being created, however, it's possible if we always throw exceptions inside
3280         // hasOwnProperty.
3281         if (!m_vm->hasOwnPropertyCache())
3282             return false;
3283
3284         insertChecks();
3285         Node* object = get(virtualRegisterForArgument(0, registerOffset));
3286         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3287         Node* resultNode = addToGraph(HasOwnProperty, object, key);
3288         set(result, resultNode);
3289         return true;
3290     }
3291
3292     case StringPrototypeSliceIntrinsic: {
3293         if (argumentCountIncludingThis < 2)
3294             return false;
3295
3296         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3297             return false;
3298
3299         insertChecks();
3300         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3301         Node* start = get(virtualRegisterForArgument(1, registerOffset));
3302         Node* end = nullptr;
3303         if (argumentCountIncludingThis > 2)
3304             end = get(virtualRegisterForArgument(2, registerOffset));
3305         Node* resultNode = addToGraph(StringSlice, thisString, start, end);
3306         set(result, resultNode);
3307         return true;
3308     }
3309
3310     case StringPrototypeToLowerCaseIntrinsic: {
3311         if (argumentCountIncludingThis != 1)
3312             return false;
3313
3314         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3315             return false;
3316
3317         insertChecks();
3318         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3319         Node* resultNode = addToGraph(ToLowerCase, thisString);
3320         set(result, resultNode);
3321         return true;
3322     }
3323
3324     case NumberPrototypeToStringIntrinsic: {
3325         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
3326             return false;
3327
3328         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3329             return false;
3330
3331         insertChecks();
3332         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
3333         if (argumentCountIncludingThis == 1) {
3334             Node* resultNode = addToGraph(ToString, thisNumber);
3335             set(result, resultNode);
3336         } else {
3337             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
3338             Node* resultNode = addToGraph(NumberToStringWithRadix, thisNumber, radix);
3339             set(result, resultNode);
3340         }
3341         return true;
3342     }
3343
3344     case NumberIsIntegerIntrinsic: {
3345         if (argumentCountIncludingThis < 2)
3346             return false;
3347
3348         insertChecks();
3349         Node* input = get(virtualRegisterForArgument(1, registerOffset));
3350         Node* resultNode = addToGraph(NumberIsInteger, input);
3351         set(result, resultNode);
3352         return true;
3353     }
3354
3355     case CPUMfenceIntrinsic:
3356     case CPURdtscIntrinsic:
3357     case CPUCpuidIntrinsic:
3358     case CPUPauseIntrinsic: {
3359 #if CPU(X86_64)
3360         if (!m_graph.m_plan.isFTL())
3361             return false;
3362         insertChecks();
3363         set(result,
3364             addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
3365         return true;
3366 #else
3367         return false;
3368 #endif
3369     }
3370
3371
3372     default:
3373         return false;
3374     }
3375 }
3376
3377 template<typename ChecksFunctor>
3378 bool ByteCodeParser::handleDOMJITCall(Node* callTarget, VirtualRegister result, const DOMJIT::Signature* signature, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3379 {
3380     if (argumentCountIncludingThis != static_cast<int>(1 + signature->argumentCount))
3381         return false;
3382     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3383         return false;
3384
3385     // FIXME: Currently, we only support functions which arguments are up to 2.
3386     // Eventually, we should extend this. But possibly, 2 or 3 can cover typical use cases.
3387     // https://bugs.webkit.org/show_bug.cgi?id=164346
3388     ASSERT_WITH_MESSAGE(argumentCountIncludingThis <= JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS, "Currently CallDOM does not support an arbitrary length arguments.");
3389
3390     insertChecks();
3391     addCall(result, Call, signature, callTarget, argumentCountIncludingThis, registerOffset, prediction);
3392     return true;
3393 }
3394
3395
3396 template<typename ChecksFunctor>
3397 bool ByteCodeParser::handleIntrinsicGetter(VirtualRegister result, SpeculatedType prediction, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
3398 {
3399     switch (variant.intrinsic()) {
3400     case TypedArrayByteLengthIntrinsic: {
3401         insertChecks();
3402
3403         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3404         Array::Type arrayType = toArrayType(type);
3405         size_t logSize = logElementSize(type);
3406
3407         variant.structureSet().forEach([&] (Structure* structure) {
3408             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3409             ASSERT(logSize == logElementSize(curType));
3410             arrayType = refineTypedArrayType(arrayType, curType);
3411             ASSERT(arrayType != Array::Generic);
3412         });
3413
3414         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode);
3415
3416         if (!logSize) {
3417             set(result, lengthNode);
3418             return true;
3419         }
3420
3421         // We can use a BitLShift here because typed arrays will never have a byteLength
3422         // that overflows int32.
3423         Node* shiftNode = jsConstant(jsNumber(logSize));
3424         set(result, addToGraph(BitLShift, lengthNode, shiftNode));
3425
3426         return true;
3427     }
3428
3429     case TypedArrayLengthIntrinsic: {
3430         insertChecks();
3431
3432         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3433         Array::Type arrayType = toArrayType(type);
3434
3435         variant.structureSet().forEach([&] (Structure* structure) {
3436             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3437             arrayType = refineTypedArrayType(arrayType, curType);
3438             ASSERT(arrayType != Array::Generic);
3439         });
3440
3441         set(result, addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
3442
3443         return true;
3444
3445     }
3446
3447     case TypedArrayByteOffsetIntrinsic: {
3448         insertChecks();
3449
3450         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3451         Array::Type arrayType = toArrayType(type);
3452
3453         variant.structureSet().forEach([&] (Structure* structure) {
3454             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3455             arrayType = refineTypedArrayType(arrayType, curType);
3456             ASSERT(arrayType != Array::Generic);
3457         });
3458
3459         set(result, addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType, Array::Read).asWord()), thisNode));
3460
3461         return true;
3462     }
3463
3464     case UnderscoreProtoIntrinsic: {
3465         insertChecks();
3466
3467         bool canFold = !variant.structureSet().isEmpty();
3468         JSValue prototype;
3469         variant.structureSet().forEach([&] (Structure* structure) {
3470             auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3471             MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3472             if (getPrototypeMethod != defaultGetPrototype) {
3473                 canFold = false;
3474                 return;
3475             }
3476
3477             if (structure->hasPolyProto()) {
3478                 canFold = false;
3479                 return;
3480             }
3481             if (!prototype)
3482                 prototype = structure->storedPrototype();
3483             else if (prototype != structure->storedPrototype())
3484                 canFold = false;
3485         });
3486
3487         // OK, only one prototype is found. We perform constant folding here.
3488         // This information is important for super's constructor call to get new.target constant.
3489         if (prototype && canFold) {
3490             set(result, weakJSConstant(prototype));
3491             return true;
3492         }
3493
3494         set(result, addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), thisNode));
3495         return true;
3496     }
3497
3498     default:
3499         return false;
3500     }
3501     RELEASE_ASSERT_NOT_REACHED();
3502 }
3503
3504 static void blessCallDOMGetter(Node* node)
3505 {
3506     DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
3507     if (snippet && !snippet->effect.mustGenerate())
3508         node->clearFlags(NodeMustGenerate);
3509 }
3510
3511 bool ByteCodeParser::handleDOMJITGetter(VirtualRegister result, const GetByIdVariant& variant, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction)
3512 {
3513     if (!variant.domAttribute())
3514         return false;
3515
3516     auto domAttribute = variant.domAttribute().value();
3517
3518     // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough,
3519     // since replacement of CustomGetterSetter always incurs Structure transition.
3520     if (!check(variant.conditionSet()))
3521         return false;
3522     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
3523     
3524     // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
3525     addToGraph(CheckSubClass, OpInfo(domAttribute.classInfo), thisNode);
3526     
3527     bool wasSeenInJIT = true;
3528     addToGraph(FilterGetByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByIdStatus(currentCodeOrigin(), GetByIdStatus(GetByIdStatus::Custom, wasSeenInJIT, variant))), thisNode);
3529
3530     CallDOMGetterData* callDOMGetterData = m_graph.m_callDOMGetterData.add();
3531     callDOMGetterData->customAccessorGetter = variant.customAccessorGetter();
3532     ASSERT(callDOMGetterData->customAccessorGetter);
3533
3534     if (const auto* domJIT = domAttribute.domJIT) {
3535         callDOMGetterData->domJIT = domJIT;
3536         Ref<DOMJIT::CallDOMGetterSnippet> snippet = domJIT->compiler()();
3537         callDOMGetterData->snippet = snippet.ptr();
3538         m_graph.m_domJITSnippets.append(WTFMove(snippet));
3539     }
3540     DOMJIT::CallDOMGetterSnippet* callDOMGetterSnippet = callDOMGetterData->snippet;
3541     callDOMGetterData->identifierNumber = identifierNumber;
3542
3543     Node* callDOMGetterNode = nullptr;
3544     // GlobalObject of thisNode is always used to create a DOMWrapper.
3545     if (callDOMGetterSnippet && callDOMGetterSnippet->requireGlobalObject) {
3546         Node* globalObject = addToGraph(GetGlobalObject, thisNode);
3547         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode, globalObject);
3548     } else
3549         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode);
3550     blessCallDOMGetter(callDOMGetterNode);
3551     set(result, callDOMGetterNode);
3552     return true;
3553 }
3554
3555 bool ByteCodeParser::handleModuleNamespaceLoad(VirtualRegister result, SpeculatedType prediction, Node* base, GetByIdStatus getById)
3556 {
3557     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
3558         return false;
3559     addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
3560
3561     addToGraph(FilterGetByIdStatus, OpInfo(m_graph.m_plan.recordedStatuses().addGetByIdStatus(currentCodeOrigin(), getById)), base);
3562
3563     // Ideally we wouldn't have to do this Phantom. But:
3564     //
3565     // For the constant case: we must do it because otherwise we would have no way of knowing
3566     // that the scope is live at OSR here.
3567     //
3568     // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
3569     // won't be able to handle an Undefined scope.
3570     addToGraph(Phantom, base);
3571
3572     // Constant folding in the bytecode parser is important for performance. This may not
3573     // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
3574     // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
3575     // would recompile. But if we can fold it here, we avoid the exit.
3576     m_graph.freeze(getById.moduleEnvironment());
3577     if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
3578         set(result, weakJSConstant(value));
3579         return true;
3580     }
3581     set(result, addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
3582     return true;
3583 }
3584
3585 template<typename ChecksFunctor>
3586 bool ByteCodeParser::handleTypedArrayConstructor(
3587     VirtualRegister result, InternalFunction* function, int registerOffset,
3588     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
3589 {
3590     if (!isTypedView(type))
3591         return false;
3592     
3593     if (function->classInfo() != constructorClassInfoForType(type))
3594         return false;
3595     
3596     if (function->globalObject(*m_vm) != m_inlineStackTop->m_codeBlock->globalObject())
3597         return false;
3598     
3599     // We only have an intrinsic for the case where you say:
3600     //
3601     // new FooArray(blah);
3602     //
3603     // Of course, 'blah' could be any of the following:
3604     //
3605     // - Integer, indicating that you want to allocate an array of that length.
3606     //   This is the thing we're hoping for, and what we can actually do meaningful
3607     //   optimizations for.
3608     //
3609     // - Array buffer, indicating that you want to create a view onto that _entire_
3610     //   buffer.
3611     //
3612     // - Non-buffer object, indicating that you want to create a copy of that
3613     //   object by pretending that it quacks like an array.
3614     //
3615     // - Anything else, indicating that you want to have an exception thrown at
3616     //   you.
3617     //
3618     // The intrinsic, NewTypedArray, will behave as if it could do any of these
3619     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
3620     // predicted Int32, then we lock it in as a normal typed array allocation.
3621     // Otherwise, NewTypedArray turns into a totally opaque function call that
3622     // may clobber the world - by virtue of it accessing properties on what could
3623     // be an object.
3624     //
3625     // Note that although the generic form of NewTypedArray sounds sort of awful,
3626     // it is actually quite likely to be more efficient than a fully generic
3627     // Construct. So, we might want to think about making NewTypedArray variadic,
3628     // or else making Construct not super slow.
3629     
3630     if (argumentCountIncludingThis != 2)
3631         return false;
3632     
3633     if (!function->globalObject(*m_vm)->typedArrayStructureConcurrently(type))
3634         return false;
3635
3636     insertChecks();
3637     set(result,
3638         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
3639     return true;
3640 }
3641
3642 template<typename ChecksFunctor>
3643 bool ByteCodeParser::handleConstantInternalFunction(
3644     Node* callTargetNode, VirtualRegister result, InternalFunction* function, int registerOffset,
3645     int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3646 {
3647     VERBOSE_LOG("    Handling constant internal function ", JSValue(function), "\n");
3648     
3649     // It so happens that the code below assumes that the result operand is valid. It's extremely
3650     // unlikely that the result operand would&