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