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