LCOV - code coverage report
Current view: top level - src/x64 - assembler-x64-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 104 114 91.2 %
Date: 2019-02-19 Functions: 21 24 87.5 %

          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    60820776 : void Assembler::emitl(uint32_t x) {
      27    60820776 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      28    60820776 :   pc_ += sizeof(uint32_t);
      29    60820776 : }
      30             : 
      31    46670315 : void Assembler::emitq(uint64_t x) {
      32    46670315 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      33    46670315 :   pc_ += sizeof(uint64_t);
      34    46670315 : }
      35             : 
      36      426426 : void Assembler::emitw(uint16_t x) {
      37      426426 :   WriteUnalignedValue(reinterpret_cast<Address>(pc_), x);
      38      426426 :   pc_ += sizeof(uint16_t);
      39      426426 : }
      40             : 
      41     3306859 : void Assembler::emit_runtime_entry(Address entry, RelocInfo::Mode rmode) {
      42             :   DCHECK(RelocInfo::IsRuntimeEntry(rmode));
      43     3306859 :   RecordRelocInfo(rmode);
      44     3306868 :   emitl(static_cast<uint32_t>(entry - options().code_range_start));
      45     3306867 : }
      46             : 
      47    10433626 : void Assembler::emit(Immediate x) {
      48    10433626 :   if (!RelocInfo::IsNone(x.rmode_)) {
      49           0 :     RecordRelocInfo(x.rmode_);
      50             :   }
      51    10433626 :   emitl(x.value_);
      52    10433687 : }
      53             : 
      54    46670327 : void Assembler::emit(Immediate64 x) {
      55    46670327 :   if (!RelocInfo::IsNone(x.rmode_)) {
      56    43785467 :     RecordRelocInfo(x.rmode_);
      57             :   }
      58    46670316 :   emitq(static_cast<uint64_t>(x.value_));
      59    46670312 : }
      60             : 
      61             : void Assembler::emit_rex_64(Register reg, Register rm_reg) {
      62    32609960 :   emit(0x48 | reg.high_bit() << 2 | rm_reg.high_bit());
      63             : }
      64             : 
      65             : void Assembler::emit_rex_64(XMMRegister reg, Register rm_reg) {
      66         761 :   emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
      67             : }
      68             : 
      69             : void Assembler::emit_rex_64(Register reg, XMMRegister rm_reg) {
      70         444 :   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    43154308 :   emit(0x48 | reg.high_bit() << 2 | op.data().rex);
      79             : }
      80             : 
      81             : void Assembler::emit_rex_64(XMMRegister reg, Operand op) {
      82        9568 :   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    58210886 :   emit(0x48 | rm_reg.high_bit());
      89             : }
      90             : 
      91      464332 : 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      214474 :   emit(0x40 | reg.high_bit() << 2 | rm_reg.high_bit());
      95             : }
      96             : 
      97             : void Assembler::emit_rex_32(Register reg, Operand op) {
      98       43418 :   emit(0x40 | reg.high_bit() << 2 | op.data().rex);
      99             : }
     100             : 
     101             : 
     102             : void Assembler::emit_rex_32(Register rm_reg) {
     103      489656 :   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    11168784 :   byte rex_bits = reg.high_bit() << 2 | rm_reg.high_bit();
     110     5584392 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     111             : }
     112             : 
     113             : void Assembler::emit_optional_rex_32(Register reg, Operand op) {
     114     7091185 :   byte rex_bits = reg.high_bit() << 2 | op.data().rex;
     115     7091185 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     116             : }
     117             : 
     118             : void Assembler::emit_optional_rex_32(XMMRegister reg, Operand op) {
     119       39773 :   byte rex_bits = (reg.code() & 0x8) >> 1 | op.data().rex;
     120       39773 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     121             : }
     122             : 
     123             : 
     124             : void Assembler::emit_optional_rex_32(XMMRegister reg, XMMRegister base) {
     125       29238 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     126       29238 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     127             : }
     128             : 
     129             : 
     130             : void Assembler::emit_optional_rex_32(XMMRegister reg, Register base) {
     131       48638 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     132       48638 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     133             : }
     134             : 
     135             : 
     136             : void Assembler::emit_optional_rex_32(Register reg, XMMRegister base) {
     137         522 :   byte rex_bits =  (reg.code() & 0x8) >> 1 | (base.code() & 0x8) >> 3;
     138         522 :   if (rex_bits != 0) emit(0x40 | rex_bits);
     139             : }
     140             : 
     141             : 
     142             : void Assembler::emit_optional_rex_32(Register rm_reg) {
     143    71802385 :   if (rm_reg.high_bit()) emit(0x41);
     144             : }
     145             : 
     146             : void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
     147        3451 :   if (rm_reg.high_bit()) emit(0x41);
     148             : }
     149             : 
     150             : void Assembler::emit_optional_rex_32(Operand op) {
     151     4529391 :   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      528042 :   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      158979 :   byte rxb = static_cast<byte>(~((reg.high_bit() << 2) | rm.data().rex)) << 5;
     166      158979 :   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     6228584 :   byte rv = static_cast<byte>(~((reg.high_bit() << 4) | v.code())) << 3;
     174     6228584 :   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      687021 :   emit(w | ((~v.code() & 0xf) << 3) | l | pp);
     182             : }
     183             : 
     184             : 
     185     2897792 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg,
     186             :                                 XMMRegister rm, VectorLength l, SIMDPrefix pp,
     187             :                                 LeadingOpcode mm, VexW w) {
     188     2897792 :   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     2897792 : }
     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         234 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     203         234 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     204         234 :   XMMRegister irm = XMMRegister::from_code(rm.code());
     205         234 :   emit_vex_prefix(ireg, ivreg, irm, l, pp, mm, w);
     206             : }
     207             : 
     208     4017813 : void Assembler::emit_vex_prefix(XMMRegister reg, XMMRegister vreg, Operand rm,
     209             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     210             :                                 VexW w) {
     211     4017813 :   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     4017813 : }
     220             : 
     221             : void Assembler::emit_vex_prefix(Register reg, Register vreg, Operand rm,
     222             :                                 VectorLength l, SIMDPrefix pp, LeadingOpcode mm,
     223             :                                 VexW w) {
     224         234 :   XMMRegister ireg = XMMRegister::from_code(reg.code());
     225         234 :   XMMRegister ivreg = XMMRegister::from_code(vreg.code());
     226         234 :   emit_vex_prefix(ireg, ivreg, rm, l, pp, mm, w);
     227             : }
     228             : 
     229             : 
     230     5199868 : Address Assembler::target_address_at(Address pc, Address constant_pool) {
     231     5200125 :   return ReadUnalignedValue<int32_t>(pc) + pc + 4;
     232             : }
     233             : 
     234     5634368 : void Assembler::set_target_address_at(Address pc, Address constant_pool,
     235             :                                       Address target,
     236             :                                       ICacheFlushMode icache_flush_mode) {
     237     5634368 :   WriteUnalignedValue(pc, static_cast<int32_t>(target - pc - 4));
     238     5634368 :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     239             :     FlushInstructionCache(pc, sizeof(int32_t));
     240             :   }
     241     5634368 : }
     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           0 : void Assembler::deserialization_set_special_target_at(
     254             :     Address instruction_payload, Code code, Address target) {
     255             :   set_target_address_at(instruction_payload,
     256             :                         !code.is_null() ? code->constant_pool() : kNullAddress,
     257           0 :                         target);
     258           0 : }
     259             : 
     260             : int Assembler::deserialization_special_target_size(
     261             :     Address instruction_payload) {
     262             :   return kSpecialTargetSize;
     263             : }
     264             : 
     265      545561 : Handle<Code> Assembler::code_target_object_handle_at(Address pc) {
     266      545561 :   return GetCodeTarget(ReadUnalignedValue<int32_t>(pc));
     267             : }
     268             : 
     269     3272596 : Address Assembler::runtime_entry_at(Address pc) {
     270     3272596 :   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       94864 :   if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     279             :     WriteUnalignedValue(
     280       37408 :         pc_, ReadUnalignedValue<int32_t>(pc_) - static_cast<int32_t>(delta));
     281       57456 :   } else if (IsInternalReference(rmode_)) {
     282             :     // Absolute code pointer inside code object moves with the code object.
     283       57456 :     WriteUnalignedValue(pc_, ReadUnalignedValue<Address>(pc_) + delta);
     284             :   }
     285             : }
     286             : 
     287             : 
     288             : Address RelocInfo::target_address() {
     289             :   DCHECK(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) || IsWasmCall(rmode_));
     290     5199872 :   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             :   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      387190 :   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    30298239 :   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     6795231 :   if (rmode_ == EMBEDDED_OBJECT) {
     322     6249670 :     return Handle<HeapObject>::cast(ReadUnalignedValue<Handle<Object>>(pc_));
     323             :   } else {
     324      545561 :     return origin->code_target_object_handle_at(pc_);
     325             :   }
     326             : }
     327             : 
     328             : Address RelocInfo::target_external_reference() {
     329             :   DCHECK(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
     330          98 :   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           0 :   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           0 :   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     6697968 :   WriteUnalignedValue(pc_, target->ptr());
     358           0 :   if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
     359      448382 :     FlushInstructionCache(pc_, sizeof(Address));
     360             :   }
     361     6694196 :   if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null()) {
     362     6249697 :     WriteBarrierForCode(host(), this, target);
     363             :   }
     364             : }
     365             : 
     366             : Address RelocInfo::target_runtime_entry(Assembler* origin) {
     367             :   DCHECK(IsRuntimeEntry(rmode_));
     368     3272596 :   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     3272594 :   if (target_address() != target) {
     376     3272594 :     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      385280 :   return ReadUnalignedValue<Address>(pc_);
     383             : }
     384             : 
     385             : void RelocInfo::WipeOut() {
     386     1548622 :   if (IsEmbeddedObject(rmode_) || IsExternalReference(rmode_) ||
     387     1161334 :       IsInternalReference(rmode_) || IsOffHeapTarget(rmode_)) {
     388      385398 :     WriteUnalignedValue(pc_, kNullAddress);
     389        1792 :   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     390             :     // Effectively write zero into the relocation.
     391             :     Assembler::set_target_address_at(pc_, constant_pool_,
     392        1792 :                                      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