From 635860845790a19bf50bbc51ba8fb66a96dde068 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 5 Mar 2009 14:34:32 -0800 Subject: auto import from //depot/cupcake/@136594 --- JavaScriptCore/bytecompiler/BytecodeGenerator.h | 480 ++++++++++++++++++++++++ 1 file changed, 480 insertions(+) create mode 100644 JavaScriptCore/bytecompiler/BytecodeGenerator.h (limited to 'JavaScriptCore/bytecompiler/BytecodeGenerator.h') diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h new file mode 100644 index 0000000..ceb5881 --- /dev/null +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich + * + * 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 +#include + +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 newLabelScope(LabelScope::Type, const Identifier* = 0); + PassRefPtr