📄 codegen-arm.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * 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.// * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT// OWNER OR 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.#include "v8.h"#include "bootstrapper.h"#include "codegen-inl.h"#include "debug.h"#include "prettyprinter.h"#include "scopeinfo.h"#include "scopes.h"#include "runtime.h"namespace v8 { namespace internal {class ArmCodeGenerator;// -----------------------------------------------------------------------------// Reference support// A reference is a C++ stack-allocated object that keeps an ECMA// reference on the execution stack while in scope. For variables// the reference is empty, indicating that it isn't necessary to// store state on the stack for keeping track of references to those.// For properties, we keep either one (named) or two (indexed) values// on the execution stack to represent the reference.class Reference BASE_EMBEDDED { public: enum Type { ILLEGAL = -1, EMPTY = 0, NAMED = 1, KEYED = 2 }; Reference(ArmCodeGenerator* cgen, Expression* expression); ~Reference(); Expression* expression() const { return expression_; } Type type() const { return type_; } void set_type(Type value) { ASSERT(type_ == ILLEGAL); type_ = value; } int size() const { return type_; } bool is_illegal() const { return type_ == ILLEGAL; } private: ArmCodeGenerator* cgen_; Expression* expression_; Type type_;};// -------------------------------------------------------------------------// Code generation state// The state is passed down the AST by the code generator. It is passed// implicitly (in a member variable) to the non-static code generator member// functions, and explicitly (as an argument) to the static member functions// and the AST node member functions.//// The state is threaded through the call stack. Constructing a state// implicitly pushes it on the owning code generator's stack of states, and// destroying one implicitly pops it.class CodeGenState BASE_EMBEDDED { public: enum AccessType { UNDEFINED, LOAD, LOAD_TYPEOF_EXPR }; // Create an initial code generator state. Destroying the initial state // leaves the code generator with a NULL state. explicit CodeGenState(ArmCodeGenerator* owner); // Create a code generator state based on a code generator's current // state. The new state has its own access type and pair of branch // labels, and no reference. CodeGenState(ArmCodeGenerator* owner, AccessType access, Label* true_target, Label* false_target); // Create a code generator state based on a code generator's current // state. The new state has an access type of LOAD, its own reference, // and inherits the pair of branch labels of the current state. CodeGenState(ArmCodeGenerator* owner, Reference* ref); // Destroy a code generator state and restore the owning code generator's // previous state. ~CodeGenState(); AccessType access() const { return access_; } Reference* ref() const { return ref_; } Label* true_target() const { return true_target_; } Label* false_target() const { return false_target_; } private: ArmCodeGenerator* owner_; AccessType access_; Reference* ref_; Label* true_target_; Label* false_target_; CodeGenState* previous_;};// -----------------------------------------------------------------------------// ArmCodeGeneratorclass ArmCodeGenerator: public CodeGenerator { public: static Handle<Code> MakeCode(FunctionLiteral* fun, Handle<Script> script, bool is_eval); MacroAssembler* masm() { return masm_; } CodeGenState* state() { return state_; } void set_state(CodeGenState* state) { state_ = state; } private: // Assembler MacroAssembler* masm_; // to generate code // Code generation state Scope* scope_; Condition cc_reg_; CodeGenState* state_; int break_stack_height_; // Labels Label function_return_; // Construction/destruction ArmCodeGenerator(int buffer_size, Handle<Script> script, bool is_eval); virtual ~ArmCodeGenerator() { delete masm_; } // Main code generation function void GenCode(FunctionLiteral* fun); // The following are used by class Reference. void LoadReference(Reference* ref); void UnloadReference(Reference* ref); // State bool has_cc() const { return cc_reg_ != al; } CodeGenState::AccessType access() const { return state_->access(); } Reference* ref() const { return state_->ref(); } bool is_referenced() const { return state_->ref() != NULL; } Label* true_target() const { return state_->true_target(); } Label* false_target() const { return state_->false_target(); } // Expressions MemOperand GlobalObject() const { return ContextOperand(cp, Context::GLOBAL_INDEX); } static MemOperand ContextOperand(Register context, int index) { return MemOperand(context, Context::SlotOffset(index)); } static MemOperand ParameterOperand(Scope* scope, int index) { // index -2 corresponds to the activated closure, -1 corresponds // to the receiver ASSERT(-2 <= index && index < scope->num_parameters()); int offset = (1 + scope->num_parameters() - index) * kPointerSize; return MemOperand(fp, offset); } MemOperand ParameterOperand(int index) const { return ParameterOperand(scope_, index); } MemOperand FunctionOperand() const { return MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset); } static MemOperand SlotOperand(MacroAssembler* masm, Scope* scope, Slot* slot, Register tmp); MemOperand SlotOperand(Slot* slot, Register tmp) { return SlotOperand(masm_, scope_, slot, tmp); } void LoadCondition(Expression* x, CodeGenState::AccessType access, Label* true_target, Label* false_target, bool force_cc); void Load(Expression* x, CodeGenState::AccessType access = CodeGenState::LOAD); void LoadGlobal(); // Special code for typeof expressions: Unfortunately, we must // be careful when loading the expression in 'typeof' // expressions. We are not allowed to throw reference errors for // non-existing properties of the global object, so we must make it // look like an explicit property access, instead of an access // through the context chain. void LoadTypeofExpression(Expression* x); // References // Generate code to fetch the value of a reference. The reference is // expected to be on top of the expression stack. It is left in place and // its value is pushed on top of it. void GetValue(Reference* ref) { ASSERT(!has_cc()); ASSERT(!ref->is_illegal()); CodeGenState new_state(this, ref); Visit(ref->expression()); } // Generate code to store a value in a reference. The stored value is // expected on top of the expression stack, with the reference immediately // below it. The expression stack is left unchanged. void SetValue(Reference* ref) { ASSERT(!has_cc()); ASSERT(!ref->is_illegal()); ref->expression()->GenerateStoreCode(masm_, scope_, ref, NOT_CONST_INIT); } // Generate code to store a value in a reference. The stored value is // expected on top of the expression stack, with the reference immediately // below it. The expression stack is left unchanged. void InitConst(Reference* ref) { ASSERT(!has_cc()); ASSERT(!ref->is_illegal()); ref->expression()->GenerateStoreCode(masm_, scope_, ref, CONST_INIT); } // Generate code to fetch a value from a property of a reference. The // reference is expected on top of the expression stack. It is left in // place and its value is pushed on top of it. void GetReferenceProperty(Expression* key); // Generate code to store a value in a property of a reference. The // stored value is expected on top of the expression stack, with the // reference immediately below it. The expression stack is left // unchanged. static void SetReferenceProperty(MacroAssembler* masm, Reference* ref, Expression* key); void ToBoolean(Label* true_target, Label* false_target); void GenericBinaryOperation(Token::Value op); void Comparison(Condition cc, bool strict = false); void SmiOperation(Token::Value op, Handle<Object> value, bool reversed); void CallWithArguments(ZoneList<Expression*>* arguments, int position); // Declare global variables and functions in the given array of // name/value pairs. virtual void DeclareGlobals(Handle<FixedArray> pairs); // Instantiate the function boilerplate. void InstantiateBoilerplate(Handle<JSFunction> boilerplate); // Control flow void Branch(bool if_true, Label* L); void CheckStack(); void CleanStack(int num_bytes); // Node visitors#define DEF_VISIT(type) \ virtual void Visit##type(type* node); NODE_LIST(DEF_VISIT)#undef DEF_VISIT void RecordStatementPosition(Node* node); // Activation frames void EnterJSFrame(); void ExitJSFrame(); virtual void GenerateIsSmi(ZoneList<Expression*>* args); virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args); virtual void GenerateIsArray(ZoneList<Expression*>* args); virtual void GenerateArgumentsLength(ZoneList<Expression*>* args); virtual void GenerateArgumentsAccess(ZoneList<Expression*>* args); virtual void GenerateValueOf(ZoneList<Expression*>* args); virtual void GenerateSetValueOf(ZoneList<Expression*>* args); virtual void GenerateFastCharCodeAt(ZoneList<Expression*>* args); virtual void GenerateObjectEquals(ZoneList<Expression*>* args); friend class Reference; friend class Property; friend class VariableProxy; friend class Slot;};// -------------------------------------------------------------------------// CodeGenState implementation.CodeGenState::CodeGenState(ArmCodeGenerator* owner) : owner_(owner), access_(UNDEFINED), ref_(NULL), true_target_(NULL), false_target_(NULL), previous_(NULL) { owner_->set_state(this);}CodeGenState::CodeGenState(ArmCodeGenerator* owner, AccessType access, Label* true_target, Label* false_target) : owner_(owner), access_(access), ref_(NULL), true_target_(true_target), false_target_(false_target), previous_(owner->state()) { owner_->set_state(this);}CodeGenState::CodeGenState(ArmCodeGenerator* owner, Reference* ref) : owner_(owner), access_(LOAD), ref_(ref), true_target_(owner->state()->true_target_), false_target_(owner->state()->false_target_), previous_(owner->state()) { owner_->set_state(this);}CodeGenState::~CodeGenState() { ASSERT(owner_->state() == this); owner_->set_state(previous_);}// -----------------------------------------------------------------------------// ArmCodeGenerator implementation#define __ masm_->Handle<Code> ArmCodeGenerator::MakeCode(FunctionLiteral* flit, Handle<Script> script, bool is_eval) {#ifdef ENABLE_DISASSEMBLER bool print_code = FLAG_print_code && !Bootstrapper::IsActive();#endif // ENABLE_DISASSEMBLER#ifdef DEBUG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -