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

📄 codegen-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
      ref_(NULL),      true_target_(NULL),      false_target_(NULL),      previous_(NULL) {  owner_->set_state(this);}CodeGenState::CodeGenState(Ia32CodeGenerator* 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(Ia32CodeGenerator* 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_);}// -----------------------------------------------------------------------------// Ia32CodeGenerator implementation#define __  masm_->Handle<Code> Ia32CodeGenerator::MakeCode(FunctionLiteral* flit,                                         Handle<Script> script,                                         bool is_eval) {#ifdef ENABLE_DISASSEMBLER  bool print_code = FLAG_print_code && !Bootstrapper::IsActive();#endif#ifdef DEBUG  bool print_source = false;  bool print_ast = false;  const char* ftype;  if (Bootstrapper::IsActive()) {    print_source = FLAG_print_builtin_source;    print_ast = FLAG_print_builtin_ast;    print_code = FLAG_print_builtin_code;    ftype = "builtin";  } else {    print_source = FLAG_print_source;    print_ast = FLAG_print_ast;    ftype = "user-defined";  }  if (FLAG_trace_codegen || print_source || print_ast) {    PrintF("*** Generate code for %s function: ", ftype);    flit->name()->ShortPrint();    PrintF(" ***\n");  }  if (print_source) {    PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(flit));  }  if (print_ast) {    PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(flit));  }#endif  // DEBUG  // Generate code.  const int initial_buffer_size = 4 * KB;  Ia32CodeGenerator cgen(initial_buffer_size, script, is_eval);  cgen.GenCode(flit);  if (cgen.HasStackOverflow()) {    ASSERT(!Top::has_pending_exception());    return Handle<Code>::null();  }  // Process any deferred code.  cgen.ProcessDeferred();  // Allocate and install the code.  CodeDesc desc;  cgen.masm()->GetCode(&desc);  ScopeInfo<> sinfo(flit->scope());  Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);  Handle<Code> code = Factory::NewCode(desc, &sinfo, flags);  // Add unresolved entries in the code to the fixup list.  Bootstrapper::AddFixup(*code, cgen.masm());#ifdef ENABLE_DISASSEMBLER  if (print_code) {    // Print the source code if available.    if (!script->IsUndefined() && !script->source()->IsUndefined()) {      PrintF("--- Raw source ---\n");      StringInputBuffer stream(String::cast(script->source()));      stream.Seek(flit->start_position());      // flit->end_position() points to the last character in the stream. We      // need to compensate by adding one to calculate the length.      int source_len = flit->end_position() - flit->start_position() + 1;      for (int i = 0; i < source_len; i++) {        if (stream.has_more()) PrintF("%c", stream.GetNext());      }      PrintF("\n\n");    }    PrintF("--- Code ---\n");    code->Disassemble();  }#endif  // ENABLE_DISASSEMBLER  return code;}Ia32CodeGenerator::Ia32CodeGenerator(int buffer_size,                                     Handle<Script> script,                                     bool is_eval)    : CodeGenerator(is_eval, script),      masm_(new MacroAssembler(NULL, buffer_size)),      scope_(NULL),      cc_reg_(no_condition),      state_(NULL),      is_inside_try_(false),      break_stack_height_(0) {}// Calling conventions:// ebp: frame pointer// esp: stack pointer// edi: caller's parameter pointer// esi: callee's contextvoid Ia32CodeGenerator::GenCode(FunctionLiteral* fun) {  // Record the position for debugging purposes.  __ RecordPosition(fun->start_position());  Scope* scope = fun->scope();  ZoneList<Statement*>* body = fun->body();  // Initialize state.  { CodeGenState state(this);    scope_ = scope;    cc_reg_ = no_condition;    // Entry    // stack: function, receiver, arguments, return address    // esp: stack pointer    // ebp: frame pointer    // edi: caller's parameter pointer    // esi: callee's context    { Comment cmnt(masm_, "[ enter JS frame");      EnterJSFrame();    }    // tos: code slot#ifdef DEBUG    if (strlen(FLAG_stop_at) > 0 &&        fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {      __ int3();    }#endif    // This section now only allocates and copies the formals into the    // arguments object. It saves the address in ecx, which is saved    // at any point before either garbage collection or ecx is    // overwritten.  The flag arguments_array_allocated communicates    // with the store into the arguments variable and guards the lazy    // pushes of ecx to TOS.  The flag arguments_array_saved notes    // when the push has happened.    bool arguments_object_allocated = false;    bool arguments_object_saved = false;    // Allocate arguments object.    // The arguments object pointer needs to be saved in ecx, since we need    // to store arguments into the context.    if (scope->arguments() != NULL) {      ASSERT(scope->arguments_shadow() != NULL);      Comment cmnt(masm_, "[ allocate arguments object");      __ push(FunctionOperand());      __ CallRuntime(Runtime::kNewArguments, 1);      __ mov(ecx, Operand(eax));      arguments_object_allocated = true;    }    // Allocate space for locals and initialize them.    if (scope->num_stack_slots() > 0) {      Comment cmnt(masm_, "[ allocate space for locals");      __ Set(eax, Immediate(Factory::undefined_value()));      for (int i = scope->num_stack_slots(); i-- > 0; ) __ push(eax);    }    if (scope->num_heap_slots() > 0) {      Comment cmnt(masm_, "[ allocate local context");      // Save the arguments object pointer, if any.      if (arguments_object_allocated && !arguments_object_saved) {        __ push(Operand(ecx));        arguments_object_saved = true;      }      // Allocate local context.      // Get outer context and create a new context based on it.      __ push(FunctionOperand());      __ CallRuntime(Runtime::kNewContext, 1);  // eax holds the result      if (kDebug) {        Label verified_true;        // Verify eax and esi are the same in debug mode        __ cmp(eax, Operand(esi));        __ j(equal, &verified_true);        __ int3();        __ bind(&verified_true);      }      // Update context local.      __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);      // Restore the arguments array pointer, if any.    }    // TODO(1241774): Improve this code:    // 1) only needed if we have a context    // 2) no need to recompute context ptr every single time    // 3) don't copy parameter operand code from SlotOperand!    {      Comment cmnt2(masm_, "[ copy context parameters into .context");      // Note that iteration order is relevant here! If we have the same      // parameter twice (e.g., function (x, y, x)), and that parameter      // needs to be copied into the context, it must be the last argument      // passed to the parameter that needs to be copied. This is a rare      // case so we don't check for it, instead we rely on the copying      // order: such a parameter is copied repeatedly into the same      // context location and thus the last value is what is seen inside      // the function.      for (int i = 0; i < scope->num_parameters(); i++) {        Variable* par = scope->parameter(i);        Slot* slot = par->slot();        if (slot != NULL && slot->type() == Slot::CONTEXT) {          // Save the arguments object pointer, if any.          if (arguments_object_allocated && !arguments_object_saved) {            __ push(Operand(ecx));            arguments_object_saved = true;          }          ASSERT(!scope->is_global_scope());  // no parameters in global scope          __ mov(eax, ParameterOperand(i));          // Loads ecx with context; used below in RecordWrite.          __ mov(SlotOperand(slot, ecx), eax);          int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize;          __ RecordWrite(ecx, offset, eax, ebx);        }      }    }    // This section stores the pointer to the arguments object that    // was allocated and copied into above. If the address was not    // saved to TOS, we push ecx onto the stack.    // Store the arguments object.    // This must happen after context initialization because    // the arguments object may be stored in the context    if (arguments_object_allocated) {      ASSERT(scope->arguments() != NULL);      ASSERT(scope->arguments_shadow() != NULL);      Comment cmnt(masm_, "[ store arguments object");      {        Reference target(this, scope->arguments());        if (!arguments_object_saved) {          __ push(Operand(ecx));        }        SetValue(&target);      }      // The value of arguments must also be stored in .arguments.      // TODO(1241813): This code can probably be improved by fusing it with      // the code that stores the arguments object above.      {        Reference target(this, scope->arguments_shadow());        Load(scope->arguments());        SetValue(&target);      }    }    // Generate code to 'execute' declarations and initialize    // functions (source elements). In case of an illegal    // redeclaration we need to handle that instead of processing the    // declarations.    if (scope->HasIllegalRedeclaration()) {      Comment cmnt(masm_, "[ illegal redeclarations");      scope->VisitIllegalRedeclaration(this);    } else {      Comment cmnt(masm_, "[ declarations");      ProcessDeclarations(scope->declarations());      // Bail out if a stack-overflow exception occurred when      // processing declarations.      if (HasStackOverflow()) return;    }    if (FLAG_trace) {      __ CallRuntime(Runtime::kTraceEnter, 1);      __ push(eax);    }    CheckStack();    // Compile the body of the function in a vanilla state. Don't    // bother compiling all the code if the scope has an illegal    // redeclaration.    if (!scope->HasIllegalRedeclaration()) {      Comment cmnt(masm_, "[ function body");#ifdef DEBUG      bool is_builtin = Bootstrapper::IsActive();      bool should_trace =          is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;      if (should_trace) {        __ CallRuntime(Runtime::kDebugTrace, 1);        __ push(eax);      }#endif      VisitStatements(body);      // Generate a return statement if necessary.      if (body->is_empty() || body->last()->AsReturnStatement() == NULL) {        Literal undefined(Factory::undefined_value());        ReturnStatement statement(&undefined);        statement.set_statement_pos(fun->end_position());        VisitReturnStatement(&statement);      }    }  }  // Code generation state must be reset.  scope_ = NULL;  ASSERT(!has_cc());  ASSERT(state_ == NULL);}Operand Ia32CodeGenerator::SlotOperand(MacroAssembler* masm,                                       Scope* scope,                                       Slot* slot,                                       Register tmp) {  // Currently, this assertion will fail if we try to assign to  // a constant variable that is constant because it is read-only  // (such as the variable referring to a named function expression).  // We need to implement assignments to read-only variables.  // Ideally, we should do this during AST generation (by converting  // such assignments into expression statements); however, in general  // we may not be able to make the decision until past AST generation,  // that is when the entire program is known.  ASSERT(slot != NULL);  int index = slot->index();  switch (slot->type()) {    case Slot::PARAMETER: return ParameterOperand(scope, index);    case Slot::LOCAL: {      ASSERT(0 <= index && index < scope->num_stack_slots());      const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;      return Operand(ebp, kLocal0Offset - index * kPointerSize);    }    case Slot::CONTEXT: {      // Follow the context chain if necessary.      ASSERT(!tmp.is(esi));  // do not overwrite context register      Register context = esi;      int chain_length = scope->ContextChainLength(slot->var()->scope());      for (int i = chain_length; i-- > 0;) {        // Load the closure.        // (All contexts, even 'with' contexts, have a closure,        // and it is the same for all contexts inside a function.        // There is no need to go to the function context first.)

⌨️ 快捷键说明

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