1/*
2 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef BytecodeGenerator_h
31#define BytecodeGenerator_h
32
33#include "CodeBlock.h"
34#include "HashTraits.h"
35#include "Instruction.h"
36#include "Label.h"
37#include "LabelScope.h"
38#include "Interpreter.h"
39#include "RegisterID.h"
40#include "SymbolTable.h"
41#include "Debugger.h"
42#include "Nodes.h"
43#include <wtf/PassRefPtr.h>
44#include <wtf/SegmentedVector.h>
45#include <wtf/Vector.h>
46
47namespace JSC {
48
49    class Identifier;
50    class ScopeChainNode;
51
52    class CallArguments {
53    public:
54        CallArguments(BytecodeGenerator& generator, ArgumentsNode* argumentsNode);
55
56        RegisterID* thisRegister() { return m_argv[0].get(); }
57        RegisterID* argumentRegister(unsigned i) { return m_argv[i + 1].get(); }
58        unsigned callFrame() { return thisRegister()->index() + count() + RegisterFile::CallFrameHeaderSize; }
59        unsigned count() { return m_argv.size(); }
60        RegisterID* profileHookRegister() { return m_profileHookRegister.get(); }
61        ArgumentsNode* argumentsNode() { return m_argumentsNode; }
62
63    private:
64        RefPtr<RegisterID> m_profileHookRegister;
65        ArgumentsNode* m_argumentsNode;
66        Vector<RefPtr<RegisterID>, 16> m_argv;
67    };
68
69    struct FinallyContext {
70        Label* finallyAddr;
71        RegisterID* retAddrDst;
72    };
73
74    struct ControlFlowContext {
75        bool isFinallyBlock;
76        FinallyContext finallyContext;
77    };
78
79    struct ForInContext {
80        RefPtr<RegisterID> expectedSubscriptRegister;
81        RefPtr<RegisterID> iterRegister;
82        RefPtr<RegisterID> indexRegister;
83        RefPtr<RegisterID> propertyRegister;
84    };
85
86    class BytecodeGenerator {
87        WTF_MAKE_FAST_ALLOCATED;
88    public:
89        typedef DeclarationStacks::VarStack VarStack;
90        typedef DeclarationStacks::FunctionStack FunctionStack;
91
92        static void setDumpsGeneratedCode(bool dumpsGeneratedCode);
93        static bool dumpsGeneratedCode();
94
95        BytecodeGenerator(ProgramNode*, ScopeChainNode*, SymbolTable*, ProgramCodeBlock*);
96        BytecodeGenerator(FunctionBodyNode*, ScopeChainNode*, SymbolTable*, CodeBlock*);
97        BytecodeGenerator(EvalNode*, ScopeChainNode*, SymbolTable*, EvalCodeBlock*);
98
99        JSGlobalData* globalData() const { return m_globalData; }
100        const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }
101
102        bool isConstructor() { return m_codeBlock->m_isConstructor; }
103
104        JSObject* generate();
105
106        // Returns the register corresponding to a local variable, or 0 if no
107        // such register exists. Registers returned by registerFor do not
108        // require explicit reference counting.
109        RegisterID* registerFor(const Identifier&);
110
111        // Returns the agument number if this is an argument, or 0 if not.
112        int argumentNumberFor(const Identifier&);
113
114        void setIsNumericCompareFunction(bool isNumericCompareFunction);
115
116        bool willResolveToArguments(const Identifier&);
117        RegisterID* uncheckedRegisterForArguments();
118
119        // Behaves as registerFor does, but ignores dynamic scope as
120        // dynamic scope should not interfere with const initialisation
121        RegisterID* constRegisterFor(const Identifier&);
122
123        // Searches the scope chain in an attempt to  statically locate the requested
124        // property.  Returns false if for any reason the property cannot be safely
125        // optimised at all.  Otherwise it will return the index and depth of the
126        // VariableObject that defines the property.  If the property cannot be found
127        // statically, depth will contain the depth of the scope chain where dynamic
128        // lookup must begin.
129        bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
130
131        // Returns the register storing "this"
132        RegisterID* thisRegister() { return &m_thisRegister; }
133
134        bool isLocal(const Identifier&);
135        bool isLocalConstant(const Identifier&);
136
137        // Returns the next available temporary register. Registers returned by
138        // newTemporary require a modified form of reference counting: any
139        // register with a refcount of 0 is considered "available", meaning that
140        // the next instruction may overwrite it.
141        RegisterID* newTemporary();
142
143        RegisterID* highestUsedRegister();
144
145        // The same as newTemporary(), but this function returns "suggestion" if
146        // "suggestion" is a temporary. This function is helpful in situations
147        // where you've put "suggestion" in a RefPtr, but you'd like to allow
148        // the next instruction to overwrite it anyway.
149        RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }
150
151        // Functions for handling of dst register
152
153        RegisterID* ignoredResult() { return &m_ignoredResultRegister; }
154
155        // Returns a place to write intermediate values of an operation
156        // which reuses dst if it is safe to do so.
157        RegisterID* tempDestination(RegisterID* dst)
158        {
159            return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();
160        }
161
162        // Returns the place to write the final output of an operation.
163        RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)
164        {
165            if (originalDst && originalDst != ignoredResult())
166                return originalDst;
167            ASSERT(tempDst != ignoredResult());
168            if (tempDst && tempDst->isTemporary())
169                return tempDst;
170            return newTemporary();
171        }
172
173        // Returns the place to write the final output of an operation.
174        RegisterID* finalDestinationOrIgnored(RegisterID* originalDst, RegisterID* tempDst = 0)
175        {
176            if (originalDst)
177                return originalDst;
178            ASSERT(tempDst != ignoredResult());
179            if (tempDst && tempDst->isTemporary())
180                return tempDst;
181            return newTemporary();
182        }
183
184        RegisterID* destinationForAssignResult(RegisterID* dst)
185        {
186            if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())
187                return dst->isTemporary() ? dst : newTemporary();
188            return 0;
189        }
190
191        // Moves src to dst if dst is not null and is different from src, otherwise just returns src.
192        RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)
193        {
194            return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;
195        }
196
197        PassRefPtr<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0);
198        PassRefPtr<Label> newLabel();
199
200        // The emitNode functions are just syntactic sugar for calling
201        // Node::emitCode. These functions accept a 0 for the register,
202        // meaning that the node should allocate a register, or ignoredResult(),
203        // meaning that the node need not put the result in a register.
204        // Other emit functions do not accept 0 or ignoredResult().
205        RegisterID* emitNode(RegisterID* dst, Node* n)
206        {
207            // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
208            ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
209            addLineInfo(n->lineNo());
210            return m_stack.recursionCheck()
211                ? n->emitBytecode(*this, dst)
212                : emitThrowExpressionTooDeepException();
213        }
214
215        RegisterID* emitNode(Node* n)
216        {
217            return emitNode(0, n);
218        }
219
220        void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
221        {
222            addLineInfo(n->lineNo());
223            if (m_stack.recursionCheck())
224                n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
225            else
226                emitThrowExpressionTooDeepException();
227        }
228
229        void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)
230        {
231            if (!m_shouldEmitRichSourceInfo)
232                return;
233
234            divot -= m_codeBlock->sourceOffset();
235            if (divot > ExpressionRangeInfo::MaxDivot) {
236                // Overflow has occurred, we can only give line number info for errors for this region
237                divot = 0;
238                startOffset = 0;
239                endOffset = 0;
240            } else if (startOffset > ExpressionRangeInfo::MaxOffset) {
241                // If the start offset is out of bounds we clear both offsets
242                // so we only get the divot marker.  Error message will have to be reduced
243                // to line and column number.
244                startOffset = 0;
245                endOffset = 0;
246            } else if (endOffset > ExpressionRangeInfo::MaxOffset) {
247                // The end offset is only used for additional context, and is much more likely
248                // to overflow (eg. function call arguments) so we are willing to drop it without
249                // dropping the rest of the range.
250                endOffset = 0;
251            }
252
253            ExpressionRangeInfo info;
254            info.instructionOffset = instructions().size();
255            info.divotPoint = divot;
256            info.startOffset = startOffset;
257            info.endOffset = endOffset;
258            m_codeBlock->addExpressionInfo(info);
259        }
260
261        ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
262        {
263            return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;
264        }
265
266        ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)
267        {
268            if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {
269                PassRefPtr<RegisterID> dst = newTemporary();
270                emitNode(dst.get(), n);
271                return dst;
272            }
273
274            return PassRefPtr<RegisterID>(emitNode(n));
275        }
276
277        RegisterID* emitLoad(RegisterID* dst, bool);
278        RegisterID* emitLoad(RegisterID* dst, double);
279        RegisterID* emitLoad(RegisterID* dst, const Identifier&);
280        RegisterID* emitLoad(RegisterID* dst, JSValue);
281
282        RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src);
283        RegisterID* emitBinaryOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2, OperandTypes);
284        RegisterID* emitEqualityOp(OpcodeID, RegisterID* dst, RegisterID* src1, RegisterID* src2);
285        RegisterID* emitUnaryNoDstOp(OpcodeID, RegisterID* src);
286
287        RegisterID* emitNewObject(RegisterID* dst);
288        RegisterID* emitNewArray(RegisterID* dst, ElementNode*); // stops at first elision
289
290        RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body);
291        RegisterID* emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* body);
292        RegisterID* emitNewFunctionInternal(RegisterID* dst, unsigned index, bool shouldNullCheck);
293        RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func);
294        RegisterID* emitNewRegExp(RegisterID* dst, PassRefPtr<RegExp> regExp);
295
296        RegisterID* emitMove(RegisterID* dst, RegisterID* src);
297
298        RegisterID* emitToJSNumber(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_to_jsnumber, dst, src); }
299        RegisterID* emitPreInc(RegisterID* srcDst);
300        RegisterID* emitPreDec(RegisterID* srcDst);
301        RegisterID* emitPostInc(RegisterID* dst, RegisterID* srcDst);
302        RegisterID* emitPostDec(RegisterID* dst, RegisterID* srcDst);
303
304        void emitCheckHasInstance(RegisterID* base);
305        RegisterID* emitInstanceOf(RegisterID* dst, RegisterID* value, RegisterID* base, RegisterID* basePrototype);
306        RegisterID* emitTypeOf(RegisterID* dst, RegisterID* src) { return emitUnaryOp(op_typeof, dst, src); }
307        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
308
309        RegisterID* emitResolve(RegisterID* dst, const Identifier& property);
310        RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue globalObject);
311        RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject);
312
313        RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
314        RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
315        RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
316
317        void emitMethodCheck();
318
319        RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property);
320        RegisterID* emitGetArgumentsLength(RegisterID* dst, RegisterID* base);
321        RegisterID* emitPutById(RegisterID* base, const Identifier& property, RegisterID* value);
322        RegisterID* emitDirectPutById(RegisterID* base, const Identifier& property, RegisterID* value);
323        RegisterID* emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier&);
324        RegisterID* emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
325        RegisterID* emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
326        RegisterID* emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value);
327        RegisterID* emitDeleteByVal(RegisterID* dst, RegisterID* base, RegisterID* property);
328        RegisterID* emitPutByIndex(RegisterID* base, unsigned index, RegisterID* value);
329        RegisterID* emitPutGetter(RegisterID* base, const Identifier& property, RegisterID* value);
330        RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value);
331
332        RegisterID* emitCall(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
333        RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
334        RegisterID* emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCount, unsigned divot, unsigned startOffset, unsigned endOffset);
335        RegisterID* emitLoadVarargs(RegisterID* argCountDst, RegisterID* thisRegister, RegisterID* args);
336
337        RegisterID* emitReturn(RegisterID* src);
338        RegisterID* emitEnd(RegisterID* src) { return emitUnaryNoDstOp(op_end, src); }
339
340        RegisterID* emitConstruct(RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
341        RegisterID* emitStrcat(RegisterID* dst, RegisterID* src, int count);
342        void emitToPrimitive(RegisterID* dst, RegisterID* src);
343
344        PassRefPtr<Label> emitLabel(Label*);
345        PassRefPtr<Label> emitJump(Label* target);
346        PassRefPtr<Label> emitJumpIfTrue(RegisterID* cond, Label* target);
347        PassRefPtr<Label> emitJumpIfFalse(RegisterID* cond, Label* target);
348        PassRefPtr<Label> emitJumpIfNotFunctionCall(RegisterID* cond, Label* target);
349        PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
350        PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth);
351
352        PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*);
353        void emitSubroutineReturn(RegisterID* retAddrSrc);
354
355        RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
356        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
357
358        RegisterID* emitCatch(RegisterID*, Label* start, Label* end);
359        void emitThrow(RegisterID* exc)
360        {
361            m_usesExceptions = true;
362            emitUnaryNoDstOp(op_throw, exc);
363        }
364
365        void emitThrowReferenceError(const UString& message);
366
367        void emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value);
368
369        RegisterID* emitPushScope(RegisterID* scope);
370        void emitPopScope();
371
372        void emitDebugHook(DebugHookID, int firstLine, int lastLine);
373
374        int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; }
375        bool hasFinaliser() { return m_finallyDepth != 0; }
376
377        void pushFinallyContext(Label* target, RegisterID* returnAddrDst);
378        void popFinallyContext();
379
380        void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
381        {
382            ForInContext context = { expectedBase, iter, index, propertyRegister };
383            m_forInContextStack.append(context);
384        }
385
386        void popOptimisedForIn()
387        {
388            m_forInContextStack.removeLast();
389        }
390
391        LabelScope* breakTarget(const Identifier&);
392        LabelScope* continueTarget(const Identifier&);
393
394        void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
395        void endSwitch(uint32_t clauseCount, RefPtr<Label>*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
396
397        CodeType codeType() const { return m_codeType; }
398
399        bool shouldEmitProfileHooks() { return m_shouldEmitProfileHooks; }
400
401        bool isStrictMode() const { return m_codeBlock->isStrictMode(); }
402
403    private:
404        void emitOpcode(OpcodeID);
405        void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
406        void retrieveLastUnaryOp(int& dstIndex, int& srcIndex);
407        ALWAYS_INLINE void rewindBinaryOp();
408        ALWAYS_INLINE void rewindUnaryOp();
409
410        PassRefPtr<Label> emitComplexJumpScopes(Label* target, ControlFlowContext* topScope, ControlFlowContext* bottomScope);
411
412        typedef HashMap<EncodedJSValue, unsigned, EncodedJSValueHash, EncodedJSValueHashTraits> JSValueMap;
413
414        struct IdentifierMapIndexHashTraits {
415            typedef int TraitType;
416            typedef IdentifierMapIndexHashTraits StorageTraits;
417            static int emptyValue() { return std::numeric_limits<int>::max(); }
418            static const bool emptyValueIsZero = false;
419            static const bool needsDestruction = false;
420            static const bool needsRef = false;
421        };
422
423        typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, IdentifierMapIndexHashTraits> IdentifierMap;
424        typedef HashMap<double, JSValue> NumberMap;
425        typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap;
426
427        RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, CallArguments&, unsigned divot, unsigned startOffset, unsigned endOffset);
428
429        RegisterID* newRegister();
430
431        // Adds a var slot and maps it to the name ident in symbolTable().
432        RegisterID* addVar(const Identifier& ident, bool isConstant)
433        {
434            RegisterID* local;
435            addVar(ident, isConstant, local);
436            return local;
437        }
438
439        // Ditto. Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
440        bool addVar(const Identifier&, bool isConstant, RegisterID*&);
441
442        // Adds an anonymous var slot. To give this slot a name, add it to symbolTable().
443        RegisterID* addVar()
444        {
445            ++m_codeBlock->m_numVars;
446            return newRegister();
447        }
448
449        // Returns the RegisterID corresponding to ident.
450        RegisterID* addGlobalVar(const Identifier& ident, bool isConstant)
451        {
452            RegisterID* local;
453            addGlobalVar(ident, isConstant, local);
454            return local;
455        }
456        // Returns true if a new RegisterID was added, false if a pre-existing RegisterID was re-used.
457        bool addGlobalVar(const Identifier&, bool isConstant, RegisterID*&);
458
459        void addParameter(const Identifier&, int parameterIndex);
460
461        void preserveLastVar();
462
463        RegisterID& registerFor(int index)
464        {
465            if (index >= 0)
466                return m_calleeRegisters[index];
467
468            if (m_parameters.size()) {
469                ASSERT(!m_globals.size());
470                return m_parameters[index + m_parameters.size() + RegisterFile::CallFrameHeaderSize];
471            }
472
473            return m_globals[-index - 1];
474        }
475
476        unsigned addConstant(const Identifier&);
477        RegisterID* addConstantValue(JSValue);
478        unsigned addRegExp(PassRefPtr<RegExp>);
479
480        FunctionExecutable* makeFunction(ExecState* exec, FunctionBodyNode* body)
481        {
482            return FunctionExecutable::create(exec, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
483        }
484
485        FunctionExecutable* makeFunction(JSGlobalData* globalData, FunctionBodyNode* body)
486        {
487            return FunctionExecutable::create(globalData, body->ident(), body->source(), body->usesArguments(), body->parameters(), body->isStrictMode(), body->lineNo(), body->lastLine());
488        }
489
490        void addLineInfo(unsigned lineNo)
491        {
492#if !ENABLE(OPCODE_SAMPLING)
493            if (m_shouldEmitRichSourceInfo)
494#endif
495                m_codeBlock->addLineInfo(instructions().size(), lineNo);
496        }
497
498        RegisterID* emitInitLazyRegister(RegisterID*);
499
500        Vector<Instruction>& instructions() { return m_codeBlock->instructions(); }
501        SymbolTable& symbolTable() { return *m_symbolTable; }
502
503        bool shouldOptimizeLocals() { return (m_codeType != EvalCode) && !m_dynamicScopeDepth; }
504        bool canOptimizeNonLocals() { return (m_codeType == FunctionCode) && !m_dynamicScopeDepth && !m_codeBlock->usesEval(); }
505
506        RegisterID* emitThrowExpressionTooDeepException();
507
508        void createArgumentsIfNecessary();
509        void createActivationIfNecessary();
510        RegisterID* createLazyRegisterIfNecessary(RegisterID*);
511
512        bool m_shouldEmitDebugHooks;
513        bool m_shouldEmitProfileHooks;
514        bool m_shouldEmitRichSourceInfo;
515
516        Strong<ScopeChainNode> m_scopeChain;
517        SymbolTable* m_symbolTable;
518
519        ScopeNode* m_scopeNode;
520        CodeBlock* m_codeBlock;
521
522        // Some of these objects keep pointers to one another. They are arranged
523        // to ensure a sane destruction order that avoids references to freed memory.
524        HashSet<RefPtr<StringImpl>, IdentifierRepHash> m_functions;
525        RegisterID m_ignoredResultRegister;
526        RegisterID m_thisRegister;
527        RegisterID* m_activationRegister;
528        SegmentedVector<RegisterID, 32> m_constantPoolRegisters;
529        SegmentedVector<RegisterID, 32> m_calleeRegisters;
530        SegmentedVector<RegisterID, 32> m_parameters;
531        SegmentedVector<RegisterID, 32> m_globals;
532        SegmentedVector<Label, 32> m_labels;
533        SegmentedVector<LabelScope, 8> m_labelScopes;
534        RefPtr<RegisterID> m_lastVar;
535        int m_finallyDepth;
536        int m_dynamicScopeDepth;
537        int m_baseScopeDepth;
538        CodeType m_codeType;
539
540        Vector<ControlFlowContext> m_scopeContextStack;
541        Vector<SwitchInfo> m_switchContextStack;
542        Vector<ForInContext> m_forInContextStack;
543
544        int m_nextGlobalIndex;
545        int m_firstConstantIndex;
546        int m_nextConstantOffset;
547        unsigned m_globalConstantIndex;
548
549        int m_globalVarStorageOffset;
550
551        bool m_hasCreatedActivation;
552        int m_firstLazyFunction;
553        int m_lastLazyFunction;
554        HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions;
555        typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
556        FunctionOffsetMap m_functionOffsets;
557
558        // Constant pool
559        IdentifierMap m_identifierMap;
560        JSValueMap m_jsValueMap;
561        NumberMap m_numberMap;
562        IdentifierStringMap m_stringMap;
563
564        JSGlobalData* m_globalData;
565
566        OpcodeID m_lastOpcodeID;
567#ifndef NDEBUG
568        size_t m_lastOpcodePosition;
569#endif
570
571        StackBounds m_stack;
572
573        bool m_usesExceptions;
574        bool m_expressionTooDeep;
575    };
576
577}
578
579#endif // BytecodeGenerator_h
580