DFG::VarargsForwardingPhase should eliminate getting argument length
[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 OSRExitIntrinsic: {
2784         insertChecks();
2785         addToGraph(ForceOSRExit);
2786         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2787         return true;
2788     }
2789         
2790     case IsFinalTierIntrinsic: {
2791         insertChecks();
2792         set(VirtualRegister(resultOperand),
2793             jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
2794         return true;
2795     }
2796         
2797     case SetInt32HeapPredictionIntrinsic: {
2798         insertChecks();
2799         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2800             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2801             if (node->hasHeapPrediction())
2802                 node->setHeapPrediction(SpecInt32Only);
2803         }
2804         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2805         return true;
2806     }
2807         
2808     case CheckInt32Intrinsic: {
2809         insertChecks();
2810         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2811             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2812             addToGraph(Phantom, Edge(node, Int32Use));
2813         }
2814         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2815         return true;
2816     }
2817         
2818     case FiatInt52Intrinsic: {
2819         if (argumentCountIncludingThis != 2)
2820             return false;
2821         insertChecks();
2822         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2823         if (enableInt52())
2824             set(VirtualRegister(resultOperand), addToGraph(FiatInt52, get(operand)));
2825         else
2826             set(VirtualRegister(resultOperand), get(operand));
2827         return true;
2828     }
2829
2830     case JSMapGetIntrinsic: {
2831         if (argumentCountIncludingThis != 2)
2832             return false;
2833
2834         insertChecks();
2835         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2836         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2837         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2838         Node* hash = addToGraph(MapHash, normalizedKey);
2839         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(normalizedKey), Edge(hash));
2840         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2841         set(VirtualRegister(resultOperand), result);
2842         return true;
2843     }
2844
2845     case JSSetHasIntrinsic:
2846     case JSMapHasIntrinsic: {
2847         if (argumentCountIncludingThis != 2)
2848             return false;
2849
2850         insertChecks();
2851         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
2852         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2853         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2854         Node* hash = addToGraph(MapHash, normalizedKey);
2855         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
2856         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(normalizedKey), Edge(hash));
2857         JSCell* sentinel = nullptr;
2858         if (intrinsic == JSMapHasIntrinsic)
2859             sentinel = m_vm->sentinelMapBucket.get();
2860         else
2861             sentinel = m_vm->sentinelSetBucket.get();
2862
2863         FrozenValue* frozenPointer = m_graph.freeze(sentinel);
2864         Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
2865         Node* result = addToGraph(LogicalNot, invertedResult);
2866         set(VirtualRegister(resultOperand), result);
2867         return true;
2868     }
2869
2870     case JSSetAddIntrinsic: {
2871         if (argumentCountIncludingThis != 2)
2872             return false;
2873
2874         insertChecks();
2875         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2876         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2877         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2878         Node* hash = addToGraph(MapHash, normalizedKey);
2879         addToGraph(SetAdd, base, normalizedKey, hash);
2880         set(VirtualRegister(resultOperand), base);
2881         return true;
2882     }
2883
2884     case JSMapSetIntrinsic: {
2885         if (argumentCountIncludingThis != 3)
2886             return false;
2887
2888         insertChecks();
2889         Node* base = get(virtualRegisterForArgument(0, registerOffset));
2890         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2891         Node* value = get(virtualRegisterForArgument(2, registerOffset));
2892
2893         Node* normalizedKey = addToGraph(NormalizeMapKey, key);
2894         Node* hash = addToGraph(MapHash, normalizedKey);
2895
2896         addVarArgChild(base);
2897         addVarArgChild(normalizedKey);
2898         addVarArgChild(value);
2899         addVarArgChild(hash);
2900         addToGraph(Node::VarArg, MapSet, OpInfo(0), OpInfo(0));
2901         set(VirtualRegister(resultOperand), base);
2902         return true;
2903     }
2904
2905     case JSSetBucketHeadIntrinsic:
2906     case JSMapBucketHeadIntrinsic: {
2907         ASSERT(argumentCountIncludingThis == 2);
2908
2909         insertChecks();
2910         Node* map = get(virtualRegisterForArgument(1, registerOffset));
2911         UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
2912         Node* result = addToGraph(GetMapBucketHead, Edge(map, useKind));
2913         set(VirtualRegister(resultOperand), result);
2914         return true;
2915     }
2916
2917     case JSSetBucketNextIntrinsic:
2918     case JSMapBucketNextIntrinsic: {
2919         ASSERT(argumentCountIncludingThis == 2);
2920
2921         insertChecks();
2922         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2923         BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2924         Node* result = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
2925         set(VirtualRegister(resultOperand), result);
2926         return true;
2927     }
2928
2929     case JSSetBucketKeyIntrinsic:
2930     case JSMapBucketKeyIntrinsic: {
2931         ASSERT(argumentCountIncludingThis == 2);
2932
2933         insertChecks();
2934         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2935         BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
2936         Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
2937         set(VirtualRegister(resultOperand), result);
2938         return true;
2939     }
2940
2941     case JSMapBucketValueIntrinsic: {
2942         ASSERT(argumentCountIncludingThis == 2);
2943
2944         insertChecks();
2945         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
2946         Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
2947         set(VirtualRegister(resultOperand), result);
2948         return true;
2949     }
2950
2951     case JSWeakMapGetIntrinsic: {
2952         if (argumentCountIncludingThis != 2)
2953             return false;
2954
2955         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2956             return false;
2957
2958         insertChecks();
2959         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2960         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2961         addToGraph(Check, Edge(key, ObjectUse));
2962         Node* hash = addToGraph(MapHash, key);
2963         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
2964         Node* result = addToGraph(ExtractValueFromWeakMapGet, OpInfo(), OpInfo(prediction), holder);
2965
2966         set(VirtualRegister(resultOperand), result);
2967         return true;
2968     }
2969
2970     case JSWeakMapHasIntrinsic: {
2971         if (argumentCountIncludingThis != 2)
2972             return false;
2973
2974         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2975             return false;
2976
2977         insertChecks();
2978         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2979         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2980         addToGraph(Check, Edge(key, ObjectUse));
2981         Node* hash = addToGraph(MapHash, key);
2982         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakMapObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
2983         Node* invertedResult = addToGraph(IsEmpty, holder);
2984         Node* result = addToGraph(LogicalNot, invertedResult);
2985
2986         set(VirtualRegister(resultOperand), result);
2987         return true;
2988     }
2989
2990     case JSWeakSetHasIntrinsic: {
2991         if (argumentCountIncludingThis != 2)
2992             return false;
2993
2994         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2995             return false;
2996
2997         insertChecks();
2998         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2999         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3000         addToGraph(Check, Edge(key, ObjectUse));
3001         Node* hash = addToGraph(MapHash, key);
3002         Node* holder = addToGraph(WeakMapGet, Edge(map, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3003         Node* invertedResult = addToGraph(IsEmpty, holder);
3004         Node* result = addToGraph(LogicalNot, invertedResult);
3005
3006         set(VirtualRegister(resultOperand), result);
3007         return true;
3008     }
3009
3010     case JSWeakSetAddIntrinsic: {
3011         if (argumentCountIncludingThis != 2)
3012             return false;
3013
3014         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3015             return false;
3016
3017         insertChecks();
3018         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3019         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3020         addToGraph(Check, Edge(key, ObjectUse));
3021         Node* hash = addToGraph(MapHash, key);
3022         addToGraph(WeakSetAdd, Edge(base, WeakSetObjectUse), Edge(key, ObjectUse), Edge(hash, Int32Use));
3023         set(VirtualRegister(resultOperand), base);
3024         return true;
3025     }
3026
3027     case JSWeakMapSetIntrinsic: {
3028         if (argumentCountIncludingThis != 3)
3029             return false;
3030
3031         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3032             return false;
3033
3034         insertChecks();
3035         Node* base = get(virtualRegisterForArgument(0, registerOffset));
3036         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3037         Node* value = get(virtualRegisterForArgument(2, registerOffset));
3038
3039         addToGraph(Check, Edge(key, ObjectUse));
3040         Node* hash = addToGraph(MapHash, key);
3041
3042         addVarArgChild(Edge(base, WeakMapObjectUse));
3043         addVarArgChild(Edge(key, ObjectUse));
3044         addVarArgChild(Edge(value));
3045         addVarArgChild(Edge(hash, Int32Use));
3046         addToGraph(Node::VarArg, WeakMapSet, OpInfo(0), OpInfo(0));
3047         set(VirtualRegister(resultOperand), base);
3048         return true;
3049     }
3050
3051     case HasOwnPropertyIntrinsic: {
3052         if (argumentCountIncludingThis != 2)
3053             return false;
3054
3055         // This can be racy, that's fine. We know that once we observe that this is created,
3056         // that it will never be destroyed until the VM is destroyed. It's unlikely that
3057         // we'd ever get to the point where we inline this as an intrinsic without the
3058         // cache being created, however, it's possible if we always throw exceptions inside
3059         // hasOwnProperty.
3060         if (!m_vm->hasOwnPropertyCache())
3061             return false;
3062
3063         insertChecks();
3064         Node* object = get(virtualRegisterForArgument(0, registerOffset));
3065         Node* key = get(virtualRegisterForArgument(1, registerOffset));
3066         Node* result = addToGraph(HasOwnProperty, object, key);
3067         set(VirtualRegister(resultOperand), result);
3068         return true;
3069     }
3070
3071     case StringPrototypeSliceIntrinsic: {
3072         if (argumentCountIncludingThis < 2)
3073             return false;
3074
3075         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3076             return false;
3077
3078         insertChecks();
3079         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3080         Node* start = get(virtualRegisterForArgument(1, registerOffset));
3081         Node* end = nullptr;
3082         if (argumentCountIncludingThis > 2)
3083             end = get(virtualRegisterForArgument(2, registerOffset));
3084         Node* result = addToGraph(StringSlice, thisString, start, end);
3085         set(VirtualRegister(resultOperand), result);
3086         return true;
3087     }
3088
3089     case StringPrototypeToLowerCaseIntrinsic: {
3090         if (argumentCountIncludingThis != 1)
3091             return false;
3092
3093         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3094             return false;
3095
3096         insertChecks();
3097         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
3098         Node* result = addToGraph(ToLowerCase, thisString);
3099         set(VirtualRegister(resultOperand), result);
3100         return true;
3101     }
3102
3103     case NumberPrototypeToStringIntrinsic: {
3104         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
3105             return false;
3106
3107         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3108             return false;
3109
3110         insertChecks();
3111         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
3112         if (argumentCountIncludingThis == 1) {
3113             Node* result = addToGraph(ToString, thisNumber);
3114             set(VirtualRegister(resultOperand), result);
3115         } else {
3116             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
3117             Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix);
3118             set(VirtualRegister(resultOperand), result);
3119         }
3120         return true;
3121     }
3122
3123     case CPUMfenceIntrinsic:
3124     case CPURdtscIntrinsic:
3125     case CPUCpuidIntrinsic:
3126     case CPUPauseIntrinsic: {
3127 #if CPU(X86_64)
3128         if (!isFTL(m_graph.m_plan.mode))
3129             return false;
3130         insertChecks();
3131         set(VirtualRegister(resultOperand),
3132             addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
3133         return true;
3134 #else
3135         return false;
3136 #endif
3137     }
3138
3139
3140     default:
3141         return false;
3142     }
3143 }
3144
3145 template<typename ChecksFunctor>
3146 bool ByteCodeParser::handleDOMJITCall(Node* callTarget, int resultOperand, const DOMJIT::Signature* signature, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3147 {
3148     if (argumentCountIncludingThis != static_cast<int>(1 + signature->argumentCount))
3149         return false;
3150     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
3151         return false;
3152
3153     // FIXME: Currently, we only support functions which arguments are up to 2.
3154     // Eventually, we should extend this. But possibly, 2 or 3 can cover typical use cases.
3155     // https://bugs.webkit.org/show_bug.cgi?id=164346
3156     ASSERT_WITH_MESSAGE(argumentCountIncludingThis <= JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS, "Currently CallDOM does not support an arbitrary length arguments.");
3157
3158     insertChecks();
3159     addCall(resultOperand, Call, signature, callTarget, argumentCountIncludingThis, registerOffset, prediction);
3160     return true;
3161 }
3162
3163
3164 template<typename ChecksFunctor>
3165 bool ByteCodeParser::handleIntrinsicGetter(int resultOperand, SpeculatedType prediction, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
3166 {
3167     switch (variant.intrinsic()) {
3168     case TypedArrayByteLengthIntrinsic: {
3169         insertChecks();
3170
3171         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3172         Array::Type arrayType = toArrayType(type);
3173         size_t logSize = logElementSize(type);
3174
3175         variant.structureSet().forEach([&] (Structure* structure) {
3176             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3177             ASSERT(logSize == logElementSize(curType));
3178             arrayType = refineTypedArrayType(arrayType, curType);
3179             ASSERT(arrayType != Array::Generic);
3180         });
3181
3182         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode);
3183
3184         if (!logSize) {
3185             set(VirtualRegister(resultOperand), lengthNode);
3186             return true;
3187         }
3188
3189         // We can use a BitLShift here because typed arrays will never have a byteLength
3190         // that overflows int32.
3191         Node* shiftNode = jsConstant(jsNumber(logSize));
3192         set(VirtualRegister(resultOperand), addToGraph(BitLShift, lengthNode, shiftNode));
3193
3194         return true;
3195     }
3196
3197     case TypedArrayLengthIntrinsic: {
3198         insertChecks();
3199
3200         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3201         Array::Type arrayType = toArrayType(type);
3202
3203         variant.structureSet().forEach([&] (Structure* structure) {
3204             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3205             arrayType = refineTypedArrayType(arrayType, curType);
3206             ASSERT(arrayType != Array::Generic);
3207         });
3208
3209         set(VirtualRegister(resultOperand), addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
3210
3211         return true;
3212
3213     }
3214
3215     case TypedArrayByteOffsetIntrinsic: {
3216         insertChecks();
3217
3218         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
3219         Array::Type arrayType = toArrayType(type);
3220
3221         variant.structureSet().forEach([&] (Structure* structure) {
3222             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
3223             arrayType = refineTypedArrayType(arrayType, curType);
3224             ASSERT(arrayType != Array::Generic);
3225         });
3226
3227         set(VirtualRegister(resultOperand), addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
3228
3229         return true;
3230     }
3231
3232     case UnderscoreProtoIntrinsic: {
3233         insertChecks();
3234
3235         bool canFold = !variant.structureSet().isEmpty();
3236         JSValue prototype;
3237         variant.structureSet().forEach([&] (Structure* structure) {
3238             auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
3239             MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
3240             if (getPrototypeMethod != defaultGetPrototype) {
3241                 canFold = false;
3242                 return;
3243             }
3244
3245             if (structure->hasPolyProto()) {
3246                 canFold = false;
3247                 return;
3248             }
3249             if (!prototype)
3250                 prototype = structure->storedPrototype();
3251             else if (prototype != structure->storedPrototype())
3252                 canFold = false;
3253         });
3254
3255         // OK, only one prototype is found. We perform constant folding here.
3256         // This information is important for super's constructor call to get new.target constant.
3257         if (prototype && canFold) {
3258             set(VirtualRegister(resultOperand), weakJSConstant(prototype));
3259             return true;
3260         }
3261
3262         set(VirtualRegister(resultOperand), addToGraph(GetPrototypeOf, OpInfo(0), OpInfo(prediction), thisNode));
3263         return true;
3264     }
3265
3266     default:
3267         return false;
3268     }
3269     RELEASE_ASSERT_NOT_REACHED();
3270 }
3271
3272 static void blessCallDOMGetter(Node* node)
3273 {
3274     DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
3275     if (snippet && !snippet->effect.mustGenerate())
3276         node->clearFlags(NodeMustGenerate);
3277 }
3278
3279 bool ByteCodeParser::handleDOMJITGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction)
3280 {
3281     if (!variant.domAttribute())
3282         return false;
3283
3284     auto domAttribute = variant.domAttribute().value();
3285
3286     // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough,
3287     // since replacement of CustomGetterSetter always incurs Structure transition.
3288     if (!check(variant.conditionSet()))
3289         return false;
3290     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
3291
3292     // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
3293     addToGraph(CheckSubClass, OpInfo(domAttribute.classInfo), thisNode);
3294
3295     CallDOMGetterData* callDOMGetterData = m_graph.m_callDOMGetterData.add();
3296     callDOMGetterData->customAccessorGetter = variant.customAccessorGetter();
3297     ASSERT(callDOMGetterData->customAccessorGetter);
3298
3299     if (const auto* domJIT = domAttribute.domJIT) {
3300         callDOMGetterData->domJIT = domJIT;
3301         Ref<DOMJIT::CallDOMGetterSnippet> snippet = domJIT->compiler()();
3302         callDOMGetterData->snippet = snippet.ptr();
3303         m_graph.m_domJITSnippets.append(WTFMove(snippet));
3304     }
3305     DOMJIT::CallDOMGetterSnippet* callDOMGetterSnippet = callDOMGetterData->snippet;
3306     callDOMGetterData->identifierNumber = identifierNumber;
3307
3308     Node* callDOMGetterNode = nullptr;
3309     // GlobalObject of thisNode is always used to create a DOMWrapper.
3310     if (callDOMGetterSnippet && callDOMGetterSnippet->requireGlobalObject) {
3311         Node* globalObject = addToGraph(GetGlobalObject, thisNode);
3312         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode, globalObject);
3313     } else
3314         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode);
3315     blessCallDOMGetter(callDOMGetterNode);
3316     set(VirtualRegister(resultOperand), callDOMGetterNode);
3317     return true;
3318 }
3319
3320 bool ByteCodeParser::handleModuleNamespaceLoad(int resultOperand, SpeculatedType prediction, Node* base, GetByIdStatus getById)
3321 {
3322     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
3323         return false;
3324     addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
3325
3326     // Ideally we wouldn't have to do this Phantom. But:
3327     //
3328     // For the constant case: we must do it because otherwise we would have no way of knowing
3329     // that the scope is live at OSR here.
3330     //
3331     // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
3332     // won't be able to handle an Undefined scope.
3333     addToGraph(Phantom, base);
3334
3335     // Constant folding in the bytecode parser is important for performance. This may not
3336     // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
3337     // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
3338     // would recompile. But if we can fold it here, we avoid the exit.
3339     m_graph.freeze(getById.moduleEnvironment());
3340     if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
3341         set(VirtualRegister(resultOperand), weakJSConstant(value));
3342         return true;
3343     }
3344     set(VirtualRegister(resultOperand), addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
3345     return true;
3346 }
3347
3348 template<typename ChecksFunctor>
3349 bool ByteCodeParser::handleTypedArrayConstructor(
3350     int resultOperand, InternalFunction* function, int registerOffset,
3351     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
3352 {
3353     if (!isTypedView(type))
3354         return false;
3355     
3356     if (function->classInfo() != constructorClassInfoForType(type))
3357         return false;
3358     
3359     if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
3360         return false;
3361     
3362     // We only have an intrinsic for the case where you say:
3363     //
3364     // new FooArray(blah);
3365     //
3366     // Of course, 'blah' could be any of the following:
3367     //
3368     // - Integer, indicating that you want to allocate an array of that length.
3369     //   This is the thing we're hoping for, and what we can actually do meaningful
3370     //   optimizations for.
3371     //
3372     // - Array buffer, indicating that you want to create a view onto that _entire_
3373     //   buffer.
3374     //
3375     // - Non-buffer object, indicating that you want to create a copy of that
3376     //   object by pretending that it quacks like an array.
3377     //
3378     // - Anything else, indicating that you want to have an exception thrown at
3379     //   you.
3380     //
3381     // The intrinsic, NewTypedArray, will behave as if it could do any of these
3382     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
3383     // predicted Int32, then we lock it in as a normal typed array allocation.
3384     // Otherwise, NewTypedArray turns into a totally opaque function call that
3385     // may clobber the world - by virtue of it accessing properties on what could
3386     // be an object.
3387     //
3388     // Note that although the generic form of NewTypedArray sounds sort of awful,
3389     // it is actually quite likely to be more efficient than a fully generic
3390     // Construct. So, we might want to think about making NewTypedArray variadic,
3391     // or else making Construct not super slow.
3392     
3393     if (argumentCountIncludingThis != 2)
3394         return false;
3395     
3396     if (!function->globalObject()->typedArrayStructureConcurrently(type))
3397         return false;
3398
3399     insertChecks();
3400     set(VirtualRegister(resultOperand),
3401         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
3402     return true;
3403 }
3404
3405 template<typename ChecksFunctor>
3406 bool ByteCodeParser::handleConstantInternalFunction(
3407     Node* callTargetNode, int resultOperand, InternalFunction* function, int registerOffset,
3408     int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks)
3409 {
3410     VERBOSE_LOG("    Handling constant internal function ", JSValue(function), "\n");
3411     
3412     // It so happens that the code below assumes that the result operand is valid. It's extremely
3413     // unlikely that the result operand would be invalid - you'd have to call this via a setter call.
3414     if (!VirtualRegister(resultOperand).isValid())
3415         return false;
3416
3417     if (kind == CodeForConstruct) {
3418         Node* newTargetNode = get(virtualRegisterForArgument(0, registerOffset));
3419         // We cannot handle the case where new.target != callee (i.e. a construct from a super call) because we
3420         // don't know what the prototype of the constructed object will be.
3421         // 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
3422         if (newTargetNode != callTargetNode)
3423             return false;
3424     }
3425
3426     if (function->classInfo() == ArrayConstructor::info()) {
3427         if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
3428             return false;
3429         
3430         insertChecks();
3431         if (argumentCountIncludingThis == 2) {
3432             set(VirtualRegister(resultOperand),
3433                 addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(virtualRegisterForArgument(1, registerOffset))));
3434             return true;
3435         }
3436         
3437         for (int i = 1; i < argumentCountIncludingThis; ++i)
3438             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
3439         set(VirtualRegister(resultOperand),
3440             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
3441         return true;
3442     }
3443
3444     if (function->classInfo() == NumberConstructor::info()) {
3445         if (kind == CodeForConstruct)
3446             return false;
3447
3448         insertChecks();
3449         if (argumentCountIncludingThis <= 1)
3450             set(VirtualRegister(resultOperand), jsConstant(jsNumber(0)));
3451         else
3452             set(VirtualRegister(resultOperand), addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
3453
3454         return true;
3455     }
3456     
3457     if (function->classInfo() == StringConstructor::info()) {
3458         insertChecks();
3459         
3460         Node* result;
3461         
3462         if (argumentCountIncludingThis <= 1)
3463             result = jsConstant(m_vm->smallStrings.emptyString());
3464         else
3465             result = addToGraph(CallStringConstructor, get(virtualRegisterForArgument(1, registerOffset)));
3466         
3467         if (kind == CodeForConstruct)
3468             result = addToGraph(NewStringObject, OpInfo(m_graph.registerStructure(function->globalObject()->stringObjectStructure())), result);
3469         
3470         set(VirtualRegister(resultOperand), result);
3471         return true;
3472     }
3473
3474     // FIXME: This should handle construction as well. https://bugs.webkit.org/show_bug.cgi?id=155591
3475     if (function->classInfo() == ObjectConstructor::info() && kind == CodeForCall) {
3476         insertChecks();
3477
3478         Node* result;
3479         if (argumentCountIncludingThis <= 1)
3480             result = addToGraph(NewObject, OpInfo(m_graph.registerStructure(function->globalObject()->objectStructureForObjectConstructor())));
3481         else
3482             result = addToGraph(CallObjectConstructor, OpInfo(m_graph.freeze(function->globalObject())), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset)));
3483         set(VirtualRegister(resultOperand), result);
3484         return true;
3485     }
3486
3487     for (unsigned typeIndex = 0; typeIndex < NumberOfTypedArrayTypes; ++typeIndex) {
3488         bool result = handleTypedArrayConstructor(
3489             resultOperand, function, registerOffset, argumentCountIncludingThis,
3490             indexToTypedArrayType(typeIndex), insertChecks);
3491         if (result)
3492             return true;
3493     }
3494     
3495     return false;
3496 }
3497
3498 Node* ByteCodeParser::handleGetByOffset(
3499     SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
3500     const InferredType::Descriptor& inferredType, NodeType op)
3501 {
3502     Node* propertyStorage;
3503     if (isInlineOffset(offset))
3504         propertyStorage = base;
3505     else
3506         propertyStorage = addToGraph(GetButterfly, base);
3507     
3508     StorageAccessData* data = m_graph.m_storageAccessData.add();
3509     data->offset = offset;
3510     data->identifierNumber = identifierNumber;
3511     data->inferredType = inferredType;
3512     m_graph.registerInferredType(inferredType);
3513     
3514     Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
3515
3516     return getByOffset;
3517 }
3518
3519 Node* ByteCodeParser::handlePutByOffset(
3520     Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
3521     Node* value)
3522 {
3523     Node* propertyStorage;
3524     if (isInlineOffset(offset))
3525         propertyStorage = base;
3526     else
3527         propertyStorage = addToGraph(GetButterfly, base);
3528     
3529     StorageAccessData* data = m_graph.m_storageAccessData.add();
3530     data->offset = offset;
3531     data->identifierNumber = identifier;
3532     data->inferredType = inferredType;
3533     m_graph.registerInferredType(inferredType);
3534     
3535     Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
3536     
3537     return result;
3538 }
3539
3540 bool ByteCodeParser::check(const ObjectPropertyCondition& condition)
3541 {
3542     if (!condition)
3543         return false;
3544     
3545     if (m_graph.watchCondition(condition))
3546         return true;
3547     
3548     Structure* structure = condition.object()->structure();
3549     if (!condition.structureEnsuresValidity(structure))
3550         return false;
3551     
3552     addToGraph(
3553         CheckStructure,
3554         OpInfo(m_graph.addStructureSet(structure)),
3555         weakJSConstant(condition.object()));
3556     return true;
3557 }
3558
3559 GetByOffsetMethod ByteCodeParser::promoteToConstant(GetByOffsetMethod method)
3560 {
3561     if (method.kind() == GetByOffsetMethod::LoadFromPrototype
3562         && method.prototype()->structure()->dfgShouldWatch()) {
3563         if (JSValue constant = m_graph.tryGetConstantProperty(method.prototype()->value(), method.prototype()->structure(), method.offset()))
3564             return GetByOffsetMethod::constant(m_graph.freeze(constant));
3565     }
3566     
3567     return method;
3568 }
3569
3570 bool ByteCodeParser::needsDynamicLookup(ResolveType type, OpcodeID opcode)
3571 {
3572     ASSERT(opcode == op_resolve_scope || opcode == op_get_from_scope || opcode == op_put_to_scope);
3573
3574     JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
3575     if (needsVarInjectionChecks(type) && globalObject->varInjectionWatchpoint()->hasBeenInvalidated())
3576         return true;
3577
3578     switch (type) {
3579     case GlobalProperty:
3580     case GlobalVar:
3581     case GlobalLexicalVar:
3582     case ClosureVar:
3583     case LocalClosureVar:
3584     case ModuleVar:
3585         return false;
3586
3587     case UnresolvedProperty:
3588     case UnresolvedPropertyWithVarInjectionChecks: {
3589         // The heuristic for UnresolvedProperty scope accesses is we will ForceOSRExit if we
3590         // haven't exited from from this access before to let the baseline JIT try to better
3591         // cache the access. If we've already exited from this operation, it's unlikely that
3592         // the baseline will come up with a better ResolveType and instead we will compile
3593         // this as a dynamic scope access.
3594
3595         // We only track our heuristic through resolve_scope since resolve_scope will
3596         // dominate unresolved gets/puts on that scope.
3597         if (opcode != op_resolve_scope)
3598             return true;
3599
3600         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, InadequateCoverage)) {
3601             // We've already exited so give up on getting better ResolveType information.
3602             return true;
3603         }
3604
3605         // We have not exited yet, so let's have the baseline get better ResolveType information for us.
3606         // This type of code is often seen when we tier up in a loop but haven't executed the part
3607         // of a function that comes after the loop.
3608         return false;
3609     }
3610
3611     case Dynamic:
3612         return true;
3613
3614     case GlobalPropertyWithVarInjectionChecks:
3615     case GlobalVarWithVarInjectionChecks:
3616     case GlobalLexicalVarWithVarInjectionChecks:
3617     case ClosureVarWithVarInjectionChecks:
3618         return false;
3619     }
3620
3621     ASSERT_NOT_REACHED();
3622     return false;
3623 }
3624
3625 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyCondition& condition)
3626 {
3627     VERBOSE_LOG("Planning a load: ", condition, "\n");
3628     
3629     // We might promote this to Equivalence, and a later DFG pass might also do such promotion
3630     // even if we fail, but for simplicity this cannot be asked to load an equivalence condition.
3631     // None of the clients of this method will request a load of an Equivalence condition anyway,
3632     // and supporting it would complicate the heuristics below.
3633     RELEASE_ASSERT(condition.kind() == PropertyCondition::Presence);
3634     
3635     // Here's the ranking of how to handle this, from most preferred to least preferred:
3636     //
3637     // 1) Watchpoint on an equivalence condition and return a constant node for the loaded value.
3638     //    No other code is emitted, and the structure of the base object is never registered.
3639     //    Hence this results in zero code and we won't jettison this compilation if the object
3640     //    transitions, even if the structure is watchable right now.
3641     //
3642     // 2) Need to emit a load,