📄 codegen-ia32.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 {#define TOS (Operand(esp, 0))class Ia32CodeGenerator;// Mode to overwrite BinaryExpression values.enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };// -----------------------------------------------------------------------------// 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(Ia32CodeGenerator* 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: Ia32CodeGenerator* 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(Ia32CodeGenerator* 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(Ia32CodeGenerator* 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(Ia32CodeGenerator* 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: Ia32CodeGenerator* owner_; AccessType access_; Reference* ref_; Label* true_target_; Label* false_target_; CodeGenState* previous_;};// -----------------------------------------------------------------------------// Ia32CodeGeneratorclass Ia32CodeGenerator: 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_; bool is_inside_try_; int break_stack_height_; // Labels Label function_return_; // Construction/destruction Ia32CodeGenerator(int buffer_size, Handle<Script> script, bool is_eval); virtual ~Ia32CodeGenerator() { 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_ >= 0; } 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 Operand GlobalObject() const { return ContextOperand(esi, Context::GLOBAL_INDEX); } // Support functions for accessing parameters. Static versions can // require some code generator state to be passed in as arguments. static Operand ParameterOperand(Scope* scope, int index) { ASSERT(-2 <= index && index < scope->num_parameters()); return Operand(ebp, (1 + scope->num_parameters() - index) * kPointerSize); } Operand ParameterOperand(int index) const { return ParameterOperand(scope_, index); } Operand ReceiverOperand() const { return ParameterOperand(-1); } Operand FunctionOperand() const { return Operand(ebp, JavaScriptFrameConstants::kFunctionOffset); } static Operand ContextOperand(Register context, int index) { return Operand(context, Context::SlotOffset(index)); } static Operand SlotOperand(MacroAssembler* masm, Scope* scope, Slot* slot, Register tmp); Operand 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); } // Same as SetValue, used to set the initial value of a constant. 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, const OverwriteMode overwrite_mode = NO_OVERWRITE); void Comparison(Condition cc, bool strict = false); // Inline small integer literals. To prevent long attacker-controlled byte // sequences, we only inline small Smi:s. static const int kMaxSmiInlinedBits = 16; bool IsInlineSmi(Literal* literal); void SmiComparison(Condition cc, Handle<Object> value, bool strict = false); void SmiOperation(Token::Value op, Handle<Object> value, bool reversed, OverwriteMode overwrite_mode); 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 // Only allow fast-case switch if the range of labels is at most // this factor times the number of case labels. // Value is derived from comparing the size of code generated by the normal // switch code for Smi-labels to the size of a single pointer. If code // quality increases this number should be decreased to match. static const int kFastSwitchMaxOverheadFactor = 5; // Minimal number of switch cases required before we allow jump-table // optimization. static const int kFastSwitchMinCaseCount = 5; // Create fast switch implementation if all labels are small integers // in a limited range. Returns false if this is not the case, and no // code has been generated (i.e., the default implementation should be used). bool TryFastCaseSwitchStatement(SwitchStatement *switchStmt); // Generate a computed jump with an empty jump table. // Binds a label to the start of the jump table. This table must // be populated later when the adresses of the targets are known. // Used by GenerateFastCaseSwitchStatement. void GenerateFastCaseSwitchJumpTable( int min_index, int range, Label *fail_label, Label &table_start); // Populate an empty jump table with the adresses of bound labels. // Used by GenerateFastCaseSwitchStatement. void PopulateFastCaseSwitchJumpTable( Label &table_start, SmartPointer<Label*> &case_targets, int table_size); // Generates a fast-case switch statement for a switch with all-Smi labels // in a limited range. // Used by TryFastCaseSwitchStatement. void GenerateFastCaseSwitchStatement( SwitchStatement *node, int min_index, int range, int default_index); 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(Ia32CodeGenerator* owner) : owner_(owner), access_(UNDEFINED),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -