1/*
2 * Copyright (C) 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 * Copyright (C) 2012 Igalia, S.L.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
16 *     its contributors may be used to endorse or promote products derived
17 *     from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef BytecodeGenerator_h
32#define BytecodeGenerator_h
33
34#include "CodeBlock.h"
35#include <wtf/HashTraits.h>
36#include "Instruction.h"
37#include "Label.h"
38#include "LabelScope.h"
39#include "Interpreter.h"
40#include "ParserError.h"
41#include "RegisterID.h"
42#include "SymbolTable.h"
43#include "Debugger.h"
44#include "Nodes.h"
45#include "StaticPropertyAnalyzer.h"
46#include "UnlinkedCodeBlock.h"
47
48#include <functional>
49
50#include <wtf/PassRefPtr.h>
51#include <wtf/SegmentedVector.h>
52#include <wtf/Vector.h>
53
54
55namespace JSC {
56
57    class Identifier;
58    class Label;
59
60    enum ExpectedFunction {
61        NoExpectedFunction,
62        ExpectObjectConstructor,
63        ExpectArrayConstructor
64    };
65
66    class CallArguments {
67    public:
68        CallArguments(BytecodeGenerator&, ArgumentsNode*, unsigned additionalArguments = 0);
69
70        RegisterID* thisRegister() { return m_argv[0].get(); }
71        RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
72        unsigned stackOffset() { return -m_argv[0]->index() + JSStack::CallFrameHeaderSize; }
73        unsigned argumentCountIncludingThis() { return m_argv.size() - m_padding; }
74        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
75        ArgumentsNode* argumentsNode() { return m_argumentsNode; }
76
77    private:
78        RefPtr<RegisterID> m_profileHookRegister;
79        ArgumentsNode* m_argumentsNode;
80        Vector<RefPtr<RegisterID>, 8, UnsafeVectorOverflow> m_argv;
81        unsigned m_padding;
82    };
83
84    struct FinallyContext {
85        StatementNode* finallyBlock;
86        unsigned scopeContextStackSize;
87        unsigned switchContextStackSize;
88        unsigned forInContextStackSize;
89        unsigned tryContextStackSize;
90        unsigned labelScopesSize;
91        int finallyDepth;
92        int dynamicScopeDepth;
93    };
94
95    struct ControlFlowContext {
96        bool isFinallyBlock;
97        FinallyContext finallyContext;
98    };
99
100    struct ForInContext {
101        RefPtr<RegisterID> expectedSubscriptRegister;
102        RefPtr<RegisterID> iterRegister;
103        RefPtr<RegisterID> indexRegister;
104        RefPtr<RegisterID> propertyRegister;
105    };
106
107    struct TryData {
108        RefPtr<Label> target;
109        unsigned targetScopeDepth;
110    };
111
112    struct TryContext {
113        RefPtr<Label> start;
114        TryData* tryData;
115    };
116
117    enum CaptureMode {
118        NotCaptured,
119        IsCaptured
120    };
121
122    class Local {
123    public:
124        Local()
125            : m_local(0)
126            , m_attributes(0)
127        {
128        }
129
130        Local(RegisterID* local, unsigned attributes, CaptureMode captureMode)
131            : m_local(local)
132            , m_attributes(attributes)
133            , m_isCaptured(captureMode == IsCaptured)
134        {
135        }
136
137        operator bool() { return m_local; }
138
139        RegisterID* get() { return m_local; }
140
141        bool isReadOnly() { return m_attributes & ReadOnly; }
142
143        bool isCaptured() { return m_isCaptured; }
144        CaptureMode captureMode() { return isCaptured() ? IsCaptured : NotCaptured; }
145
146    private:
147        RegisterID* m_local;
148        unsigned m_attributes;
149        bool m_isCaptured;
150    };
151
152    struct TryRange {
153        RefPtr<Label> start;
154        RefPtr<Label> end;
155        TryData* tryData;
156    };
157
158    class BytecodeGenerator {
159        WTF_MAKE_FAST_ALLOCATED;
160    public:
161        typedef DeclarationStacks::VarStack VarStack;
162        typedef DeclarationStacks::FunctionStack FunctionStack;
163
164        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);
165        BytecodeGenerator(VM&, FunctionBodyNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);
166        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);
167
168        ~BytecodeGenerator();
169
170        VM* vm() const { return m_vm; }
171        const CommonIdentifiers& propertyNames() const { return *m_vm->propertyNames; }
172
173        bool isConstructor() { return m_codeBlock->isConstructor(); }
174
175        ParserError generate();
176
177        bool isArgumentNumber(const Identifier&, int);
178
179        void setIsNumericCompareFunction(bool isNumericCompareFunction);
180
181        bool willResolveToArguments(const Identifier&);
182        RegisterID* uncheckedRegisterForArguments();
183
184        bool isCaptured(int operand);
185        CaptureMode captureMode(int operand) { return isCaptured(operand) ? IsCaptured : NotCaptured; }
186
187        Local local(const Identifier&);
188        Local constLocal(const Identifier&);
189
190        // Returns the register storing "this"
191        RegisterID* thisRegister() { return &m_thisRegister; }
192
193        // Returns the next available temporary register. Registers returned by
194        // newTemporary require a modified form of reference counting: any
195        // register with a refcount of 0 is considered "available", meaning that
196        // the next instruction may overwrite it.
197        RegisterID* newTemporary();
198
199        // The same as newTemporary(), but this function returns "suggestion" if
200        // "suggestion" is a temporary. This function is helpful in situations
201        // where you've put "suggestion" in a RefPtr, but you'd like to allow
202        // the next instruction to overwrite it anyway.
203        RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
204
205        // Functions for handling of dst register
206
207        RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
208
209        // Returns a place to write intermediate values of an operation
210        // which reuses dst if it is safe to do so.
211        RegisterID* tempDestination(RegisterID* dst)
212        {
213            return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
214        }
215
216        // Returns the place to write the final output of an operation.
217        RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
218        {
219            if (originalDst && originalDst != ignoredResult())
220                return originalDst;
221            ASSERT(tempDst != ignoredResult());
222            if (tempDst && tempDst->isTemporary())
223                return tempDst;
224            return newTemporary();
225        }
226
227        RegisterID* destinationForAssignResult(RegisterID* dst)
228        {
229            if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
230                return dst->isTemporary() ? dst : newTemporary();
231            return 0;
232        }
233
234        // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
235        RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
236        {
237            return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
238        }
239
240        LabelScopePtr newLabelScope(LabelScope::Type, const Identifier* = 0);
241        PassRefPtr<Label> newLabel();
242
243        void emitNode(RegisterID* dst, StatementNode* n)
244        {
245            // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
246            ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
247            // Should never store directly into a captured variable.
248            ASSERT(!dst || dst == ignoredResult() || !isCaptured(dst->index()));
249            if (!m_vm->isSafeToRecurse()) {
250                emitThrowExpressionTooDeepException();
251                return;
252            }
253            n->emitBytecode(*this, dst);
254        }
255
256        void emitNode(StatementNode* n)
257        {
258            emitNode(0, n);
259        }
260
261        RegisterID* emitNode(RegisterID* dst, ExpressionNode* n)
262        {
263            // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
264            ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
265            // Should never store directly into a captured variable.
266            ASSERT(!dst || dst == ignoredResult() || !isCaptured(dst->index()));
267            if (!m_vm->isSafeToRecurse())
268                return emitThrowExpressionTooDeepException();
269            return n->emitBytecode(*this, dst);
270        }
271
272        RegisterID* emitNode(ExpressionNode* n)
273        {
274            return emitNode(0, n);
275        }
276
277        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, FallThroughMode fallThroughMode)
278        {
279            if (!m_vm->isSafeToRecurse()) {
280                emitThrowExpressionTooDeepException();
281                return;
282            }
283
284            n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMode);
285        }
286
287        void emitExpressionInfo(const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd)
288        {
289            ASSERT(divot.offset >= divotStart.offset);
290            ASSERT(divotEnd.offset >= divot.offset);
291
292            int sourceOffset = m_scopeNode->source().startOffset();
293            unsigned firstLine = m_scopeNode->source().firstLine();
294
295            int divotOffset = divot.offset - sourceOffset;
296            int startOffset = divot.offset - divotStart.offset;
297            int endOffset = divotEnd.offset - divot.offset;
298
299            unsigned line = divot.line;
300            ASSERT(line >= firstLine);
301            line -= firstLine;
302
303            int lineStart = divot.lineStartOffset;
304            if (lineStart > sourceOffset)
305                lineStart -= sourceOffset;
306            else
307                lineStart = 0;
308
309            if (divotOffset < lineStart)
310                return;
311
312            unsigned column = divotOffset - lineStart;
313
314            unsigned instructionOffset = instructions().size();
315            if (!m_isBuiltinFunction)
316                m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
317        }
318
319        ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
320        {
321            return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
322        }
323
324        ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
325        {
326            if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
327                PassRefPtr<RegisterID> dst = newTemporary();
328                emitNode(dst.get(), n);
329                return dst;
330            }
331
332            return emitNode(n);
333        }
334
335        RegisterID* emitLoad(RegisterID* dst, bool);
336        RegisterID* emitLoad(RegisterID* dst, double);
337        RegisterID* emitLoad(RegisterID* dst, const Identifier&);
338        RegisterID* emitLoad(RegisterID* dst, JSValue);
339        RegisterID* emitLoadGlobalObject(RegisterID* dst);
340
341        RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
342        RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
343        RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
344        RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
345
346        RegisterID* emitCreateThis(RegisterID* dst);
347        RegisterID* emitNewObject(RegisterID* dst);
348        RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
349
350        RegisterID* emitNewFunction(RegisterID* dst, CaptureMode, FunctionBodyNode*);
351        RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body);
352        RegisterID* emitNewFunctionInternal(RegisterID* dst, CaptureMode, unsigned index, bool shouldNullCheck);
353        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
354        RegisterID* emitNewRegExp(RegisterID* dst, RegExp*);
355
356        RegisterID* emitMove(RegisterID* dst, CaptureMode, RegisterID* src);
357        RegisterID* emitMove(RegisterID* dst, RegisterID* src);
358
359        RegisterID* emitToNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_number, dst, src); }
360        RegisterID* emitInc(RegisterID* srcDst);
361        RegisterID* emitDec(RegisterID* srcDst);
362
363        void emitCheckHasInstance(RegisterID* dst, RegisterID* value, RegisterID* base, Label* target);
364        RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* basePrototype);
365        RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
366        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
367
368        RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value);
369
370        RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
371        RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
372        RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
373        RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
374        RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
375        RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
376        RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
377        RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
378        RegisterID* emitDirectPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
379        RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
380        RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
381        void emitPutGetterSetter(RegisterID* base, const Identifier& property, RegisterID* getter, RegisterID* setter);
382
383        ExpectedFunction expectedFunctionForIdentifier(const Identifier&);
384        RegisterID* emitCall(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
385        RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
386        RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
387
388        void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function<void(BytecodeGenerator&, RegisterID*)>& callBack);
389
390        RegisterID* emitReturn(RegisterID* src);
391        RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
392
393        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
394        RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
395        void emitToPrimitive(RegisterID* dst, RegisterID* src);
396
397        ResolveType resolveType();
398        RegisterID* emitResolveScope(RegisterID* dst, const Identifier&);
399        RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode);
400        RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode);
401
402        PassRefPtr<Label> emitLabel(Label*);
403        void emitLoopHint();
404        PassRefPtr<Label> emitJump(Label* target);
405        PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
406        PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
407        PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
408        PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
409        void emitPopScopes(int targetScopeDepth);
410
411        RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
412        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
413
414        void emitReadOnlyExceptionIfNeeded();
415
416        // Start a try block. 'start' must have been emitted.
417        TryData* pushTry(Label* start);
418        // End a try block. 'end' must have been emitted.
419        RegisterID* popTryAndEmitCatch(TryData*, RegisterID* targetRegister, Label* end);
420
421        void emitThrow(RegisterID* exc)
422        {
423            m_usesExceptions = true;
424            emitUnaryNoDstOp(op_throw, exc);
425        }
426
427        void emitThrowReferenceError(const String& message);
428
429        void emitPushFunctionNameScope(const Identifier& property, RegisterID* value, unsigned attributes);
430        void emitPushCatchScope(const Identifier& property, RegisterID* value, unsigned attributes);
431
432        RegisterID* emitPushWithScope(RegisterID* scope);
433        void emitPopScope();
434
435        void emitDebugHook(DebugHookID, unsigned line, unsigned charOffset, unsigned lineStart);
436
437        int scopeDepth() { return m_localScopeDepth + m_finallyDepth; }
438        bool hasFinaliser() { return m_finallyDepth != 0; }
439
440        void pushFinallyContext(StatementNode* finallyBlock);
441        void popFinallyContext();
442
443        void pushOptimisedForIn(RegisterID* expectedSubscript, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
444        {
445            ForInContext context = { expectedSubscript, iter, index, propertyRegister };
446            m_forInContextStack.append(context);
447        }
448
449        void popOptimisedForIn()
450        {
451            m_forInContextStack.removeLast();
452        }
453
454        LabelScopePtr breakTarget(const Identifier&);
455        LabelScopePtr continueTarget(const Identifier&);
456
457        void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
458        void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
459
460        CodeType codeType() const { return m_codeType; }
461
462        bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
463        bool shouldEmitDebugHooks() { return m_shouldEmitDebugHooks; }
464
465        bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
466
467        bool isBuiltinFunction() const { return m_isBuiltinFunction; }
468
469    private:
470        friend class Label;
471
472        void emitOpcode(OpcodeID);
473        UnlinkedArrayAllocationProfile newArrayAllocationProfile();
474        UnlinkedObjectAllocationProfile newObjectAllocationProfile();
475        UnlinkedArrayProfile newArrayProfile();
476        UnlinkedValueProfile emitProfiledOpcode(OpcodeID);
477        int kill(RegisterID* dst)
478        {
479            int index = dst->index();
480            m_staticPropertyAnalyzer.kill(index);
481            return index;
482        }
483
484        void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
485        void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
486        ALWAYS_INLINE void rewindBinaryOp();
487        ALWAYS_INLINE void rewindUnaryOp();
488
489        void emitComplexPopScopes(ControlFlowContext* topScope, ControlFlowContext* bottomScope);
490
491        typedef HashMap<double, JSValue> NumberMap;
492        typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
493
494        // Helper for emitCall() and emitConstruct(). This works because the set of
495        // expected functions have identical behavior for both call and construct
496        // (i.e. "Object()" is identical to "new Object()").
497        ExpectedFunction emitExpectedFunctionSnippet(RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, Label* done);
498
499        RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, ExpectedFunction, CallArguments&, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
500
501        RegisterID* newRegister();
502
503        // Adds a var slot and maps it to the name ident in symbolTable().
504        enum WatchMode { IsWatchable, NotWatchable };
505        RegisterID* addVar(const Identifier& ident, ConstantMode constantMode, WatchMode watchMode)
506        {
507            RegisterID* local;
508            addVar(ident, constantMode, watchMode, local);
509            return local;
510        }
511
512        // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
513        bool addVar(const Identifier&, ConstantMode, WatchMode, RegisterID*&);
514
515        // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
516        RegisterID* addVar()
517        {
518            ++m_codeBlock->m_numVars;
519            return newRegister();
520        }
521
522        // Returns the index of the added var.
523        void addParameter(const Identifier&, int parameterIndex);
524        RegisterID* resolveCallee(FunctionBodyNode*);
525        void addCallee(FunctionBodyNode*, RegisterID*);
526
527        void preserveLastVar();
528
529        RegisterID& registerFor(int index)
530        {
531            if (operandIsLocal(index))
532                return m_calleeRegisters[VirtualRegister(index).toLocal()];
533
534            if (index == JSStack::Callee)
535                return m_calleeRegister;
536
537            ASSERT(m_parameters.size());
538            return m_parameters[VirtualRegister(index).toArgument()];
539        }
540
541        unsigned addConstant(const Identifier&);
542        RegisterID* addConstantValue(JSValue);
543        RegisterID* addConstantEmptyValue();
544        unsigned addRegExp(RegExp*);
545
546        unsigned addConstantBuffer(unsigned length);
547
548        UnlinkedFunctionExecutable* makeFunction(FunctionBodyNode* body)
549        {
550            return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), body, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction);
551        }
552
553        RegisterID* emitInitLazyRegister(RegisterID*);
554
555        RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
556        RegisterID* emitCallVarargs(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, RegisterID* profileHookRegister, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd);
557
558    public:
559        JSString* addStringConstant(const Identifier&);
560
561        Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow>& instructions() { return m_instructions; }
562
563        SymbolTable& symbolTable() { return *m_symbolTable; }
564
565        bool shouldOptimizeLocals()
566        {
567            if (m_codeType != FunctionCode)
568                return false;
569
570            if (m_localScopeDepth)
571                return false;
572
573            return true;
574        }
575
576        bool canOptimizeNonLocals()
577        {
578            if (m_localScopeDepth)
579                return false;
580
581            if (m_codeType == EvalCode)
582                return false;
583
584            if (m_codeType == FunctionCode && m_codeBlock->usesEval())
585                return false;
586
587            return true;
588        }
589
590        bool shouldTearOffArgumentsEagerly()
591        {
592            return m_codeType == FunctionCode && isStrictMode() && m_scopeNode->modifiesParameter();
593        }
594
595        RegisterID* emitThrowExpressionTooDeepException();
596
597        void createArgumentsIfNecessary();
598        void createActivationIfNecessary();
599        RegisterID* createLazyRegisterIfNecessary(RegisterID*);
600
601        unsigned watchableVariable(int operand)
602        {
603            VirtualRegister reg(operand);
604            if (!reg.isLocal())
605                return UINT_MAX;
606            if (static_cast<size_t>(reg.toLocal()) >= m_watchableVariables.size())
607                return UINT_MAX;
608            Identifier& ident = m_watchableVariables[reg.toLocal()];
609            if (ident.isNull())
610                return UINT_MAX;
611            return addConstant(ident);
612        }
613
614        bool hasWatchableVariable(int operand)
615        {
616            return watchableVariable(operand) != UINT_MAX;
617        }
618
619        Vector<UnlinkedInstruction, 0, UnsafeVectorOverflow> m_instructions;
620
621        bool m_shouldEmitDebugHooks;
622        bool m_shouldEmitProfileHooks;
623
624        SymbolTable* m_symbolTable;
625
626        ScopeNode* m_scopeNode;
627        Strong<UnlinkedCodeBlock> m_codeBlock;
628
629        // Some of these objects keep pointers to one another. They are arranged
630        // to ensure a sane destruction order that avoids references to freed memory.
631        HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
632        RegisterID m_ignoredResultRegister;
633        RegisterID m_thisRegister;
634        RegisterID m_calleeRegister;
635        RegisterID* m_activationRegister;
636        RegisterID* m_emptyValueRegister;
637        RegisterID* m_globalObjectRegister;
638        Vector<Identifier, 16> m_watchableVariables;
639        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
640        SegmentedVector<RegisterID, 32> m_calleeRegisters;
641        SegmentedVector<RegisterID, 32> m_parameters;
642        SegmentedVector<Label, 32> m_labels;
643        LabelScopeStore m_labelScopes;
644        RefPtr<RegisterID> m_lastVar;
645        int m_finallyDepth;
646        int m_localScopeDepth;
647        CodeType m_codeType;
648
649        Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
650        Vector<SwitchInfo> m_switchContextStack;
651        Vector<ForInContext> m_forInContextStack;
652        Vector<TryContext> m_tryContextStack;
653        Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
654
655        Vector<TryRange> m_tryRanges;
656        SegmentedVector<TryData, 8> m_tryData;
657
658        int m_firstConstantIndex;
659        int m_nextConstantOffset;
660        unsigned m_globalConstantIndex;
661
662        int m_globalVarStorageOffset;
663
664        int m_firstLazyFunction;
665        int m_lastLazyFunction;
666        HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int>> m_lazyFunctions;
667        typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
668        FunctionOffsetMap m_functionOffsets;
669
670        // Constant pool
671        IdentifierMap m_identifierMap;
672        JSValueMap m_jsValueMap;
673        NumberMap m_numberMap;
674        IdentifierStringMap m_stringMap;
675
676        StaticPropertyAnalyzer m_staticPropertyAnalyzer;
677
678        VM* m_vm;
679
680        OpcodeID m_lastOpcodeID;
681#ifndef NDEBUG
682        size_t m_lastOpcodePosition;
683#endif
684
685        bool m_usesExceptions;
686        bool m_expressionTooDeep;
687        bool m_isBuiltinFunction;
688    };
689
690}
691
692#endif // BytecodeGenerator_h
693