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