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