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