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