LCOV - code coverage report
Current view: top level - src/x64 - assembler-x64-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 140 142 98.6 %
Date: 2017-10-20 Functions: 22 26 84.6 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_X64_ASSEMBLER_X64_INL_H_
       6             : #define V8_X64_ASSEMBLER_X64_INL_H_
       7             : 
       8             : #include "src/x64/assembler-x64.h"
       9             : 
      10             : #include "src/base/cpu.h"
      11             : #include "src/debug/debug.h"
      12             : #include "src/objects-inl.h"
      13             : #include "src/v8memory.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : bool CpuFeatures::SupportsCrankshaft() { return true; }
      19             : 
      20             : bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(SSE4_1); }
      21             : 
      22             : // -----------------------------------------------------------------------------
      23             : // Implementation of Assembler
      24             : 
      25             : 
      26             : static const byte kCallOpcode = 0xE8;
      27             : 
      28             : 
      29             : void Assembler::emitl(uint32_t x) {
      30  1243083785 :   Memory::uint32_at(pc_) = x;
      31  1243083785 :   pc_ += sizeof(uint32_t);
      32             : }
      33             : 
      34             : 
      35    11546013 : void Assembler::emitp(void* x, RelocInfo::Mode rmode) {
      36    11546013 :   uintptr_t value = reinterpret_cast<uintptr_t>(x);
      37    11546013 :   Memory::uintptr_at(pc_) = value;
      38    11546013 :   if (!RelocInfo::IsNone(rmode)) {
      39     8551797 :     RecordRelocInfo(rmode, value);
      40             :   }
      41    11546019 :   pc_ += sizeof(uintptr_t);
      42    11546019 : }
      43             : 
      44             : 
      45             : void Assembler::emitq(uint64_t x) {
      46     1104730 :   Memory::uint64_at(pc_) = x;
      47     1104730 :   pc_ += sizeof(uint64_t);
      48             : }
      49             : 
      50             : 
      51             : void Assembler::emitw(uint16_t x) {
      52        9466 :   Memory::uint16_at(pc_) = x;
      53        9466 :   pc_ += sizeof(uint16_t);
      54             : }
      55             : 
      56     6032360 : void Assembler::emit_code_target(Handle<Code> target, RelocInfo::Mode rmode) {
      57             :   DCHECK(RelocInfo::IsCodeTarget(rmode));
      58     6032360 :   RecordRelocInfo(rmode);
      59    12064888 :   int current = static_cast<int>(code_targets_.size());
      60    15535693 :   if (current > 0 && !target.is_null() &&
      61             :       code_targets_.back().address() == target.address()) {
      62             :     // Optimization if we keep jumping to the same code target.
      63     1169360 :     emitl(current - 1);
      64             :   } else {
      65     4863084 :     code_targets_.push_back(target);
      66     4863088 :     emitl(current);
      67             :   }
      68     6032448 : }
      69             : 
      70             : 
      71             : void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
      72             :   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
      73     3087699 :   RecordRelocInfo(rmode);
      74     3087704 :   emitl(static_cast<uint32_t>(entry - isolate_data().code_range_start_));
      75             : }
      76             : 
      77     4830838 : void Assembler::emit(Immediate x) {
      78     4830838 :   if (!RelocInfo::IsNone(x.rmode_)) {
      79        3261 :     RecordRelocInfo(x.rmode_);
      80             :   }
      81     4830839 :   emitl(x.value_);
      82     4830839 : }
      83             : 
      84             : void Assembler::emit_rex_64(Register reg, Register rm_reg) {
      85    21457034 :   emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
      86             : }
      87             : 
      88             : 
      89             : void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
      90         856 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      91             : }
      92             : 
      93             : 
      94             : void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
      95         241 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      96             : }
      97             : 
      98             : 
      99             : void Assembler::emit_rex_64(Register reg, const Operand& op) {
     100    26528067 :   emit(0x48 | reg.high_bit() << 2 | op.rex_);
     101             : }
     102             : 
     103             : 
     104             : void Assembler::emit_rex_64(XMMRegister reg, const Operand& op) {
     105         516 :   emit(0x48 | (reg.code() & 0x8) >> 1 | op.rex_);
     106             : }
     107             : 
     108             : 
     109             : void Assembler::emit_rex_64(Register rm_reg) {
     110             :   DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
     111    19422243 :   emit(0x48 | rm_reg.high_bit());
     112             : }
     113             : 
     114             : 
     115             : void Assembler::emit_rex_64(const Operand& op) {
     116      133941 :   emit(0x48 | op.rex_);
     117             : }
     118             : 
     119             : 
     120             : void Assembler::emit_rex_32(Register reg, Register rm_reg) {
     121       35372 :   emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
     122             : }
     123             : 
     124             : 
     125             : void Assembler::emit_rex_32(Register reg, const Operand& op) {
     126        8744 :   emit(0x40 | reg.high_bit() << 2  | op.rex_);
     127             : }
     128             : 
     129             : 
     130             : void Assembler::emit_rex_32(Register rm_reg) {
     131      181606 :   emit(0x40 | rm_reg.high_bit());
     132             : }
     133             : 
     134             : 
     135             : void Assembler::emit_rex_32(const Operand& op) {
     136             :   emit(0x40 | op.rex_);
     137             : }
     138             : 
     139             : 
     140             : void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
     141     5277432 :   byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
     142     2638716 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     143             : }
     144             : 
     145             : 
     146             : void Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
     147     5461392 :   byte rex_bits =  reg.high_bit() << 2 | op.rex_;
     148     5461392 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     149             : }
     150             : 
     151             : 
     152             : void Assembler::emit_optional_rex_32(XMMRegister reg, const Operand& op) {
     153       23548 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | op.rex_;
     154       23548 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     155             : }
     156             : 
     157             : 
     158             : void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
     159        9378 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     160        9378 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     161             : }
     162             : 
     163             : 
     164             : void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
     165       37720 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     166       37720 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     167             : }
     168             : 
     169             : 
     170             : void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
     171         240 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     172         240 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     173             : }
     174             : 
     175             : 
     176             : void Assembler::emit_optional_rex_32(Register rm_reg) {
     177    25242341 :   if (rm_reg.high_bit()) emit(0x41);
     178             : }
     179             : 
     180             : void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
     181         268 :   if (rm_reg.high_bit()) emit(0x41);
     182             : }
     183             : 
     184             : void Assembler::emit_optional_rex_32(const Operand& op) {
     185     3916916 :   if (op.rex_ != 0) emit(0x40 | op.rex_);
     186             : }
     187             : 
     188             : 
     189             : // byte 1 of 3-byte VEX
     190             : void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
     191             :                                 LeadingOpcode m) {
     192      634465 :   byte rxb = ~((reg.high_bit() << 2) | rm.high_bit()) << 5;
     193      634465 :   emit(rxb | m);
     194             : }
     195             : 
     196             : 
     197             : // byte 1 of 3-byte VEX
     198             : void Assembler::emit_vex3_byte1(XMMRegister reg, const Operand& rm,
     199             :                                 LeadingOpcode m) {
     200       24125 :   byte rxb = ~((reg.high_bit() << 2) | rm.rex_) << 5;
     201       24125 :   emit(rxb | m);
     202             : }
     203             : 
     204             : 
     205             : // byte 1 of 2-byte VEX
     206             : void Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
     207             :                                 SIMDPrefix pp) {
     208     4302341 :   byte rv = ~((reg.high_bit() << 4) | v.code()) << 3;
     209     4302341 :   emit(rv | l | pp);
     210             : }
     211             : 
     212             : 
     213             : // byte 2 of 3-byte VEX
     214             : void Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
     215             :                                 SIMDPrefix pp) {
     216      658590 :   emit(w | ((~v.code() & 0xf) << 3) | l | pp);
     217             : }
     218             : 
     219             : 
     220     1981977 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
     221             :                                 XMMRegister rm, VectorLength l, SIMDPrefix pp,
     222             :                                 LeadingOpcode mm, VexW w) {
     223     1981977 :   if (rm.high_bit() || mm != k0F || w != kW0) {
     224             :     emit_vex3_byte0();
     225             :     emit_vex3_byte1(reg, rm, mm);
     226             :     emit_vex3_byte2(w, vreg, l, pp);
     227             :   } else {
     228             :     emit_vex2_byte0();
     229             :     emit_vex2_byte1(reg, vreg, l, pp);
     230             :   }
     231     1981977 : }
     232             : 
     233             : 
     234             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
     235             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     236             :                                 VexW w) {
     237         312 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     238         312 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     239         312 :   XMMRegister irm = XMMRegister::from_code(rm.code());
     240         312 :   emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
     241             : }
     242             : 
     243             : 
     244     2978954 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
     245       24125 :                                 const Operand& rm, VectorLength l,
     246             :                                 SIMDPrefix pp, LeadingOpcode mm, VexW w) {
     247     2978954 :   if (rm.rex_ || mm != k0F || w != kW0) {
     248             :     emit_vex3_byte0();
     249             :     emit_vex3_byte1(reg, rm, mm);
     250             :     emit_vex3_byte2(w, vreg, l, pp);
     251             :   } else {
     252             :     emit_vex2_byte0();
     253             :     emit_vex2_byte1(reg, vreg, l, pp);
     254             :   }
     255     2978954 : }
     256             : 
     257             : 
     258             : void Assembler::emit_vex_prefix(Register reg, Register vreg, const Operand& rm,
     259             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     260             :                                 VexW w) {
     261         312 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     262         312 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     263         312 :   emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
     264             : }
     265             : 
     266             : 
     267             : Address Assembler::target_address_at(Address pc, Address constant_pool) {
     268   207424870 :   return Memory::int32_at(pc) + pc + 4;
     269             : }
     270             : 
     271             : 
     272             : void Assembler::set_target_address_at(Isolate* isolate, Address pc,
     273             :                                       Address constant_pool, Address target,
     274             :                                       ICacheFlushMode icache_flush_mode) {
     275             :   DCHECK_IMPLIES(isolate == nullptr, icache_flush_mode == SKIP_ICACHE_FLUSH);
     276   192412557 :   Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
     277     9617953 :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     278   182799923 :     Assembler::FlushICache(isolate, pc, sizeof(int32_t));
     279             :   }
     280             : }
     281             : 
     282   207424870 : Address Assembler::target_address_at(Address pc, Code* code) {
     283             :   Address constant_pool = code ? code->constant_pool() : nullptr;
     284   207424870 :   return target_address_at(pc, constant_pool);
     285             : }
     286             : 
     287        5319 : void Assembler::set_target_address_at(Isolate* isolate, Address pc, Code* code,
     288             :                                       Address target,
     289             :                                       ICacheFlushMode icache_flush_mode) {
     290             :   Address constant_pool = code ? code->constant_pool() : nullptr;
     291             :   set_target_address_at(isolate, pc, constant_pool, target, icache_flush_mode);
     292        5319 : }
     293             : 
     294             : void Assembler::deserialization_set_target_internal_reference_at(
     295             :     Isolate* isolate, Address pc, Address target, RelocInfo::Mode mode) {
     296    35924336 :   Memory::Address_at(pc) = target;
     297             : }
     298             : 
     299             : 
     300             : Address Assembler::target_address_from_return_address(Address pc) {
     301             :   return pc - kCallTargetAddressOffset;
     302             : }
     303             : 
     304             : void Assembler::deserialization_set_special_target_at(
     305             :     Isolate* isolate, Address instruction_payload, Code* code, Address target) {
     306             :   set_target_address_at(isolate, instruction_payload, code, target);
     307             : }
     308             : 
     309     6025821 : Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
     310    12051642 :   return code_targets_[Memory::int32_at(pc)];
     311             : }
     312             : 
     313     3077632 : Address Assembler::runtime_entry_at(Address pc) {
     314     3077632 :   return Memory::int32_at(pc) + isolate_data().code_range_start_;
     315             : }
     316             : 
     317             : // -----------------------------------------------------------------------------
     318             : // Implementation of RelocInfo
     319             : 
     320             : // The modes possibly affected by apply must be in kApplyMask.
     321             : void RelocInfo::apply(intptr_t delta) {
     322      500415 :   if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     323      173830 :     Memory::int32_at(pc_) -= static_cast<int32_t>(delta);
     324      326585 :   } else if (IsInternalReference(rmode_)) {
     325             :     // absolute code pointer inside code object moves with the code object.
     326      326585 :     Memory::Address_at(pc_) += delta;
     327             :   }
     328             : }
     329             : 
     330             : 
     331             : Address RelocInfo::target_address() {
     332             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
     333   207424855 :   return Assembler::target_address_at(pc_, host_);
     334             : }
     335             : 
     336             : Address RelocInfo::target_address_address() {
     337             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
     338             :                               || rmode_ == EMBEDDED_OBJECT
     339             :                               || rmode_ == EXTERNAL_REFERENCE);
     340             :   return reinterpret_cast<Address>(pc_);
     341             : }
     342             : 
     343             : 
     344             : Address RelocInfo::constant_pool_entry_address() {
     345           0 :   UNREACHABLE();
     346             : }
     347             : 
     348             : 
     349             : int RelocInfo::target_address_size() {
     350     1719180 :   if (IsCodedSpecially()) {
     351             :     return Assembler::kSpecialTargetSize;
     352             :   } else {
     353             :     return kPointerSize;
     354             :   }
     355             : }
     356             : 
     357             : HeapObject* RelocInfo::target_object() {
     358             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     359    13038687 :   return HeapObject::cast(Memory::Object_at(pc_));
     360             : }
     361             : 
     362             : Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
     363             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     364    11015353 :   if (rmode_ == EMBEDDED_OBJECT) {
     365     4989532 :     return Handle<HeapObject>::cast(Memory::Object_Handle_at(pc_));
     366             :   } else {
     367     6025821 :     return origin->code_target_object_handle_at(pc_);
     368             :   }
     369             : }
     370             : 
     371             : 
     372             : Address RelocInfo::target_external_reference() {
     373             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     374      817925 :   return Memory::Address_at(pc_);
     375             : }
     376             : 
     377             : 
     378             : Address RelocInfo::target_internal_reference() {
     379             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     380      172753 :   return Memory::Address_at(pc_);
     381             : }
     382             : 
     383             : 
     384             : Address RelocInfo::target_internal_reference_address() {
     385             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     386             :   return reinterpret_cast<Address>(pc_);
     387             : }
     388             : 
     389             : void RelocInfo::set_target_object(HeapObject* target,
     390             :                                   WriteBarrierMode write_barrier_mode,
     391    10164206 :                                   ICacheFlushMode icache_flush_mode) {
     392             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     393     8349923 :   Memory::Object_at(pc_) = target;
     394             :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     395     3359351 :     Assembler::FlushICache(target->GetIsolate(), pc_, sizeof(Address));
     396             :   }
     397     5173093 :   if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != nullptr) {
     398             :     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(host(), this,
     399     4991113 :                                                                   target);
     400     4991113 :     host()->GetHeap()->RecordWriteIntoCode(host(), this, target);
     401             :   }
     402             : }
     403             : 
     404             : 
     405             : Address RelocInfo::target_runtime_entry(Assembler* origin) {
     406             :   DCHECK(IsRuntimeEntry(rmode_));
     407     3077632 :   return origin->runtime_entry_at(pc_);
     408             : }
     409             : 
     410             : void RelocInfo::set_target_runtime_entry(Isolate* isolate, Address target,
     411             :                                          WriteBarrierMode write_barrier_mode,
     412             :                                          ICacheFlushMode icache_flush_mode) {
     413             :   DCHECK(IsRuntimeEntry(rmode_));
     414     3077632 :   if (target_address() != target) {
     415     3077632 :     set_target_address(isolate, target, write_barrier_mode, icache_flush_mode);
     416             :   }
     417             : }
     418             : 
     419             : void RelocInfo::WipeOut(Isolate* isolate) {
     420       18140 :   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
     421        6392 :       IsInternalReference(rmode_)) {
     422        6429 :     Memory::Address_at(pc_) = nullptr;
     423        5319 :   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     424             :     // Effectively write zero into the relocation.
     425             :     Assembler::set_target_address_at(isolate, pc_, host_,
     426        5319 :                                      pc_ + sizeof(int32_t));
     427             :   } else {
     428           0 :     UNREACHABLE();
     429             :   }
     430             : }
     431             : 
     432             : template <typename ObjectVisitor>
     433   880550615 : void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) {
     434             :   RelocInfo::Mode mode = rmode();
     435   440277063 :   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     436      716326 :     visitor->VisitEmbeddedPointer(host(), this);
     437     8260229 :     Assembler::FlushICache(isolate, pc_, sizeof(Address));
     438   432016834 :   } else if (RelocInfo::IsCodeTarget(mode)) {
     439    13310220 :     visitor->VisitCodeTarget(host(), this);
     440   229409952 :   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     441   375407730 :     visitor->VisitExternalReference(host(), this);
     442    41706087 :   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
     443    78044544 :     visitor->VisitInternalReference(host(), this);
     444     2683815 :   } else if (RelocInfo::IsRuntimeEntry(mode)) {
     445     5367630 :     visitor->VisitRuntimeEntry(host(), this);
     446             :   }
     447   440277137 : }
     448             : 
     449             : // -----------------------------------------------------------------------------
     450             : // Implementation of Operand
     451             : 
     452             : void Operand::set_modrm(int mod, Register rm_reg) {
     453             :   DCHECK(is_uint2(mod));
     454    38714461 :   buf_[0] = mod << 6 | rm_reg.low_bits();
     455             :   // Set REX.B to the high bit of rm.code().
     456    38200323 :   rex_ |= rm_reg.high_bit();
     457             : }
     458             : 
     459             : 
     460             : void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
     461             :   DCHECK_EQ(len_, 1);
     462             :   DCHECK(is_uint2(scale));
     463             :   // Use SIB with no index register only for base rsp or r12. Otherwise we
     464             :   // would skip the SIB byte entirely.
     465             :   DCHECK(index != rsp || base == rsp || base == r12);
     466    10119355 :   buf_[1] = (scale << 6) | (index.low_bits() << 3) | base.low_bits();
     467     7960532 :   rex_ |= index.high_bit() << 1 | base.high_bit();
     468     5864685 :   len_ = 2;
     469             : }
     470             : 
     471             : void Operand::set_disp8(int disp) {
     472             :   DCHECK(is_int8(disp));
     473             :   DCHECK(len_ == 1 || len_ == 2);
     474    26296494 :   int8_t* p = reinterpret_cast<int8_t*>(&buf_[len_]);
     475    26296494 :   *p = disp;
     476    26296494 :   len_ += sizeof(int8_t);
     477             : }
     478             : 
     479             : void Operand::set_disp32(int disp) {
     480             :   DCHECK(len_ == 1 || len_ == 2);
     481     6842800 :   int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
     482     6842800 :   *p = disp;
     483     6842800 :   len_ += sizeof(int32_t);
     484             : }
     485             : 
     486             : void Operand::set_disp64(int64_t disp) {
     487             :   DCHECK_EQ(1, len_);
     488      451162 :   int64_t* p = reinterpret_cast<int64_t*>(&buf_[len_]);
     489      451162 :   *p = disp;
     490      451162 :   len_ += sizeof(disp);
     491             : }
     492             : }  // namespace internal
     493             : }  // namespace v8
     494             : 
     495             : #endif  // V8_X64_ASSEMBLER_X64_INL_H_

Generated by: LCOV version 1.10