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

📄 macro-assembler-ia32.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
// 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 "runtime.h"#include "serialize.h"namespace v8 { namespace internal {MacroAssembler::MacroAssembler(void* buffer, int size)    : Assembler(buffer, size),      unresolved_(0),      generating_stub_(false),      allow_stub_calls_(true) {}static void RecordWriteHelper(MacroAssembler* masm,                              Register object,                              Register addr,                              Register scratch) {  Label fast;  // Compute the page address from the heap object pointer, leave it  // in 'object'.  masm->and_(object, ~Page::kPageAlignmentMask);  // Compute the bit addr in the remembered set, leave it in "addr".  masm->sub(addr, Operand(object));  masm->shr(addr, kObjectAlignmentBits);  // If the bit offset lies beyond the normal remembered set range, it is in  // the extra remembered set area of a large object.  masm->cmp(addr, Page::kPageSize / kPointerSize);  masm->j(less, &fast);  // Adjust 'addr' to be relative to the start of the extra remembered set  // and the page address in 'object' to be the address of the extra  // remembered set.  masm->sub(Operand(addr), Immediate(Page::kPageSize / kPointerSize));  // Load the array length into 'scratch' and multiply by four to get the  // size in bytes of the elements.  masm->mov(scratch, Operand(object, Page::kObjectStartOffset                                     + FixedArray::kLengthOffset));  masm->shl(scratch, kObjectAlignmentBits);  // Add the page header, array header, and array body size to the page  // address.  masm->add(Operand(object), Immediate(Page::kObjectStartOffset                                       + Array::kHeaderSize));  masm->add(object, Operand(scratch));  // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction  // to limit code size. We should probably evaluate this decision by  // measuring the performance of an equivalent implementation using  // "simpler" instructions  masm->bind(&fast);  masm->bts(Operand(object, 0), addr);}class RecordWriteStub : public CodeStub { public:  RecordWriteStub(Register object, Register addr, Register scratch)      : object_(object), addr_(addr), scratch_(scratch) { }  void Generate(MacroAssembler* masm); private:  Register object_;  Register addr_;  Register scratch_;  const char* GetName() { return "RecordWriteStub"; }#ifdef DEBUG  void Print() {    PrintF("RecordWriteStub (object reg %d), (addr reg %d), (scratch reg %d)\n",           object_.code(), addr_.code(), scratch_.code());  }#endif  // Minor key encoding in 12 bits of three registers (object, address and  // scratch) OOOOAAAASSSS.  class ScratchBits: public BitField<uint32_t, 0, 4> {};  class AddressBits: public BitField<uint32_t, 4, 4> {};  class ObjectBits: public BitField<uint32_t, 8, 4> {};  Major MajorKey() { return RecordWrite; }  int MinorKey() {    // Encode the registers.    return ObjectBits::encode(object_.code()) |           AddressBits::encode(addr_.code()) |           ScratchBits::encode(scratch_.code());  }};void RecordWriteStub::Generate(MacroAssembler* masm) {  RecordWriteHelper(masm, object_, addr_, scratch_);  masm->ret(0);}// Set the remembered set bit for [object+offset].// object is the object being stored into, value is the object being stored.// If offset is zero, then the scratch register contains the array index into// the elements array represented as a Smi.// All registers are clobbered by the operation.void MacroAssembler::RecordWrite(Register object, int offset,                                 Register value, Register scratch) {  // First, check if a remembered set write is even needed. The tests below  // catch stores of Smis and stores into young gen (which does not have space  // for the remembered set bits.  Label done;  // This optimization cannot survive serialization and deserialization,  // so we disable as long as serialization can take place.  int32_t new_space_start =      reinterpret_cast<int32_t>(ExternalReference::new_space_start().address());  if (Serializer::enabled() || new_space_start < 0) {    // Cannot do smart bit-twiddling. Need to do two consecutive checks.    // Check for Smi first.    test(value, Immediate(kSmiTagMask));    j(zero, &done);    // Test that the object address is not in the new space.  We cannot    // set remembered set bits in the new space.    mov(value, Operand(object));    and_(value, Heap::NewSpaceMask());    cmp(Operand(value), Immediate(ExternalReference::new_space_start()));    j(equal, &done);  } else {    // move the value SmiTag into the sign bit    shl(value, 31);    // combine the object with value SmiTag    or_(value, Operand(object));    // remove the uninteresing bits inside the page    and_(value, Heap::NewSpaceMask() | (1 << 31));    // xor has two effects:    // - if the value was a smi, then the result will be negative    // - if the object is pointing into new space area the page bits will    //   all be zero    xor_(value, new_space_start | (1 << 31));    // Check for both conditions in one branch    j(less_equal, &done);  }  if ((offset > 0) && (offset < Page::kMaxHeapObjectSize)) {    // Compute the bit offset in the remembered set, leave it in 'value'.    mov(value, Operand(object));    and_(value, Page::kPageAlignmentMask);    add(Operand(value), Immediate(offset));    shr(value, kObjectAlignmentBits);    // Compute the page address from the heap object pointer, leave it in    // 'object'.    and_(object, ~Page::kPageAlignmentMask);    // NOTE: For now, we use the bit-test-and-set (bts) x86 instruction    // to limit code size. We should probably evaluate this decision by    // measuring the performance of an equivalent implementation using    // "simpler" instructions    bts(Operand(object, 0), value);  } else {    Register dst = scratch;    if (offset != 0) {      lea(dst, Operand(object, offset));    } else {      // array access: calculate the destination address in the same manner as      // KeyedStoreIC::GenerateGeneric      lea(dst,          Operand(object, dst, times_2, Array::kHeaderSize - kHeapObjectTag));    }    // If we are already generating a shared stub, not inlining the    // record write code isn't going to save us any memory.    if (generating_stub()) {      RecordWriteHelper(this, object, dst, value);    } else {      RecordWriteStub stub(object, dst, value);      CallStub(&stub);    }  }  bind(&done);}void MacroAssembler::SaveRegistersToMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of registers to memory location.  for (int i = 0; i < kNumJSCallerSaved; i++) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      Register reg = { r };      ExternalReference reg_addr =          ExternalReference(Debug_Address::Register(i));      mov(Operand::StaticVariable(reg_addr), reg);    }  }}void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of memory location to registers.  for (int i = kNumJSCallerSaved; --i >= 0;) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      Register reg = { r };      ExternalReference reg_addr =          ExternalReference(Debug_Address::Register(i));      mov(reg, Operand::StaticVariable(reg_addr));    }  }}void MacroAssembler::PushRegistersFromMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Push the content of the memory location to the stack.  for (int i = 0; i < kNumJSCallerSaved; i++) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      ExternalReference reg_addr =          ExternalReference(Debug_Address::Register(i));      push(Operand::StaticVariable(reg_addr));    }  }}void MacroAssembler::PopRegistersToMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Pop the content from the stack to the memory location.  for (int i = kNumJSCallerSaved; --i >= 0;) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      ExternalReference reg_addr =          ExternalReference(Debug_Address::Register(i));      pop(Operand::StaticVariable(reg_addr));    }  }}void MacroAssembler::CopyRegistersFromStackToMemory(Register base,                                                    Register scratch,                                                    RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of the stack to the memory location and adjust base.  for (int i = kNumJSCallerSaved; --i >= 0;) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      mov(scratch, Operand(base, 0));      ExternalReference reg_addr =          ExternalReference(Debug_Address::Register(i));      mov(Operand::StaticVariable(reg_addr), scratch);      lea(base, Operand(base, kPointerSize));    }  }}void MacroAssembler::Set(Register dst, const Immediate& x) {  if (x.is_zero()) {    xor_(dst, Operand(dst));  // shorter than mov  } else {    mov(Operand(dst), x);  }}void MacroAssembler::Set(const Operand& dst, const Immediate& x) {  mov(dst, x);}void MacroAssembler::FCmp() {

⌨️ 快捷键说明

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