Home | History | Annotate | Download | only in bytecompiler
      1 /*
      2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Cameron Zwarich <cwzwarich (at) 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 
     47 namespace 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