LCOV - code coverage report
Current view: top level - src/x64 - assembler-x64-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 94 107 87.9 %
Date: 2019-04-17 Functions: 9 11 81.8 %

          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    48993215 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      28    63234782 :   pc_ += sizeof(uint32_t);
      29             : }
      30             : 
      31             : void Assembler::emitq(uint64_t x) {
      32    50466791 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      33    50466791 :   pc_ += sizeof(uint64_t);
      34             : }
      35             : 
      36             : void Assembler::emitw(uint16_t x) {
      37      374865 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      38      374865 :   pc_ += sizeof(uint16_t);
      39             : }
      40             : 
      41     3335848 : void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
      42             :   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
      43     3335848 :   RecordRelocInfo(rmode);
      44     3335854 :   emitl(static_cast<uint32_t>(entry - options().code_range_start));
      45     3335854 : }
      46             : 
      47    10651942 : void Assembler::emit(Immediate x) {
      48    10651942 :   if (!RelocInfo::IsNone(x.rmode_)) {
      49           0 :     RecordRelocInfo(x.rmode_);
      50             :   }
      51    10651942 :   emitl(x.value_);
      52    10651942 : }
      53             : 
      54    50466793 : void Assembler::emit(Immediate64 x) {
      55    50466793 :   if (!RelocInfo::IsNone(x.rmode_)) {
      56    48704436 :     RecordRelocInfo(x.rmode_);
      57             :   }
      58    50466791 :   emitq(static_cast<uint64_t>(x.value_));
      59    50466791 : }
      60             : 
      61             : void Assembler::emit_rex_64(Register reg, Register rm_reg) {
      62    33818118 :   emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
      63             : }
      64             : 
      65             : void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
      66         873 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      67             : }
      68             : 
      69             : void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
      70         416 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      71             : }
      72             : 
      73             : void Assembler::emit_rex_64(XMMRegister reg, XMMRegister rm_reg) {
      74          17 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      75             : }
      76             : 
      77             : void Assembler::emit_rex_64(Register reg, Operand op) {
      78    44088019 :   emit(0x48 | reg.high_bit() << 2 | op.data().rex);
      79             : }
      80             : 
      81             : void Assembler::emit_rex_64(XMMRegister reg, Operand op) {
      82       10758 :   emit(0x48 | (reg.code() & 0x8) >> 1 | op.data().rex);
      83             : }
      84             : 
      85             : 
      86             : void Assembler::emit_rex_64(Register rm_reg) {
      87             :   DCHECK_EQ(rm_reg.code() & 0xf, rm_reg.code());
      88    62692647 :   emit(0x48 | rm_reg.high_bit());
      89             : }
      90             : 
      91      465248 : void Assembler::emit_rex_64(Operand op) { emit(0x48 | op.data().rex); }
      92             : 
      93             : void Assembler::emit_rex_32(Register reg, Register rm_reg) {
      94      215782 :   emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
      95             : }
      96             : 
      97             : void Assembler::emit_rex_32(Register reg, Operand op) {
      98       44525 :   emit(0x40 | reg.high_bit() << 2 | op.data().rex);
      99             : }
     100             : 
     101             : 
     102             : void Assembler::emit_rex_32(Register rm_reg) {
     103      518027 :   emit(0x40 | rm_reg.high_bit());
     104             : }
     105             : 
     106             : void Assembler::emit_rex_32(Operand op) { emit(0x40 | op.data().rex); }
     107             : 
     108             : void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
     109    10020880 :   byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
     110     5010440 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     111             : }
     112             : 
     113             : void Assembler::emit_optional_rex_32(Register reg, Operand op) {
     114     6106191 :   byte rex_bits = reg.high_bit() << 2 | op.data().rex;
     115     7472457 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     116             : }
     117             : 
     118             : void Assembler::emit_optional_rex_32(XMMRegister reg, Operand op) {
     119       42048 :   byte rex_bits = (reg.code() & 0x8) >> 1 | op.data().rex;
     120       42048 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     121             : }
     122             : 
     123             : 
     124             : void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
     125       28127 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     126       28127 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     127             : }
     128             : 
     129             : 
     130             : void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
     131       46989 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     132       46989 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     133             : }
     134             : 
     135             : 
     136             : void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
     137         548 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     138         548 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     139             : }
     140             : 
     141             : 
     142             : void Assembler::emit_optional_rex_32(Register rm_reg) {
     143    77639310 :   if (rm_reg.high_bit()) emit(0x41);
     144             : }
     145             : 
     146             : void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
     147        3767 :   if (rm_reg.high_bit()) emit(0x41);
     148             : }
     149             : 
     150             : void Assembler::emit_optional_rex_32(Operand op) {
     151     4523240 :   if (op.data().rex != 0) emit(0x40 | op.data().rex);
     152             : }
     153             : 
     154             : 
     155             : // byte 1 of 3-byte VEX
     156             : void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
     157             :                                 LeadingOpcode m) {
     158             :   byte rxb = static_cast<byte>(~((reg.high_bit() << 2) | rm.high_bit())) << 5;
     159      592285 :   emit(rxb | m);
     160             : }
     161             : 
     162             : 
     163             : // byte 1 of 3-byte VEX
     164             : void Assembler::emit_vex3_byte1(XMMRegister reg, Operand rm, LeadingOpcode m) {
     165      166131 :   byte rxb = static_cast<byte>(~((reg.high_bit() << 2) | rm.data().rex)) << 5;
     166      166131 :   emit(rxb | m);
     167             : }
     168             : 
     169             : 
     170             : // byte 1 of 2-byte VEX
     171             : void Assembler::emit_vex2_byte1(XMMRegister reg, XMMRegister v, VectorLength l,
     172             :                                 SIMDPrefix pp) {
     173     5981093 :   byte rv = static_cast<byte>(~((reg.high_bit() << 4) | v.code())) << 3;
     174     5981093 :   emit(rv | l | pp);
     175             : }
     176             : 
     177             : 
     178             : // byte 2 of 3-byte VEX
     179             : void Assembler::emit_vex3_byte2(VexW w, XMMRegister v, VectorLength l,
     180             :                                 SIMDPrefix pp) {
     181      758416 :   emit(w | ((~v.code() & 0xf) << 3) | l | pp);
     182             : }
     183             : 
     184             : 
     185     2997250 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
     186             :                                 XMMRegister rm, VectorLength l, SIMDPrefix pp,
     187             :                                 LeadingOpcode mm, VexW w) {
     188     2997250 :   if (rm.high_bit() || mm != k0F || w != kW0) {
     189             :     emit_vex3_byte0();
     190             :     emit_vex3_byte1(reg, rm, mm);
     191             :     emit_vex3_byte2(w, vreg, l, pp);
     192             :   } else {
     193             :     emit_vex2_byte0();
     194             :     emit_vex2_byte1(reg, vreg, l, pp);
     195             :   }
     196     2997250 : }
     197             : 
     198             : 
     199             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Register rm,
     200             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     201             :                                 VexW w) {
     202           0 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     203           0 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     204           0 :   XMMRegister irm = XMMRegister::from_code(rm.code());
     205           0 :   emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
     206             : }
     207             : 
     208     3742259 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg, Operand rm,
     209             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     210             :                                 VexW w) {
     211     3742259 :   if (rm.data().rex || mm != k0F || w != kW0) {
     212             :     emit_vex3_byte0();
     213             :     emit_vex3_byte1(reg, rm, mm);
     214             :     emit_vex3_byte2(w, vreg, l, pp);
     215             :   } else {
     216             :     emit_vex2_byte0();
     217             :     emit_vex2_byte1(reg, vreg, l, pp);
     218             :   }
     219     3742259 : }
     220             : 
     221             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Operand rm,
     222             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     223             :                                 VexW w) {
     224           0 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     225           0 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     226           0 :   emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
     227             : }
     228             : 
     229             : 
     230      191547 : Address Assembler::target_address_at(Address pc, Address constant_pool) {
     231     5219235 :   return ReadUnalignedValue<int32_t>(pc) + pc + 4;
     232             : }
     233             : 
     234     5661168 : void Assembler::set_target_address_at(Address pc, Address constant_pool,
     235             :                                       Address target,
     236             :                                       ICacheFlushMode icache_flush_mode) {
     237     5661168 :   WriteUnalignedValue(pc, static_cast<int32_t>(target - pc - 4));
     238     5661168 :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     239             :     FlushInstructionCache(pc, sizeof(int32_t));
     240             :   }
     241     5661168 : }
     242             : 
     243             : void Assembler::deserialization_set_target_internal_reference_at(
     244             :     Address pc, Address target, RelocInfo::Mode mode) {
     245             :   WriteUnalignedValue(pc, target);
     246             : }
     247             : 
     248             : 
     249             : Address Assembler::target_address_from_return_address(Address pc) {
     250           0 :   return pc - kCallTargetAddressOffset;
     251             : }
     252             : 
     253             : void Assembler::deserialization_set_special_target_at(
     254             :     Address instruction_payload, Code code, Address target) {
     255           0 :   set_target_address_at(instruction_payload,
     256             :                         !code.is_null() ? code->constant_pool() : kNullAddress,
     257           0 :                         target);
     258             : }
     259             : 
     260             : int Assembler::deserialization_special_target_size(
     261             :     Address instruction_payload) {
     262             :   return kSpecialTargetSize;
     263             : }
     264             : 
     265             : Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
     266      532301 :   return GetCodeTarget(ReadUnalignedValue<int32_t>(pc));
     267             : }
     268             : 
     269             : Address Assembler::runtime_entry_at(Address pc) {
     270     3332856 :   return ReadUnalignedValue<int32_t>(pc) + options().code_range_start;
     271             : }
     272             : 
     273             : // -----------------------------------------------------------------------------
     274             : // Implementation of RelocInfo
     275             : 
     276             : // The modes possibly affected by apply must be in kApplyMask.
     277             : void RelocInfo::apply(intptr_t delta) {
     278      170259 :   if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     279       39605 :     WriteUnalignedValue(
     280       39605 :         pc_, ReadUnalignedValue<int32_t>(pc_) - static_cast<int32_t>(delta));
     281      130654 :   } else if (IsInternalReference(rmode_)) {
     282             :     // Absolute code pointer inside code object moves with the code object.
     283      261308 :     WriteUnalignedValue(pc_, ReadUnalignedValue<Address>(pc_) + delta);
     284             :   }
     285             : }
     286             : 
     287             : 
     288             : Address RelocInfo::target_address() {
     289             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
     290     1886177 :   return Assembler::target_address_at(pc_, constant_pool_);
     291             : }
     292             : 
     293             : Address RelocInfo::target_address_address() {
     294             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_) ||
     295             :          IsWasmStubCall(rmode_) || IsEmbeddedObject(rmode_) ||
     296             :          IsExternalReference(rmode_) || IsOffHeapTarget(rmode_));
     297    94849796 :   return pc_;
     298             : }
     299             : 
     300             : 
     301             : Address RelocInfo::constant_pool_entry_address() {
     302           0 :   UNREACHABLE();
     303             : }
     304             : 
     305             : 
     306             : int RelocInfo::target_address_size() {
     307      398926 :   if (IsCodedSpecially()) {
     308             :     return Assembler::kSpecialTargetSize;
     309             :   } else {
     310             :     return kSystemPointerSize;
     311             :   }
     312             : }
     313             : 
     314             : HeapObject RelocInfo::target_object() {
     315             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     316    18527712 :   return HeapObject::cast(Object(ReadUnalignedValue<Address>(pc_)));
     317             : }
     318             : 
     319             : Handle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
     320             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     321     6821376 :   if (rmode_ == EMBEDDED_OBJECT) {
     322    12578150 :     return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
     323             :   } else {
     324      532301 :     return origin->code_target_object_handle_at(pc_);
     325             :   }
     326             : }
     327             : 
     328             : Address RelocInfo::target_external_reference() {
     329             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     330         114 :   return ReadUnalignedValue<Address>(pc_);
     331             : }
     332             : 
     333             : void RelocInfo::set_target_external_reference(
     334             :     Address target, ICacheFlushMode icache_flush_mode) {
     335             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     336          16 :   WriteUnalignedValue(pc_, target);
     337             :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     338             :     FlushInstructionCache(pc_, sizeof(Address));
     339             :   }
     340             : }
     341             : 
     342             : Address RelocInfo::target_internal_reference() {
     343             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     344          96 :   return ReadUnalignedValue<Address>(pc_);
     345             : }
     346             : 
     347             : 
     348             : Address RelocInfo::target_internal_reference_address() {
     349             :   DCHECK(rmode_ == INTERNAL_REFERENCE);
     350             :   return pc_;
     351             : }
     352             : 
     353             : void RelocInfo::set_target_object(Heap* heap, HeapObject target,
     354             :                                   WriteBarrierMode write_barrier_mode,
     355             :                                   ICacheFlushMode icache_flush_mode) {
     356             :   DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
     357     6716710 :   WriteUnalignedValue(pc_, target->ptr());
     358             :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     359      427636 :     FlushInstructionCache(pc_, sizeof(Address));
     360             :   }
     361     6712418 :   if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) {
     362     6289083 :     WriteBarrierForCode(host(), this, target);
     363             :   }
     364             : }
     365             : 
     366             : Address RelocInfo::target_runtime_entry(Assembler* origin) {
     367             :   DCHECK(IsRuntimeEntry(rmode_));
     368     3332856 :   return origin->runtime_entry_at(pc_);
     369             : }
     370             : 
     371             : void RelocInfo::set_target_runtime_entry(Address target,
     372             :                                          WriteBarrierMode write_barrier_mode,
     373             :                                          ICacheFlushMode icache_flush_mode) {
     374             :   DCHECK(IsRuntimeEntry(rmode_));
     375     3332856 :   if (target_address() != target) {
     376     3332856 :     set_target_address(target, write_barrier_mode, icache_flush_mode);
     377             :   }
     378             : }
     379             : 
     380             : Address RelocInfo::target_off_heap_target() {
     381             :   DCHECK(IsOffHeapTarget(rmode_));
     382      396981 :   return ReadUnalignedValue<Address>(pc_);
     383             : }
     384             : 
     385             : void RelocInfo::WipeOut() {
     386     1196758 :   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
     387      797734 :       IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
     388      397099 :     WriteUnalignedValue(pc_, kNullAddress);
     389        1827 :   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     390             :     // Effectively write zero into the relocation.
     391        1827 :     Assembler::set_target_address_at(pc_, constant_pool_,
     392        3654 :                                      pc_ + sizeof(int32_t));
     393             :   } else {
     394           0 :     UNREACHABLE();
     395             :   }
     396             : }
     397             : 
     398             : }  // namespace internal
     399             : }  // namespace v8
     400             : 
     401             : #endif  // V8_X64_ASSEMBLER_X64_INL_H_

Generated by: LCOV version 1.10