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