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