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