v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-riscv-inl.h
Go to the documentation of this file.
1// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// - Neither the name of Sun Microsystems or the names of contributors may
16// be used to endorse or promote products derived from this software without
17// specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// The original source code covered by the above license above has been
32// modified significantly by Google Inc.
33// Copyright 2021 the V8 project authors. All rights reserved.
34
35#ifndef V8_CODEGEN_RISCV_ASSEMBLER_RISCV_INL_H_
36#define V8_CODEGEN_RISCV_ASSEMBLER_RISCV_INL_H_
37
39// Include the non-inl header before the rest of the headers.
40
43#include "src/debug/debug.h"
49
50namespace v8 {
51namespace internal {
52
53bool CpuFeatures::SupportsOptimizer() { return IsSupported(FPU); }
54
56 if (buffer_space() <= kGap) {
57 GrowBuffer();
58 }
59}
60
61// -----------------------------------------------------------------------------
62// WritableRelocInfo.
63
64void WritableRelocInfo::apply(intptr_t delta) {
66 // Absolute code pointer inside code object moves with the code object.
68 } else {
71 }
72}
73
79}
80
83 // Read the address of the word containing the target_address in an
84 // instruction stream.
85 // The only architecture-independent user of this function is the serializer.
86 // The serializer uses it to find out how many raw bytes of instruction to
87 // output before the next target.
88 // For an instruction like LUI/ORI where the target bits are mixed into the
89 // instruction bits, the size of the target will be zero, indicating that the
90 // serializer should not step forward in memory after a target is resolved
91 // and written. In this case the target_address_address function should
92 // return the end of the instructions to be patched, allowing the
93 // deserializer to deserialize the instructions as raw bytes and put them in
94 // place, ready to be patched with the target. After jump optimization,
95 // that is the address of the instruction that follows J/JAL/JR/JALR
96 // instruction.
97#ifdef V8_TARGET_ARCH_RISCV64
99#elif defined(V8_TARGET_ARCH_RISCV32)
101#endif
102}
103
105
107 if (IsCodedSpecially()) {
109 } else {
110 return kSystemPointerSize;
111 }
112}
113
116 WritableJitAllocation* jit_allocation, ICacheFlushMode icache_flush_mode) {
118 Assembler::set_uint32_constant_at(pc, constant_pool, target, jit_allocation,
119 icache_flush_mode);
120 } else {
121 UNREACHABLE();
122 }
123}
124
127 disasm::NameConverter converter;
128 disasm::Disassembler disasm(converter);
129 base::EmbeddedVector<char, 128> disasm_buffer;
130
131 disasm.InstructionDecode(disasm_buffer, reinterpret_cast<uint8_t*>(pc));
132 DEBUG_PRINTF("%s\n", disasm_buffer.begin());
133 disasm.InstructionDecode(disasm_buffer,
134 reinterpret_cast<uint8_t*>(pc + kInstrSize));
135 DEBUG_PRINTF("%s\n", disasm_buffer.begin());
136
137 DEBUG_PRINTF("\t target_compressed_address_at %d\n",
139 return static_cast<Tagged_t>(uint32_constant_at(pc, constant_pool));
140}
141
142WasmCodePointer RelocInfo::wasm_code_pointer_table_entry() const {
144 return WasmCodePointer(Assembler::uint32_constant_at(pc_, constant_pool_));
145}
146
148 WasmCodePointer target, ICacheFlushMode icache_flush_mode) {
151 &jit_allocation_, icache_flush_mode);
152}
153
156 int index =
157 static_cast<int>(target_address_at(pc, constant_pool)) & 0xFFFFFFFF;
158 return GetCodeTarget(index);
159}
160
162 Address pc, Address const_pool) {
163 DEBUG_PRINTF("\tcompressed_embedded_object_handle_at: pc: 0x%" PRIxPTR " \t ",
164 pc);
166}
167
169 DEBUG_PRINTF("\tembedded_object_handle_at: pc: 0x%" PRIxPTR " \n", pc);
170 disasm::NameConverter converter;
171 disasm::Disassembler disasm(converter);
173
174 disasm.InstructionDecode(disasm_buffer, reinterpret_cast<uint8_t*>(pc));
175 DEBUG_PRINTF("%s\n", disasm_buffer.begin());
176 disasm.InstructionDecode(disasm_buffer,
177 reinterpret_cast<uint8_t*>(pc + kInstrSize));
178 DEBUG_PRINTF("%s\n", disasm_buffer.begin());
179#if V8_TARGET_ARCH_RISCV64
180 Instr instr1 = Assembler::instr_at(pc);
182 DCHECK(IsAuipc(instr1));
183 DCHECK(IsLd(instr2));
184 int32_t embedded_target_offset = BrachlongOffset(instr1, instr2);
185 DEBUG_PRINTF("\tembedded_target_offset %d\n", embedded_target_offset);
186 static_assert(sizeof(EmbeddedObjectIndex) == sizeof(intptr_t));
187 DEBUG_PRINTF("\t EmbeddedObjectIndex %lu\n",
188 Memory<EmbeddedObjectIndex>(pc + embedded_target_offset));
189 return GetEmbeddedObject(
190 Memory<EmbeddedObjectIndex>(pc + embedded_target_offset));
191#else
194 auto target = target_address_at(pc, kNullAddress);
195 DEBUG_PRINTF("\ttarget %d\n", target);
196 return Handle<HeapObject>(reinterpret_cast<Address*>(target));
197#endif
198}
199
200#if V8_TARGET_ARCH_RISCV64
202 Address pc, EmbeddedObjectIndex data) {
203 Instr instr1 = Assembler::instr_at(pc);
205 DCHECK(IsAuipc(instr1));
206 DCHECK(IsLd(instr2));
207 int32_t embedded_target_offset = BrachlongOffset(instr1, instr2);
208 Memory<EmbeddedObjectIndex>(pc + embedded_target_offset) = data;
209}
210#endif
211
213 Address instruction_payload, Tagged<Code> code, Address target) {
214 set_target_address_at(instruction_payload,
215 !code.is_null() ? code->constant_pool() : kNullAddress,
216 target);
217}
218
220 Address instruction_payload) {
221 return kSpecialTargetSize;
222}
223
225 Address target) {
226#ifdef V8_TARGET_ARCH_RISCV64
227 set_target_value_at(pc, static_cast<uint64_t>(target));
228#elif defined(V8_TARGET_ARCH_RISCV32)
229 set_target_value_at(pc, static_cast<uint32_t>(target));
230#endif
231}
232
234 Address pc, Address target, WritableJitAllocation& jit_allocation,
235 RelocInfo::Mode mode) {
236 jit_allocation.WriteUnalignedValue<Address>(pc, target);
237}
238
239Tagged<HeapObject> RelocInfo::target_object(PtrComprCageBase cage_base) {
242 return Cast<HeapObject>(
244 cage_base,
246 } else {
247 return Cast<HeapObject>(
249 }
250}
251
252DirectHandle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
253 if (IsCodeTarget(rmode_)) {
254 return Cast<HeapObject>(
255 origin->code_target_object_handle_at(pc_, constant_pool_));
257 return origin->compressed_embedded_object_handle_at(pc_, constant_pool_);
258 } else if (IsFullEmbeddedObject(rmode_)) {
259 return origin->embedded_object_handle_at(pc_);
260 } else {
262 return origin->relative_code_target_object_handle_at(pc_);
263 }
264}
265
267 ICacheFlushMode icache_flush_mode) {
271 // We must not compress pointers to objects outside of the main pointer
272 // compression cage as we wouldn't be able to decompress them with the
273 // correct cage base.
276 !HeapLayout::InCodeSpace(target));
280 icache_flush_mode);
281 } else {
284 &jit_allocation_, icache_flush_mode);
285 }
286}
287
291}
292
294 Address target, ICacheFlushMode icache_flush_mode) {
297 &jit_allocation_, icache_flush_mode);
298}
299
302 return Memory<Address>(pc_);
303 } else {
304 // Encoded internal references are j/jal instructions.
308 return address;
309 }
310}
311
314 return pc_;
315}
316
320}
321
323 Address pc) const {
324 Instr instr1 = Assembler::instr_at(pc);
326 DCHECK(IsAuipc(instr1));
327 DCHECK(IsJalr(instr2));
328 int32_t code_target_index = BrachlongOffset(instr1, instr2);
329 return Cast<Code>(GetEmbeddedObject(code_target_index));
330}
331
333 Instr instr1 = Assembler::instr_at(pc);
335 DCHECK(IsAuipc(instr1));
336 DCHECK(IsJalr(instr2));
337 int32_t builtin_id = BrachlongOffset(instr1, instr2);
338 DCHECK(Builtins::IsBuiltinId(builtin_id));
339 return static_cast<Builtin>(builtin_id);
340}
341
342Builtin RelocInfo::target_builtin_at(Assembler* origin) {
345}
346
350}
351
352EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
353
355 Instruction* instr0 = Instruction::At((unsigned char*)pc);
356 Instruction* instr1 = Instruction::At((unsigned char*)(pc + 1 * kInstrSize));
357
358 // Interpret instructions for address generated by li: See listing in
359 // Assembler::set_target_address_at() just below.
360 if (IsLui(*reinterpret_cast<Instr*>(instr0)) &&
361 IsAddi(*reinterpret_cast<Instr*>(instr1))) {
362 // Assemble the 32bit value.
363 int32_t constant32 = (int32_t)(instr0->Imm20UValue() << kImm20Shift) +
364 (int32_t)instr1->Imm12Value();
365 return constant32;
366 }
367 // We should never get here, force a bad address if we do.
368 UNREACHABLE();
369}
370
372 WritableJitAllocation* jit_allocation,
373 ICacheFlushMode icache_flush_mode) {
374 Instruction* instr0 = Instruction::At((unsigned char*)pc);
375 Instruction* instr1 = Instruction::At((unsigned char*)(pc + 1 * kInstrSize));
376#ifdef DEBUG
377 // Check we have the result from a li macro-instruction.
378 DCHECK(IsLui(*reinterpret_cast<Instr*>(instr0)) &&
379 IsAddi(*reinterpret_cast<Instr*>(instr1)));
380#endif
381 int32_t high_20 = (((int32_t)target + 0x800) >> 12); // 20 bits
382 int32_t low_12 = (int32_t)target << 20 >> 20; // 12 bits
383 instr_at_put(pc, SetHi20Offset(high_20, instr0->InstructionBits()),
384 jit_allocation);
386 SetLo12Offset(low_12, instr1->InstructionBits()),
387 jit_allocation);
388 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
390 }
391 DCHECK_EQ(static_cast<uint32_t>(target_constant32_at(pc)), target);
392}
393
395 Instruction* instr0 = reinterpret_cast<Instruction*>(pc);
396 Instruction* instr1 = reinterpret_cast<Instruction*>(pc + 1 * kInstrSize);
397 CHECK(IsLui(*reinterpret_cast<Instr*>(instr0)));
398 CHECK(IsAddi(*reinterpret_cast<Instr*>(instr1)));
399 return target_constant32_at(pc);
400}
402 uint32_t new_constant,
403 WritableJitAllocation* jit_allocation,
404 ICacheFlushMode icache_flush_mode) {
405 Instruction* instr1 = reinterpret_cast<Instruction*>(pc);
406 Instruction* instr2 = reinterpret_cast<Instruction*>(pc + 1 * kInstrSize);
407 CHECK(IsLui(*reinterpret_cast<Instr*>(instr1)));
408 CHECK(IsAddi(*reinterpret_cast<Instr*>(instr2)));
409 set_target_constant32_at(pc, new_constant, jit_allocation, icache_flush_mode);
410}
411
412[[nodiscard]] static inline Instr SetHi20Offset(int32_t hi20, Instr instr) {
414 DCHECK(is_int20(hi20));
415 instr = (instr & ~kImm31_12Mask) | ((hi20 & kImm19_0Mask) << 12);
416 return instr;
417}
418
419[[nodiscard]] static inline Instr SetLo12Offset(int32_t lo12, Instr instr) {
421 DCHECK(is_int12(lo12));
422 instr &= ~kImm12Mask;
423 int32_t imm12 = lo12 << kImm12Shift;
425 Assembler::IsAddi(instr | (imm12 & kImm12Mask)));
426 return instr | (imm12 & kImm12Mask);
427}
428
429} // namespace internal
430} // namespace v8
431
432#endif // V8_CODEGEN_RISCV_ASSEMBLER_RISCV_INL_H_
#define DEBUG_PRINTF(...)
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
constexpr T * begin() const
Definition vector.h:96
IndirectHandle< Code > GetCodeTarget(intptr_t code_target_index) const
Definition assembler.cc:279
IndirectHandle< HeapObject > GetEmbeddedObject(EmbeddedObjectIndex index) const
Definition assembler.cc:300
static bool IsAddi(Instr instr)
static bool IsAuipc(Instr instr)
static void set_target_value_at(Address pc, uint64_t target, WritableJitAllocation *jit_allocation=nullptr, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static constexpr int kSpecialTargetSize
static void deserialization_set_target_internal_reference_at(Address pc, Address target, WritableJitAllocation &jit_allocation, RelocInfo::Mode mode=RelocInfo::INTERNAL_REFERENCE)
V8_INLINE Handle< Code > relative_code_target_object_handle_at(Address pc_) const
static Tagged_t target_compressed_address_at(Address pc, Address constant_pool)
static int32_t target_constant32_at(Address pc)
static void RelocateRelativeReference(RelocInfo::Mode rmode, Address pc, intptr_t pc_delta, WritableJitAllocation *jit_allocation=nullptr)
static void set_target_compressed_address_at(Address pc, Address constant_pool, Tagged_t target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static Address target_constant_address_at(Address pc)
static void set_uint32_constant_at(Address pc, Address constant_pool, uint32_t new_constant, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static bool IsJalr(Instr instr)
void instr_at_put(int pos, Instr instr)
static bool IsLui(Instr instr)
static void set_target_internal_reference_encoded_at(Address pc, Address target)
static constexpr int kGap
static int RelocateInternalReference(RelocInfo::Mode rmode, Address pc, intptr_t pc_delta, WritableJitAllocation *jit_allocation=nullptr)
static V8_INLINE void set_target_address_at(Address pc, Address constant_pool, Address target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
Handle< HeapObject > compressed_embedded_object_handle_at(Address pc, Address constant_pool)
static constexpr int kInstructionsFor32BitConstant
static Builtin target_builtin_at(Address pc)
static constexpr int kInstructionsFor64BitConstant
static void deserialization_set_special_target_at(Address location, Tagged< Code > code, Address target)
static int deserialization_special_target_size(Address location)
static void set_target_constant32_at(Address pc, uint32_t target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode)
void set_embedded_object_index_referenced_from(Address p, EmbeddedObjectIndex index)
Handle< HeapObject > embedded_object_handle_at(Address pc, Address constant_pool)
static V8_INLINE Address target_address_at(Address pc, Address constant_pool)
Instruction * pc() const
Handle< Code > code_target_object_handle_at(Address pc)
static uint32_t uint32_constant_at(Address pc, Address constant_pool)
static int BrachlongOffset(Instr auipc, Instr jalr)
static constexpr bool IsBuiltinId(Builtin builtin)
Definition builtins.h:128
static bool IsSupported(CpuFeature f)
V8_INLINE EnsureSpace(Assembler *assembler)
static V8_INLINE bool InTrustedSpace(Tagged< HeapObject > object)
static V8_INLINE bool InCodeSpace(Tagged< HeapObject > object)
static Instruction * At(Address pc)
V8_INLINE Address target_internal_reference()
static constexpr bool IsInternalReference(Mode mode)
Definition reloc-info.h:238
static constexpr bool IsOffHeapTarget(Mode mode)
Definition reloc-info.h:244
static constexpr bool IsRelativeCodeTarget(Mode mode)
Definition reloc-info.h:200
static constexpr bool IsCodeTargetMode(Mode mode)
Definition reloc-info.h:197
static constexpr bool IsCompressedEmbeddedObject(Mode mode)
Definition reloc-info.h:206
V8_INLINE Address target_address()
static constexpr bool IsNearBuiltinEntry(Mode mode)
Definition reloc-info.h:247
static constexpr bool IsInternalReferenceEncoded(Mode mode)
Definition reloc-info.h:241
V8_INLINE Address target_internal_reference_address()
static constexpr bool IsCodeTarget(Mode mode)
Definition reloc-info.h:196
static constexpr bool IsWasmCall(Mode mode)
Definition reloc-info.h:213
V8_INLINE int target_address_size()
V8_INLINE Builtin target_builtin_at(Assembler *origin)
V8_INLINE WasmCodePointer wasm_code_pointer_table_entry() const
V8_INLINE Address target_off_heap_target()
static constexpr bool IsWasmStubCall(Mode mode)
Definition reloc-info.h:214
static constexpr bool IsEmbeddedObjectMode(Mode mode)
Definition reloc-info.h:209
static constexpr bool IsExternalReference(Mode mode)
Definition reloc-info.h:235
V8_INLINE Address target_external_reference()
V8_INLINE Tagged< HeapObject > target_object(PtrComprCageBase cage_base)
V8_INLINE Address constant_pool_entry_address()
V8_INLINE JSDispatchHandle js_dispatch_handle()
V8_INLINE DirectHandle< HeapObject > target_object_handle(Assembler *origin)
static constexpr bool IsFullEmbeddedObject(Mode mode)
Definition reloc-info.h:203
bool HasTargetAddressAddress() const
V8_INLINE Address target_address_address()
static V8_INLINE Tagged_t CompressObject(Address tagged)
static V8_INLINE Address DecompressTagged(TOnHeapAddress on_heap_addr, Tagged_t raw_value)
V8_INLINE void WriteUnalignedValue(Address address, T value)
V8_INLINE void set_target_object(Tagged< InstructionStream > host, Tagged< HeapObject > target, WriteBarrierMode write_barrier_mode=UPDATE_WRITE_BARRIER, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
WritableJitAllocation & jit_allocation_
Definition reloc-info.h:462
V8_INLINE void set_wasm_code_pointer_table_entry(WasmCodePointer, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
V8_INLINE void apply(intptr_t delta)
V8_INLINE void set_target_external_reference(Address, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
#define V8_EXTERNAL_CODE_SPACE_BOOL
Definition globals.h:255
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
#define V8_ENABLE_SANDBOX_BOOL
Definition globals.h:160
TNode< Object > target
Instruction * instr
int int32_t
Definition unicode.cc:40
const int kImm12Shift
void FlushInstructionCache(void *start, size_t size)
kInterpreterTrampolineOffset Tagged< HeapObject >
Address Tagged_t
Definition globals.h:547
base::StrongAlias< JSDispatchHandleAliasTag, uint32_t > JSDispatchHandle
Definition globals.h:557
static Instr SetHi20Offset(int32_t hi20, Instr instr)
constexpr int kSystemPointerSize
Definition globals.h:410
const uint32_t kImm19_0Mask
constexpr uint8_t kInstrSize
static constexpr Address kNullAddress
Definition v8-internal.h:53
static Instr SetLo12Offset(int32_t lo12, Instr instr)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Local< T > Handle
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485