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

📄 codegen-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
  // The value to convert should be popped from the stack.  __ pop(eax);  // Fast case checks.  // 'false' => false.  __ cmp(eax, Factory::false_value());  __ j(equal, false_target);  // 'true' => true.  __ cmp(eax, Factory::true_value());  __ j(equal, true_target);  // 'undefined' => false.  __ cmp(eax, Factory::undefined_value());  __ j(equal, false_target);  // Smi => false iff zero.  ASSERT(kSmiTag == 0);  __ test(eax, Operand(eax));  __ j(zero, false_target);  __ test(eax, Immediate(kSmiTagMask));  __ j(zero, true_target);  // Call the stub for all other cases.  __ push(eax);  // Undo the pop(eax) from above.  ToBooleanStub stub;  __ CallStub(&stub);  // Convert result (eax) to condition code.  __ test(eax, Operand(eax));  ASSERT(not_equal == not_zero);  cc_reg_ = not_equal;}void Ia32CodeGenerator::GetReferenceProperty(Expression* key) {  ASSERT(!ref()->is_illegal());  Reference::Type type = ref()->type();  // TODO(1241834): Make sure that this it is safe to ignore the distinction  // between access types LOAD and LOAD_TYPEOF_EXPR. If there is a chance  // that reference errors can be thrown below, we must distinguish between  // the two kinds of loads (typeof expression loads must not throw a  // reference error).  if (type == Reference::NAMED) {    // Compute the name of the property.    Literal* literal = key->AsLiteral();    Handle<String> name(String::cast(*literal->handle()));    Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));    Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();    // Setup the name register.    __ Set(ecx, Immediate(name));    if (var != NULL) {      ASSERT(var->is_global());      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);    } else {      __ call(ic, RelocInfo::CODE_TARGET);    }  } else {    // Access keyed property.    ASSERT(type == Reference::KEYED);    // Call IC code.    Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));    Variable* var = ref()->expression()->AsVariableProxy()->AsVariable();    if (var != NULL) {      ASSERT(var->is_global());      __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);    } else {      __ call(ic, RelocInfo::CODE_TARGET);    }  }  __ push(eax);  // IC call leaves result in eax, push it out}void Ia32CodeGenerator::SetReferenceProperty(MacroAssembler* masm,                                             Reference* ref,                                             Expression* key) {  ASSERT(!ref->is_illegal());  Reference::Type type = ref->type();  if (type == Reference::NAMED) {    // Compute the name of the property.    Literal* literal = key->AsLiteral();    Handle<String> name(String::cast(*literal->handle()));    // Call the appropriate IC code.    Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));    // TODO(1222589): Make the IC grab the values from the stack.    masm->pop(eax);    // Setup the name register.    masm->Set(ecx, Immediate(name));    masm->call(ic, RelocInfo::CODE_TARGET);  } else {    // Access keyed property.    ASSERT(type == Reference::KEYED);    // Call IC code.    Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));    // TODO(1222589): Make the IC grab the values from the stack.    masm->pop(eax);    masm->call(ic, RelocInfo::CODE_TARGET);  }  masm->push(eax);  // IC call leaves result in eax, push it out}#undef __#define __  masm->class FloatingPointHelper : public AllStatic { public:  // Code pattern for loading floating point values. Input values must  // be either smi or heap number objects (fp values). Requirements:  // operand_1 on TOS+1 , operand_2 on TOS+2; Returns operands as  // floating point numbers on FPU stack.  static void LoadFloatOperands(MacroAssembler* masm, Register scratch);  // Test if operands are smi or number objects (fp). Requirements:  // operand_1 in eax, operand_2 in edx; falls through on float  // operands, jumps to the non_float label otherwise.  static void CheckFloatOperands(MacroAssembler* masm,                                 Label* non_float,                                 Register scratch);  // Allocate a heap number in new space with undefined value.  // Returns tagged pointer in eax, or jumps to need_gc if new space is full.  static void AllocateHeapNumber(MacroAssembler* masm,                                 Label* need_gc,                                 Register scratch1,                                 Register scratch2);};class GenericBinaryOpStub: public CodeStub { public:  GenericBinaryOpStub(Token::Value op, OverwriteMode mode)      : op_(op), mode_(mode) { } private:  Token::Value op_;  OverwriteMode mode_;  const char* GetName();#ifdef DEBUG  void Print() {    PrintF("GenericBinaryOpStub (op %s), (mode %d)\n",           Token::String(op_),           static_cast<int>(mode_));  }#endif  // Minor key encoding in 16 bits OOOOOOOOOOOOOOMM.  class ModeBits: public BitField<OverwriteMode, 0, 2> {};  class OpBits: public BitField<Token::Value, 2, 14> {};  Major MajorKey() { return GenericBinaryOp; }  int MinorKey() {    // Encode the parameters in a unique 16 bit value.    return OpBits::encode(op_) |           ModeBits::encode(mode_);  }  void Generate(MacroAssembler* masm);};const char* GenericBinaryOpStub::GetName() {  switch (op_) {  case Token::ADD: return "GenericBinaryOpStub_ADD";  case Token::SUB: return "GenericBinaryOpStub_SUB";  case Token::MUL: return "GenericBinaryOpStub_MUL";  case Token::DIV: return "GenericBinaryOpStub_DIV";  case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR";  case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";  case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";  case Token::SAR: return "GenericBinaryOpStub_SAR";  case Token::SHL: return "GenericBinaryOpStub_SHL";  case Token::SHR: return "GenericBinaryOpStub_SHR";  default:         return "GenericBinaryOpStub";  }}void GenericBinaryOpStub::Generate(MacroAssembler* masm) {  Label call_runtime;  __ mov(eax, Operand(esp, 1 * kPointerSize));  // Get y.  __ mov(edx, Operand(esp, 2 * kPointerSize));  // Get x.  // 1. Smi case.  switch (op_) {    case Token::ADD: {      // eax: y.      // edx: x.      Label revert;      __ mov(ecx, Operand(eax));      __ or_(ecx, Operand(edx));  // ecx = x | y.      __ add(eax, Operand(edx));  // Add y optimistically.      // Go slow-path in case of overflow.      __ j(overflow, &revert, not_taken);      // Go slow-path in case of non-smi operands.      ASSERT(kSmiTag == 0);  // adjust code below      __ test(ecx, Immediate(kSmiTagMask));      __ j(not_zero, &revert, not_taken);      __ ret(2 * kPointerSize);  // Remove all operands.      // Revert optimistic add.      __ bind(&revert);      __ sub(eax, Operand(edx));      break;    }    case Token::SUB: {      // eax: y.      // edx: x.      Label revert;      __ mov(ecx, Operand(edx));      __ or_(ecx, Operand(eax));  // ecx = x | y.      __ sub(edx, Operand(eax));  // Subtract y optimistically.      // Go slow-path in case of overflow.      __ j(overflow, &revert, not_taken);      // Go slow-path in case of non-smi operands.      ASSERT(kSmiTag == 0);  // adjust code below      __ test(ecx, Immediate(kSmiTagMask));      __ j(not_zero, &revert, not_taken);      __ mov(eax, Operand(edx));      __ ret(2 * kPointerSize);  // Remove all operands.      // Revert optimistic sub.      __ bind(&revert);      __ add(edx, Operand(eax));      break;    }    case Token::MUL: {      // eax: y      // edx: x      // a) both operands smi and result fits into a smi -> return.      // b) at least one of operands non-smi -> non_smi_operands.      // c) result does not fit in a smi -> non_smi_result.      Label non_smi_operands, non_smi_result;      // Tag check.      __ mov(ecx, Operand(edx));      __ or_(ecx, Operand(eax));  // ecx = x | y.      ASSERT(kSmiTag == 0);  // Adjust code below.      __ test(ecx, Immediate(kSmiTagMask));      // Jump if not both smi; check if float numbers.      __ j(not_zero, &non_smi_operands, not_taken);      // Get copies of operands.      __ mov(ebx, Operand(eax));      __ mov(ecx, Operand(edx));      // If the smi tag is 0 we can just leave the tag on one operand.      ASSERT(kSmiTag == 0);  // adjust code below      // Remove tag from one of the operands (but keep sign).      __ sar(ecx, kSmiTagSize);      // Do multiplication.      __ imul(eax, Operand(ecx));  // Multiplication of Smis; result in eax.      // Go slow on overflows.      __ j(overflow, &non_smi_result, not_taken);      // ...but operands OK for float arithmetic.      // If the result is +0 we may need to check if the result should      // really be -0. Welcome to the -0 fan club.      __ NegativeZeroTest(eax, ebx, edx, ecx, &non_smi_result);      __ ret(2 * kPointerSize);      __ bind(&non_smi_result);      // TODO(1243132): Do not check float operands here.      __ bind(&non_smi_operands);      __ mov(eax, Operand(esp, 1 * kPointerSize));      __ mov(edx, Operand(esp, 2 * kPointerSize));      break;    }    case Token::DIV: {      // eax: y      // edx: x      Label non_smi_operands, non_smi_result, division_by_zero;      __ mov(ebx, Operand(eax));  // Get y      __ mov(eax, Operand(edx));  // Get x      __ cdq();  // Sign extend eax into edx:eax.      // Tag check.      __ mov(ecx, Operand(ebx));      __ or_(ecx, Operand(eax));  // ecx = x | y.      ASSERT(kSmiTag == 0);  // Adjust code below.      __ test(ecx, Immediate(kSmiTagMask));      // Jump if not both smi; check if float numbers.      __ j(not_zero, &non_smi_operands, not_taken);      __ test(ebx, Operand(ebx));  // Check for 0 divisor.      __ j(zero, &division_by_zero, not_taken);      __ idiv(ebx);      // Check for the corner case of dividing the most negative smi by -1.      // (We cannot use the overflow flag, since it is not set by idiv.)      ASSERT(kSmiTag == 0 && kSmiTagSize == 1);      __ cmp(eax, 0x40000000);      __ j(equal, &non_smi_result);      // If the result is +0 we may need to check if the result should      // really be -0. Welcome to the -0 fan club.      __ NegativeZeroTest(eax, ecx, &non_smi_result);  // Use ecx = x | y.      __ test(edx, Operand(edx));      // Use floats if there's a remainder.      __ j(not_zero, &non_smi_result, not_taken);      __ shl(eax, kSmiTagSize);      __ ret(2 * kPointerSize);  // Remove all operands.      __ bind(&division_by_zero);      __ mov(eax, Operand(esp, 1 * kPointerSize));      __ mov(edx, Operand(esp, 2 * kPointerSize));      __ jmp(&call_runtime);  // Division by zero must go through runtime.      __ bind(&non_smi_result);      // TODO(1243132): Do not check float operands here.      __ bind(&non_smi_operands);      __ mov(eax, Operand(esp, 1 * kPointerSize));      __ mov(edx, Operand(esp, 2 * kPointerSize));      break;    }    case Token::MOD: {      Label slow;      __ mov(ebx, Operand(eax));  // get y      __ mov(eax, Operand(edx));  // get x      __ cdq();  // sign extend eax into edx:eax      // tag check      __ mov(ecx, Operand(ebx));      __ or_(ecx, Operand(eax));  // ecx = x | y;      ASSERT(kSmiTag == 0);  // adjust code below      __ test(ecx, Immediate(kSmiTagMask));      __ j(not_zero, &slow, not_taken);      __ test(ebx, Operand(ebx));  // test for y == 0      __ j(zero, &slow);      // Fast case: Do integer division and use remainder.      __ idiv(ebx);      __ NegativeZeroTest(edx, ecx, &slow);  // use ecx = x | y      __ mov(eax, Operand(edx));      __ ret(2 * kPointerSize);      // Slow case: Call runtime operator implementation.      __ bind(&slow);      __ mov(eax, Operand(esp, 1 * kPointerSize));      __ mov(edx, Operand(esp, 2 * kPointerSize));      __ jmp(&call_runtime);      break;    }    case Token::BIT_OR:    case Token::BIT_AND:    case Token::BIT_XOR:    case Token::SAR:    case Token::SHL:    case Token::SHR: {      // Smi-case for bitops should already have been inlined.      break;    }    default: {      UNREACHABLE();    }  }  // 2. Floating point case.  switch (op_) {    case Token::ADD:    case Token::SUB:    case Token::MUL:    case Token::DIV: {      // eax: y      // edx: x      FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);      // Fast-case: Both operands are numbers.      // Allocate a heap number, if needed.      Label skip_allocation;      switch (mode_) {        case OVERWRITE_LEFT:          __ mov(eax, Operand(edx));          // Fall through!        case OVERWRITE_RIGHT:          // If the argument in eax is already an object, we skip the          // allocation of a heap number.          __ test(eax, Immediate(kSmiTagMask));          __ j(not_zero, &skip_allocation, not_taken);

⌨️ 快捷键说明

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