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