diff options
Diffstat (limited to 'deps/v8/src/ia32/assembler-ia32-inl.h')
-rw-r--r-- | deps/v8/src/ia32/assembler-ia32-inl.h | 152 |
1 files changed, 92 insertions, 60 deletions
diff --git a/deps/v8/src/ia32/assembler-ia32-inl.h b/deps/v8/src/ia32/assembler-ia32-inl.h index 97aeeae72..c7ec6d991 100644 --- a/deps/v8/src/ia32/assembler-ia32-inl.h +++ b/deps/v8/src/ia32/assembler-ia32-inl.h @@ -37,60 +37,63 @@ #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_ #define V8_IA32_ASSEMBLER_IA32_INL_H_ -#include "ia32/assembler-ia32.h" +#include "src/ia32/assembler-ia32.h" -#include "cpu.h" -#include "debug.h" +#include "src/assembler.h" +#include "src/debug.h" namespace v8 { namespace internal { +bool CpuFeatures::SupportsCrankshaft() { return true; } + static const byte kCallOpcode = 0xE8; static const int kNoCodeAgeSequenceLength = 5; // The modes possibly affected by apply must be in kApplyMask. -void RelocInfo::apply(intptr_t delta) { +void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { + bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH; if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) { int32_t* p = reinterpret_cast<int32_t*>(pc_); *p -= delta; // Relocate entry. - CPU::FlushICache(p, sizeof(uint32_t)); + if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); } else if (rmode_ == CODE_AGE_SEQUENCE) { if (*pc_ == kCallOpcode) { int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); *p -= delta; // Relocate entry. - CPU::FlushICache(p, sizeof(uint32_t)); + if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); } } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) { // Special handling of js_return when a break point is set (call // instruction has been inserted). int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); *p -= delta; // Relocate entry. - CPU::FlushICache(p, sizeof(uint32_t)); + if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); } else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { // Special handling of a debug break slot when a break point is set (call // instruction has been inserted). int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1); *p -= delta; // Relocate entry. - CPU::FlushICache(p, sizeof(uint32_t)); + if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); } else if (IsInternalReference(rmode_)) { // absolute code pointer inside code object moves with the code object. int32_t* p = reinterpret_cast<int32_t*>(pc_); *p += delta; // Relocate entry. - CPU::FlushICache(p, sizeof(uint32_t)); + if (flush_icache) CpuFeatures::FlushICache(p, sizeof(uint32_t)); } } Address RelocInfo::target_address() { - ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); + DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); return Assembler::target_address_at(pc_, host_); } Address RelocInfo::target_address_address() { - ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) + DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || rmode_ == EMBEDDED_OBJECT || rmode_ == EXTERNAL_REFERENCE); return reinterpret_cast<Address>(pc_); @@ -108,10 +111,13 @@ int RelocInfo::target_address_size() { } -void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { - Assembler::set_target_address_at(pc_, host_, target); - ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); - if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { +void RelocInfo::set_target_address(Address target, + WriteBarrierMode write_barrier_mode, + ICacheFlushMode icache_flush_mode) { + Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode); + DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); + if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL && + IsCodeTarget(rmode_)) { Object* target_code = Code::GetCodeFromTargetAddress(target); host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( host(), this, HeapObject::cast(target_code)); @@ -120,23 +126,26 @@ void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { Object* RelocInfo::target_object() { - ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); + DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); return Memory::Object_at(pc_); } Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { - ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); + DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); return Memory::Object_Handle_at(pc_); } -void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { - ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); - ASSERT(!target->IsConsString()); +void RelocInfo::set_target_object(Object* target, + WriteBarrierMode write_barrier_mode, + ICacheFlushMode icache_flush_mode) { + DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); Memory::Object_at(pc_) = target; - CPU::FlushICache(pc_, sizeof(Address)); - if (mode == UPDATE_WRITE_BARRIER && + if (icache_flush_mode != SKIP_ICACHE_FLUSH) { + CpuFeatures::FlushICache(pc_, sizeof(Address)); + } + if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL && target->IsHeapObject()) { host()->GetHeap()->incremental_marking()->RecordWrite( @@ -146,43 +155,50 @@ void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { Address RelocInfo::target_reference() { - ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE); + DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE); return Memory::Address_at(pc_); } Address RelocInfo::target_runtime_entry(Assembler* origin) { - ASSERT(IsRuntimeEntry(rmode_)); + DCHECK(IsRuntimeEntry(rmode_)); return reinterpret_cast<Address>(*reinterpret_cast<int32_t*>(pc_)); } void RelocInfo::set_target_runtime_entry(Address target, - WriteBarrierMode mode) { - ASSERT(IsRuntimeEntry(rmode_)); - if (target_address() != target) set_target_address(target, mode); + WriteBarrierMode write_barrier_mode, + ICacheFlushMode icache_flush_mode) { + DCHECK(IsRuntimeEntry(rmode_)); + if (target_address() != target) { + set_target_address(target, write_barrier_mode, icache_flush_mode); + } } Handle<Cell> RelocInfo::target_cell_handle() { - ASSERT(rmode_ == RelocInfo::CELL); + DCHECK(rmode_ == RelocInfo::CELL); Address address = Memory::Address_at(pc_); return Handle<Cell>(reinterpret_cast<Cell**>(address)); } Cell* RelocInfo::target_cell() { - ASSERT(rmode_ == RelocInfo::CELL); + DCHECK(rmode_ == RelocInfo::CELL); return Cell::FromValueAddress(Memory::Address_at(pc_)); } -void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) { - ASSERT(rmode_ == RelocInfo::CELL); +void RelocInfo::set_target_cell(Cell* cell, + WriteBarrierMode write_barrier_mode, + ICacheFlushMode icache_flush_mode) { + DCHECK(rmode_ == RelocInfo::CELL); Address address = cell->address() + Cell::kValueOffset; Memory::Address_at(pc_) = address; - CPU::FlushICache(pc_, sizeof(Address)); - if (mode == UPDATE_WRITE_BARRIER && host() != NULL) { + if (icache_flush_mode != SKIP_ICACHE_FLUSH) { + CpuFeatures::FlushICache(pc_, sizeof(Address)); + } + if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) { // TODO(1550) We are passing NULL as a slot because cell can never be on // evacuation candidate. host()->GetHeap()->incremental_marking()->RecordWrite( @@ -192,36 +208,38 @@ void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) { Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { - ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); - ASSERT(*pc_ == kCallOpcode); + DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); + DCHECK(*pc_ == kCallOpcode); return Memory::Object_Handle_at(pc_ + 1); } Code* RelocInfo::code_age_stub() { - ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); - ASSERT(*pc_ == kCallOpcode); + DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); + DCHECK(*pc_ == kCallOpcode); return Code::GetCodeFromTargetAddress( Assembler::target_address_at(pc_ + 1, host_)); } -void RelocInfo::set_code_age_stub(Code* stub) { - ASSERT(*pc_ == kCallOpcode); - ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); - Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); +void RelocInfo::set_code_age_stub(Code* stub, + ICacheFlushMode icache_flush_mode) { + DCHECK(*pc_ == kCallOpcode); + DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); + Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start(), + icache_flush_mode); } Address RelocInfo::call_address() { - ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || + DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); return Assembler::target_address_at(pc_ + 1, host_); } void RelocInfo::set_call_address(Address target) { - ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || + DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); Assembler::set_target_address_at(pc_ + 1, host_, target); if (host() != NULL) { @@ -243,7 +261,7 @@ void RelocInfo::set_call_object(Object* target) { Object** RelocInfo::call_object_address() { - ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || + DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); return reinterpret_cast<Object**>(pc_ + 1); } @@ -275,14 +293,14 @@ void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { RelocInfo::Mode mode = rmode(); if (mode == RelocInfo::EMBEDDED_OBJECT) { visitor->VisitEmbeddedPointer(this); - CPU::FlushICache(pc_, sizeof(Address)); + CpuFeatures::FlushICache(pc_, sizeof(Address)); } else if (RelocInfo::IsCodeTarget(mode)) { visitor->VisitCodeTarget(this); } else if (mode == RelocInfo::CELL) { visitor->VisitCell(this); } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { visitor->VisitExternalReference(this); - CPU::FlushICache(pc_, sizeof(Address)); + CpuFeatures::FlushICache(pc_, sizeof(Address)); } else if (RelocInfo::IsCodeAgeSequence(mode)) { visitor->VisitCodeAgeSequence(this); } else if (((RelocInfo::IsJSReturn(mode) && @@ -302,14 +320,14 @@ void RelocInfo::Visit(Heap* heap) { RelocInfo::Mode mode = rmode(); if (mode == RelocInfo::EMBEDDED_OBJECT) { StaticVisitor::VisitEmbeddedPointer(heap, this); - CPU::FlushICache(pc_, sizeof(Address)); + CpuFeatures::FlushICache(pc_, sizeof(Address)); } else if (RelocInfo::IsCodeTarget(mode)) { StaticVisitor::VisitCodeTarget(heap, this); } else if (mode == RelocInfo::CELL) { StaticVisitor::VisitCell(heap, this); } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { StaticVisitor::VisitExternalReference(this); - CPU::FlushICache(pc_, sizeof(Address)); + CpuFeatures::FlushICache(pc_, sizeof(Address)); } else if (RelocInfo::IsCodeAgeSequence(mode)) { StaticVisitor::VisitCodeAgeSequence(heap, this); } else if (heap->isolate()->debug()->has_break_points() && @@ -348,7 +366,7 @@ Immediate::Immediate(Handle<Object> handle) { // Verify all Objects referred by code are NOT in new space. Object* obj = *handle; if (obj->IsHeapObject()) { - ASSERT(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); + DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); x_ = reinterpret_cast<intptr_t>(handle.location()); rmode_ = RelocInfo::EMBEDDED_OBJECT; } else { @@ -381,7 +399,7 @@ void Assembler::emit(Handle<Object> handle) { AllowDeferredHandleDereference heap_object_check; // Verify all Objects referred by code are NOT in new space. Object* obj = *handle; - ASSERT(!isolate()->heap()->InNewSpace(obj)); + DCHECK(!isolate()->heap()->InNewSpace(obj)); if (obj->IsHeapObject()) { emit(reinterpret_cast<intptr_t>(handle.location()), RelocInfo::EMBEDDED_OBJECT); @@ -434,7 +452,7 @@ void Assembler::emit_code_relative_offset(Label* label) { void Assembler::emit_w(const Immediate& x) { - ASSERT(RelocInfo::IsNone(x.rmode_)); + DCHECK(RelocInfo::IsNone(x.rmode_)); uint16_t value = static_cast<uint16_t>(x.x_); reinterpret_cast<uint16_t*>(pc_)[0] = value; pc_ += sizeof(uint16_t); @@ -449,10 +467,13 @@ Address Assembler::target_address_at(Address pc, void Assembler::set_target_address_at(Address pc, ConstantPoolArray* constant_pool, - Address target) { + Address target, + ICacheFlushMode icache_flush_mode) { int32_t* p = reinterpret_cast<int32_t*>(pc); *p = target - (pc + sizeof(int32_t)); - CPU::FlushICache(p, sizeof(int32_t)); + if (icache_flush_mode != SKIP_ICACHE_FLUSH) { + CpuFeatures::FlushICache(p, sizeof(int32_t)); + } } @@ -461,6 +482,11 @@ Address Assembler::target_address_from_return_address(Address pc) { } +Address Assembler::break_address_from_return_address(Address pc) { + return pc - Assembler::kPatchDebugBreakSlotReturnOffset; +} + + Displacement Assembler::disp_at(Label* L) { return Displacement(long_at(L->pos())); } @@ -482,7 +508,7 @@ void Assembler::emit_near_disp(Label* L) { byte disp = 0x00; if (L->is_near_linked()) { int offset = L->near_link_pos() - pc_offset(); - ASSERT(is_int8(offset)); + DCHECK(is_int8(offset)); disp = static_cast<byte>(offset & 0xFF); } L->link_to(pc_offset(), Label::kNear); @@ -491,30 +517,30 @@ void Assembler::emit_near_disp(Label* L) { void Operand::set_modrm(int mod, Register rm) { - ASSERT((mod & -4) == 0); + DCHECK((mod & -4) == 0); buf_[0] = mod << 6 | rm.code(); len_ = 1; } void Operand::set_sib(ScaleFactor scale, Register index, Register base) { - ASSERT(len_ == 1); - ASSERT((scale & -4) == 0); + DCHECK(len_ == 1); + DCHECK((scale & -4) == 0); // Use SIB with no index register only for base esp. - ASSERT(!index.is(esp) || base.is(esp)); + DCHECK(!index.is(esp) || base.is(esp)); buf_[1] = scale << 6 | index.code() << 3 | base.code(); len_ = 2; } void Operand::set_disp8(int8_t disp) { - ASSERT(len_ == 1 || len_ == 2); + DCHECK(len_ == 1 || len_ == 2); *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp; } void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) { - ASSERT(len_ == 1 || len_ == 2); + DCHECK(len_ == 1 || len_ == 2); int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]); *p = disp; len_ += sizeof(int32_t); @@ -539,6 +565,12 @@ Operand::Operand(int32_t disp, RelocInfo::Mode rmode) { set_dispr(disp, rmode); } + +Operand::Operand(Immediate imm) { + // [disp/r] + set_modrm(0, ebp); + set_dispr(imm.x_, imm.rmode_); +} } } // namespace v8::internal #endif // V8_IA32_ASSEMBLER_IA32_INL_H_ |