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