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