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