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