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