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

📄 codegen-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
  // Object case: Check key against length in the elements array.  __ ldr(r3, FieldMemOperand(r3, JSObject::kElementsOffset));  // Check that the object is in fast mode (not dictionary).  __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset));  __ cmp(r2, Operand(Factory::hash_table_map()));  __ b(eq, &slow);  // Untag the key (for checking against untagged length in the fixed array).  __ mov(r1, Operand(r1, ASR, kSmiTagSize));  // Compute address to store into and check array bounds.  __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));  __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));  __ cmp(r1, Operand(ip));  __ b(lo, &fast);  // Slow case: Push extra copies of the arguments (3).  __ bind(&slow);  __ ldm(ia, sp, r1.bit() | r3.bit());  // r0 == value, r1 == key, r3 == object  __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());  // Do tail-call to runtime routine.  __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3);  // Extra capacity case: Check if there is extra capacity to  // perform the store and update the length. Used for adding one  // element to the array by writing to array[array.length].  // r0 == value, r1 == key, r2 == elements, r3 == object  __ bind(&extra);  __ b(ne, &slow);  // do not leave holes in the array  __ mov(r1, Operand(r1, ASR, kSmiTagSize));  // untag  __ ldr(ip, FieldMemOperand(r2, Array::kLengthOffset));  __ cmp(r1, Operand(ip));  __ b(hs, &slow);  __ mov(r1, Operand(r1, LSL, kSmiTagSize));  // restore tag  __ add(r1, r1, Operand(1 << kSmiTagSize));  // and increment  __ str(r1, FieldMemOperand(r3, JSArray::kLengthOffset));  __ mov(r3, Operand(r2));  // NOTE: Computing the address to store into must take the fact  // that the key has been incremented into account.  int displacement = Array::kHeaderSize - kHeapObjectTag -      ((1 << kSmiTagSize) * 2);  __ add(r2, r2, Operand(displacement));  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));  __ b(&fast);  // Array case: Get the length and the elements array from the JS  // array. Check that the array is in fast mode; if it is the  // length is always a smi.  // r0 == value, r3 == object  __ bind(&array);  __ ldr(r2, FieldMemOperand(r3, JSObject::kElementsOffset));  __ ldr(r1, FieldMemOperand(r2, HeapObject::kMapOffset));  __ cmp(r1, Operand(Factory::hash_table_map()));  __ b(eq, &slow);  // Check the key against the length in the array, compute the  // address to store into and fall through to fast case.  __ ldr(r1, MemOperand(sp));  // r0 == value, r1 == key, r2 == elements, r3 == object.  __ ldr(ip, FieldMemOperand(r3, JSArray::kLengthOffset));  __ cmp(r1, Operand(ip));  __ b(hs, &extra);  __ mov(r3, Operand(r2));  __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));  __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));  // Fast case: Do the store.  // r0 == value, r2 == address to store into, r3 == elements  __ bind(&fast);  __ str(r0, MemOperand(r2));  // Skip write barrier if the written value is a smi.  __ tst(r0, Operand(kSmiTagMask));  __ b(eq, &exit);  // Update write barrier for the elements array address.  __ sub(r1, r2, Operand(r3));  __ RecordWrite(r3, r1, r2);  __ bind(&exit);  masm->StubReturn(1);}class GenericBinaryOpStub : public CodeStub { public:  explicit GenericBinaryOpStub(Token::Value op) : op_(op) { } private:  Token::Value op_;  Major MajorKey() { return GenericBinaryOp; }  int MinorKey() { return static_cast<int>(op_); }  void Generate(MacroAssembler* masm);  const char* 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";    }  }#ifdef DEBUG  void Print() { PrintF("GenericBinaryOpStub (%s)\n", Token::String(op_)); }#endif};void GenericBinaryOpStub::Generate(MacroAssembler* masm) {  // r1 : x  // r0 : y  // result : r0  switch (op_) {    case Token::ADD: {      Label slow, exit;      // fast path      __ orr(r2, r1, Operand(r0));  // r2 = x | y;      __ add(r0, r1, Operand(r0), SetCC);  // add y optimistically      // go slow-path in case of overflow      __ b(vs, &slow);      // go slow-path in case of non-smi operands      ASSERT(kSmiTag == 0);  // adjust code below      __ tst(r2, Operand(kSmiTagMask));      __ b(eq, &exit);      // slow path      __ bind(&slow);      __ sub(r0, r0, Operand(r1));  // revert optimistic add      __ push(r1);      __ push(r0);      __ mov(r0, Operand(1));  // set number of arguments      __ InvokeBuiltin(Builtins::ADD, JUMP_JS);      // done      __ bind(&exit);      break;    }    case Token::SUB: {      Label slow, exit;      // fast path      __ orr(r2, r1, Operand(r0));  // r2 = x | y;      __ sub(r3, r1, Operand(r0), SetCC);  // subtract y optimistically      // go slow-path in case of overflow      __ b(vs, &slow);      // go slow-path in case of non-smi operands      ASSERT(kSmiTag == 0);  // adjust code below      __ tst(r2, Operand(kSmiTagMask));      __ mov(r0, Operand(r3), LeaveCC, eq);  // conditionally set r0 to result      __ b(eq, &exit);      // slow path      __ bind(&slow);      __ push(r1);      __ push(r0);      __ mov(r0, Operand(1));  // set number of arguments      __ InvokeBuiltin(Builtins::SUB, JUMP_JS);      // done      __ bind(&exit);      break;    }    case Token::MUL: {      Label slow, exit;      // tag check      __ orr(r2, r1, Operand(r0));  // r2 = x | y;      ASSERT(kSmiTag == 0);  // adjust code below      __ tst(r2, Operand(kSmiTagMask));      __ b(ne, &slow);      // remove tag from one operand (but keep sign), so that result is smi      __ mov(ip, Operand(r0, ASR, kSmiTagSize));      // do multiplication      __ smull(r3, r2, r1, ip);  // r3 = lower 32 bits of ip*r1      // go slow on overflows (overflow bit is not set)      __ mov(ip, Operand(r3, ASR, 31));      __ cmp(ip, Operand(r2));  // no overflow if higher 33 bits are identical      __ b(ne, &slow);      // go slow on zero result to handle -0      __ tst(r3, Operand(r3));      __ mov(r0, Operand(r3), LeaveCC, ne);      __ b(ne, &exit);      // slow case      __ bind(&slow);      __ push(r1);      __ push(r0);      __ mov(r0, Operand(1));  // set number of arguments      __ InvokeBuiltin(Builtins::MUL, JUMP_JS);      // done      __ bind(&exit);      break;    }    case Token::BIT_OR:    case Token::BIT_AND:    case Token::BIT_XOR: {      Label slow, exit;      // tag check      __ orr(r2, r1, Operand(r0));  // r2 = x | y;      ASSERT(kSmiTag == 0);  // adjust code below      __ tst(r2, Operand(kSmiTagMask));      __ b(ne, &slow);      switch (op_) {        case Token::BIT_OR:  __ orr(r0, r0, Operand(r1)); break;        case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break;        case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;        default: UNREACHABLE();      }      __ b(&exit);      __ bind(&slow);      __ push(r1);  // restore stack      __ push(r0);      __ mov(r0, Operand(1));  // 1 argument (not counting receiver).      switch (op_) {        case Token::BIT_OR:          __ InvokeBuiltin(Builtins::BIT_OR, JUMP_JS);          break;        case Token::BIT_AND:          __ InvokeBuiltin(Builtins::BIT_AND, JUMP_JS);          break;        case Token::BIT_XOR:          __ InvokeBuiltin(Builtins::BIT_XOR, JUMP_JS);          break;        default:          UNREACHABLE();      }      __ bind(&exit);      break;    }    case Token::SHL:    case Token::SHR:    case Token::SAR: {      Label slow, exit;      // tag check      __ orr(r2, r1, Operand(r0));  // r2 = x | y;      ASSERT(kSmiTag == 0);  // adjust code below      __ tst(r2, Operand(kSmiTagMask));      __ b(ne, &slow);      // remove tags from operands (but keep sign)      __ mov(r3, Operand(r1, ASR, kSmiTagSize));  // x      __ mov(r2, Operand(r0, ASR, kSmiTagSize));  // y      // use only the 5 least significant bits of the shift count      __ and_(r2, r2, Operand(0x1f));      // perform operation      switch (op_) {        case Token::SAR:          __ mov(r3, Operand(r3, ASR, r2));          // no checks of result necessary          break;        case Token::SHR:          __ mov(r3, Operand(r3, LSR, r2));          // check that the *unsigned* result fits in a smi          // neither of the two high-order bits can be set:          // - 0x80000000: high bit would be lost when smi tagging          // - 0x40000000: this number would convert to negative when          // smi tagging these two cases can only happen with shifts          // by 0 or 1 when handed a valid smi          __ and_(r2, r3, Operand(0xc0000000), SetCC);          __ b(ne, &slow);          break;        case Token::SHL:          __ mov(r3, Operand(r3, LSL, r2));          // check that the *signed* result fits in a smi          __ add(r2, r3, Operand(0x40000000), SetCC);          __ b(mi, &slow);          break;        default: UNREACHABLE();      }      // tag result and store it in r0      ASSERT(kSmiTag == 0);  // adjust code below      __ mov(r0, Operand(r3, LSL, kSmiTagSize));      __ b(&exit);      // slow case      __ bind(&slow);      __ push(r1);  // restore stack      __ push(r0);      __ mov(r0, Operand(1));  // 1 argument (not counting receiver).      switch (op_) {        case Token::SAR: __ InvokeBuiltin(Builtins::SAR, JUMP_JS); break;        case Token::SHR: __ InvokeBuiltin(Builtins::SHR, JUMP_JS); break;        case Token::SHL: __ InvokeBuiltin(Builtins::SHL, JUMP_JS); break;        default: UNREACHABLE();      }      __ bind(&exit);      break;    }    default: UNREACHABLE();  }  __ Ret();}void StackCheckStub::Generate(MacroAssembler* masm) {  Label within_limit;  __ mov(ip, Operand(ExternalReference::address_of_stack_guard_limit()));  __ ldr(ip, MemOperand(ip));  __ cmp(sp, Operand(ip));  __ b(hs, &within_limit);  // Do tail-call to runtime routine.  __ push(r0);  __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1);  __ bind(&within_limit);  masm->StubReturn(1);}void UnarySubStub::Generate(MacroAssembler* masm) {  Label undo;  Label slow;  Label done;  // Enter runtime system if the value is not a smi.  __ tst(r0, Operand(kSmiTagMask));  __ b(ne, &slow);  // Enter runtime system if the value of the expression is zero  // to make sure that we switch between 0 and -0.  __ cmp(r0, Operand(0));  __ b(eq, &slow);  // The value of the expression is a smi that is not zero.  Try  // optimistic subtraction '0 - value'.  __ rsb(r1, r0, Operand(0), SetCC);  __ b(vs, &slow);  // If result is a smi we are done.  __ tst(r1, Operand(kSmiTagMask));  __ mov(r0, Operand(r1), LeaveCC, eq);  // conditionally set r0 to result  __ b(eq, &done);  // Enter runtime system.  __ bind(&slow);  __ push(r0);  __ mov(r0, Operand(0));  // set number of arguments  __ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_JS);  __ bind(&done);  masm->StubReturn(1);}class InvokeBuiltinStub : public CodeStub { public:  enum Kind { Inc, Dec, ToNumber };  InvokeBuiltinStub(Kind kind, int argc) : kind_(kind), argc_(argc) { } private:  Kind kind_;  int argc_;  Major MajorKey() { return InvokeBuiltin; }  int MinorKey() { return (argc_ << 3) | static_cast<int>(kind_); }  void Generate(MacroAssembler* masm);  const char* GetName() { return "InvokeBuiltinStub"; }#ifdef DEBUG  void Print() {    PrintF("InvokeBuiltinStub (kind %d, argc, %d)\n",           static_cast<int>(kind_),           argc_);  }#endif};void InvokeBuiltinStub::Generate(MacroAssembler* masm) {  __ push(r0);  __ mov(r0, Operand(0));  // set number of arguments  switch (kind_) {    case ToNumber: __ InvokeBuiltin(Builtins::TO_NUMBER, JUMP_JS); break;    case Inc:      __ InvokeBuiltin(Builtins::INC, JUMP_JS);       break;    case Dec:      __ InvokeBuiltin(Builtins::DEC, JUMP_JS);       break;    default: UNREACHABLE();  }

⌨️ 快捷键说明

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