v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-ppc-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
6// are 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
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been modified
34// significantly by Google Inc.
35// Copyright 2014 the V8 project authors. All rights reserved.
36
37#ifndef V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_
38#define V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_
39
41// Include the non-inl header before the rest of the headers.
42
45#include "src/debug/debug.h"
48
49namespace v8 {
50namespace internal {
51
52bool CpuFeatures::SupportsOptimizer() { return true; }
53
54void WritableRelocInfo::apply(intptr_t delta) {
55 // absolute code pointer inside code object moves with the code object.
57 // Jump table entry
58 Address target = Memory<Address>(pc_);
59 jit_allocation_.WriteValue(pc_, target + delta);
60 } else {
61 // mov sequence
66 }
67}
68
71 // Jump table entry
72 return Memory<Address>(pc_);
73 } else {
74 // mov sequence
77 }
78}
79
82 return pc_;
83}
84
88}
89
92
95 // We return the PC for embedded constant pool since this function is used
96 // by the serializer and expects the address to reside within the code
97 // object.
98 return pc_;
99 }
100
101 // Read the address of the word containing the target_address in an
102 // instruction stream.
103 // The only architecture-independent user of this function is the serializer.
104 // The serializer uses it to find out how many raw bytes of instruction to
105 // output before the next target.
106 // For an instruction like LIS/ORI where the target bits are mixed into the
107 // instruction bits, the size of the target will be zero, indicating that the
108 // serializer should not step forward in memory after a target is resolved
109 // and written.
110 return pc_;
111}
112
120 }
121 UNREACHABLE();
122}
123
126 WritableJitAllocation* jit_allocation, ICacheFlushMode icache_flush_mode) {
128 static_cast<Address>(target), jit_allocation,
129 icache_flush_mode);
130}
131
133 if (IsCodedSpecially()) {
135 } else {
136 return kSystemPointerSize;
137 }
138}
139
142 return static_cast<Tagged_t>(target_address_at(pc, constant_pool));
143}
144
147 int index =
148 static_cast<int>(target_address_at(pc, constant_pool)) & 0xFFFFFFFF;
149 return GetCodeTarget(index);
150}
151
152Tagged<HeapObject> RelocInfo::target_object(PtrComprCageBase cage_base) {
155 Tagged_t compressed =
157 DCHECK(!HAS_SMI_TAG(compressed));
158 Tagged<Object> obj(
159 V8HeapCompressionScheme::DecompressTagged(cage_base, compressed));
160 return Cast<HeapObject>(obj);
161 } else {
162 return Cast<HeapObject>(
164 }
165}
166
168 Address pc, Address const_pool) {
170}
171
172DirectHandle<HeapObject> RelocInfo::target_object_handle(Assembler* origin) {
174 if (IsCodeTarget(rmode_)) {
175 return Cast<HeapObject>(
176 origin->code_target_object_handle_at(pc_, constant_pool_));
177 } else {
179 return origin->compressed_embedded_object_handle_at(pc_, constant_pool_);
180 }
181 return DirectHandle<HeapObject>::FromSlot(reinterpret_cast<Address*>(
183 }
184}
185
187 ICacheFlushMode icache_flush_mode) {
191 // We must not compress pointers to objects outside of the main pointer
192 // compression cage as we wouldn't be able to decompress them with the
193 // correct cage base.
196 !HeapLayout::InCodeSpace(target));
200 icache_flush_mode);
201 } else {
204 &jit_allocation_, icache_flush_mode);
205 }
206}
207
211}
212
214 Address target, ICacheFlushMode icache_flush_mode) {
217 &jit_allocation_, icache_flush_mode);
218}
219
220WasmCodePointer RelocInfo::wasm_code_pointer_table_entry() const {
222 return WasmCodePointer{Assembler::uint32_constant_at(pc_, constant_pool_)};
223}
224
226 WasmCodePointer target, ICacheFlushMode icache_flush_mode) {
229 &jit_allocation_, icache_flush_mode);
230}
231
235}
236
237Builtin RelocInfo::target_builtin_at(Assembler* origin) { UNREACHABLE(); }
238
242}
243
244Operand::Operand(Register rm) : rm_(rm), rmode_(RelocInfo::NO_INFO) {}
245
246void Assembler::UntrackBranch() {
247 DCHECK(!trampoline_emitted_);
248 DCHECK_GT(tracked_branch_count_, 0);
249 int count = --tracked_branch_count_;
250 if (count == 0) {
251 // Reset
252 next_trampoline_check_ = kMaxInt;
253 } else {
254 next_trampoline_check_ += kTrampolineSlotsSize;
255 }
256}
257
258// Fetch the 32bit value from the FIXED_SEQUENCE lis/ori
259Address Assembler::target_address_at(Address pc, Address constant_pool) {
260 if (V8_EMBEDDED_CONSTANT_POOL_BOOL && constant_pool) {
262 if (IsConstantPoolLoadStart(pc, &access))
263 return Memory<Address>(target_constant_pool_address_at(
264 pc, constant_pool, access, ConstantPoolEntry::INTPTR));
265 }
266
267 Instr instr1 = instr_at(pc);
268 Instr instr2 = instr_at(pc + kInstrSize);
269 // Interpret 2 instructions generated by lis/ori
270 if (IsLis(instr1) && IsOri(instr2)) {
271 Instr instr4 = instr_at(pc + (3 * kInstrSize));
272 Instr instr5 = instr_at(pc + (4 * kInstrSize));
273 // Assemble the 64 bit value.
274 uint64_t hi = (static_cast<uint32_t>((instr1 & kImm16Mask) << 16) |
275 static_cast<uint32_t>(instr2 & kImm16Mask));
276 uint64_t lo = (static_cast<uint32_t>((instr4 & kImm16Mask) << 16) |
277 static_cast<uint32_t>(instr5 & kImm16Mask));
278 return static_cast<Address>((hi << 32) | lo);
279 }
280
281 UNREACHABLE();
282}
283
284const uint32_t kLoadIntptrOpcode = LD;
285
286// Constant pool load sequence detection:
287// 1) REGULAR access:
288// load <dst>, kConstantPoolRegister + <offset>
289//
290// 2) OVERFLOWED access:
291// addis <scratch>, kConstantPoolRegister, <offset_high>
292// load <dst>, <scratch> + <offset_low>
293bool Assembler::IsConstantPoolLoadStart(Address pc,
295 Instr instr = instr_at(pc);
296 uint32_t opcode = instr & kOpcodeMask;
297 if (GetRA(instr) != kConstantPoolRegister) return false;
298 bool overflowed = (opcode == ADDIS);
299#ifdef DEBUG
300 if (overflowed) {
301 opcode = instr_at(pc + kInstrSize) & kOpcodeMask;
302 }
303 DCHECK(opcode == kLoadIntptrOpcode || opcode == LFD);
304#endif
305 if (access) {
306 *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
307 : ConstantPoolEntry::REGULAR);
308 }
309 return true;
310}
311
312bool Assembler::IsConstantPoolLoadEnd(Address pc,
314 Instr instr = instr_at(pc);
315 uint32_t opcode = instr & kOpcodeMask;
316 bool overflowed = false;
317 if (!(opcode == kLoadIntptrOpcode || opcode == LFD)) return false;
318 if (GetRA(instr) != kConstantPoolRegister) {
319 instr = instr_at(pc - kInstrSize);
320 opcode = instr & kOpcodeMask;
321 if ((opcode != ADDIS) || GetRA(instr) != kConstantPoolRegister) {
322 return false;
323 }
324 overflowed = true;
325 }
326 if (access) {
327 *access = (overflowed ? ConstantPoolEntry::OVERFLOWED
328 : ConstantPoolEntry::REGULAR);
329 }
330 return true;
331}
332
333int Assembler::GetConstantPoolOffset(Address pc,
336 bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
337#ifdef DEBUG
338 ConstantPoolEntry::Access access_check =
339 static_cast<ConstantPoolEntry::Access>(-1);
340 DCHECK(IsConstantPoolLoadStart(pc, &access_check));
341 DCHECK(access_check == access);
342#endif
343 int offset;
344 if (overflowed) {
345 offset = (instr_at(pc) & kImm16Mask) << 16;
346 offset += SIGN_EXT_IMM16(instr_at(pc + kInstrSize) & kImm16Mask);
347 DCHECK(!is_int16(offset));
348 } else {
349 offset = SIGN_EXT_IMM16((instr_at(pc) & kImm16Mask));
350 }
351 return offset;
352}
353
354void Assembler::PatchConstantPoolAccessInstruction(
357 Address pc = reinterpret_cast<Address>(buffer_start_) + pc_offset;
358 bool overflowed = (access == ConstantPoolEntry::OVERFLOWED);
359 CHECK(overflowed != is_int16(offset));
360#ifdef DEBUG
361 ConstantPoolEntry::Access access_check =
362 static_cast<ConstantPoolEntry::Access>(-1);
363 DCHECK(IsConstantPoolLoadStart(pc, &access_check));
364 DCHECK(access_check == access);
365#endif
366 if (overflowed) {
367 int hi_word = static_cast<int>(offset >> 16);
368 int lo_word = static_cast<int>(offset & 0xffff);
369 if (lo_word & 0x8000) hi_word++;
370
371 Instr instr1 = instr_at(pc);
372 Instr instr2 = instr_at(pc + kInstrSize);
373 instr1 &= ~kImm16Mask;
374 instr1 |= (hi_word & kImm16Mask);
375 instr2 &= ~kImm16Mask;
376 instr2 |= (lo_word & kImm16Mask);
377 instr_at_put(pc, instr1);
378 instr_at_put(pc + kInstrSize, instr2);
379 } else {
380 Instr instr = instr_at(pc);
381 instr &= ~kImm16Mask;
382 instr |= (offset & kImm16Mask);
383 instr_at_put(pc, instr);
384 }
385}
386
387Address Assembler::target_constant_pool_address_at(
388 Address pc, Address constant_pool, ConstantPoolEntry::Access access,
390 Address addr = constant_pool;
391 DCHECK(addr);
392 addr += GetConstantPoolOffset(pc, access, type);
393 return addr;
394}
395
396int Assembler::deserialization_special_target_size(
397 Address instruction_payload) {
398 return kSpecialTargetSize;
399}
400
401void Assembler::deserialization_set_target_internal_reference_at(
402 Address pc, Address target, WritableJitAllocation& jit_allocation,
403 RelocInfo::Mode mode) {
404 if (RelocInfo::IsInternalReferenceEncoded(mode)) {
405 set_target_address_at(pc, kNullAddress, target, &jit_allocation,
406 SKIP_ICACHE_FLUSH);
407 } else {
408 jit_allocation.WriteUnalignedValue<Address>(pc, target);
409 }
410}
411
412// This code assumes the FIXED_SEQUENCE of lis/ori
413void Assembler::set_target_address_at(Address pc, Address constant_pool,
414 Address target,
415 WritableJitAllocation* jit_allocation,
416 ICacheFlushMode icache_flush_mode) {
417 if (V8_EMBEDDED_CONSTANT_POOL_BOOL && constant_pool) {
418 ConstantPoolEntry::Access access;
419 if (IsConstantPoolLoadStart(pc, &access)) {
420 if (jit_allocation) {
421 jit_allocation->WriteUnalignedValue<Address>(
422 target_constant_pool_address_at(pc, constant_pool, access,
423 ConstantPoolEntry::INTPTR),
424 target);
425 } else {
426 Memory<Address>(target_constant_pool_address_at(
427 pc, constant_pool, access, ConstantPoolEntry::INTPTR)) = target;
428 }
429 return;
430 }
431 }
432
433 Instr instr1 = instr_at(pc);
434 Instr instr2 = instr_at(pc + kInstrSize);
435 // Interpret 2 instructions generated by lis/ori
436 if (IsLis(instr1) && IsOri(instr2)) {
437 Instr instr4 = instr_at(pc + (3 * kInstrSize));
438 Instr instr5 = instr_at(pc + (4 * kInstrSize));
439 // Needs to be fixed up when mov changes to handle 64-bit values.
440 uint32_t* p = reinterpret_cast<uint32_t*>(pc);
441 uintptr_t itarget = static_cast<uintptr_t>(target);
442
443 instr5 &= ~kImm16Mask;
444 instr5 |= itarget & kImm16Mask;
445 itarget = itarget >> 16;
446
447 instr4 &= ~kImm16Mask;
448 instr4 |= itarget & kImm16Mask;
449 itarget = itarget >> 16;
450
451 instr2 &= ~kImm16Mask;
452 instr2 |= itarget & kImm16Mask;
453 itarget = itarget >> 16;
454
455 instr1 &= ~kImm16Mask;
456 instr1 |= itarget & kImm16Mask;
457 itarget = itarget >> 16;
458
459 if (jit_allocation) {
460 jit_allocation->WriteUnalignedValue(reinterpret_cast<Address>(&p[0]),
461 instr1);
462 jit_allocation->WriteUnalignedValue(reinterpret_cast<Address>(&p[1]),
463 instr2);
464 jit_allocation->WriteUnalignedValue(reinterpret_cast<Address>(&p[3]),
465 instr4);
466 jit_allocation->WriteUnalignedValue(reinterpret_cast<Address>(&p[4]),
467 instr5);
468 } else {
469 *p = instr1;
470 *(p + 1) = instr2;
471 *(p + 3) = instr4;
472 *(p + 4) = instr5;
473 }
474 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
475 FlushInstructionCache(p, 5 * kInstrSize);
476 }
477 return;
478 }
479 UNREACHABLE();
480}
481
482uint32_t Assembler::uint32_constant_at(Address pc, Address constant_pool) {
483 return static_cast<uint32_t>(Assembler::target_address_at(pc, constant_pool));
484}
485
486void Assembler::set_uint32_constant_at(Address pc, Address constant_pool,
487 uint32_t new_constant,
488 WritableJitAllocation* jit_allocation,
489 ICacheFlushMode icache_flush_mode) {
490 Assembler::set_target_address_at(pc, constant_pool,
491 static_cast<Address>(new_constant),
492 jit_allocation, icache_flush_mode);
493}
494} // namespace internal
495} // namespace v8
496
497#endif // V8_CODEGEN_PPC_ASSEMBLER_PPC_INL_H_
IndirectHandle< Code > GetCodeTarget(intptr_t code_target_index) const
Definition assembler.cc:279
IndirectHandle< HeapObject > GetEmbeddedObject(EmbeddedObjectIndex index) const
Definition assembler.cc:300
static constexpr int kSpecialTargetSize
static V8_INLINE Address target_constant_pool_address_at(Address pc, Address constant_pool, ConstantPoolEntry::Access access, ConstantPoolEntry::Type type)
static Tagged_t target_compressed_address_at(Address pc, Address constant_pool)
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 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 V8_INLINE bool IsConstantPoolLoadStart(Address pc, ConstantPoolEntry::Access *access=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 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 V8_INLINE DirectHandle FromSlot(Address *slot)
Definition handles.h:687
static V8_INLINE bool InTrustedSpace(Tagged< HeapObject > object)
static V8_INLINE bool InCodeSpace(Tagged< HeapObject > object)
V8_INLINE Operand(int32_t immediate, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
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 IsCompressedEmbeddedObject(Mode mode)
Definition reloc-info.h:206
V8_INLINE Address target_address()
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
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 WriteValue(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 HAS_SMI_TAG(value)
Definition globals.h:1771
#define V8_EMBEDDED_CONSTANT_POOL_BOOL
Definition globals.h:81
#define V8_ENABLE_SANDBOX_BOOL
Definition globals.h:160
#define SIGN_EXT_IMM16(imm)
int32_t offset
TNode< Object > target
Instruction * instr
int pc_offset
uintptr_t Address
Definition memory.h:13
constexpr BarrierOption LD
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
const uint32_t kLoadIntptrOpcode
constexpr int kImm16Mask
constexpr Register kConstantPoolRegister
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr uint8_t kInstrSize
const int kOpcodeMask
constexpr int kMaxInt
Definition globals.h:374
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define UNREACHABLE()
Definition logging.h:67
#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_GT(v1, v2)
Definition logging.h:487