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

📄 codegen-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
        masm->mov(tmp, ContextOperand(context, Context::CLOSURE_INDEX));        // Load the function context (which is the incoming, outer context).        masm->mov(tmp, FieldOperand(tmp, JSFunction::kContextOffset));        context = tmp;      }      // We may have a 'with' context now. Get the function context.      // (In fact this mov may never be the needed, since the scope analysis      // may not permit a direct context access in this case and thus we are      // always at a function context. However it is safe to dereference be-      // cause the function context of a function context is itself. Before      // deleting this mov we should try to create a counter-example first,      // though...)      masm->mov(tmp, ContextOperand(context, Context::FCONTEXT_INDEX));      return ContextOperand(tmp, index);    }    default:      UNREACHABLE();      return Operand(eax);  }}// Loads a value on TOS. If it is a boolean value, the result may have been// (partially) translated into branches, or it may have set the condition code// register. If force_cc is set, the value is forced to set the condition code// register and no value is pushed. If the condition code register was set,// has_cc() is true and cc_reg_ contains the condition to test for 'true'.void Ia32CodeGenerator::LoadCondition(Expression* x,                                      CodeGenState::AccessType access,                                      Label* true_target,                                      Label* false_target,                                      bool force_cc) {  ASSERT(access == CodeGenState::LOAD ||         access == CodeGenState::LOAD_TYPEOF_EXPR);  ASSERT(!has_cc() && !is_referenced());  { CodeGenState new_state(this, access, true_target, false_target);    Visit(x);  }  if (force_cc && !has_cc()) {    ToBoolean(true_target, false_target);  }  ASSERT(has_cc() || !force_cc);}void Ia32CodeGenerator::Load(Expression* x, CodeGenState::AccessType access) {  ASSERT(access == CodeGenState::LOAD ||         access == CodeGenState::LOAD_TYPEOF_EXPR);  Label true_target;  Label false_target;  LoadCondition(x, access, &true_target, &false_target, false);  if (has_cc()) {    // convert cc_reg_ into a bool    Label loaded, materialize_true;    __ j(cc_reg_, &materialize_true);    __ push(Immediate(Factory::false_value()));    __ jmp(&loaded);    __ bind(&materialize_true);    __ push(Immediate(Factory::true_value()));    __ bind(&loaded);    cc_reg_ = no_condition;  }  if (true_target.is_linked() || false_target.is_linked()) {    // we have at least one condition value    // that has been "translated" into a branch,    // thus it needs to be loaded explicitly again    Label loaded;    __ jmp(&loaded);  // don't lose current TOS    bool both = true_target.is_linked() && false_target.is_linked();    // reincarnate "true", if necessary    if (true_target.is_linked()) {      __ bind(&true_target);      __ push(Immediate(Factory::true_value()));    }    // if both "true" and "false" need to be reincarnated,    // jump across code for "false"    if (both)      __ jmp(&loaded);    // reincarnate "false", if necessary    if (false_target.is_linked()) {      __ bind(&false_target);      __ push(Immediate(Factory::false_value()));    }    // everything is loaded at this point    __ bind(&loaded);  }  ASSERT(!has_cc());}void Ia32CodeGenerator::LoadGlobal() {  __ push(GlobalObject());}// TODO(1241834): Get rid of this function in favor of just using Load, now// that we have the LOAD_TYPEOF_EXPR access type. => Need to handle// global variables w/o reference errors elsewhere.void Ia32CodeGenerator::LoadTypeofExpression(Expression* x) {  Variable* variable = x->AsVariableProxy()->AsVariable();  if (variable != NULL && !variable->is_this() && variable->is_global()) {    // NOTE: This is somewhat nasty. We force the compiler to load    // the variable as if through '<global>.<variable>' to make sure we    // do not get reference errors.    Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);    Literal key(variable->name());    // TODO(1241834): Fetch the position from the variable instead of using    // no position.    Property property(&global, &key, RelocInfo::kNoPosition);    Load(&property);  } else {    Load(x, CodeGenState::LOAD_TYPEOF_EXPR);  }}Reference::Reference(Ia32CodeGenerator* cgen, Expression* expression)    : cgen_(cgen), expression_(expression), type_(ILLEGAL) {  cgen->LoadReference(this);}Reference::~Reference() {  cgen_->UnloadReference(this);}void Ia32CodeGenerator::LoadReference(Reference* ref) {  Expression* e = ref->expression();  Property* property = e->AsProperty();  Variable* var = e->AsVariableProxy()->AsVariable();  if (property != NULL) {    Load(property->obj());    // Used a named reference if the key is a literal symbol.    // We don't use a named reference if they key is a string that can be    // legally parsed as an integer.  This is because, otherwise we don't    // get into the slow case code that handles [] on String objects.    Literal* literal = property->key()->AsLiteral();    uint32_t dummy;    if (literal != NULL && literal->handle()->IsSymbol() &&      !String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {      ref->set_type(Reference::NAMED);    } else {      Load(property->key());      ref->set_type(Reference::KEYED);    }  } else if (var != NULL) {    if (var->is_global()) {      // global variable      LoadGlobal();      ref->set_type(Reference::NAMED);    } else {      // local variable      ref->set_type(Reference::EMPTY);    }  } else {    Load(e);    __ CallRuntime(Runtime::kThrowReferenceError, 1);    __ push(eax);  }}void Ia32CodeGenerator::UnloadReference(Reference* ref) {  // Pop n references on the stack while preserving TOS  Comment cmnt(masm_, "[ UnloadReference");  int size = ref->size();  if (size <= 0) {    // Do nothing. No popping is necessary.  } else if (size == 1) {    __ pop(eax);    __ mov(TOS, eax);  } else {    __ pop(eax);    __ add(Operand(esp), Immediate(size * kPointerSize));    __ push(eax);  }}void Property::GenerateStoreCode(MacroAssembler* masm,                                 Scope* scope,                                 Reference* ref,                                 InitState init_state) {  Comment cmnt(masm, "[ Store to Property");  masm->RecordPosition(position());  Ia32CodeGenerator::SetReferenceProperty(masm, ref, key());}void VariableProxy::GenerateStoreCode(MacroAssembler* masm,                                      Scope* scope,                                      Reference* ref,                                      InitState init_state) {  Comment cmnt(masm, "[ Store to VariableProxy");  Variable* node = var();  Expression* expr = node->rewrite();  if (expr != NULL) {    expr->GenerateStoreCode(masm, scope, ref, init_state);  } else {    ASSERT(node->is_global());    if (node->AsProperty() != NULL) {      masm->RecordPosition(node->AsProperty()->position());    }    Ia32CodeGenerator::SetReferenceProperty(masm, ref,                                            new Literal(node->name()));  }}void Slot::GenerateStoreCode(MacroAssembler* masm,                             Scope* scope,                             Reference* ref,                             InitState init_state) {  Comment cmnt(masm, "[ Store to Slot");  if (type() == Slot::LOOKUP) {    ASSERT(var()->mode() == Variable::DYNAMIC);    // For now, just do a runtime call.    masm->push(Operand(esi));    masm->push(Immediate(var()->name()));    if (init_state == CONST_INIT) {      // Same as the case for a normal store, but ignores attribute      // (e.g. READ_ONLY) of context slot so that we can initialize const      // properties (introduced via eval("const foo = (some expr);")). Also,      // uses the current function context instead of the top context.      //      // Note that we must declare the foo upon entry of eval(), via a      // context slot declaration, but we cannot initialize it at the same      // time, because the const declaration may be at the end of the eval      // code (sigh...) and the const variable may have been used before      // (where its value is 'undefined'). Thus, we can only do the      // initialization when we actually encounter the expression and when      // the expression operands are defined and valid, and thus we need the      // split into 2 operations: declaration of the context slot followed      // by initialization.      masm->CallRuntime(Runtime::kInitializeConstContextSlot, 3);    } else {      masm->CallRuntime(Runtime::kStoreContextSlot, 3);    }    // Storing a variable must keep the (new) value on the expression    // stack. This is necessary for compiling assignment expressions.    masm->push(eax);  } else {    ASSERT(var()->mode() != Variable::DYNAMIC);    Label exit;    if (init_state == CONST_INIT) {      ASSERT(var()->mode() == Variable::CONST);      // Only the first const initialization must be executed (the slot      // still contains 'the hole' value). When the assignment is executed,      // the code is identical to a normal store (see below).      Comment cmnt(masm, "[ Init const");      masm->mov(eax, Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx));      masm->cmp(eax, Factory::the_hole_value());      masm->j(not_equal, &exit);    }    // We must execute the store.    // Storing a variable must keep the (new) value on the stack. This is    // necessary for compiling assignment expressions.  ecx may be loaded    // with context; used below in RecordWrite.    //    // Note: We will reach here even with node->var()->mode() ==    // Variable::CONST because of const declarations which will initialize    // consts to 'the hole' value and by doing so, end up calling this    // code.    masm->pop(eax);    masm->mov(Ia32CodeGenerator::SlotOperand(masm, scope, this, ecx), eax);    masm->push(eax);  // RecordWrite may destroy the value in eax.    if (type() == Slot::CONTEXT) {      // ecx is loaded with context when calling SlotOperand above.      int offset = FixedArray::kHeaderSize + index() * kPointerSize;      masm->RecordWrite(ecx, offset, eax, ebx);    }    // If we definitely did not jump over the assignment, we do not need to    // bind the exit label.  Doing so can defeat peephole optimization.    if (init_state == CONST_INIT) masm->bind(&exit);  }}#undef __#define __  masm->class ToBooleanStub: public CodeStub { public:  ToBooleanStub() { }  void Generate(MacroAssembler* masm); private:  Major MajorKey() { return ToBoolean; }  int MinorKey() { return 0; }  const char* GetName() { return "ToBooleanStub"; }#ifdef DEBUG  void Print() {    PrintF("ToBooleanStub\n");  }#endif};// NOTE: The stub does not handle the inlined cases (Smis, Booleans, undefined).void ToBooleanStub::Generate(MacroAssembler* masm) {  Label false_result, true_result, not_string;  __ mov(eax, Operand(esp, 1 * kPointerSize));  // 'null' => false.  __ cmp(eax, Factory::null_value());  __ j(equal, &false_result);  // Get the map and type of the heap object.  __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));  __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));  // Undetectable => false.  __ movzx_b(ebx, FieldOperand(edx, Map::kBitFieldOffset));  __ and_(ebx, 1 << Map::kIsUndetectable);  __ j(not_zero, &false_result);  // JavaScript object => true.  __ cmp(ecx, FIRST_JS_OBJECT_TYPE);  __ j(above_equal, &true_result);  // String value => false iff empty.  __ cmp(ecx, FIRST_NONSTRING_TYPE);  __ j(above_equal, &not_string);  __ and_(ecx, kStringSizeMask);  __ cmp(ecx, kShortStringTag);  __ j(not_equal, &true_result);  // Empty string is always short.  __ mov(edx, FieldOperand(eax, String::kLengthOffset));  __ shr(edx, String::kShortLengthShift);  __ j(zero, &false_result);  __ jmp(&true_result);  __ bind(&not_string);  // HeapNumber => false iff +0, -0, or NaN.  __ cmp(edx, Factory::heap_number_map());  __ j(not_equal, &true_result);  __ fldz();  __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));  __ fucompp();  __ push(eax);  __ fnstsw_ax();  __ sahf();  __ pop(eax);  __ j(zero, &false_result);  __ jmp(&true_result);  // Return 1/0 for true/false in eax.  __ bind(&true_result);  __ mov(eax, 1);  __ ret(1 * kPointerSize);  __ bind(&false_result);  __ mov(eax, 0);  __ ret(1 * kPointerSize);}#undef __#define __  masm_->// ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and// convert it to a boolean in the condition code register or jump to// 'false_target'/'true_target' as appropriate.void Ia32CodeGenerator::ToBoolean(Label* true_target, Label* false_target) {  Comment cmnt(masm_, "[ ToBoolean");

⌨️ 快捷键说明

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