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