v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-arm-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 2012 the V8 project authors. All rights reserved.
36
37#ifndef V8_CODEGEN_ARM_ASSEMBLER_ARM_INL_H_
38#define V8_CODEGEN_ARM_ASSEMBLER_ARM_INL_H_
39
41// Include the non-inl header before the rest of the headers.
42
45#include "src/debug/debug.h"
47#include "src/objects/smi.h"
48
49namespace v8 {
50namespace internal {
51
52bool CpuFeatures::SupportsOptimizer() { return true; }
53
55 return CpuFeatures::IsSupported(VFP32DREGS) ? 32 : 16;
56}
57
58void WritableRelocInfo::apply(intptr_t delta) {
60 // absolute code pointer inside code object moves with the code object.
61 int32_t* p = reinterpret_cast<int32_t*>(pc_);
62 jit_allocation_.WriteValue(pc_, *p + delta); // relocate entry
65 int32_t branch_offset = branch->GetBranchOffset() - delta;
66 branch->SetBranchOffset(branch_offset, &jit_allocation_);
67 }
68}
69
75
78 if (Assembler::IsMovW(Memory<int32_t>(pc_))) {
79 return pc_;
80 } else if (Assembler::IsLdrPcImmediateOffset(Memory<int32_t>(pc_))) {
82 } else {
85 return pc_;
86 }
87}
88
93
95
101
110
117
122
129
134
141
146
151
156
158
163
165 Address pc) const {
166 Instruction* branch = Instruction::At(pc);
167 int code_target_index = branch->GetBranchOffset() / kInstrSize;
168 return GetCodeTarget(code_target_index);
169}
170
171Operand Operand::Zero() { return Operand(static_cast<int32_t>(0)); }
172
174 : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
175 value_.immediate = static_cast<int32_t>(f.address());
176}
177
178Operand::Operand(Tagged<Smi> value) : rmode_(RelocInfo::NO_INFO) {
179 value_.immediate = static_cast<intptr_t>(value.ptr());
180}
181
182Operand::Operand(Register rm) : rm_(rm), shift_op_(LSL), shift_imm_(0) {}
183
185 if (V8_UNLIKELY(buffer_space() <= kGap)) {
186 GrowBuffer();
187 }
189}
190
192 CheckBuffer();
193 *reinterpret_cast<Instr*>(pc_) = x;
194 pc_ += kInstrSize;
195}
196
200
206
208 return IsLdrPcImmediateOffset(Memory<int32_t>(pc));
209}
210
217
220 // This is a constant pool lookup. Return the value in the constant pool.
221 return Memory<Address>(constant_pool_entry_address(pc, constant_pool));
222 } else if (CpuFeatures::IsSupported(ARMv7) && IsMovW(Memory<int32_t>(pc))) {
223 // This is an movw / movt immediate load. Return the immediate.
224 DCHECK(IsMovW(Memory<int32_t>(pc)) &&
225 IsMovT(Memory<int32_t>(pc + kInstrSize)));
226 Instruction* movw_instr = Instruction::At(pc);
227 Instruction* movt_instr = Instruction::At(pc + kInstrSize);
228 return static_cast<Address>((movt_instr->ImmedMovwMovtValue() << 16) |
229 movw_instr->ImmedMovwMovtValue());
230 } else if (IsMovImmed(Memory<int32_t>(pc))) {
231 // This is an mov / orr immediate load. Return the immediate.
232 DCHECK(IsMovImmed(Memory<int32_t>(pc)) &&
233 IsOrrImmed(Memory<int32_t>(pc + kInstrSize)) &&
234 IsOrrImmed(Memory<int32_t>(pc + 2 * kInstrSize)) &&
235 IsOrrImmed(Memory<int32_t>(pc + 3 * kInstrSize)));
236 Instr mov_instr = instr_at(pc);
237 Instr orr_instr_1 = instr_at(pc + kInstrSize);
238 Instr orr_instr_2 = instr_at(pc + 2 * kInstrSize);
239 Instr orr_instr_3 = instr_at(pc + 3 * kInstrSize);
240 Address ret = static_cast<Address>(
241 DecodeShiftImm(mov_instr) | DecodeShiftImm(orr_instr_1) |
242 DecodeShiftImm(orr_instr_2) | DecodeShiftImm(orr_instr_3));
243 return ret;
244 } else {
245 Instruction* branch = Instruction::At(pc);
246 int32_t delta = branch->GetBranchOffset();
247 return pc + delta + Instruction::kPcLoadDelta;
248 }
249}
250
252 Address target,
253 WritableJitAllocation* jit_allocation,
254 ICacheFlushMode icache_flush_mode) {
256 // This is a constant pool lookup. Update the entry in the constant pool.
257 if (jit_allocation) {
258 jit_allocation->WriteValue<Address>(
260 } else {
262 }
263 // Intuitively, we would think it is necessary to always flush the
264 // instruction cache after patching a target address in the code as follows:
265 // FlushInstructionCache(pc, sizeof(target));
266 // However, on ARM, no instruction is actually patched in the case
267 // of embedded constants of the form:
268 // ldr ip, [pp, #...]
269 // since the instruction accessing this address in the constant pool remains
270 // unchanged.
271 } else if (CpuFeatures::IsSupported(ARMv7) && IsMovW(Memory<int32_t>(pc))) {
272 // This is an movw / movt immediate load. Patch the immediate embedded in
273 // the instructions.
274 DCHECK(IsMovW(Memory<int32_t>(pc)));
275 DCHECK(IsMovT(Memory<int32_t>(pc + kInstrSize)));
276 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
277 uint32_t immediate = static_cast<uint32_t>(target);
278 if (jit_allocation) {
279 jit_allocation->WriteValue(
280 reinterpret_cast<Address>(&instr_ptr[0]),
281 PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF));
282 jit_allocation->WriteValue(
283 reinterpret_cast<Address>(&instr_ptr[1]),
284 PatchMovwImmediate(instr_ptr[1], immediate >> 16));
285 } else {
286 instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF);
287 instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16);
288 }
289 DCHECK(IsMovW(Memory<int32_t>(pc)));
290 DCHECK(IsMovT(Memory<int32_t>(pc + kInstrSize)));
291 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
293 }
294 } else if (IsMovImmed(Memory<int32_t>(pc))) {
295 // This is an mov / orr immediate load. Patch the immediate embedded in
296 // the instructions.
297 DCHECK(IsMovImmed(Memory<int32_t>(pc)) &&
298 IsOrrImmed(Memory<int32_t>(pc + kInstrSize)) &&
299 IsOrrImmed(Memory<int32_t>(pc + 2 * kInstrSize)) &&
300 IsOrrImmed(Memory<int32_t>(pc + 3 * kInstrSize)));
301 uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
302 uint32_t immediate = static_cast<uint32_t>(target);
303 if (jit_allocation) {
304 jit_allocation->WriteValue(
305 reinterpret_cast<Address>(&instr_ptr[0]),
306 PatchShiftImm(instr_ptr[0], immediate & kImm8Mask));
307 jit_allocation->WriteValue(
308 reinterpret_cast<Address>(&instr_ptr[1]),
309 PatchShiftImm(instr_ptr[1], immediate & (kImm8Mask << 8)));
310 jit_allocation->WriteValue(
311 reinterpret_cast<Address>(&instr_ptr[2]),
312 PatchShiftImm(instr_ptr[2], immediate & (kImm8Mask << 16)));
313 jit_allocation->WriteValue(
314 reinterpret_cast<Address>(&instr_ptr[3]),
315 PatchShiftImm(instr_ptr[3], immediate & (kImm8Mask << 24)));
316 } else {
317 instr_ptr[0] = PatchShiftImm(instr_ptr[0], immediate & kImm8Mask);
318 instr_ptr[1] = PatchShiftImm(instr_ptr[1], immediate & (kImm8Mask << 8));
319 instr_ptr[2] = PatchShiftImm(instr_ptr[2], immediate & (kImm8Mask << 16));
320 instr_ptr[3] = PatchShiftImm(instr_ptr[3], immediate & (kImm8Mask << 24));
321 }
322 DCHECK(IsMovImmed(Memory<int32_t>(pc)) &&
323 IsOrrImmed(Memory<int32_t>(pc + kInstrSize)) &&
324 IsOrrImmed(Memory<int32_t>(pc + 2 * kInstrSize)) &&
325 IsOrrImmed(Memory<int32_t>(pc + 3 * kInstrSize)));
326 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
328 }
329 } else {
330 intptr_t branch_offset = target - pc - Instruction::kPcLoadDelta;
331 Instruction* branch = Instruction::At(pc);
332 branch->SetBranchOffset(branch_offset, jit_allocation);
333 if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
335 }
336 }
337}
338
343
345 uint32_t new_constant,
346 WritableJitAllocation* jit_allocation,
347 ICacheFlushMode icache_flush_mode) {
349 Memory<uint32_t>(constant_pool_entry_address(pc, constant_pool)) =
350 new_constant;
351 // Icache flushing not needed for Ldr via the constant pool.
352}
353
354EnsureSpace::EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
355
356template <typename T>
359 DCHECK_NOT_NULL(available);
360 for (int index = 0; index < T::kNumRegisters; index++) {
361 T reg = T::from_code(index);
362 uint64_t mask = reg.ToVfpRegList();
363 if ((*available & mask) == mask) {
364 return true;
365 }
366 }
367 return false;
368}
369
370template <typename T>
373 DCHECK_NOT_NULL(available);
374 for (int index = 0; index < T::kNumRegisters; index++) {
375 T reg = T::from_code(index);
376 uint64_t mask = reg.ToVfpRegList();
377 if ((*available & mask) == mask) {
378 *available &= ~mask;
379 return reg;
380 }
381 }
382 UNREACHABLE();
383}
384
385} // namespace internal
386} // namespace v8
387
388#endif // V8_CODEGEN_ARM_ASSEMBLER_ARM_INL_H_
IndirectHandle< Code > GetCodeTarget(intptr_t code_target_index) const
Definition assembler.cc:279
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
int branch_offset(Label *L)
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)
VfpRegList * GetScratchVfpRegisterList()
static bool IsMovImmed(Instr instr)
V8_INLINE void MaybeCheckConstPool()
static Instr PatchShiftImm(Instr instr, int immed)
static V8_INLINE Address constant_pool_entry_address(Address pc, Address constant_pool)
static constexpr int kGap
static bool IsMovW(Instr instr)
static V8_INLINE bool is_constant_pool_load(Address pc)
static bool IsMovT(Instr instr)
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)
static bool IsOrrImmed(Instr instr)
static int DecodeShiftImm(Instr instr)
static bool IsLdrPcImmediateOffset(Instr instr)
static int deserialization_special_target_size(Address location)
static bool IsBOrBlPcImmediateOffset(Instr instr)
static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate)
static V8_INLINE Address target_address_at(Address pc, Address constant_pool)
static int GetLdrRegisterImmediateOffset(Instr instr)
Instruction * pc() const
static uint32_t uint32_constant_at(Address pc, Address constant_pool)
static bool IsSupported(CpuFeature f)
static V8_INLINE DirectHandle FromSlot(Address *slot)
Definition handles.h:687
static int SupportedRegisterCount()
V8_INLINE EnsureSpace(Assembler *assembler)
V8_EXPORT_PRIVATE Address address() const
static constexpr int kPcLoadDelta
void SetBranchOffset(int32_t branch_offset, WritableJitAllocation *jit_allocation)
static Instruction * At(Address pc)
union v8::internal::Operand::Value value_
static V8_INLINE Operand Zero()
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 IsRelativeCodeTarget(Mode mode)
Definition reloc-info.h:200
static constexpr bool IsCodeTargetMode(Mode mode)
Definition reloc-info.h:197
V8_INLINE Address target_address()
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
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()
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)
TNode< Object > target
Instruction * instr
LiftoffRegister reg
int x
uint32_t const mask
constexpr int kPointerSize
Definition globals.h:599
uint64_t VfpRegList
void FlushInstructionCache(void *start, size_t size)
constexpr ShiftOp LSL
base::StrongAlias< JSDispatchHandleAliasTag, uint32_t > JSDispatchHandle
Definition globals.h:557
constexpr int kImm8Mask
constexpr uint8_t kInstrSize
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK(condition)
Definition logging.h:482
#define V8_UNLIKELY(condition)
Definition v8config.h:660