LCOV - code coverage report
Current view: top level - src/x64 - assembler-x64-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 110 121 90.9 %
Date: 2019-01-20 Functions: 14 19 73.7 %

          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::SupportsOptimizer() { return true; }
      19             : 
      20             : bool CpuFeatures::SupportsWasmSimd128() { return IsSupported(SSE4_1); }
      21             : 
      22             : // -----------------------------------------------------------------------------
      23             : // Implementation of Assembler
      24             : 
      25             : 
      26             : void Assembler::emitl(uint32_t x) {
      27    62641708 :   Memory<uint32_t>(pc_) = x;
      28    62641708 :   pc_ += sizeof(uint32_t);
      29             : }
      30             : 
      31    13487375 : void Assembler::emitp(Address x, RelocInfo::Mode rmode) {
      32    13487375 :   Memory<uintptr_t>(pc_) = x;
      33    13487375 :   if (!RelocInfo::IsNone(rmode)) {
      34    12920543 :     RecordRelocInfo(rmode, x);
      35             :   }
      36    13487374 :   pc_ += sizeof(uintptr_t);
      37    13487374 : }
      38             : 
      39             : 
      40             : void Assembler::emitq(uint64_t x) {
      41     2866283 :   Memory<uint64_t>(pc_) = x;
      42     2866283 :   pc_ += sizeof(uint64_t);
      43             : }
      44             : 
      45             : 
      46             : void Assembler::emitw(uint16_t x) {
      47      423595 :   Memory<uint16_t>(pc_) = x;
      48      423595 :   pc_ += sizeof(uint16_t);
      49             : }
      50             : 
      51             : void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
      52             :   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
      53     2736597 :   RecordRelocInfo(rmode);
      54     2736609 :   emitl(static_cast<uint32_t>(entry - options().code_range_start));
      55             : }
      56             : 
      57    11343762 : void Assembler::emit(Immediate x) {
      58    11343762 :   if (!RelocInfo::IsNone(x.rmode_)) {
      59           0 :     RecordRelocInfo(x.rmode_);
      60             :   }
      61    11343762 :   emitl(x.value_);
      62    11343762 : }
      63             : 
      64             : void Assembler::emit_rex_64(Register reg, Register rm_reg) {
      65    37700584 :   emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
      66             : }
      67             : 
      68             : 
      69             : void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
      70         753 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      71             : }
      72             : 
      73             : 
      74             : void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
      75         448 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      76             : }
      77             : 
      78             : void Assembler::emit_rex_64(XMMRegister reg, XMMRegister rm_reg) {
      79          35 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      80             : }
      81             : 
      82             : void Assembler::emit_rex_64(Register reg, Operand op) {
      83    41571694 :   emit(0x48 | reg.high_bit() << 2 | op.data().rex);
      84             : }
      85             : 
      86             : void Assembler::emit_rex_64(XMMRegister reg, Operand op) {
      87       26273 :   emit(0x48 | (reg.code() & 0x8) >> 1 | op.data().rex);
      88             : }
      89             : 
      90             : 
      91             : void Assembler::emit_rex_64(Register rm_reg) {
      92             :   DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
      93    28462596 :   emit(0x48 | rm_reg.high_bit());
      94             : }
      95             : 
      96      480448 : void Assembler::emit_rex_64(Operand op) { emit(0x48 | op.data().rex); }
      97             : 
      98             : void Assembler::emit_rex_32(Register reg, Register rm_reg) {
      99      211182 :   emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
     100             : }
     101             : 
     102             : void Assembler::emit_rex_32(Register reg, Operand op) {
     103       49333 :   emit(0x40 | reg.high_bit() << 2 | op.data().rex);
     104             : }
     105             : 
     106             : 
     107             : void Assembler::emit_rex_32(Register rm_reg) {
     108      471348 :   emit(0x40 | rm_reg.high_bit());
     109             : }
     110             : 
     111             : void Assembler::emit_rex_32(Operand op) { emit(0x40 | op.data().rex); }
     112             : 
     113             : void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
     114    12602118 :   byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
     115     6301059 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     116             : }
     117             : 
     118             : void Assembler::emit_optional_rex_32(Register reg, Operand op) {
     119     7880368 :   byte rex_bits = reg.high_bit() << 2 | op.data().rex;
     120     7880368 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     121             : }
     122             : 
     123             : void Assembler::emit_optional_rex_32(XMMRegister reg, Operand op) {
     124       50923 :   byte rex_bits = (reg.code() & 0x8) >> 1 | op.data().rex;
     125       50923 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     126             : }
     127             : 
     128             : 
     129             : void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
     130       56801 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     131       56801 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     132             : }
     133             : 
     134             : 
     135             : void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
     136       66748 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     137       66748 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     138             : }
     139             : 
     140             : 
     141             : void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
     142         511 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     143         511 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     144             : }
     145             : 
     146             : 
     147             : void Assembler::emit_optional_rex_32(Register rm_reg) {
     148    48339978 :   if (rm_reg.high_bit()) emit(0x41);
     149             : }
     150             : 
     151             : void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
     152        9386 :   if (rm_reg.high_bit()) emit(0x41);
     153             : }
     154             : 
     155             : void Assembler::emit_optional_rex_32(Operand op) {
     156     4679648 :   if (op.data().rex != 0) emit(0x40 | op.data().rex);
     157             : }
     158             : 
     159             : 
     160             : // byte 1 of 3-byte VEX
     161             : void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
     162             :                                 LeadingOpcode m) {
     163      568653 :   byte rxb = ~((reg.high_bit() << 2) | rm.high_bit()) << 5;
     164      568653 :   emit(rxb | m);
     165             : }
     166             : 
     167             : 
     168             : // byte 1 of 3-byte VEX
     169             : void Assembler::emit_vex3_byte1(XMMRegister reg, Operand rm, LeadingOpcode m) {
     170      163750 :   byte rxb = ~((reg.high_bit() << 2) | rm.data().rex) << 5;
     171      163750 :   emit(rxb | m);
     172             : }
     173             : 
     174             : 
     175             : // byte 1 of 2-byte VEX
     176             : void Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
     177             :                                 SIMDPrefix pp) {
     178     6628498 :   byte rv = ~((reg.high_bit() << 4) | v.code()) << 3;
     179     6628498 :   emit(rv | l | pp);
     180             : }
     181             : 
     182             : 
     183             : // byte 2 of 3-byte VEX
     184             : void Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
     185             :                                 SIMDPrefix pp) {
     186      732403 :   emit(w | ((~v.code() & 0xf) << 3) | l | pp);
     187             : }
     188             : 
     189             : 
     190     3123357 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
     191             :                                 XMMRegister rm, VectorLength l, SIMDPrefix pp,
     192             :                                 LeadingOpcode mm, VexW w) {
     193     3123357 :   if (rm.high_bit() || mm != k0F || w != kW0) {
     194             :     emit_vex3_byte0();
     195             :     emit_vex3_byte1(reg, rm, mm);
     196             :     emit_vex3_byte2(w, vreg, l, pp);
     197             :   } else {
     198             :     emit_vex2_byte0();
     199             :     emit_vex2_byte1(reg, vreg, l, pp);
     200             :   }
     201     3123357 : }
     202             : 
     203             : 
     204             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
     205             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     206             :                                 VexW w) {
     207         260 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     208         260 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     209         260 :   XMMRegister irm = XMMRegister::from_code(rm.code());
     210         260 :   emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
     211             : }
     212             : 
     213     4237544 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg, Operand rm,
     214             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     215             :                                 VexW w) {
     216     4237544 :   if (rm.data().rex || mm != k0F || w != kW0) {
     217             :     emit_vex3_byte0();
     218             :     emit_vex3_byte1(reg, rm, mm);
     219             :     emit_vex3_byte2(w, vreg, l, pp);
     220             :   } else {
     221             :     emit_vex2_byte0();
     222             :     emit_vex2_byte1(reg, vreg, l, pp);
     223             :   }
     224     4237544 : }
     225             : 
     226             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Operand rm,
     227             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     228             :                                 VexW w) {
     229         260 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     230         260 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     231         260 :   emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
     232             : }
     233             : 
     234             : 
     235     4470045 : Address Assembler::target_address_at(Address pc, Address constant_pool) {
     236     4470339 :   return Memory<int32_t>(pc) + pc + 4;
     237             : }
     238             : 
     239           0 : void Assembler::set_target_address_at(Address pc, Address constant_pool,
     240             :                                       Address target,
     241             :                                       ICacheFlushMode icache_flush_mode) {
     242     5504291 :   Memory<int32_t>(pc) = static_cast<int32_t>(target - pc - 4);
     243     5504291 :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     244             :     Assembler::FlushICache(pc, sizeof(int32_t));
     245             :   }
     246           0 : }
     247             : 
     248             : void Assembler::deserialization_set_target_internal_reference_at(
     249             :     Address pc, Address target, RelocInfo::Mode mode) {
     250           0 :   Memory<Address>(pc) = target;
     251             : }
     252             : 
     253             : 
     254             : Address Assembler::target_address_from_return_address(Address pc) {
     255           0 :   return pc - kCallTargetAddressOffset;
     256             : }
     257             : 
     258             : void Assembler::deserialization_set_special_target_at(
     259             :     Address instruction_payload, Code code, Address target) {
     260             :   set_target_address_at(instruction_payload,
     261             :                         !code.is_null() ? code->constant_pool() : kNullAddress,
     262             :                         target);
     263             : }
     264             : 
     265             : int Assembler::deserialization_special_target_size(
     266             :     Address instruction_payload) {
     267             :   return kSpecialTargetSize;
     268             : }
     269             : 
     270      954278 : Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
     271      954278 :   return GetCodeTarget(Memory<int32_t>(pc));
     272             : }
     273             : 
     274     2702430 : Address Assembler::runtime_entry_at(Address pc) {
     275     2702430 :   return Memory<int32_t>(pc) + options().code_range_start;
     276             : }
     277             : 
     278             : // -----------------------------------------------------------------------------
     279             : // Implementation of RelocInfo
     280             : 
     281             : // The modes possibly affected by apply must be in kApplyMask.
     282             : void RelocInfo::apply(intptr_t delta) {
     283      257283 :   if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     284       27321 :     Memory<int32_t>(pc_) -= static_cast<int32_t>(delta);
     285      229962 :   } else if (IsInternalReference(rmode_)) {
     286             :     // absolute code pointer inside code object moves with the code object.
     287      229962 :     Memory<Address>(pc_) += delta;
     288             :   }
     289             : }
     290             : 
     291             : 
     292             : Address RelocInfo::target_address() {
     293             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
     294     4470042 :   return Assembler::target_address_at(pc_, constant_pool_);
     295             : }
     296             : 
     297             : Address RelocInfo::target_address_address() {
     298             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
     299             :          IsWasmStubCall(rmode_) || IsEmbeddedObject(rmode_) ||
     300             :          IsExternalReference(rmode_) || IsOffHeapTarget(rmode_));
     301             :   return pc_;
     302             : }
     303             : 
     304             : 
     305             : Address RelocInfo::constant_pool_entry_address() {
     306           0 :   UNREACHABLE();
     307             : }
     308             : 
     309             : 
     310             : int RelocInfo::target_address_size() {
     311      379404 :   if (IsCodedSpecially()) {
     312             :     return Assembler::kSpecialTargetSize;
     313             :   } else {
     314             :     return kSystemPointerSize;
     315             :   }
     316             : }
     317             : 
     318             : HeapObject RelocInfo::target_object() {
     319             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     320    28339271 :   return HeapObject::cast(Object(Memory<Address>(pc_)));
     321             : }
     322             : 
     323             : Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
     324             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     325     6907943 :   if (rmode_ == EMBEDDED_OBJECT) {
     326     5953665 :     return Handle<HeapObject>::cast(Memory<Handle<Object>>(pc_));
     327             :   } else {
     328      954278 :     return origin->code_target_object_handle_at(pc_);
     329             :   }
     330             : }
     331             : 
     332             : Address RelocInfo::target_external_reference() {
     333             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     334         118 :   return Memory<Address>(pc_);
     335             : }
     336             : 
     337             : void RelocInfo::set_target_external_reference(
     338             :     Address target, ICacheFlushMode icache_flush_mode) {
     339             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     340           0 :   Memory<Address>(pc_) = target;
     341             :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     342             :     Assembler::FlushICache(pc_, sizeof(Address));
     343             :   }
     344             : }
     345             : 
     346             : Address RelocInfo::target_internal_reference() {
     347             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     348           0 :   return Memory<Address>(pc_);
     349             : }
     350             : 
     351             : 
     352             : Address RelocInfo::target_internal_reference_address() {
     353             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     354             :   return pc_;
     355             : }
     356             : 
     357             : void RelocInfo::set_target_object(Heap* heap, HeapObject target,
     358             :                                   WriteBarrierMode write_barrier_mode,
     359             :                                   ICacheFlushMode icache_flush_mode) {
     360             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     361     6400625 :   Memory<Address>(pc_) = target->ptr();
     362             :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     363      446961 :     Assembler::FlushICache(pc_, sizeof(Address));
     364             :   }
     365     6396493 :   if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) {
     366     5953670 :     WriteBarrierForCode(host(), this, target);
     367             :   }
     368             : }
     369             : 
     370             : Address RelocInfo::target_runtime_entry(Assembler* origin) {
     371             :   DCHECK(IsRuntimeEntry(rmode_));
     372     2702431 :   return origin->runtime_entry_at(pc_);
     373             : }
     374             : 
     375             : void RelocInfo::set_target_runtime_entry(Address target,
     376             :                                          WriteBarrierMode write_barrier_mode,
     377     2702430 :                                          ICacheFlushMode icache_flush_mode) {
     378             :   DCHECK(IsRuntimeEntry(rmode_));
     379     2702430 :   if (target_address() != target) {
     380     2702430 :     set_target_address(target, write_barrier_mode, icache_flush_mode);
     381             :   }
     382             : }
     383             : 
     384             : Address RelocInfo::target_off_heap_target() {
     385             :   DCHECK(IsOffHeapTarget(rmode_));
     386      379261 :   return Memory<Address>(pc_);
     387             : }
     388             : 
     389             : void RelocInfo::WipeOut() {
     390     1517448 :   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
     391     1137926 :       IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
     392      379404 :     Memory<Address>(pc_) = kNullAddress;
     393           0 :   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     394             :     // Effectively write zero into the relocation.
     395             :     Assembler::set_target_address_at(pc_, constant_pool_,
     396           0 :                                      pc_ + sizeof(int32_t));
     397             :   } else {
     398           0 :     UNREACHABLE();
     399             :   }
     400             : }
     401             : 
     402             : template <typename ObjectVisitor>
     403   137146606 : void RelocInfo::Visit(ObjectVisitor* visitor) {
     404             :   RelocInfo::Mode mode = rmode();
     405   137146606 :   if (mode == RelocInfo::EMBEDDED_OBJECT) {
     406     6638936 :     visitor->VisitEmbeddedPointer(host(), this);
     407     6639032 :     Assembler::FlushICache(pc_, sizeof(Address));
     408   130507670 :   } else if (RelocInfo::IsCodeTargetMode(mode)) {
     409      133600 :     visitor->VisitCodeTarget(host(), this);
     410   130374070 :   } else if (mode == RelocInfo::EXTERNAL_REFERENCE) {
     411        2621 :     visitor->VisitExternalReference(host(), this);
     412   130371449 :   } else if (mode == RelocInfo::INTERNAL_REFERENCE) {
     413         250 :     visitor->VisitInternalReference(host(), this);
     414   130371199 :   } else if (RelocInfo::IsRuntimeEntry(mode)) {
     415     3186401 :     visitor->VisitRuntimeEntry(host(), this);
     416   127184798 :   } else if (RelocInfo::IsOffHeapTarget(mode)) {
     417   127218579 :     visitor->VisitOffHeapTarget(host(), this);
     418             :   }
     419   136842526 : }
     420             : 
     421             : }  // namespace internal
     422             : }  // namespace v8
     423             : 
     424             : #endif  // V8_X64_ASSEMBLER_X64_INL_H_

Generated by: LCOV version 1.10