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

📄 codegen-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
// 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 + -