b8e199ad1754cb6742dcdcd04bcae3804bf50674
[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 = 0;
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, thisArgument);
1387 }
1388
1389 Node* ByteCodeParser::getArgumentCount()
1390 {
1391     Node* argumentCount;
1392     if (m_inlineStackTop->m_inlineCallFrame) {
1393         if (m_inlineStackTop->m_inlineCallFrame->isVarargs())
1394             argumentCount = get(VirtualRegister(CallFrameSlot::argumentCount));
1395         else
1396             argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->arguments.size()))->value());
1397     } else
1398         argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(0), OpInfo(SpecInt32Only));
1399     return argumentCount;
1400 }
1401
1402 void ByteCodeParser::emitArgumentPhantoms(int registerOffset, int argumentCountIncludingThis)
1403 {
1404     for (int i = 0; i < argumentCountIncludingThis; ++i)
1405         addToGraph(Phantom, get(virtualRegisterForArgument(i, registerOffset)));
1406 }
1407
1408 unsigned ByteCodeParser::inliningCost(CallVariant callee, int argumentCountIncludingThis, CallMode callMode)
1409 {
1410     CodeSpecializationKind kind = specializationKindFor(callMode);
1411     if (verbose)
1412         dataLog("Considering inlining ", callee, " into ", currentCodeOrigin(), "\n");
1413     
1414     if (m_hasDebuggerEnabled) {
1415         if (verbose)
1416             dataLog("    Failing because the debugger is in use.\n");
1417         return UINT_MAX;
1418     }
1419
1420     FunctionExecutable* executable = callee.functionExecutable();
1421     if (!executable) {
1422         if (verbose)
1423             dataLog("    Failing because there is no function executable.\n");
1424         return UINT_MAX;
1425     }
1426     
1427     // Do we have a code block, and does the code block's size match the heuristics/requirements for
1428     // being an inline candidate? We might not have a code block (1) if code was thrown away,
1429     // (2) if we simply hadn't actually made this call yet or (3) code is a builtin function and
1430     // specialization kind is construct. In the former 2 cases, we could still theoretically attempt
1431     // to inline it if we had a static proof of what was being called; this might happen for example
1432     // if you call a global function, where watchpointing gives us static information. Overall,
1433     // it's a rare case because we expect that any hot callees would have already been compiled.
1434     CodeBlock* codeBlock = executable->baselineCodeBlockFor(kind);
1435     if (!codeBlock) {
1436         if (verbose)
1437             dataLog("    Failing because no code block available.\n");
1438         return UINT_MAX;
1439     }
1440
1441     // Does the number of arguments we're passing match the arity of the target? We currently
1442     // inline only if the number of arguments passed is greater than or equal to the number
1443     // arguments expected.
1444     if (codeBlock->numParameters() > argumentCountIncludingThis) {
1445         if (verbose)
1446             dataLog("    Failing because of arity mismatch.\n");
1447         return UINT_MAX;
1448     }
1449
1450     CapabilityLevel capabilityLevel = inlineFunctionForCapabilityLevel(
1451         codeBlock, kind, callee.isClosureCall());
1452     if (verbose) {
1453         dataLog("    Call mode: ", callMode, "\n");
1454         dataLog("    Is closure call: ", callee.isClosureCall(), "\n");
1455         dataLog("    Capability level: ", capabilityLevel, "\n");
1456         dataLog("    Might inline function: ", mightInlineFunctionFor(codeBlock, kind), "\n");
1457         dataLog("    Might compile function: ", mightCompileFunctionFor(codeBlock, kind), "\n");
1458         dataLog("    Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n");
1459         dataLog("    Is inlining candidate: ", codeBlock->ownerScriptExecutable()->isInliningCandidate(), "\n");
1460     }
1461     if (!canInline(capabilityLevel)) {
1462         if (verbose)
1463             dataLog("    Failing because the function is not inlineable.\n");
1464         return UINT_MAX;
1465     }
1466     
1467     // Check if the caller is already too large. We do this check here because that's just
1468     // where we happen to also have the callee's code block, and we want that for the
1469     // purpose of unsetting SABI.
1470     if (!isSmallEnoughToInlineCodeInto(m_codeBlock)) {
1471         codeBlock->m_shouldAlwaysBeInlined = false;
1472         if (verbose)
1473             dataLog("    Failing because the caller is too large.\n");
1474         return UINT_MAX;
1475     }
1476     
1477     // FIXME: this should be better at predicting how much bloat we will introduce by inlining
1478     // this function.
1479     // https://bugs.webkit.org/show_bug.cgi?id=127627
1480     
1481     // FIXME: We currently inline functions that have run in LLInt but not in Baseline. These
1482     // functions have very low fidelity profiling, and presumably they weren't very hot if they
1483     // haven't gotten to Baseline yet. Consider not inlining these functions.
1484     // https://bugs.webkit.org/show_bug.cgi?id=145503
1485     
1486     // Have we exceeded inline stack depth, or are we trying to inline a recursive call to
1487     // too many levels? If either of these are detected, then don't inline. We adjust our
1488     // heuristics if we are dealing with a function that cannot otherwise be compiled.
1489     
1490     unsigned depth = 0;
1491     unsigned recursion = 0;
1492     
1493     for (InlineStackEntry* entry = m_inlineStackTop; entry; entry = entry->m_caller) {
1494         ++depth;
1495         if (depth >= Options::maximumInliningDepth()) {
1496             if (verbose)
1497                 dataLog("    Failing because depth exceeded.\n");
1498             return UINT_MAX;
1499         }
1500         
1501         if (entry->executable() == executable) {
1502             ++recursion;
1503             if (recursion >= Options::maximumInliningRecursion()) {
1504                 if (verbose)
1505                     dataLog("    Failing because recursion detected.\n");
1506                 return UINT_MAX;
1507             }
1508         }
1509     }
1510     
1511     if (verbose)
1512         dataLog("    Inlining should be possible.\n");
1513     
1514     // It might be possible to inline.
1515     return codeBlock->instructionCount();
1516 }
1517
1518 template<typename ChecksFunctor>
1519 void ByteCodeParser::inlineCall(Node* callTargetNode, int resultOperand, CallVariant callee, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, InlineCallFrame::Kind kind, CallerLinkability callerLinkability, const ChecksFunctor& insertChecks)
1520 {
1521     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1522     
1523     ASSERT(inliningCost(callee, argumentCountIncludingThis, InlineCallFrame::callModeFor(kind)) != UINT_MAX);
1524     
1525     CodeBlock* codeBlock = callee.functionExecutable()->baselineCodeBlockFor(specializationKind);
1526     insertChecks(codeBlock);
1527
1528     // FIXME: Don't flush constants!
1529     
1530     int inlineCallFrameStart = m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset() + CallFrame::headerSizeInRegisters;
1531     
1532     ensureLocals(
1533         VirtualRegister(inlineCallFrameStart).toLocal() + 1 +
1534         CallFrame::headerSizeInRegisters + codeBlock->m_numCalleeLocals);
1535     
1536     size_t argumentPositionStart = m_graph.m_argumentPositions.size();
1537
1538     VirtualRegister resultReg(resultOperand);
1539     if (resultReg.isValid())
1540         resultReg = m_inlineStackTop->remapOperand(resultReg);
1541
1542     VariableAccessData* calleeVariable = nullptr;
1543     if (callee.isClosureCall()) {
1544         Node* calleeSet = set(
1545             VirtualRegister(registerOffset + CallFrameSlot::callee), callTargetNode, ImmediateNakedSet);
1546         
1547         calleeVariable = calleeSet->variableAccessData();
1548         calleeVariable->mergeShouldNeverUnbox(true);
1549     }
1550     
1551     InlineStackEntry inlineStackEntry(
1552         this, codeBlock, codeBlock, m_graph.lastBlock(), callee.function(), resultReg,
1553         (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
1554     
1555     // This is where the actual inlining really happens.
1556     unsigned oldIndex = m_currentIndex;
1557     m_currentIndex = 0;
1558
1559     // At this point, it's again OK to OSR exit.
1560     m_exitOK = true;
1561
1562     InlineVariableData inlineVariableData;
1563     inlineVariableData.inlineCallFrame = m_inlineStackTop->m_inlineCallFrame;
1564     inlineVariableData.argumentPositionStart = argumentPositionStart;
1565     inlineVariableData.calleeVariable = 0;
1566     
1567     RELEASE_ASSERT(
1568         m_inlineStackTop->m_inlineCallFrame->isClosureCall
1569         == callee.isClosureCall());
1570     if (callee.isClosureCall()) {
1571         RELEASE_ASSERT(calleeVariable);
1572         inlineVariableData.calleeVariable = calleeVariable;
1573     }
1574     
1575     m_graph.m_inlineVariableData.append(inlineVariableData);
1576
1577     parseCodeBlock();
1578     clearCaches(); // Reset our state now that we're back to the outer code.
1579     
1580     m_currentIndex = oldIndex;
1581     m_exitOK = false;
1582     
1583     // If the inlined code created some new basic blocks, then we have linking to do.
1584     if (inlineStackEntry.m_callsiteBlockHead != m_graph.lastBlock()) {
1585         
1586         ASSERT(!inlineStackEntry.m_unlinkedBlocks.isEmpty());
1587         if (inlineStackEntry.m_callsiteBlockHeadNeedsLinking)
1588             linkBlock(inlineStackEntry.m_callsiteBlockHead, inlineStackEntry.m_blockLinkingTargets);
1589         else
1590             ASSERT(inlineStackEntry.m_callsiteBlockHead->isLinked);
1591         
1592         if (callerLinkability == CallerDoesNormalLinking)
1593             cancelLinkingForBlock(inlineStackEntry.m_caller, inlineStackEntry.m_callsiteBlockHead);
1594         
1595         linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
1596     } else
1597         ASSERT(inlineStackEntry.m_unlinkedBlocks.isEmpty());
1598     
1599     BasicBlock* lastBlock = m_graph.lastBlock();
1600     // If there was a return, but no early returns, then we're done. We allow parsing of
1601     // the caller to continue in whatever basic block we're in right now.
1602     if (!inlineStackEntry.m_didEarlyReturn && inlineStackEntry.m_didReturn) {
1603         if (Options::verboseDFGByteCodeParsing())
1604             dataLog("    Allowing parsing to continue in last inlined block.\n");
1605         
1606         ASSERT(lastBlock->isEmpty() || !lastBlock->terminal());
1607         
1608         // If we created new blocks then the last block needs linking, but in the
1609         // caller. It doesn't need to be linked to, but it needs outgoing links.
1610         if (!inlineStackEntry.m_unlinkedBlocks.isEmpty()) {
1611             // For debugging purposes, set the bytecodeBegin. Note that this doesn't matter
1612             // for release builds because this block will never serve as a potential target
1613             // in the linker's binary search.
1614             if (Options::verboseDFGByteCodeParsing())
1615                 dataLog("        Repurposing last block from ", lastBlock->bytecodeBegin, " to ", m_currentIndex, "\n");
1616             lastBlock->bytecodeBegin = m_currentIndex;
1617             if (callerLinkability == CallerDoesNormalLinking) {
1618                 if (verbose)
1619                     dataLog("Adding unlinked block ", RawPointer(m_graph.lastBlock()), " (one return)\n");
1620                 m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(m_graph.lastBlock()));
1621             }
1622         }
1623         
1624         m_currentBlock = m_graph.lastBlock();
1625         return;
1626     }
1627
1628     if (Options::verboseDFGByteCodeParsing())
1629         dataLog("    Creating new block after inlining.\n");
1630
1631     // If we get to this point then all blocks must end in some sort of terminals.
1632     ASSERT(lastBlock->terminal());
1633
1634     // Need to create a new basic block for the continuation at the caller.
1635     Ref<BasicBlock> block = adoptRef(*new BasicBlock(nextOffset, m_numArguments, m_numLocals, 1));
1636
1637     // Link the early returns to the basic block we're about to create.
1638     for (size_t i = 0; i < inlineStackEntry.m_unlinkedBlocks.size(); ++i) {
1639         if (!inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking)
1640             continue;
1641         BasicBlock* blockToLink = inlineStackEntry.m_unlinkedBlocks[i].m_block;
1642         ASSERT(!blockToLink->isLinked);
1643         Node* node = blockToLink->terminal();
1644         ASSERT(node->op() == Jump);
1645         ASSERT(!node->targetBlock());
1646         node->targetBlock() = block.ptr();
1647         inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking = false;
1648         if (verbose)
1649             dataLog("Marking ", RawPointer(blockToLink), " as linked (jumps to return)\n");
1650         blockToLink->didLink();
1651     }
1652     
1653     m_currentBlock = block.ptr();
1654     ASSERT(m_inlineStackTop->m_caller->m_blockLinkingTargets.isEmpty() || m_inlineStackTop->m_caller->m_blockLinkingTargets.last()->bytecodeBegin < nextOffset);
1655     if (verbose)
1656         dataLog("Adding unlinked block ", RawPointer(block.ptr()), " (many returns)\n");
1657     if (callerLinkability == CallerDoesNormalLinking) {
1658         m_inlineStackTop->m_caller->m_unlinkedBlocks.append(UnlinkedBlock(block.ptr()));
1659         m_inlineStackTop->m_caller->m_blockLinkingTargets.append(block.ptr());
1660     }
1661     m_graph.appendBlock(WTFMove(block));
1662     prepareToParseBlock();
1663 }
1664
1665 void ByteCodeParser::cancelLinkingForBlock(InlineStackEntry* inlineStackEntry, BasicBlock* block)
1666 {
1667     // It's possible that the callsite block head is not owned by the caller.
1668     if (!inlineStackEntry->m_unlinkedBlocks.isEmpty()) {
1669         // It's definitely owned by the caller, because the caller created new blocks.
1670         // Assert that this all adds up.
1671         ASSERT_UNUSED(block, inlineStackEntry->m_unlinkedBlocks.last().m_block == block);
1672         ASSERT(inlineStackEntry->m_unlinkedBlocks.last().m_needsNormalLinking);
1673         inlineStackEntry->m_unlinkedBlocks.last().m_needsNormalLinking = false;
1674     } else {
1675         // It's definitely not owned by the caller. Tell the caller that he does not
1676         // need to link his callsite block head, because we did it for him.
1677         ASSERT(inlineStackEntry->m_callsiteBlockHeadNeedsLinking);
1678         ASSERT_UNUSED(block, inlineStackEntry->m_callsiteBlockHead == block);
1679         inlineStackEntry->m_callsiteBlockHeadNeedsLinking = false;
1680     }
1681 }
1682
1683 template<typename ChecksFunctor>
1684 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)
1685 {
1686     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1687     
1688     if (!inliningBalance)
1689         return false;
1690     
1691     if (verbose)
1692         dataLog("    Considering callee ", callee, "\n");
1693     
1694     // Intrinsics and internal functions can only be inlined if we're not doing varargs. This is because
1695     // we currently don't have any way of getting profiling information for arguments to non-JS varargs
1696     // calls. The prediction propagator won't be of any help because LoadVarargs obscures the data flow,
1697     // and there are no callsite value profiles and native function won't have callee value profiles for
1698     // those arguments. Even worse, if the intrinsic decides to exit, it won't really have anywhere to
1699     // exit to: LoadVarargs is effectful and it's part of the op_call_varargs, so we can't exit without
1700     // calling LoadVarargs twice.
1701     if (!InlineCallFrame::isVarargs(kind)) {
1702
1703         bool didInsertChecks = false;
1704         auto insertChecksWithAccounting = [&] () {
1705             insertChecks(nullptr);
1706             didInsertChecks = true;
1707         };
1708     
1709         if (InternalFunction* function = callee.internalFunction()) {
1710             if (handleConstantInternalFunction(callTargetNode, resultOperand, function, registerOffset, argumentCountIncludingThis, specializationKind, prediction, insertChecksWithAccounting)) {
1711                 RELEASE_ASSERT(didInsertChecks);
1712                 addToGraph(Phantom, callTargetNode);
1713                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1714                 inliningBalance--;
1715                 return true;
1716             }
1717             RELEASE_ASSERT(!didInsertChecks);
1718             return false;
1719         }
1720     
1721         Intrinsic intrinsic = callee.intrinsicFor(specializationKind);
1722         if (intrinsic != NoIntrinsic) {
1723             if (handleIntrinsicCall(callTargetNode, resultOperand, intrinsic, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1724                 RELEASE_ASSERT(didInsertChecks);
1725                 addToGraph(Phantom, callTargetNode);
1726                 emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1727                 inliningBalance--;
1728                 return true;
1729             }
1730
1731             RELEASE_ASSERT(!didInsertChecks);
1732             // We might still try to inline the Intrinsic because it might be a builtin JS function.
1733         }
1734
1735         if (Options::useDOMJIT()) {
1736             if (const DOMJIT::Signature* signature = callee.signatureFor(specializationKind)) {
1737                 if (handleDOMJITCall(callTargetNode, resultOperand, signature, registerOffset, argumentCountIncludingThis, prediction, insertChecksWithAccounting)) {
1738                     RELEASE_ASSERT(didInsertChecks);
1739                     addToGraph(Phantom, callTargetNode);
1740                     emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
1741                     inliningBalance--;
1742                     return true;
1743                 }
1744                 RELEASE_ASSERT(!didInsertChecks);
1745             }
1746         }
1747     }
1748     
1749     unsigned myInliningCost = inliningCost(callee, argumentCountIncludingThis, InlineCallFrame::callModeFor(kind));
1750     if (myInliningCost > inliningBalance)
1751         return false;
1752
1753     Instruction* savedCurrentInstruction = m_currentInstruction;
1754     inlineCall(callTargetNode, resultOperand, callee, registerOffset, argumentCountIncludingThis, nextOffset, kind, callerLinkability, insertChecks);
1755     inliningBalance -= myInliningCost;
1756     m_currentInstruction = savedCurrentInstruction;
1757     return true;
1758 }
1759
1760 bool ByteCodeParser::handleInlining(
1761     Node* callTargetNode, int resultOperand, const CallLinkStatus& callLinkStatus,
1762     int registerOffsetOrFirstFreeReg, VirtualRegister thisArgument,
1763     VirtualRegister argumentsArgument, unsigned argumentsOffset, int argumentCountIncludingThis,
1764     unsigned nextOffset, NodeType callOp, InlineCallFrame::Kind kind, SpeculatedType prediction)
1765 {
1766     if (verbose) {
1767         dataLog("Handling inlining...\n");
1768         dataLog("Stack: ", currentCodeOrigin(), "\n");
1769     }
1770     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
1771     
1772     if (!callLinkStatus.size()) {
1773         if (verbose)
1774             dataLog("Bailing inlining.\n");
1775         return false;
1776     }
1777     
1778     if (InlineCallFrame::isVarargs(kind)
1779         && callLinkStatus.maxNumArguments() > Options::maximumVarargsForInlining()) {
1780         if (verbose)
1781             dataLog("Bailing inlining because of varargs.\n");
1782         return false;
1783     }
1784         
1785     unsigned inliningBalance = Options::maximumFunctionForCallInlineCandidateInstructionCount();
1786     if (specializationKind == CodeForConstruct)
1787         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForConstructInlineCandidateInstructionCount());
1788     if (callLinkStatus.isClosureCall())
1789         inliningBalance = std::min(inliningBalance, Options::maximumFunctionForClosureCallInlineCandidateInstructionCount());
1790     
1791     // First check if we can avoid creating control flow. Our inliner does some CFG
1792     // simplification on the fly and this helps reduce compile times, but we can only leverage
1793     // this in cases where we don't need control flow diamonds to check the callee.
1794     if (!callLinkStatus.couldTakeSlowPath() && callLinkStatus.size() == 1) {
1795         int registerOffset;
1796         
1797         // Only used for varargs calls.
1798         unsigned mandatoryMinimum = 0;
1799         unsigned maxNumArguments = 0;
1800
1801         if (InlineCallFrame::isVarargs(kind)) {
1802             if (FunctionExecutable* functionExecutable = callLinkStatus[0].functionExecutable())
1803                 mandatoryMinimum = functionExecutable->parameterCount();
1804             else
1805                 mandatoryMinimum = 0;
1806             
1807             // includes "this"
1808             maxNumArguments = std::max(
1809                 callLinkStatus.maxNumArguments(),
1810                 mandatoryMinimum + 1);
1811             
1812             // We sort of pretend that this *is* the number of arguments that were passed.
1813             argumentCountIncludingThis = maxNumArguments;
1814             
1815             registerOffset = registerOffsetOrFirstFreeReg + 1;
1816             registerOffset -= maxNumArguments; // includes "this"
1817             registerOffset -= CallFrame::headerSizeInRegisters;
1818             registerOffset = -WTF::roundUpToMultipleOf(
1819                 stackAlignmentRegisters(),
1820                 -registerOffset);
1821         } else
1822             registerOffset = registerOffsetOrFirstFreeReg;
1823         
1824         bool result = attemptToInlineCall(
1825             callTargetNode, resultOperand, callLinkStatus[0], registerOffset,
1826             argumentCountIncludingThis, nextOffset, kind, CallerDoesNormalLinking, prediction,
1827             inliningBalance, [&] (CodeBlock* codeBlock) {
1828                 emitFunctionChecks(callLinkStatus[0], callTargetNode, thisArgument);
1829
1830                 // If we have a varargs call, we want to extract the arguments right now.
1831                 if (InlineCallFrame::isVarargs(kind)) {
1832                     int remappedRegisterOffset =
1833                         m_inlineStackTop->remapOperand(VirtualRegister(registerOffset)).offset();
1834                     
1835                     ensureLocals(VirtualRegister(remappedRegisterOffset).toLocal());
1836                     
1837                     int argumentStart = registerOffset + CallFrame::headerSizeInRegisters;
1838                     int remappedArgumentStart =
1839                         m_inlineStackTop->remapOperand(VirtualRegister(argumentStart)).offset();
1840
1841                     LoadVarargsData* data = m_graph.m_loadVarargsData.add();
1842                     data->start = VirtualRegister(remappedArgumentStart + 1);
1843                     data->count = VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount);
1844                     data->offset = argumentsOffset;
1845                     data->limit = maxNumArguments;
1846                     data->mandatoryMinimum = mandatoryMinimum;
1847
1848                     if (callOp == TailCallForwardVarargs)
1849                         addToGraph(ForwardVarargs, OpInfo(data));
1850                     else
1851                         addToGraph(LoadVarargs, OpInfo(data), get(argumentsArgument));
1852
1853                     // LoadVarargs may OSR exit. Hence, we need to keep alive callTargetNode, thisArgument
1854                     // and argumentsArgument for the baseline JIT. However, we only need a Phantom for
1855                     // callTargetNode because the other 2 are still in use and alive at this point.
1856                     addToGraph(Phantom, callTargetNode);
1857
1858                     // In DFG IR before SSA, we cannot insert control flow between after the
1859                     // LoadVarargs and the last SetArgument. This isn't a problem once we get to DFG
1860                     // SSA. Fortunately, we also have other reasons for not inserting control flow
1861                     // before SSA.
1862             
1863                     VariableAccessData* countVariable = newVariableAccessData(
1864                         VirtualRegister(remappedRegisterOffset + CallFrameSlot::argumentCount));
1865                     // This is pretty lame, but it will force the count to be flushed as an int. This doesn't
1866                     // matter very much, since our use of a SetArgument and Flushes for this local slot is
1867                     // mostly just a formality.
1868                     countVariable->predict(SpecInt32Only);
1869                     countVariable->mergeIsProfitableToUnbox(true);
1870                     Node* setArgumentCount = addToGraph(SetArgument, OpInfo(countVariable));
1871                     m_currentBlock->variablesAtTail.setOperand(countVariable->local(), setArgumentCount);
1872
1873                     set(VirtualRegister(argumentStart), get(thisArgument), ImmediateNakedSet);
1874                     for (unsigned argument = 1; argument < maxNumArguments; ++argument) {
1875                         VariableAccessData* variable = newVariableAccessData(
1876                             VirtualRegister(remappedArgumentStart + argument));
1877                         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.
1878                         
1879                         // For a while it had been my intention to do things like this inside the
1880                         // prediction injection phase. But in this case it's really best to do it here,
1881                         // because it's here that we have access to the variable access datas for the
1882                         // inlining we're about to do.
1883                         //
1884                         // Something else that's interesting here is that we'd really love to get
1885                         // predictions from the arguments loaded at the callsite, rather than the
1886                         // arguments received inside the callee. But that probably won't matter for most
1887                         // calls.
1888                         if (codeBlock && argument < static_cast<unsigned>(codeBlock->numParameters())) {
1889                             ConcurrentJSLocker locker(codeBlock->m_lock);
1890                             if (ValueProfile* profile = codeBlock->valueProfileForArgument(argument))
1891                                 variable->predict(profile->computeUpdatedPrediction(locker));
1892                         }
1893                         
1894                         Node* setArgument = addToGraph(SetArgument, OpInfo(variable));
1895                         m_currentBlock->variablesAtTail.setOperand(variable->local(), setArgument);
1896                     }
1897                 }
1898             });
1899         if (verbose) {
1900             dataLog("Done inlining (simple).\n");
1901             dataLog("Stack: ", currentCodeOrigin(), "\n");
1902             dataLog("Result: ", result, "\n");
1903         }
1904         return result;
1905     }
1906     
1907     // We need to create some kind of switch over callee. For now we only do this if we believe that
1908     // we're in the top tier. We have two reasons for this: first, it provides us an opportunity to
1909     // do more detailed polyvariant/polymorphic profiling; and second, it reduces compile times in
1910     // the DFG. And by polyvariant profiling we mean polyvariant profiling of *this* call. Note that
1911     // we could improve that aspect of this by doing polymorphic inlining but having the profiling
1912     // also.
1913     if (!isFTL(m_graph.m_plan.mode) || !Options::usePolymorphicCallInlining()
1914         || InlineCallFrame::isVarargs(kind)) {
1915         if (verbose) {
1916             dataLog("Bailing inlining (hard).\n");
1917             dataLog("Stack: ", currentCodeOrigin(), "\n");
1918         }
1919         return false;
1920     }
1921     
1922     // If the claim is that this did not originate from a stub, then we don't want to emit a switch
1923     // statement. Whenever the non-stub profiling says that it could take slow path, it really means that
1924     // it has no idea.
1925     if (!Options::usePolymorphicCallInliningForNonStubStatus()
1926         && !callLinkStatus.isBasedOnStub()) {
1927         if (verbose) {
1928             dataLog("Bailing inlining (non-stub polymorphism).\n");
1929             dataLog("Stack: ", currentCodeOrigin(), "\n");
1930         }
1931         return false;
1932     }
1933     
1934     unsigned oldOffset = m_currentIndex;
1935     
1936     bool allAreClosureCalls = true;
1937     bool allAreDirectCalls = true;
1938     for (unsigned i = callLinkStatus.size(); i--;) {
1939         if (callLinkStatus[i].isClosureCall())
1940             allAreDirectCalls = false;
1941         else
1942             allAreClosureCalls = false;
1943     }
1944     
1945     Node* thingToSwitchOn;
1946     if (allAreDirectCalls)
1947         thingToSwitchOn = callTargetNode;
1948     else if (allAreClosureCalls)
1949         thingToSwitchOn = addToGraph(GetExecutable, callTargetNode);
1950     else {
1951         // FIXME: We should be able to handle this case, but it's tricky and we don't know of cases
1952         // where it would be beneficial. It might be best to handle these cases as if all calls were
1953         // closure calls.
1954         // https://bugs.webkit.org/show_bug.cgi?id=136020
1955         if (verbose) {
1956             dataLog("Bailing inlining (mix).\n");
1957             dataLog("Stack: ", currentCodeOrigin(), "\n");
1958         }
1959         return false;
1960     }
1961     
1962     if (verbose) {
1963         dataLog("Doing hard inlining...\n");
1964         dataLog("Stack: ", currentCodeOrigin(), "\n");
1965     }
1966     
1967     int registerOffset = registerOffsetOrFirstFreeReg;
1968     
1969     // This makes me wish that we were in SSA all the time. We need to pick a variable into which to
1970     // store the callee so that it will be accessible to all of the blocks we're about to create. We
1971     // get away with doing an immediate-set here because we wouldn't have performed any side effects
1972     // yet.
1973     if (verbose)
1974         dataLog("Register offset: ", registerOffset);
1975     VirtualRegister calleeReg(registerOffset + CallFrameSlot::callee);
1976     calleeReg = m_inlineStackTop->remapOperand(calleeReg);
1977     if (verbose)
1978         dataLog("Callee is going to be ", calleeReg, "\n");
1979     setDirect(calleeReg, callTargetNode, ImmediateSetWithFlush);
1980
1981     // It's OK to exit right now, even though we set some locals. That's because those locals are not
1982     // user-visible.
1983     m_exitOK = true;
1984     addToGraph(ExitOK);
1985     
1986     SwitchData& data = *m_graph.m_switchData.add();
1987     data.kind = SwitchCell;
1988     addToGraph(Switch, OpInfo(&data), thingToSwitchOn);
1989     
1990     BasicBlock* originBlock = m_currentBlock;
1991     if (verbose)
1992         dataLog("Marking ", RawPointer(originBlock), " as linked (origin of poly inline)\n");
1993     originBlock->didLink();
1994     cancelLinkingForBlock(m_inlineStackTop, originBlock);
1995     
1996     // Each inlined callee will have a landing block that it returns at. They should all have jumps
1997     // to the continuation block, which we create last.
1998     Vector<BasicBlock*> landingBlocks;
1999     
2000     // We may force this true if we give up on inlining any of the edges.
2001     bool couldTakeSlowPath = callLinkStatus.couldTakeSlowPath();
2002     
2003     if (verbose)
2004         dataLog("About to loop over functions at ", currentCodeOrigin(), ".\n");
2005     
2006     for (unsigned i = 0; i < callLinkStatus.size(); ++i) {
2007         m_currentIndex = oldOffset;
2008         Ref<BasicBlock> block = adoptRef(*new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
2009         m_currentBlock = block.ptr();
2010         m_graph.appendBlock(block.copyRef());
2011         prepareToParseBlock();
2012         
2013         Node* myCallTargetNode = getDirect(calleeReg);
2014         
2015         bool inliningResult = attemptToInlineCall(
2016             myCallTargetNode, resultOperand, callLinkStatus[i], registerOffset,
2017             argumentCountIncludingThis, nextOffset, kind, CallerLinksManually, prediction,
2018             inliningBalance, [&] (CodeBlock*) { });
2019         
2020         if (!inliningResult) {
2021             // That failed so we let the block die. Nothing interesting should have been added to
2022             // the block. We also give up on inlining any of the (less frequent) callees.
2023             ASSERT(m_currentBlock == block.ptr());
2024             ASSERT(m_graph.m_blocks.last() == block.ptr());
2025             m_graph.killBlockAndItsContents(block.ptr());
2026             m_graph.m_blocks.removeLast();
2027             
2028             // The fact that inlining failed means we need a slow path.
2029             couldTakeSlowPath = true;
2030             break;
2031         }
2032         
2033         JSCell* thingToCaseOn;
2034         if (allAreDirectCalls)
2035             thingToCaseOn = callLinkStatus[i].nonExecutableCallee();
2036         else {
2037             ASSERT(allAreClosureCalls);
2038             thingToCaseOn = callLinkStatus[i].executable();
2039         }
2040         data.cases.append(SwitchCase(m_graph.freeze(thingToCaseOn), block.ptr()));
2041         m_currentIndex = nextOffset;
2042         m_exitOK = true;
2043         processSetLocalQueue(); // This only comes into play for intrinsics, since normal inlined code will leave an empty queue.
2044         if (Node* terminal = m_currentBlock->terminal())
2045             ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
2046         else {
2047             addToGraph(Jump);
2048             landingBlocks.append(m_currentBlock);
2049         }
2050         if (verbose)
2051             dataLog("Marking ", RawPointer(m_currentBlock), " as linked (tail of poly inlinee)\n");
2052         m_currentBlock->didLink();
2053
2054         if (verbose)
2055             dataLog("Finished inlining ", callLinkStatus[i], " at ", currentCodeOrigin(), ".\n");
2056     }
2057     
2058     Ref<BasicBlock> slowPathBlock = adoptRef(
2059         *new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
2060     m_currentIndex = oldOffset;
2061     m_exitOK = true;
2062     data.fallThrough = BranchTarget(slowPathBlock.ptr());
2063     m_graph.appendBlock(slowPathBlock.copyRef());
2064     if (verbose)
2065         dataLog("Marking ", RawPointer(slowPathBlock.ptr()), " as linked (slow path block)\n");
2066     slowPathBlock->didLink();
2067     prepareToParseBlock();
2068     m_currentBlock = slowPathBlock.ptr();
2069     Node* myCallTargetNode = getDirect(calleeReg);
2070     if (couldTakeSlowPath) {
2071         addCall(
2072             resultOperand, callOp, nullptr, myCallTargetNode, argumentCountIncludingThis,
2073             registerOffset, prediction);
2074     } else {
2075         addToGraph(CheckBadCell);
2076         addToGraph(Phantom, myCallTargetNode);
2077         emitArgumentPhantoms(registerOffset, argumentCountIncludingThis);
2078         
2079         set(VirtualRegister(resultOperand), addToGraph(BottomValue));
2080     }
2081
2082     m_currentIndex = nextOffset;
2083     m_exitOK = true; // Origin changed, so it's fine to exit again.
2084     processSetLocalQueue();
2085     if (Node* terminal = m_currentBlock->terminal())
2086         ASSERT_UNUSED(terminal, terminal->op() == TailCall || terminal->op() == TailCallVarargs || terminal->op() == TailCallForwardVarargs);
2087     else {
2088         addToGraph(Jump);
2089         landingBlocks.append(m_currentBlock);
2090     }
2091     
2092     Ref<BasicBlock> continuationBlock = adoptRef(
2093         *new BasicBlock(UINT_MAX, m_numArguments, m_numLocals, 1));
2094     m_graph.appendBlock(continuationBlock.copyRef());
2095     if (verbose)
2096         dataLog("Adding unlinked block ", RawPointer(continuationBlock.ptr()), " (continuation)\n");
2097     m_inlineStackTop->m_unlinkedBlocks.append(UnlinkedBlock(continuationBlock.ptr()));
2098     prepareToParseBlock();
2099     m_currentBlock = continuationBlock.ptr();
2100     
2101     for (unsigned i = landingBlocks.size(); i--;)
2102         landingBlocks[i]->terminal()->targetBlock() = continuationBlock.ptr();
2103     
2104     m_currentIndex = oldOffset;
2105     m_exitOK = true;
2106     
2107     if (verbose) {
2108         dataLog("Done inlining (hard).\n");
2109         dataLog("Stack: ", currentCodeOrigin(), "\n");
2110     }
2111     return true;
2112 }
2113
2114 template<typename ChecksFunctor>
2115 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis, const ChecksFunctor& insertChecks)
2116 {
2117     ASSERT(op == ArithMin || op == ArithMax);
2118
2119     if (argumentCountIncludingThis == 1) {
2120         insertChecks();
2121         double result = op == ArithMax ? -std::numeric_limits<double>::infinity() : +std::numeric_limits<double>::infinity();
2122         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsDoubleNumber(result)))));
2123         return true;
2124     }
2125      
2126     if (argumentCountIncludingThis == 2) {
2127         insertChecks();
2128         Node* result = get(VirtualRegister(virtualRegisterForArgument(1, registerOffset)));
2129         addToGraph(Phantom, Edge(result, NumberUse));
2130         set(VirtualRegister(resultOperand), result);
2131         return true;
2132     }
2133     
2134     if (argumentCountIncludingThis == 3) {
2135         insertChecks();
2136         set(VirtualRegister(resultOperand), addToGraph(op, get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset))));
2137         return true;
2138     }
2139     
2140     // Don't handle >=3 arguments for now.
2141     return false;
2142 }
2143
2144 template<typename ChecksFunctor>
2145 bool ByteCodeParser::handleIntrinsicCall(Node* callee, int resultOperand, Intrinsic intrinsic, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2146 {
2147     switch (intrinsic) {
2148
2149     // Intrinsic Functions:
2150
2151     case AbsIntrinsic: {
2152         if (argumentCountIncludingThis == 1) { // Math.abs()
2153             insertChecks();
2154             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2155             return true;
2156         }
2157
2158         if (!MacroAssembler::supportsFloatingPointAbs())
2159             return false;
2160
2161         insertChecks();
2162         Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
2163         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
2164             node->mergeFlags(NodeMayOverflowInt32InDFG);
2165         set(VirtualRegister(resultOperand), node);
2166         return true;
2167     }
2168
2169     case MinIntrinsic:
2170         return handleMinMax(resultOperand, ArithMin, registerOffset, argumentCountIncludingThis, insertChecks);
2171         
2172     case MaxIntrinsic:
2173         return handleMinMax(resultOperand, ArithMax, registerOffset, argumentCountIncludingThis, insertChecks);
2174
2175     case CosIntrinsic:
2176     case FRoundIntrinsic:
2177     case LogIntrinsic:
2178     case SinIntrinsic:
2179     case SqrtIntrinsic:
2180     case TanIntrinsic: {
2181         if (argumentCountIncludingThis == 1) {
2182             insertChecks();
2183             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2184             return true;
2185         }
2186
2187         NodeType nodeType = Unreachable;
2188         switch (intrinsic) {
2189         case CosIntrinsic:
2190             nodeType = ArithCos;
2191             break;
2192         case FRoundIntrinsic:
2193             nodeType = ArithFRound;
2194             break;
2195         case LogIntrinsic:
2196             nodeType = ArithLog;
2197             break;
2198         case SinIntrinsic:
2199             nodeType = ArithSin;
2200             break;
2201         case SqrtIntrinsic:
2202             nodeType = ArithSqrt;
2203             break;
2204         case TanIntrinsic:
2205             nodeType = ArithTan;
2206             break;
2207         default:
2208             RELEASE_ASSERT_NOT_REACHED();
2209         }
2210         insertChecks();
2211         set(VirtualRegister(resultOperand), addToGraph(nodeType, get(virtualRegisterForArgument(1, registerOffset))));
2212         return true;
2213     }
2214
2215     case PowIntrinsic: {
2216         if (argumentCountIncludingThis < 3) {
2217             // Math.pow() and Math.pow(x) return NaN.
2218             insertChecks();
2219             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2220             return true;
2221         }
2222         insertChecks();
2223         VirtualRegister xOperand = virtualRegisterForArgument(1, registerOffset);
2224         VirtualRegister yOperand = virtualRegisterForArgument(2, registerOffset);
2225         set(VirtualRegister(resultOperand), addToGraph(ArithPow, get(xOperand), get(yOperand)));
2226         return true;
2227     }
2228         
2229     case ArrayPushIntrinsic: {
2230         if (argumentCountIncludingThis != 2)
2231             return false;
2232         
2233         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2234         if (!arrayMode.isJSArray())
2235             return false;
2236         switch (arrayMode.type()) {
2237         case Array::Int32:
2238         case Array::Double:
2239         case Array::Contiguous:
2240         case Array::ArrayStorage: {
2241             insertChecks();
2242             Node* arrayPush = addToGraph(ArrayPush, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2243             set(VirtualRegister(resultOperand), arrayPush);
2244             
2245             return true;
2246         }
2247             
2248         default:
2249             return false;
2250         }
2251     }
2252
2253     case ArraySliceIntrinsic: {
2254 #if USE(JSVALUE32_64)
2255         if (isX86() || isMIPS()) {
2256             // There aren't enough registers for this to be done easily.
2257             return false;
2258         }
2259 #endif
2260         if (argumentCountIncludingThis < 2)
2261             return false;
2262
2263         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadConstantCache)
2264             || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
2265             return false;
2266
2267         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2268         if (!arrayMode.isJSArray())
2269             return false;
2270
2271         if (arrayMode.arrayClass() != Array::OriginalArray)
2272             return false;
2273
2274         switch (arrayMode.type()) {
2275         case Array::Double:
2276         case Array::Int32:
2277         case Array::Contiguous: {
2278             JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
2279
2280             InlineWatchpointSet& objectPrototypeTransition = globalObject->objectPrototype()->structure()->transitionWatchpointSet();
2281             InlineWatchpointSet& arrayPrototypeTransition = globalObject->arrayPrototype()->structure()->transitionWatchpointSet();
2282
2283             // FIXME: We could easily relax the Array/Object.prototype transition as long as we OSR exitted if we saw a hole.
2284             if (globalObject->arraySpeciesWatchpoint().state() == IsWatched
2285                 && globalObject->havingABadTimeWatchpoint()->isStillValid()
2286                 && arrayPrototypeTransition.isStillValid()
2287                 && objectPrototypeTransition.isStillValid()
2288                 && globalObject->arrayPrototypeChainIsSane()) {
2289
2290                 m_graph.watchpoints().addLazily(globalObject->arraySpeciesWatchpoint());
2291                 m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
2292                 m_graph.watchpoints().addLazily(arrayPrototypeTransition);
2293                 m_graph.watchpoints().addLazily(objectPrototypeTransition);
2294
2295                 insertChecks();
2296
2297                 Node* array = get(virtualRegisterForArgument(0, registerOffset));
2298                 // We do a few things here to prove that we aren't skipping doing side-effects in an observable way:
2299                 // 1. We ensure that the "constructor" property hasn't been changed (because the observable
2300                 // effects of slice require that we perform a Get(array, "constructor") and we can skip
2301                 // that if we're an original array structure. (We can relax this in the future by using
2302                 // TryGetById and CheckCell).
2303                 //
2304                 // 2. We check that the array we're calling slice on has the same global object as the lexical
2305                 // global object that this code is running in. This requirement is necessary because we setup the
2306                 // watchpoints above on the lexical global object. This means that code that calls slice on
2307                 // arrays produced by other global objects won't get this optimization. We could relax this
2308                 // requirement in the future by checking that the watchpoint hasn't fired at runtime in the code
2309                 // we generate instead of registering it as a watchpoint that would invalidate the compilation.
2310                 //
2311                 // 3. By proving we're an original array structure, we guarantee that the incoming array
2312                 // isn't a subclass of Array.
2313
2314                 StructureSet structureSet;
2315                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32));
2316                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous));
2317                 structureSet.add(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble));
2318                 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), array);
2319
2320                 addVarArgChild(array);
2321                 addVarArgChild(get(virtualRegisterForArgument(1, registerOffset))); // Start index.
2322                 if (argumentCountIncludingThis >= 3)
2323                     addVarArgChild(get(virtualRegisterForArgument(2, registerOffset))); // End index.
2324                 addVarArgChild(addToGraph(GetButterfly, array));
2325
2326                 Node* arraySlice = addToGraph(Node::VarArg, ArraySlice, OpInfo(), OpInfo());
2327                 set(VirtualRegister(resultOperand), arraySlice);
2328                 return true;
2329             }
2330
2331             return false;
2332         }
2333         default:
2334             return false;
2335         }
2336
2337         RELEASE_ASSERT_NOT_REACHED();
2338         return false;
2339     }
2340         
2341     case ArrayPopIntrinsic: {
2342         if (argumentCountIncludingThis != 1)
2343             return false;
2344         
2345         ArrayMode arrayMode = getArrayMode(m_currentInstruction[OPCODE_LENGTH(op_call) - 2].u.arrayProfile);
2346         if (!arrayMode.isJSArray())
2347             return false;
2348         switch (arrayMode.type()) {
2349         case Array::Int32:
2350         case Array::Double:
2351         case Array::Contiguous:
2352         case Array::ArrayStorage: {
2353             insertChecks();
2354             Node* arrayPop = addToGraph(ArrayPop, OpInfo(arrayMode.asWord()), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)));
2355             set(VirtualRegister(resultOperand), arrayPop);
2356             return true;
2357         }
2358             
2359         default:
2360             return false;
2361         }
2362     }
2363
2364     case ParseIntIntrinsic: {
2365         if (argumentCountIncludingThis < 2)
2366             return false;
2367
2368         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2369             return false;
2370
2371         insertChecks();
2372         VirtualRegister valueOperand = virtualRegisterForArgument(1, registerOffset);
2373         Node* parseInt;
2374         if (argumentCountIncludingThis == 2)
2375             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand));
2376         else {
2377             ASSERT(argumentCountIncludingThis > 2);
2378             VirtualRegister radixOperand = virtualRegisterForArgument(2, registerOffset);
2379             parseInt = addToGraph(ParseInt, OpInfo(), OpInfo(prediction), get(valueOperand), get(radixOperand));
2380         }
2381         set(VirtualRegister(resultOperand), parseInt);
2382         return true;
2383     }
2384
2385     case CharCodeAtIntrinsic: {
2386         if (argumentCountIncludingThis != 2)
2387             return false;
2388
2389         insertChecks();
2390         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2391         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2392         Node* charCode = addToGraph(StringCharCodeAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2393
2394         set(VirtualRegister(resultOperand), charCode);
2395         return true;
2396     }
2397
2398     case CharAtIntrinsic: {
2399         if (argumentCountIncludingThis != 2)
2400             return false;
2401
2402         insertChecks();
2403         VirtualRegister thisOperand = virtualRegisterForArgument(0, registerOffset);
2404         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2405         Node* charCode = addToGraph(StringCharAt, OpInfo(ArrayMode(Array::String).asWord()), get(thisOperand), get(indexOperand));
2406
2407         set(VirtualRegister(resultOperand), charCode);
2408         return true;
2409     }
2410     case Clz32Intrinsic: {
2411         insertChecks();
2412         if (argumentCountIncludingThis == 1)
2413             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_graph.freeze(jsNumber(32)))));
2414         else {
2415             Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2416             set(VirtualRegister(resultOperand), addToGraph(ArithClz32, operand));
2417         }
2418         return true;
2419     }
2420     case FromCharCodeIntrinsic: {
2421         if (argumentCountIncludingThis != 2)
2422             return false;
2423
2424         insertChecks();
2425         VirtualRegister indexOperand = virtualRegisterForArgument(1, registerOffset);
2426         Node* charCode = addToGraph(StringFromCharCode, get(indexOperand));
2427
2428         set(VirtualRegister(resultOperand), charCode);
2429
2430         return true;
2431     }
2432
2433     case RegExpExecIntrinsic: {
2434         if (argumentCountIncludingThis != 2)
2435             return false;
2436         
2437         insertChecks();
2438         Node* regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)));
2439         set(VirtualRegister(resultOperand), regExpExec);
2440         
2441         return true;
2442     }
2443         
2444     case RegExpTestIntrinsic:
2445     case RegExpTestFastIntrinsic: {
2446         if (argumentCountIncludingThis != 2)
2447             return false;
2448
2449         if (intrinsic == RegExpTestIntrinsic) {
2450             // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2451             if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2452                 return false;
2453
2454             JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2455             Structure* regExpStructure = globalObject->regExpStructure();
2456             m_graph.registerStructure(regExpStructure);
2457             ASSERT(regExpStructure->storedPrototype().isObject());
2458             ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2459
2460             FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2461             Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2462
2463             auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2464                 JSValue currentProperty;
2465                 if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2466                     return false;
2467                 
2468                 return currentProperty == primordialProperty;
2469             };
2470
2471             // Check that RegExp.exec is still the primordial RegExp.prototype.exec
2472             if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2473                 return false;
2474
2475             // Check that regExpObject is actually a RegExp object.
2476             Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2477             addToGraph(Check, Edge(regExpObject, RegExpObjectUse));
2478
2479             // Check that regExpObject's exec is actually the primodial RegExp.prototype.exec.
2480             UniquedStringImpl* execPropertyID = m_vm->propertyNames->exec.impl();
2481             unsigned execIndex = m_graph.identifiers().ensure(execPropertyID);
2482             Node* actualProperty = addToGraph(TryGetById, OpInfo(execIndex), OpInfo(SpecFunction), Edge(regExpObject, CellUse));
2483             FrozenValue* regExpPrototypeExec = m_graph.freeze(globalObject->regExpProtoExecFunction());
2484             addToGraph(CheckCell, OpInfo(regExpPrototypeExec), Edge(actualProperty, CellUse));
2485         }
2486
2487         insertChecks();
2488         Node* regExpObject = get(virtualRegisterForArgument(0, registerOffset));
2489         Node* regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), addToGraph(GetGlobalObject, callee), regExpObject, get(virtualRegisterForArgument(1, registerOffset)));
2490         set(VirtualRegister(resultOperand), regExpExec);
2491         
2492         return true;
2493     }
2494
2495     case IsTypedArrayViewIntrinsic: {
2496         ASSERT(argumentCountIncludingThis == 2);
2497
2498         insertChecks();
2499         set(VirtualRegister(resultOperand), addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
2500         return true;
2501     }
2502
2503     case StringPrototypeReplaceIntrinsic: {
2504         if (argumentCountIncludingThis != 3)
2505             return false;
2506
2507         // Don't inline intrinsic if we exited due to "search" not being a RegExp or String object.
2508         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2509             return false;
2510
2511         // Don't inline intrinsic if we exited due to one of the primordial RegExp checks failing.
2512         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2513             return false;
2514
2515         JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
2516         Structure* regExpStructure = globalObject->regExpStructure();
2517         m_graph.registerStructure(regExpStructure);
2518         ASSERT(regExpStructure->storedPrototype().isObject());
2519         ASSERT(regExpStructure->storedPrototype().asCell()->classInfo(*m_vm) == RegExpPrototype::info());
2520
2521         FrozenValue* regExpPrototypeObjectValue = m_graph.freeze(regExpStructure->storedPrototype());
2522         Structure* regExpPrototypeStructure = regExpPrototypeObjectValue->structure();
2523
2524         auto isRegExpPropertySame = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
2525             JSValue currentProperty;
2526             if (!m_graph.getRegExpPrototypeProperty(regExpStructure->storedPrototypeObject(), regExpPrototypeStructure, propertyUID, currentProperty))
2527                 return false;
2528
2529             return currentProperty == primordialProperty;
2530         };
2531
2532         // Check that searchRegExp.exec is still the primordial RegExp.prototype.exec
2533         if (!isRegExpPropertySame(globalObject->regExpProtoExecFunction(), m_vm->propertyNames->exec.impl()))
2534             return false;
2535
2536         // Check that searchRegExp.global is still the primordial RegExp.prototype.global
2537         if (!isRegExpPropertySame(globalObject->regExpProtoGlobalGetter(), m_vm->propertyNames->global.impl()))
2538             return false;
2539
2540         // Check that searchRegExp.unicode is still the primordial RegExp.prototype.unicode
2541         if (!isRegExpPropertySame(globalObject->regExpProtoUnicodeGetter(), m_vm->propertyNames->unicode.impl()))
2542             return false;
2543
2544         // Check that searchRegExp[Symbol.match] is still the primordial RegExp.prototype[Symbol.replace]
2545         if (!isRegExpPropertySame(globalObject->regExpProtoSymbolReplaceFunction(), m_vm->propertyNames->replaceSymbol.impl()))
2546             return false;
2547
2548         insertChecks();
2549
2550         Node* result = addToGraph(StringReplace, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2551         set(VirtualRegister(resultOperand), result);
2552         return true;
2553     }
2554         
2555     case StringPrototypeReplaceRegExpIntrinsic: {
2556         if (argumentCountIncludingThis != 3)
2557             return false;
2558         
2559         insertChecks();
2560         Node* result = addToGraph(StringReplaceRegExp, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(0, registerOffset)), get(virtualRegisterForArgument(1, registerOffset)), get(virtualRegisterForArgument(2, registerOffset)));
2561         set(VirtualRegister(resultOperand), result);
2562         return true;
2563     }
2564         
2565     case RoundIntrinsic:
2566     case FloorIntrinsic:
2567     case CeilIntrinsic:
2568     case TruncIntrinsic: {
2569         if (argumentCountIncludingThis == 1) {
2570             insertChecks();
2571             set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
2572             return true;
2573         }
2574         insertChecks();
2575         Node* operand = get(virtualRegisterForArgument(1, registerOffset));
2576         NodeType op;
2577         if (intrinsic == RoundIntrinsic)
2578             op = ArithRound;
2579         else if (intrinsic == FloorIntrinsic)
2580             op = ArithFloor;
2581         else if (intrinsic == CeilIntrinsic)
2582             op = ArithCeil;
2583         else {
2584             ASSERT(intrinsic == TruncIntrinsic);
2585             op = ArithTrunc;
2586         }
2587         Node* roundNode = addToGraph(op, OpInfo(0), OpInfo(prediction), operand);
2588         set(VirtualRegister(resultOperand), roundNode);
2589         return true;
2590     }
2591     case IMulIntrinsic: {
2592         if (argumentCountIncludingThis != 3)
2593             return false;
2594         insertChecks();
2595         VirtualRegister leftOperand = virtualRegisterForArgument(1, registerOffset);
2596         VirtualRegister rightOperand = virtualRegisterForArgument(2, registerOffset);
2597         Node* left = get(leftOperand);
2598         Node* right = get(rightOperand);
2599         set(VirtualRegister(resultOperand), addToGraph(ArithIMul, left, right));
2600         return true;
2601     }
2602
2603     case RandomIntrinsic: {
2604         if (argumentCountIncludingThis != 1)
2605             return false;
2606         insertChecks();
2607         set(VirtualRegister(resultOperand), addToGraph(ArithRandom));
2608         return true;
2609     }
2610         
2611     case DFGTrueIntrinsic: {
2612         insertChecks();
2613         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2614         return true;
2615     }
2616         
2617     case OSRExitIntrinsic: {
2618         insertChecks();
2619         addToGraph(ForceOSRExit);
2620         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2621         return true;
2622     }
2623         
2624     case IsFinalTierIntrinsic: {
2625         insertChecks();
2626         set(VirtualRegister(resultOperand),
2627             jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
2628         return true;
2629     }
2630         
2631     case SetInt32HeapPredictionIntrinsic: {
2632         insertChecks();
2633         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2634             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2635             if (node->hasHeapPrediction())
2636                 node->setHeapPrediction(SpecInt32Only);
2637         }
2638         set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
2639         return true;
2640     }
2641         
2642     case CheckInt32Intrinsic: {
2643         insertChecks();
2644         for (int i = 1; i < argumentCountIncludingThis; ++i) {
2645             Node* node = get(virtualRegisterForArgument(i, registerOffset));
2646             addToGraph(Phantom, Edge(node, Int32Use));
2647         }
2648         set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
2649         return true;
2650     }
2651         
2652     case FiatInt52Intrinsic: {
2653         if (argumentCountIncludingThis != 2)
2654             return false;
2655         insertChecks();
2656         VirtualRegister operand = virtualRegisterForArgument(1, registerOffset);
2657         if (enableInt52())
2658             set(VirtualRegister(resultOperand), addToGraph(FiatInt52, get(operand)));
2659         else
2660             set(VirtualRegister(resultOperand), get(operand));
2661         return true;
2662     }
2663
2664     case JSMapGetIntrinsic: {
2665         if (argumentCountIncludingThis != 2)
2666             return false;
2667
2668         insertChecks();
2669         Node* map = get(virtualRegisterForArgument(0, registerOffset));
2670         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2671         Node* hash = addToGraph(MapHash, key);
2672         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash));
2673         Node* result = addToGraph(LoadFromJSMapBucket, OpInfo(), OpInfo(prediction), bucket);
2674         set(VirtualRegister(resultOperand), result);
2675         return true;
2676     }
2677
2678     case JSSetHasIntrinsic:
2679     case JSMapHasIntrinsic: {
2680         if (argumentCountIncludingThis != 2)
2681             return false;
2682
2683         insertChecks();
2684         Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
2685         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2686         Node* hash = addToGraph(MapHash, key);
2687         UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
2688         Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash));
2689         Node* result = addToGraph(IsNonEmptyMapBucket, bucket);
2690         set(VirtualRegister(resultOperand), result);
2691         return true;
2692     }
2693
2694     case HasOwnPropertyIntrinsic: {
2695         if (argumentCountIncludingThis != 2)
2696             return false;
2697
2698         // This can be racy, that's fine. We know that once we observe that this is created,
2699         // that it will never be destroyed until the VM is destroyed. It's unlikely that
2700         // we'd ever get to the point where we inline this as an intrinsic without the
2701         // cache being created, however, it's possible if we always throw exceptions inside
2702         // hasOwnProperty.
2703         if (!m_vm->hasOwnPropertyCache())
2704             return false;
2705
2706         insertChecks();
2707         Node* object = get(virtualRegisterForArgument(0, registerOffset));
2708         Node* key = get(virtualRegisterForArgument(1, registerOffset));
2709         Node* result = addToGraph(HasOwnProperty, object, key);
2710         set(VirtualRegister(resultOperand), result);
2711         return true;
2712     }
2713
2714     case StringPrototypeToLowerCaseIntrinsic: {
2715         if (argumentCountIncludingThis != 1)
2716             return false;
2717
2718         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2719             return false;
2720
2721         insertChecks();
2722         Node* thisString = get(virtualRegisterForArgument(0, registerOffset));
2723         Node* result = addToGraph(ToLowerCase, thisString);
2724         set(VirtualRegister(resultOperand), result);
2725         return true;
2726     }
2727
2728     case NumberPrototypeToStringIntrinsic: {
2729         if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
2730             return false;
2731
2732         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2733             return false;
2734
2735         insertChecks();
2736         Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
2737         if (argumentCountIncludingThis == 1) {
2738             Node* result = addToGraph(ToString, thisNumber);
2739             set(VirtualRegister(resultOperand), result);
2740         } else {
2741             Node* radix = get(virtualRegisterForArgument(1, registerOffset));
2742             Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix);
2743             set(VirtualRegister(resultOperand), result);
2744         }
2745         return true;
2746     }
2747
2748     default:
2749         return false;
2750     }
2751 }
2752
2753 template<typename ChecksFunctor>
2754 bool ByteCodeParser::handleDOMJITCall(Node* callTarget, int resultOperand, const DOMJIT::Signature* signature, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2755 {
2756     if (argumentCountIncludingThis != static_cast<int>(1 + signature->argumentCount))
2757         return false;
2758     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
2759         return false;
2760
2761     // FIXME: Currently, we only support functions which arguments are up to 2.
2762     // Eventually, we should extend this. But possibly, 2 or 3 can cover typical use cases.
2763     // https://bugs.webkit.org/show_bug.cgi?id=164346
2764     ASSERT_WITH_MESSAGE(argumentCountIncludingThis <= JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS, "Currently CallDOM does not support an arbitrary length arguments.");
2765
2766     insertChecks();
2767     addCall(resultOperand, Call, signature, callTarget, argumentCountIncludingThis, registerOffset, prediction);
2768     return true;
2769 }
2770
2771
2772 template<typename ChecksFunctor>
2773 bool ByteCodeParser::handleIntrinsicGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, const ChecksFunctor& insertChecks)
2774 {
2775     switch (variant.intrinsic()) {
2776     case TypedArrayByteLengthIntrinsic: {
2777         insertChecks();
2778
2779         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
2780         Array::Type arrayType = toArrayType(type);
2781         size_t logSize = logElementSize(type);
2782
2783         variant.structureSet().forEach([&] (Structure* structure) {
2784             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
2785             ASSERT(logSize == logElementSize(curType));
2786             arrayType = refineTypedArrayType(arrayType, curType);
2787             ASSERT(arrayType != Array::Generic);
2788         });
2789
2790         Node* lengthNode = addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode);
2791
2792         if (!logSize) {
2793             set(VirtualRegister(resultOperand), lengthNode);
2794             return true;
2795         }
2796
2797         // We can use a BitLShift here because typed arrays will never have a byteLength
2798         // that overflows int32.
2799         Node* shiftNode = jsConstant(jsNumber(logSize));
2800         set(VirtualRegister(resultOperand), addToGraph(BitLShift, lengthNode, shiftNode));
2801
2802         return true;
2803     }
2804
2805     case TypedArrayLengthIntrinsic: {
2806         insertChecks();
2807
2808         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
2809         Array::Type arrayType = toArrayType(type);
2810
2811         variant.structureSet().forEach([&] (Structure* structure) {
2812             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
2813             arrayType = refineTypedArrayType(arrayType, curType);
2814             ASSERT(arrayType != Array::Generic);
2815         });
2816
2817         set(VirtualRegister(resultOperand), addToGraph(GetArrayLength, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
2818
2819         return true;
2820
2821     }
2822
2823     case TypedArrayByteOffsetIntrinsic: {
2824         insertChecks();
2825
2826         TypedArrayType type = (*variant.structureSet().begin())->classInfo()->typedArrayStorageType;
2827         Array::Type arrayType = toArrayType(type);
2828
2829         variant.structureSet().forEach([&] (Structure* structure) {
2830             TypedArrayType curType = structure->classInfo()->typedArrayStorageType;
2831             arrayType = refineTypedArrayType(arrayType, curType);
2832             ASSERT(arrayType != Array::Generic);
2833         });
2834
2835         set(VirtualRegister(resultOperand), addToGraph(GetTypedArrayByteOffset, OpInfo(ArrayMode(arrayType).asWord()), thisNode));
2836
2837         return true;
2838     }
2839
2840     default:
2841         return false;
2842     }
2843     RELEASE_ASSERT_NOT_REACHED();
2844 }
2845
2846 static void blessCallDOMGetter(Node* node)
2847 {
2848     DOMJIT::CallDOMGetterPatchpoint* patchpoint = node->callDOMGetterData()->patchpoint;
2849     if (!patchpoint->effect.mustGenerate())
2850         node->clearFlags(NodeMustGenerate);
2851 }
2852
2853 bool ByteCodeParser::handleDOMJITGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, unsigned identifierNumber, SpeculatedType prediction)
2854 {
2855     if (!variant.domJIT())
2856         return false;
2857
2858     DOMJIT::GetterSetter* domJIT = variant.domJIT();
2859
2860     // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough,
2861     // since replacement of CustomGetterSetter always incurs Structure transition.
2862     if (!check(variant.conditionSet()))
2863         return false;
2864     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
2865
2866     Ref<DOMJIT::Patchpoint> checkDOMPatchpoint = domJIT->checkDOM();
2867     m_graph.m_domJITPatchpoints.append(checkDOMPatchpoint.ptr());
2868     // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
2869     addToGraph(CheckDOM, OpInfo(checkDOMPatchpoint.ptr()), OpInfo(domJIT->thisClassInfo()), thisNode);
2870
2871     CallDOMGetterData* callDOMGetterData = m_graph.m_callDOMGetterData.add();
2872     Ref<DOMJIT::CallDOMGetterPatchpoint> callDOMGetterPatchpoint = domJIT->callDOMGetter();
2873     m_graph.m_domJITPatchpoints.append(callDOMGetterPatchpoint.ptr());
2874
2875     callDOMGetterData->domJIT = domJIT;
2876     callDOMGetterData->patchpoint = callDOMGetterPatchpoint.ptr();
2877     callDOMGetterData->identifierNumber = identifierNumber;
2878
2879     Node* callDOMGetterNode = nullptr;
2880     // GlobalObject of thisNode is always used to create a DOMWrapper.
2881     if (callDOMGetterPatchpoint->requireGlobalObject) {
2882         Node* globalObject = addToGraph(GetGlobalObject, thisNode);
2883         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode, globalObject);
2884     } else
2885         callDOMGetterNode = addToGraph(CallDOMGetter, OpInfo(callDOMGetterData), OpInfo(prediction), thisNode);
2886     blessCallDOMGetter(callDOMGetterNode);
2887     set(VirtualRegister(resultOperand), callDOMGetterNode);
2888     return true;
2889 }
2890
2891 bool ByteCodeParser::handleModuleNamespaceLoad(int resultOperand, SpeculatedType prediction, Node* base, GetByIdStatus getById)
2892 {
2893     if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell))
2894         return false;
2895     addToGraph(CheckCell, OpInfo(m_graph.freeze(getById.moduleNamespaceObject())), Edge(base, CellUse));
2896
2897     // Ideally we wouldn't have to do this Phantom. But:
2898     //
2899     // For the constant case: we must do it because otherwise we would have no way of knowing
2900     // that the scope is live at OSR here.
2901     //
2902     // For the non-constant case: GetClosureVar could be DCE'd, but baseline's implementation
2903     // won't be able to handle an Undefined scope.
2904     addToGraph(Phantom, base);
2905
2906     // Constant folding in the bytecode parser is important for performance. This may not
2907     // have executed yet. If it hasn't, then we won't have a prediction. Lacking a
2908     // prediction, we'd otherwise think that it has to exit. Then when it did execute, we
2909     // would recompile. But if we can fold it here, we avoid the exit.
2910     m_graph.freeze(getById.moduleEnvironment());
2911     if (JSValue value = m_graph.tryGetConstantClosureVar(getById.moduleEnvironment(), getById.scopeOffset())) {
2912         set(VirtualRegister(resultOperand), weakJSConstant(value));
2913         return true;
2914     }
2915     set(VirtualRegister(resultOperand), addToGraph(GetClosureVar, OpInfo(getById.scopeOffset().offset()), OpInfo(prediction), weakJSConstant(getById.moduleEnvironment())));
2916     return true;
2917 }
2918
2919 template<typename ChecksFunctor>
2920 bool ByteCodeParser::handleTypedArrayConstructor(
2921     int resultOperand, InternalFunction* function, int registerOffset,
2922     int argumentCountIncludingThis, TypedArrayType type, const ChecksFunctor& insertChecks)
2923 {
2924     if (!isTypedView(type))
2925         return false;
2926     
2927     if (function->classInfo() != constructorClassInfoForType(type))
2928         return false;
2929     
2930     if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
2931         return false;
2932     
2933     // We only have an intrinsic for the case where you say:
2934     //
2935     // new FooArray(blah);
2936     //
2937     // Of course, 'blah' could be any of the following:
2938     //
2939     // - Integer, indicating that you want to allocate an array of that length.
2940     //   This is the thing we're hoping for, and what we can actually do meaningful
2941     //   optimizations for.
2942     //
2943     // - Array buffer, indicating that you want to create a view onto that _entire_
2944     //   buffer.
2945     //
2946     // - Non-buffer object, indicating that you want to create a copy of that
2947     //   object by pretending that it quacks like an array.
2948     //
2949     // - Anything else, indicating that you want to have an exception thrown at
2950     //   you.
2951     //
2952     // The intrinsic, NewTypedArray, will behave as if it could do any of these
2953     // things up until we do Fixup. Thereafter, if child1 (i.e. 'blah') is
2954     // predicted Int32, then we lock it in as a normal typed array allocation.
2955     // Otherwise, NewTypedArray turns into a totally opaque function call that
2956     // may clobber the world - by virtue of it accessing properties on what could
2957     // be an object.
2958     //
2959     // Note that although the generic form of NewTypedArray sounds sort of awful,
2960     // it is actually quite likely to be more efficient than a fully generic
2961     // Construct. So, we might want to think about making NewTypedArray variadic,
2962     // or else making Construct not super slow.
2963     
2964     if (argumentCountIncludingThis != 2)
2965         return false;
2966     
2967     if (!function->globalObject()->typedArrayStructureConcurrently(type))
2968         return false;
2969
2970     insertChecks();
2971     set(VirtualRegister(resultOperand),
2972         addToGraph(NewTypedArray, OpInfo(type), get(virtualRegisterForArgument(1, registerOffset))));
2973     return true;
2974 }
2975
2976 template<typename ChecksFunctor>
2977 bool ByteCodeParser::handleConstantInternalFunction(
2978     Node* callTargetNode, int resultOperand, InternalFunction* function, int registerOffset,
2979     int argumentCountIncludingThis, CodeSpecializationKind kind, SpeculatedType prediction, const ChecksFunctor& insertChecks)
2980 {
2981     if (verbose)
2982         dataLog("    Handling constant internal function ", JSValue(function), "\n");
2983
2984     if (kind == CodeForConstruct) {
2985         Node* newTargetNode = get(virtualRegisterForArgument(0, registerOffset));
2986         // We cannot handle the case where new.target != callee (i.e. a construct from a super call) because we
2987         // don't know what the prototype of the constructed object will be.
2988         // 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
2989         if (newTargetNode != callTargetNode)
2990             return false;
2991     }
2992
2993     if (function->classInfo() == ArrayConstructor::info()) {
2994         if (function->globalObject() != m_inlineStackTop->m_codeBlock->globalObject())
2995             return false;
2996         
2997         insertChecks();
2998         if (argumentCountIncludingThis == 2) {
2999             set(VirtualRegister(resultOperand),
3000                 addToGraph(NewArrayWithSize, OpInfo(ArrayWithUndecided), get(virtualRegisterForArgument(1, registerOffset))));
3001             return true;
3002         }
3003         
3004         for (int i = 1; i < argumentCountIncludingThis; ++i)
3005             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
3006         set(VirtualRegister(resultOperand),
3007             addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
3008         return true;
3009     }
3010
3011     if (function->classInfo() == NumberConstructor::info()) {
3012         if (kind == CodeForConstruct)
3013             return false;
3014
3015         insertChecks();
3016         if (argumentCountIncludingThis <= 1)
3017             set(VirtualRegister(resultOperand), jsConstant(jsNumber(0)));
3018         else
3019             set(VirtualRegister(resultOperand), addToGraph(ToNumber, OpInfo(0), OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
3020
3021         return true;
3022     }
3023     
3024     if (function->classInfo() == StringConstructor::info()) {
3025         insertChecks();
3026         
3027         Node* result;
3028         
3029         if (argumentCountIncludingThis <= 1)
3030             result = jsConstant(m_vm->smallStrings.emptyString());
3031         else
3032             result = addToGraph(CallStringConstructor, get(virtualRegisterForArgument(1, registerOffset)));
3033         
3034         if (kind == CodeForConstruct)
3035             result = addToGraph(NewStringObject, OpInfo(m_graph.registerStructure(function->globalObject()->stringObjectStructure())), result);
3036         
3037         set(VirtualRegister(resultOperand), result);
3038         return true;
3039     }
3040
3041     // FIXME: This should handle construction as well. https://bugs.webkit.org/show_bug.cgi?id=155591
3042     if (function->classInfo() == ObjectConstructor::info() && kind == CodeForCall) {
3043         insertChecks();
3044
3045         Node* result;
3046         if (argumentCountIncludingThis <= 1)
3047             result = addToGraph(NewObject, OpInfo(m_graph.registerStructure(function->globalObject()->objectStructureForObjectConstructor())));
3048         else
3049             result = addToGraph(CallObjectConstructor, get(virtualRegisterForArgument(1, registerOffset)));
3050         set(VirtualRegister(resultOperand), result);
3051         return true;
3052     }
3053
3054     for (unsigned typeIndex = 0; typeIndex < NUMBER_OF_TYPED_ARRAY_TYPES; ++typeIndex) {
3055         bool result = handleTypedArrayConstructor(
3056             resultOperand, function, registerOffset, argumentCountIncludingThis,
3057             indexToTypedArrayType(typeIndex), insertChecks);
3058         if (result)
3059             return true;
3060     }
3061     
3062     return false;
3063 }
3064
3065 Node* ByteCodeParser::handleGetByOffset(
3066     SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
3067     const InferredType::Descriptor& inferredType, NodeType op)
3068 {
3069     Node* propertyStorage;
3070     if (isInlineOffset(offset))
3071         propertyStorage = base;
3072     else
3073         propertyStorage = addToGraph(GetButterfly, base);
3074     
3075     StorageAccessData* data = m_graph.m_storageAccessData.add();
3076     data->offset = offset;
3077     data->identifierNumber = identifierNumber;
3078     data->inferredType = inferredType;
3079     m_graph.registerInferredType(inferredType);
3080     
3081     Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
3082
3083     return getByOffset;
3084 }
3085
3086 Node* ByteCodeParser::handlePutByOffset(
3087     Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor& inferredType,
3088     Node* value)
3089 {
3090     Node* propertyStorage;
3091     if (isInlineOffset(offset))
3092         propertyStorage = base;
3093     else
3094         propertyStorage = addToGraph(GetButterfly, base);
3095     
3096     StorageAccessData* data = m_graph.m_storageAccessData.add();
3097     data->offset = offset;
3098     data->identifierNumber = identifier;
3099     data->inferredType = inferredType;
3100     m_graph.registerInferredType(inferredType);
3101     
3102     Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
3103     
3104     return result;
3105 }
3106
3107 bool ByteCodeParser::check(const ObjectPropertyCondition& condition)
3108 {
3109     if (!condition)
3110         return false;
3111     
3112     if (m_graph.watchCondition(condition))
3113         return true;
3114     
3115     Structure* structure = condition.object()->structure();
3116     if (!condition.structureEnsuresValidity(structure))
3117         return false;
3118     
3119     addToGraph(
3120         CheckStructure,
3121         OpInfo(m_graph.addStructureSet(structure)),
3122         weakJSConstant(condition.object()));
3123     return true;
3124 }
3125
3126 GetByOffsetMethod ByteCodeParser::promoteToConstant(GetByOffsetMethod method)
3127 {
3128     if (method.kind() == GetByOffsetMethod::LoadFromPrototype
3129         && method.prototype()->structure()->dfgShouldWatch()) {
3130         if (JSValue constant = m_graph.tryGetConstantProperty(method.prototype()->value(), method.prototype()->structure(), method.offset()))
3131             return GetByOffsetMethod::constant(m_graph.freeze(constant));
3132     }
3133     
3134     return method;
3135 }
3136
3137 bool ByteCodeParser::needsDynamicLookup(ResolveType type, OpcodeID opcode)
3138 {
3139     ASSERT(opcode == op_resolve_scope || opcode == op_get_from_scope || opcode == op_put_to_scope);
3140
3141     JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
3142     if (needsVarInjectionChecks(type) && globalObject->varInjectionWatchpoint()->hasBeenInvalidated())
3143         return true;
3144
3145     switch (type) {
3146     case GlobalProperty:
3147     case GlobalVar:
3148     case GlobalLexicalVar:
3149     case ClosureVar:
3150     case LocalClosureVar:
3151     case ModuleVar:
3152         return false;
3153
3154     case UnresolvedProperty:
3155     case UnresolvedPropertyWithVarInjectionChecks: {
3156         // The heuristic for UnresolvedProperty scope accesses is we will ForceOSRExit if we
3157         // haven't exited from from this access before to let the baseline JIT try to better
3158         // cache the access. If we've already exited from this operation, it's unlikely that
3159         // the baseline will come up with a better ResolveType and instead we will compile
3160         // this as a dynamic scope access.
3161
3162         // We only track our heuristic through resolve_scope since resolve_scope will
3163         // dominate unresolved gets/puts on that scope.
3164         if (opcode != op_resolve_scope)
3165             return true;
3166
3167         if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, InadequateCoverage)) {
3168             // We've already exited so give up on getting better ResolveType information.
3169             return true;
3170         }
3171
3172         // We have not exited yet, so let's have the baseline get better ResolveType information for us.
3173         // This type of code is often seen when we tier up in a loop but haven't executed the part
3174         // of a function that comes after the loop.
3175         return false;
3176     }
3177
3178     case Dynamic:
3179         return true;
3180
3181     case GlobalPropertyWithVarInjectionChecks:
3182     case GlobalVarWithVarInjectionChecks:
3183     case GlobalLexicalVarWithVarInjectionChecks:
3184     case ClosureVarWithVarInjectionChecks:
3185         return false;
3186     }
3187
3188     ASSERT_NOT_REACHED();
3189     return false;
3190 }
3191
3192 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyCondition& condition)
3193 {
3194     if (verbose)
3195         dataLog("Planning a load: ", condition, "\n");
3196     
3197     // We might promote this to Equivalence, and a later DFG pass might also do such promotion
3198     // even if we fail, but for simplicity this cannot be asked to load an equivalence condition.
3199     // None of the clients of this method will request a load of an Equivalence condition anyway,
3200     // and supporting it would complicate the heuristics below.
3201     RELEASE_ASSERT(condition.kind() == PropertyCondition::Presence);
3202     
3203     // Here's the ranking of how to handle this, from most preferred to least preferred:
3204     //
3205     // 1) Watchpoint on an equivalence condition and return a constant node for the loaded value.
3206     //    No other code is emitted, and the structure of the base object is never registered.
3207     //    Hence this results in zero code and we won't jettison this compilation if the object
3208     //    transitions, even if the structure is watchable right now.
3209     //
3210     // 2) Need to emit a load, and the current structure of the base is going to be watched by the
3211     //    DFG anyway (i.e. dfgShouldWatch). Watch the structure and emit the load. Don't watch the
3212     //    condition, since the act of turning the base into a constant in IR will cause the DFG to
3213     //    watch the structure anyway and doing so would subsume watching the condition.
3214     //
3215     // 3) Need to emit a load, and the current structure of the base is watchable but not by the
3216     //    DFG (i.e. transitionWatchpointSetIsStillValid() and !dfgShouldWatchIfPossible()). Watch
3217     //    the condition, and emit a load.
3218     //
3219     // 4) Need to emit a load, and the current structure of the base is not watchable. Emit a
3220     //    structure check, and emit a load.
3221     //
3222     // 5) The condition does not hold. Give up and return null.
3223     
3224     // First, try to promote Presence to Equivalence. We do this before doing anything else
3225     // because it's the most profitable. Also, there are cases where the presence is watchable but
3226     // we don't want to watch it unless it became an equivalence (see the relationship between
3227     // (1), (2), and (3) above).
3228     ObjectPropertyCondition equivalenceCondition = condition.attemptToMakeEquivalenceWithoutBarrier(*m_vm);
3229     if (m_graph.watchCondition(equivalenceCondition))
3230         return GetByOffsetMethod::constant(m_graph.freeze(equivalenceCondition.requiredValue()));
3231     
3232     // At this point, we'll have to materialize the condition's base as a constant in DFG IR. Once
3233     // we do this, the frozen value will have its own idea of what the structure is. Use that from
3234     // now on just because it's less confusing.
3235     FrozenValue* base = m_graph.freeze(condition.object());
3236     Structure* structure = base->structure();
3237     
3238     // Check if the structure that we've registered makes the condition hold. If not, just give
3239     // up. This is case (5) above.
3240     if (!condition.structureEnsuresValidity(structure))
3241         return GetByOffsetMethod();
3242     
3243     // If the structure is watched by the DFG already, then just use this fact to emit the load.
3244     // This is case (2) above.
3245     if (structure->dfgShouldWatch())
3246         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3247     
3248     // If we can watch the condition right now, then we can emit the load after watching it. This
3249     // is case (3) above.
3250     if (m_graph.watchCondition(condition))
3251         return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3252     
3253     // We can't watch anything but we know that the current structure satisfies the condition. So,
3254     // check for that structure and then emit the load.
3255     addToGraph(
3256         CheckStructure, 
3257         OpInfo(m_graph.addStructureSet(structure)),
3258         addToGraph(JSConstant, OpInfo(base)));
3259     return promoteToConstant(GetByOffsetMethod::loadFromPrototype(base, condition.offset()));
3260 }
3261
3262 Node* ByteCodeParser::load(
3263     SpeculatedType prediction, unsigned identifierNumber, const GetByOffsetMethod& method,
3264     NodeType op)
3265 {
3266     switch (method.kind()) {
3267     case GetByOffsetMethod::Invalid:
3268         return nullptr;
3269     case GetByOffsetMethod::Constant:
3270         return addToGraph(JSConstant, OpInfo(method.constant()));
3271     case GetByOffsetMethod::LoadFromPrototype: {
3272         Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
3273         return handleGetByOffset(
3274             prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
3275     }
3276     case GetByOffsetMethod::Load:
3277         // Will never see this from planLoad().
3278         RELEASE_ASSERT_NOT_REACHED();
3279         return nullptr;
3280     }
3281     
3282     RELEASE_ASSERT_NOT_REACHED();
3283     return nullptr;
3284 }
3285
3286 Node* ByteCodeParser::load(
3287     SpeculatedType prediction, const ObjectPropertyCondition& condition, NodeType op)
3288 {
3289     GetByOffsetMethod method = planLoad(condition);
3290     return load(prediction, m_graph.identifiers().ensure(condition.uid()), method, op);
3291 }
3292
3293 bool ByteCodeParser::check(const ObjectPropertyConditionSet& conditionSet)
3294 {
3295     for (const ObjectPropertyCondition condition : conditionSet) {
3296         if (!check(condition))
3297             return false;
3298     }
3299     return true;
3300 }
3301
3302 GetByOffsetMethod ByteCodeParser::planLoad(const ObjectPropertyConditionSet& conditionSet)
3303 {
3304     if (verbose)
3305         dataLog("conditionSet = ", conditionSet, "\n");
3306     
3307     GetByOffsetMethod result;
3308     for (const ObjectPropertyCondition condition : conditionSet) {
3309         switch (condition.kind()) {
3310         case PropertyCondition::Presence:
3311             RELEASE_ASSERT(!result); // Should only see exactly one of these.
3312             result = planLoad(condition);
3313             if (!result)
3314                 return GetByOffsetMethod();
3315             break;
3316         default:
3317             if (!check(condition))
3318                 return GetByOffsetMethod();
3319             break;
3320         }
3321     }
3322     if (!result) {
3323         // We have a unset property.
3324         ASSERT(!conditionSet.numberOfConditionsWithKind(PropertyCondition::Presence));
3325         return GetByOffsetMethod::constant(m_constantUndefined);
3326     }
3327     return result;
3328 }
3329
3330 Node* ByteCodeParser::load(
3331     SpeculatedType prediction, const ObjectPropertyConditionSet& conditionSet, NodeType op)
3332 {
3333     GetByOffsetMethod method = planLoad(conditionSet);
3334     return load(
3335         prediction,
3336         m_graph.identifiers().ensure(conditionSet.slotBaseCondition().uid()),
3337         method, op);
3338 }
3339
3340 ObjectPropertyCondition ByteCodeParser::presenceLike(
3341     JSObject* knownBase, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
3342 {
3343     if (set.isEmpty())
3344         return ObjectPropertyCondition();
3345     unsigned attributes;
3346     PropertyOffset firstOffset = set[0]->getConcurrently(uid, attributes);
3347     if (firstOffset != offset)
3348         return ObjectPropertyCondition();
3349     for (unsigned i = 1; i < set.size(); ++i) {
3350         unsigned otherAttributes;
3351         PropertyOffset otherOffset = set[i]->getConcurrently(uid, otherAttributes);
3352         if (otherOffset != offset || otherAttributes != attributes)
3353             return ObjectPropertyCondition();
3354     }
3355     return ObjectPropertyCondition::presenceWithoutBarrier(knownBase, uid, offset, attributes);
3356 }
3357
3358 bool ByteCodeParser::checkPresenceLike(
3359     JSObject* knownBase, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
3360 {
3361     return check(presenceLike(knownBase, uid, offset, set));
3362 }
3363
3364 void ByteCodeParser::checkPresenceLike(
3365     Node* base, UniquedStringImpl* uid, PropertyOffset offset, const StructureSet& set)
3366 {
3367     if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>(*m_vm)) {
3368         if (checkPresenceLike(knownBase, uid, offset, set))
3369             return;
3370     }
3371
3372     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(set)), base);
3373 }
3374
3375 template<typename VariantType>
3376 Node* ByteCodeParser::load(
3377     SpeculatedType prediction, Node* base, unsigned identifierNumber, const VariantType& variant)
3378 {
3379     // Make sure backwards propagation knows that we've used base.
3380     addToGraph(Phantom, base);
3381     
3382     bool needStructureCheck = true;
3383     
3384     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
3385     
3386     if (JSObject* knownBase = base->dynamicCastConstant<JSObject*>(*m_vm)) {
3387         // Try to optimize away the structure check. Note that it's not worth doing anything about this
3388         // if the base's structure is watched.
3389         Structure* structure = base->constant()->structure();
3390         if (!structure->dfgShouldWatch()) {
3391             if (!variant.conditionSet().isEmpty()) {
3392                 // This means that we're loading from a prototype or we have a property miss. We expect
3393                 // the base not to have the property. We can only use ObjectPropertyCondition if all of
3394                 // the structures in the variant.structureSet() agree on the prototype (it would be
3395                 // hilariously rare if they didn't). Note that we are relying on structureSet() having
3396                 // at least one element. That will always be true here because of how GetByIdStatus/PutByIdStatus work.
3397                 JSObject* prototype = variant.structureSet()[0]->storedPrototypeObject();
3398                 bool allAgree = true;
3399                 for (unsigned i = 1; i < variant.structureSet().size(); ++i) {
3400                     if (variant.structureSet()[i]->storedPrototypeObject() != prototype) {
3401                         allAgree = false;
3402                         break;
3403                     }
3404                 }
3405                 if (allAgree) {
3406                     ObjectPropertyCondition condition = ObjectPropertyCondition::absenceWithoutBarrier(
3407                         knownBase, uid, prototype);
3408                     if (check(condition))
3409                         needStructureCheck = false;
3410                 }
3411             } else {
3412                 // This means we're loading directly from base. We can avoid all of the code that follows
3413                 // if we can prove that the property is a constant. Otherwise, we try to prove that the
3414                 // property is watchably present, in which case we get rid of the structure check.
3415
3416                 ObjectPropertyCondition presenceCondition =
3417                     presenceLike(knownBase, uid, variant.offset(), variant.structureSet());
3418                 if (presenceCondition) {
3419                     ObjectPropertyCondition equivalenceCondition =
3420                         presenceCondition.attemptToMakeEquivalenceWithoutBarrier(*m_vm);
3421                     if (m_graph.watchCondition(equivalenceCondition))
3422                         return weakJSConstant(equivalenceCondition.requiredValue());
3423                     
3424                     if (check(presenceCondition))
3425                         needStructureCheck = false;
3426                 }
3427             }
3428         }
3429     }
3430
3431     if (needStructureCheck)
3432         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
3433
3434     if (variant.isPropertyUnset()) {
3435         if (m_graph.watchConditions(variant.conditionSet()))
3436             return jsConstant(jsUndefined());
3437         return nullptr;
3438     }
3439
3440     SpeculatedType loadPrediction;
3441     NodeType loadOp;
3442     if (variant.callLinkStatus() || variant.intrinsic() != NoIntrinsic) {
3443         loadPrediction = SpecCellOther;
3444         loadOp = GetGetterSetterByOffset;
3445     } else {
3446         loadPrediction = prediction;
3447         loadOp = GetByOffset;
3448     }
3449     
3450     Node* loadedValue;
3451     if (!variant.conditionSet().isEmpty())
3452         loadedValue = load(loadPrediction, variant.conditionSet(), loadOp);
3453     else {
3454         if (needStructureCheck && base->hasConstant()) {
3455             // We did emit a structure check. That means that we have an opportunity to do constant folding
3456             // here, since we didn't do it above.
3457             JSValue constant = m_graph.tryGetConstantProperty(
3458                 base->asJSValue(), *m_graph.addStructureSet(variant.structureSet()), variant.offset());
3459             if (constant)
3460                 return weakJSConstant(constant);
3461         }
3462
3463         InferredType::Descriptor inferredType;
3464         if (needStructureCheck) {
3465             for (Structure* structure : variant.structureSet()) {
3466                 InferredType::Descriptor thisType = m_graph.inferredTypeForProperty(structure, uid);
3467                 inferredType.merge(thisType);
3468             }
3469         } else
3470             inferredType = InferredType::Top;
3471         
3472         loadedValue = handleGetByOffset(
3473             loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
3474     }
3475
3476     return loadedValue;
3477 }
3478
3479 Node* ByteCodeParser::store(Node* base, unsigned identifier, const PutByIdVariant& variant, Node* value)
3480 {
3481     RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
3482
3483     checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
3484     return handlePutByOffset(base, identifier, variant.offset(), variant.requiredType(), value);
3485 }
3486
3487 void ByteCodeParser::handleGetById(
3488     int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
3489     GetByIdStatus getByIdStatus, AccessType type, unsigned instructionSize)
3490 {
3491     // Attempt to reduce the set of things in the GetByIdStatus.
3492     if (base->op() == NewObject) {
3493         bool ok = true;
3494         for (unsigned i = m_currentBlock->size(); i--;) {
3495             Node* node = m_currentBlock->at(i);
3496             if (node == base)
3497                 break;
3498             if (writesOverlap(m_graph, node, JSCell_structureID)) {
3499                 ok = false;
3500                 break;
3501             }
3502         }
3503         if (ok)
3504             getByIdStatus.filter(base->structure().get());
3505     }
3506     
3507     NodeType getById;
3508     if (type == AccessType::Get)
3509         getById = getByIdStatus.makesCalls() ? GetByIdFlush : GetById;
3510     else
3511         getById = TryGetById;
3512
3513     if (getById != TryGetById && getByIdStatus.isModuleNamespace()) {
3514         if (handleModuleNamespaceLoad(destinationOperand, prediction, base, getByIdStatus)) {
3515             if (m_graph.compilation())
3516                 m_graph.compilation()->noticeInlinedGetById();
3517             return;
3518         }
3519     }
3520
3521     // Special path for custom accessors since custom's offset does not have any meanings.
3522     // So, this is completely different from Simple one. But we have a chance to optimize it when we use DOMJIT.
3523     if (Options::useDOMJIT() && getByIdStatus.isCustom()) {
3524         ASSERT(getByIdStatus.numVariants() == 1);
3525         ASSERT(!getByIdStatus.makesCalls());
3526         GetByIdVariant variant = getByIdStatus[0];
3527         ASSERT(variant.domJIT());
3528         if (handleDOMJITGetter(destinationOperand, variant, base, identifierNumber, prediction)) {
3529             if (m_graph.compilation())
3530                 m_graph.compilation()->noticeInlinedGetById();
3531             return;
3532         }
3533     }
3534
3535     ASSERT(type == AccessType::Get || !getByIdStatus.makesCalls());
3536     if (!getByIdStatus.isSimple() || !getByIdStatus.numVariants() || !Options::useAccessInlining()) {
3537         set(VirtualRegister(destinationOperand),
3538             addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
3539         return;
3540     }
3541     
3542     if (getByIdStatus.numVariants() > 1) {
3543         if (getByIdStatus.makesCalls() || !isFTL(m_graph.m_plan.mode)
3544             || !Options::usePolymorphicAccessInlining()) {
3545             set(VirtualRegister(destinationOperand),
3546                 addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
3547             return;
3548         }
3549         
3550         Vector<MultiGetByOffsetCase, 2> cases;
3551         
3552         // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
3553         //    optimal, if there is some rarely executed case in the chain that requires a lot
3554         //    of checks and those checks are not watchpointable.
3555         for (const GetByIdVariant& variant : getByIdStatus.variants()) {
3556             if (variant.intrinsic() != NoIntrinsic) {
3557                 set(VirtualRegister(destinationOperand),
3558                     addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
3559                 return;
3560             }
3561
3562             if (variant.conditionSet().isEmpty()) {
3563                 cases.append(
3564                     MultiGetByOffsetCase(
3565                         *m_graph.addStructureSet(variant.structureSet()),
3566                         GetByOffsetMethod::load(variant.offset())));
3567                 continue;
3568             }
3569
3570             GetByOffsetMethod method = planLoad(variant.conditionSet());
3571             if (!method) {
3572                 set(VirtualRegister(destinationOperand),
3573                     addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
3574                 return;
3575             }
3576             
3577             cases.append(MultiGetByOffsetCase(*m_graph.addStructureSet(variant.structureSet()), method));
3578         }
3579
3580         if (m_graph.compilation())
3581             m_graph.compilation()->noticeInlinedGetById();
3582     
3583         // 2) Emit a MultiGetByOffset
3584         MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
3585         data->cases = cases;
3586         data->identifierNumber = identifierNumber;
3587         set(VirtualRegister(destinationOperand),
3588             addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base));
3589         return;
3590     }
3591     
3592     ASSERT(getByIdStatus.numVariants() == 1);
3593     GetByIdVariant variant = getByIdStatus[0];
3594                 
3595     Node* loadedValue = load(prediction, base, identifierNumber, variant);
3596     if (!loadedValue) {
3597         set(VirtualRegister(destinationOperand),
3598             addToGraph(getById, OpInfo(identifierNumber), OpInfo(prediction), base));
3599         return;
3600     }
3601
3602     if (m_graph.compilation())
3603         m_graph.compilation()->noticeInlinedGetById();
3604
3605     ASSERT(type == AccessType::Get || !variant.callLinkStatus());
3606     if (!variant.callLinkStatus() && variant.intrinsic() == NoIntrinsic) {
3607         set(VirtualRegister(destinationOperand), loadedValue);
3608         return;
3609     }
3610     
3611     Node* getter = addToGraph(GetGetter, loadedValue);
3612
3613     if (handleIntrinsicGetter(destinationOperand, variant, base,
3614             [&] () {
3615                 addToGraph(CheckCell, OpInfo(m_graph.freeze(variant.intrinsicFunction())), getter, base);
3616             })) {
3617         addToGraph(Phantom, getter);
3618         return;
3619     }
3620
3621     ASSERT(variant.intrinsic() == NoIntrinsic);
3622
3623     // Make a call. We don't try to get fancy with using the smallest operand number because
3624     // the stack layout phase should compress the stack anyway.
3625     
3626     unsigned numberOfParameters = 0;
3627     numberOfParameters++; // The 'this' argument.
3628     numberOfParameters++; // True return PC.
3629     
3630     // Start with a register offset that corresponds to the last in-use register.
3631     int registerOffset = virtualRegisterForLocal(
3632         m_inlineStackTop->m_profiledBlock->m_numCalleeLocals - 1).offset();
3633     registerOffset -= numberOfParameters;
3634     registerOffset -= CallFrame::headerSizeInRegisters;
3635     
3636     // Get the alignment right.
3637     registerOffset = -WTF::roundUpToMultipleOf(
3638         stackAlignmentRegisters(),
3639         -registerOffset);
3640     
3641     ensureLocals(
3642         m_inlineStackTop->remapOperand(
3643             VirtualRegister(registerOffset)).toLocal());
3644     
3645     // Issue SetLocals. This has two effects:
3646     // 1) That's how handleCall() sees the arguments.
3647     // 2) If we inline then this ensures that the arguments&nb