⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bytecodegenerator.h

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 H
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1.  Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer. * 2.  Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution. * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of *     its contributors may be used to endorse or promote products derived *     from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#ifndef BytecodeGenerator_h#define BytecodeGenerator_h#include "CodeBlock.h"#include "HashTraits.h"#include "Instruction.h"#include "Label.h"#include "LabelScope.h"#include "Interpreter.h"#include "RegisterID.h"#include "SegmentedVector.h"#include "SymbolTable.h"#include "Debugger.h"#include "Nodes.h"#include <wtf/PassRefPtr.h>#include <wtf/Vector.h>namespace JSC {    class Identifier;    class ScopeChain;    class ScopeNode;    struct FinallyContext {        Label* finallyAddr;        RegisterID* retAddrDst;    };    struct ControlFlowContext {        bool isFinallyBlock;        FinallyContext finallyContext;    };    class BytecodeGenerator {    public:        typedef DeclarationStacks::VarStack VarStack;        typedef DeclarationStacks::FunctionStack FunctionStack;        static void setDumpsGeneratedCode(bool dumpsGeneratedCode);        static bool dumpsGeneratedCode();        BytecodeGenerator(ProgramNode*, const Debugger*, const ScopeChain&, SymbolTable*, ProgramCodeBlock*);        BytecodeGenerator(FunctionBodyNode*, const Debugger*, const ScopeChain&, SymbolTable*, CodeBlock*);        BytecodeGenerator(EvalNode*, const Debugger*, const ScopeChain&, SymbolTable*, EvalCodeBlock*);        JSGlobalData* globalData() const { return m_globalData; }        const CommonIdentifiers& propertyNames() const { return *m_globalData->propertyNames; }        void generate();        // Returns the register corresponding to a local variable, or 0 if no        // such register exists. Registers returned by registerFor do not        // require explicit reference counting.        RegisterID* registerFor(const Identifier&);        // Behaves as registerFor does, but ignores dynamic scope as        // dynamic scope should not interfere with const initialisation        RegisterID* constRegisterFor(const Identifier&);        // Searches the scope chain in an attempt to  statically locate the requested        // property.  Returns false if for any reason the property cannot be safely        // optimised at all.  Otherwise it will return the index and depth of the        // VariableObject that defines the property.  If the property cannot be found        // statically, depth will contain the depth of the scope chain where dynamic        // lookup must begin.        //        // NB: depth does _not_ include the local scope.  eg. a depth of 0 refers        // to the scope containing this codeblock.        bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, JSObject*& globalObject);        // Returns the register storing "this"        RegisterID* thisRegister() { return &m_thisRegister; }        bool isLocal(const Identifier&);        bool isLocalConstant(const Identifier&);        // Returns the next available temporary register. Registers returned by        // newTemporary require a modified form of reference counting: any        // register with a refcount of 0 is considered "available", meaning that        // the next instruction may overwrite it.        RegisterID* newTemporary();        RegisterID* highestUsedRegister();        // The same as newTemporary(), but this function returns "suggestion" if        // "suggestion" is a temporary. This function is helpful in situations        // where you've put "suggestion" in a RefPtr, but you'd like to allow        // the next instruction to overwrite it anyway.        RegisterID* newTemporaryOr(RegisterID* suggestion) { return suggestion->isTemporary() ? suggestion : newTemporary(); }        // Functions for handling of dst register        RegisterID* ignoredResult() { return &m_ignoredResultRegister; }        // Returns a place to write intermediate values of an operation        // which reuses dst if it is safe to do so.        RegisterID* tempDestination(RegisterID* dst)        {            return (dst && dst != ignoredResult() && dst->isTemporary()) ? dst : newTemporary();        }        // Returns the place to write the final output of an operation.        RegisterID* finalDestination(RegisterID* originalDst, RegisterID* tempDst = 0)        {            if (originalDst && originalDst != ignoredResult())                return originalDst;            ASSERT(tempDst != ignoredResult());            if (tempDst && tempDst->isTemporary())                return tempDst;            return newTemporary();        }        RegisterID* destinationForAssignResult(RegisterID* dst)        {            if (dst && dst != ignoredResult() && m_codeBlock->needsFullScopeChain())                return dst->isTemporary() ? dst : newTemporary();            return 0;        }        // Moves src to dst if dst is not null and is different from src, otherwise just returns src.        RegisterID* moveToDestinationIfNeeded(RegisterID* dst, RegisterID* src)        {            return dst == ignoredResult() ? 0 : (dst && dst != src) ? emitMove(dst, src) : src;        }        PassRefPtr<LabelScope> newLabelScope(LabelScope::Type, const Identifier* = 0);        PassRefPtr<Label> newLabel();        // The emitNode functions are just syntactic sugar for calling        // Node::emitCode. These functions accept a 0 for the register,        // meaning that the node should allocate a register, or ignoredResult(),        // meaning that the node need not put the result in a register.        // Other emit functions do not accept 0 or ignoredResult().        RegisterID* emitNode(RegisterID* dst, Node* n)        {            // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.            ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());            if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) {                LineInfo info = { instructions().size(), n->lineNo() };                m_codeBlock->addLineInfo(info);            }            if (m_emitNodeDepth >= s_maxEmitNodeDepth)                return emitThrowExpressionTooDeepException();            ++m_emitNodeDepth;            RegisterID* r = n->emitBytecode(*this, dst);            --m_emitNodeDepth;            return r;        }        RegisterID* emitNode(Node* n)        {            return emitNode(0, n);        }        void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset)        {             divot -= m_codeBlock->sourceOffset();            if (divot > ExpressionRangeInfo::MaxDivot) {                // Overflow has occurred, we can only give line number info for errors for this region                divot = 0;                startOffset = 0;                endOffset = 0;            } else if (startOffset > ExpressionRangeInfo::MaxOffset) {                // If the start offset is out of bounds we clear both offsets                // so we only get the divot marker.  Error message will have to be reduced                // to line and column number.                startOffset = 0;                endOffset = 0;            } else if (endOffset > ExpressionRangeInfo::MaxOffset) {                // The end offset is only used for additional context, and is much more likely                // to overflow (eg. function call arguments) so we are willing to drop it without                // dropping the rest of the range.                endOffset = 0;            }                        ExpressionRangeInfo info;            info.instructionOffset = instructions().size();            info.divotPoint = divot;            info.startOffset = startOffset;            info.endOffset = endOffset;            m_codeBlock->addExpressionInfo(info);        }        void emitGetByIdExceptionInfo(OpcodeID opcodeID)        {            // Only op_construct and op_instanceof need exception info for            // a preceding op_get_by_id.            ASSERT(opcodeID == op_construct || opcodeID == op_instanceof);            GetByIdExceptionInfo info;            info.bytecodeOffset = instructions().size();            info.isOpConstruct = (opcodeID == op_construct);            m_codeBlock->addGetByIdExceptionInfo(info);        }                ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)        {            return (m_codeType != FunctionCode || m_codeBlock->needsFullScopeChain() || rightHasAssignments) && !rightIsPure;        }        ALWAYS_INLINE PassRefPtr<RegisterID> emitNodeForLeftHandSide(ExpressionNode* n, bool rightHasAssignments, bool rightIsPure)        {            if (leftHandSideNeedsCopy(rightHasAssignments, rightIsPure)) {                PassRefPtr<RegisterID> dst = newTemporary();                emitNode(dst.get(), n);                return dst;            }            return PassRefPtr<RegisterID>(emitNode(n));        }        RegisterID* emitLoad(RegisterID* dst, bool);        RegisterID* emitLoad(RegisterID* dst, double);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -