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