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