v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
reloc-info.cc
Go to the documentation of this file.
1// Copyright 2018 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
6
7#include "src/base/vlq.h"
18
19namespace v8 {
20namespace internal {
21
22using namespace detail; // NOLINT(build/namespaces)
23
24uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
25 // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
26 // Otherwise write a variable length PC jump for the bits that do
27 // not fit in the kSmallPCDeltaBits bits.
28 if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
30 uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
31 DCHECK_GT(pc_jump, 0);
32 base::VLQEncodeUnsigned([this](uint8_t byte) { *--pos_ = byte; }, pc_jump);
33 // Return the remaining kSmallPCDeltaBits of the pc_delta.
34 return pc_delta & kSmallPCDeltaMask;
35}
36
37void RelocInfoWriter::WriteShortTaggedPC(uint32_t pc_delta, int tag) {
38 // Write a byte of tagged pc-delta, possibly preceded by an explicit pc-jump.
39 pc_delta = WriteLongPCJump(pc_delta);
40 *--pos_ = pc_delta << kTagBits | tag;
41}
42
43void RelocInfoWriter::WriteShortData(uint8_t data_delta) {
44 *--pos_ = data_delta;
45}
46
48 static_assert(RelocInfo::NUMBER_OF_MODES <= (1 << kLongTagBits));
49 *--pos_ = static_cast<int>((rmode << kTagBits) | kDefaultTag);
50}
51
52void RelocInfoWriter::WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode) {
53 // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
54 pc_delta = WriteLongPCJump(pc_delta);
55 WriteMode(rmode);
56 *--pos_ = pc_delta;
57}
58
60 for (int i = 0; i < kIntSize; i++) {
61 *--pos_ = static_cast<uint8_t>(number);
62 // Signed right shift is arithmetic shift. Tested in test-utils.cc.
63 number = number >> kBitsPerByte;
64 }
65}
66
68 RelocInfo::Mode rmode = rinfo->rmode();
69#ifdef DEBUG
70 uint8_t* begin_pos = pos_;
71#endif
73 DCHECK_GE(rinfo->pc() - reinterpret_cast<Address>(last_pc_), 0);
74 // Use unsigned delta-encoding for pc.
75 uint32_t pc_delta =
76 static_cast<uint32_t>(rinfo->pc() - reinterpret_cast<Address>(last_pc_));
77
78 // The two most common modes are given small tags, and usually fit in a byte.
81 } else if (rmode == RelocInfo::CODE_TARGET) {
84 } else if (rmode == RelocInfo::WASM_STUB_CALL) {
86 } else {
87 WriteModeAndPC(pc_delta, rmode);
88 if (RelocInfo::IsDeoptReason(rmode)) {
89 DCHECK_LT(rinfo->data(), 1 << kBitsPerByte);
90 WriteShortData(static_cast<uint8_t>(rinfo->data()));
91 } else if (RelocInfo::IsConstPool(rmode) ||
95 WriteIntData(static_cast<int>(rinfo->data()));
96 }
97 }
98 last_pc_ = reinterpret_cast<uint8_t*>(rinfo->pc());
99#ifdef DEBUG
100 DCHECK_LE(begin_pos - pos_, kMaxSize);
101#endif
102}
103
104template <typename RelocInfoT>
106 int x = 0;
107 for (int i = 0; i < kIntSize; i++) {
108 x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
109 }
110 rinfo_.data_ = x;
111}
112
113template <typename RelocInfoT>
115 // Read the 32-kSmallPCDeltaBits most significant bits of the
116 // pc jump as a VLQ encoded integer.
117 uint32_t pc_jump = base::VLQDecodeUnsigned([this] { return *--pos_; });
118 // The least significant kSmallPCDeltaBits bits will be added
119 // later.
120 rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
121}
122
123template <typename RelocInfoT>
125 uint8_t unsigned_b = *pos_;
126 rinfo_.data_ = unsigned_b;
127}
128
129template <typename RelocInfoT>
131 DCHECK(!done());
132 // Basically, do the opposite of RelocInfoWriter::Write.
133 // Reading of data is as far as possible avoided for unwanted modes,
134 // but we must always update the pc.
135 //
136 // We exit this loop by returning when we find a mode we want.
137 while (pos_ > end_) {
138 int tag = AdvanceGetTag();
139 if (tag == kEmbeddedObjectTag) {
140 ReadShortTaggedPC();
141 if (SetMode(RelocInfo::FULL_EMBEDDED_OBJECT)) return;
142 } else if (tag == kCodeTargetTag) {
143 ReadShortTaggedPC();
144 if (SetMode(RelocInfo::CODE_TARGET)) return;
145 } else if (tag == kWasmStubCallTag) {
146 ReadShortTaggedPC();
147 if (SetMode(RelocInfo::WASM_STUB_CALL)) return;
148 } else {
150 RelocInfo::Mode rmode = GetMode();
151 if (rmode == RelocInfo::PC_JUMP) {
152 AdvanceReadLongPCJump();
153 } else {
154 AdvanceReadPC();
155 if (RelocInfo::IsDeoptReason(rmode)) {
156 Advance();
157 if (SetMode(rmode)) {
158 ReadShortData();
159 return;
160 }
161 } else if (RelocInfo::IsConstPool(rmode) ||
163 RelocInfo::IsDeoptId(rmode) ||
166 if (SetMode(rmode)) {
167 AdvanceReadInt();
168 return;
169 }
170 Advance(kIntSize);
171 } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
172 return;
173 }
174 }
175 }
176 }
177 done_ = true;
178}
179
181 : RelocIterator(code->instruction_stream(), mode_mask) {}
182
185 istream->instruction_start(), istream->constant_pool(),
186 // Use unchecked accessors since this can be called during GC
187 istream->unchecked_relocation_info()->end(),
188 istream->unchecked_relocation_info()->begin(), mode_mask) {}
189
191 : RelocIterator(code_reference.instruction_start(),
192 code_reference.constant_pool(),
193 code_reference.relocation_end(),
194 code_reference.relocation_start(), kAllModesMask) {}
195
197 int mode_mask)
198 : RelocIterator(embedded_data->InstructionStartOf(code->builtin_id()),
199 code->constant_pool(), code->relocation_end(),
200 code->relocation_start(), mode_mask) {}
201
204 Address const_pool, int mode_mask)
205 : RelocIterator(reinterpret_cast<Address>(instructions.begin()), const_pool,
206 reloc_info.begin() + reloc_info.size(), reloc_info.begin(),
207 mode_mask) {}
208
210 const uint8_t* pos, const uint8_t* end,
211 int mode_mask)
213 RelocInfo(pc, RelocInfo::NO_INFO, 0, constant_pool), pos, end,
214 mode_mask) {}
215
217 WritableJitAllocation& jit_allocation, Tagged<InstructionStream> istream,
218 Address constant_pool, int mode_mask)
220 WritableRelocInfo(jit_allocation, istream->instruction_start(),
221 RelocInfo::NO_INFO, 0, constant_pool),
222 // Use unchecked accessors since this can be called during GC
223 istream->unchecked_relocation_info()->end(),
224 istream->unchecked_relocation_info()->begin(), mode_mask) {}
225
227 WritableJitAllocation& jit_allocation, base::Vector<uint8_t> instructions,
229 int mode_mask)
231 WritableRelocInfo(jit_allocation,
232 reinterpret_cast<Address>(instructions.begin()),
233 RelocInfo::NO_INFO, 0, constant_pool),
234 reloc_info.begin() + reloc_info.size(), reloc_info.begin(),
235 mode_mask) {}
236
237// -----------------------------------------------------------------------------
238// Implementation of RelocInfo
239
240// static
242#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64) || \
243 defined(V8_TARGET_ARCH_X64)
244 return false;
245#elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_MIPS64) || \
246 defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_S390X) || \
247 defined(V8_TARGET_ARCH_RISCV64) || defined(V8_TARGET_ARCH_LOONG64) || \
248 defined(V8_TARGET_ARCH_RISCV32)
249 return true;
250#endif
251}
252
257
263
268
274
279
285
293
295 Address target,
296 WriteBarrierMode write_barrier_mode,
297 ICacheFlushMode icache_flush_mode) {
298 set_target_address(target, icache_flush_mode);
299 if (IsCodeTargetMode(rmode_) && !v8_flags.disable_write_barriers) {
300 Tagged<InstructionStream> target_code =
302 WriteBarrier::ForRelocInfo(host, this, target_code, write_barrier_mode);
303 }
304}
305
308 WriteBarrierMode write_barrier_mode, ICacheFlushMode icache_flush_mode) {
311 &jit_allocation_, icache_flush_mode);
312 if (!v8_flags.disable_write_barriers && handle != kNullJSDispatchHandle) {
313 WriteBarrier::ForJSDispatchHandle(host, handle, write_barrier_mode);
314 }
315}
316
318 ICacheFlushMode icache_flush_mode) {
321 icache_flush_mode);
322}
323
325 // TODO(jgruber): Investigate whether WASM_CALL is still appropriate on
326 // non-intel platforms now that wasm code is no longer on the heap.
327#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
328 static constexpr int kTargetAddressAddressModeMask =
333#else
334 static constexpr int kTargetAddressAddressModeMask =
338#endif
339 return (ModeMask(rmode_) & kTargetAddressAddressModeMask) != 0;
340}
341
342#ifdef ENABLE_DISASSEMBLER
343const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
344 switch (rmode) {
345 case NO_INFO:
346 return "no reloc";
348 return "compressed embedded object";
350 return "full embedded object";
351 case CODE_TARGET:
352 return "code target";
354 return "relative code target";
356 return "external reference";
358 return "internal reference";
360 return "encoded internal reference";
362 return "js dispatch handle";
363 case OFF_HEAP_TARGET:
364 return "off heap target";
366 return "near builtin entry";
368 return "deopt script offset";
370 return "deopt inlining id";
371 case DEOPT_REASON:
372 return "deopt reason";
373 case DEOPT_ID:
374 return "deopt index";
375 case DEOPT_NODE_ID:
376 return "deopt node id";
377 case CONST_POOL:
378 return "constant pool";
379 case VENEER_POOL:
380 return "veneer pool";
381 case WASM_CALL:
382 return "internal wasm call";
383 case WASM_STUB_CALL:
384 return "wasm stub call";
386 return "wasm canonical signature id";
388 return "wasm code pointer table entry";
389 case NUMBER_OF_MODES:
390 case PC_JUMP:
391 UNREACHABLE();
392 }
393 return "unknown relocation type";
394}
395
396void RelocInfo::Print(Isolate* isolate, std::ostream& os) {
397 os << reinterpret_cast<const void*>(pc_) << " " << RelocModeName(rmode_);
398 switch (rmode_) {
401 os << " (" << data() << ")";
402 break;
403 case DEOPT_REASON:
404 os << " ("
406 << ")";
407 break;
409 os << " (" << Brief(target_object(isolate)) << ")";
410 break;
412 os << " (" << Brief(target_object(isolate)) << " compressed)";
413 break;
415 if (isolate) {
416 ExternalReferenceEncoder ref_encoder(isolate);
417 os << " ("
418 << ref_encoder.NameOfAddress(isolate, target_external_reference())
419 << ") ";
420 }
421 os << " (" << reinterpret_cast<const void*>(target_external_reference())
422 << ")";
423 break;
424 case JS_DISPATCH_HANDLE: {
425#ifdef V8_ENABLE_LEAPTIERING
426 Tagged<Code> target_code =
427 IsolateGroup::current()->js_dispatch_table()->GetCode(
429 os << " (" << CodeKindToString(target_code->kind());
430 if (Builtins::IsBuiltin(target_code)) {
431 os << " " << Builtins::name(target_code->builtin_id());
432 }
433 os << ") (" << js_dispatch_handle() << ")";
434 break;
435#else
436 UNREACHABLE();
437#endif
438 }
439 default:
441 const Address code_target = target_address();
442 Tagged<Code> target_code = Code::FromTargetAddress(code_target);
443 os << " (" << CodeKindToString(target_code->kind());
444 if (Builtins::IsBuiltin(target_code)) {
445 os << " " << Builtins::name(target_code->builtin_id());
446 }
447 os << ") (" << reinterpret_cast<const void*>(target_address()) << ")";
448 } else if (IsConstPool(rmode_)) {
449 os << " (size " << static_cast<int>(data_) << ")";
450 } else if (IsWasmStubCall(rmode_)) {
451 os << " (";
452 Address addr = target_address();
453 if (isolate != nullptr) {
454 Builtin builtin =
456 os << (Builtins::IsBuiltinId(builtin) ? Builtins::name(builtin)
457 : "<UNRECOGNIZED>")
458 << ") (";
459 }
460 os << reinterpret_cast<const void*>(addr) << ")";
461 }
462 break;
463 }
464 os << "\n";
465}
466#endif // ENABLE_DISASSEMBLER
467
468#ifdef VERIFY_HEAP
469void RelocInfo::Verify(Isolate* isolate) {
470 switch (rmode_) {
472 Object::VerifyPointer(isolate, target_object(isolate));
473 break;
475 Object::VerifyAnyTagged(isolate, target_object(isolate));
476 break;
477 case CODE_TARGET:
479 // convert inline target address to code object
480 Address addr = target_address();
481 CHECK_NE(addr, kNullAddress);
482 // Check that we can find the right code object.
485 Tagged<Code> lookup_result =
486 isolate->heap()->FindCodeForInnerPointer(addr);
487 CHECK_EQ(code.address(), lookup_result->instruction_stream().address());
488 break;
489 }
494 Tagged<Code> lookup_result = isolate->heap()->FindCodeForInnerPointer(pc);
495 CHECK_GE(target, lookup_result->instruction_start());
496 CHECK_LT(target, lookup_result->instruction_end());
497 break;
498 }
499 case JS_DISPATCH_HANDLE: {
500#ifdef V8_ENABLE_LEAPTIERING
501 JSDispatchTable::Space* space =
502 isolate->heap()->js_dispatch_table_space();
503 JSDispatchTable::Space* ro_space =
504 isolate->read_only_heap()->js_dispatch_table_space();
505 IsolateGroup::current()->js_dispatch_table()->VerifyEntry(
506 js_dispatch_handle(), space, ro_space);
507 break;
508#else
509 UNREACHABLE();
510#endif
511 }
512 case OFF_HEAP_TARGET: {
514 CHECK_NE(addr, kNullAddress);
517 break;
518 }
519 case WASM_STUB_CALL:
520 case NEAR_BUILTIN_ENTRY: {
521 Address addr = target_address();
525 break;
526 }
530 case DEOPT_REASON:
531 case DEOPT_ID:
532 case DEOPT_NODE_ID:
533 case CONST_POOL:
534 case VENEER_POOL:
535 case WASM_CALL:
536 case NO_INFO:
539 break;
540 case NUMBER_OF_MODES:
541 case PC_JUMP:
542 UNREACHABLE();
543 }
544}
545#endif // VERIFY_HEAP
546
549template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
551
552} // namespace internal
553} // namespace v8
int pos_
SourcePosition pos
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 void set_target_address_at(Address pc, Address constant_pool, Address target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static V8_INLINE Address target_address_at(Address pc, Address constant_pool)
static uint32_t uint32_constant_at(Address pc, Address constant_pool)
static constexpr bool IsBuiltinId(Builtin builtin)
Definition builtins.h:128
static bool IsBuiltin(const Tagged< Code > code)
Definition builtins.cc:356
static V8_EXPORT_PRIVATE const char * name(Builtin builtin)
Definition builtins.cc:226
static Tagged< Code > FromTargetAddress(Address address)
Definition code-inl.h:671
static Tagged< InstructionStream > FromTargetAddress(Address address)
static IsolateGroup * current()
static Builtin TryLookupCode(Isolate *isolate, Address address)
void WriteShortData(uint8_t data_delta)
Definition reloc-info.cc:43
void WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode)
Definition reloc-info.cc:52
void WriteIntData(int data_delta)
Definition reloc-info.cc:59
void WriteMode(RelocInfo::Mode rmode)
Definition reloc-info.cc:47
void WriteShortTaggedPC(uint32_t pc_delta, int tag)
Definition reloc-info.cc:37
void Write(const RelocInfo *rinfo)
Definition reloc-info.cc:67
static constexpr int kMaxSize
Definition reloc-info.h:488
uint32_t WriteLongPCJump(uint32_t pc_delta)
Definition reloc-info.cc:24
static constexpr bool IsDeoptReason(Mode mode)
Definition reloc-info.h:228
V8_INLINE Address target_internal_reference()
static constexpr bool IsConstPool(Mode mode)
Definition reloc-info.h:223
static constexpr bool IsDeoptNodeId(Mode mode)
Definition reloc-info.h:232
void set_off_heap_target_address(Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
static constexpr bool IsCodeTargetMode(Mode mode)
Definition reloc-info.h:197
static constexpr int ModeMask(Mode mode)
Definition reloc-info.h:272
V8_INLINE Address target_address()
static constexpr bool IsNearBuiltinEntry(Mode mode)
Definition reloc-info.h:247
static constexpr int kMaxCallSize
Definition reloc-info.h:101
V8_EXPORT_PRIVATE uint32_t wasm_canonical_sig_id() const
V8_INLINE Address target_internal_reference_address()
static constexpr bool IsWasmCall(Mode mode)
Definition reloc-info.h:213
static constexpr bool IsDeoptId(Mode mode)
Definition reloc-info.h:231
V8_INLINE Address target_off_heap_target()
static constexpr bool IsWasmStubCall(Mode mode)
Definition reloc-info.h:214
static constexpr bool IsJSDispatchHandle(Mode mode)
Definition reloc-info.h:254
V8_INLINE Address target_external_reference()
V8_INLINE Tagged< HeapObject > target_object(PtrComprCageBase cage_base)
Address wasm_call_address() const
static bool OffHeapTargetIsCodedSpecially()
V8_INLINE JSDispatchHandle js_dispatch_handle()
intptr_t data() const
Definition reloc-info.h:278
bool HasTargetAddressAddress() const
Address pc() const
Definition reloc-info.h:275
static constexpr bool IsVeneerPool(Mode mode)
Definition reloc-info.h:224
static constexpr bool IsDeoptPosition(Mode mode)
Definition reloc-info.h:225
Address wasm_stub_call_address() const
RelocIterator(Tagged< InstructionStream > istream, int mode_mask)
void set_js_dispatch_handle(Tagged< InstructionStream > host, JSDispatchHandle handle, WriteBarrierMode write_barrier_mode=UPDATE_WRITE_BARRIER, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void set_wasm_stub_call_address(Address)
void set_target_address(Tagged< InstructionStream > host, Address target, WriteBarrierMode write_barrier_mode=UPDATE_WRITE_BARRIER, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
WritableJitAllocation & jit_allocation_
Definition reloc-info.h:462
void set_wasm_canonical_sig_id(uint32_t)
WritableRelocIterator(WritableJitAllocation &jit_allocation, Tagged< InstructionStream > istream, Address constant_pool, int mode_mask)
static void ForJSDispatchHandle(Tagged< HeapObject > host, JSDispatchHandle handle, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
static void ForRelocInfo(Tagged< InstructionStream > host, RelocInfo *rinfo, Tagged< HeapObject > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
bool done_
Definition compiler.cc:3788
const v8::base::TimeTicks end_
Definition sweeper.cc:54
int end
#define EXPORT_TEMPLATE_DEFINE(export)
int x
uint32_t VLQDecodeUnsigned(GetNextFunction &&get_next)
Definition vlq.h:80
void VLQEncodeUnsigned(Function &&process_byte, uint32_t value)
Definition vlq.h:23
constexpr int kDefaultTag
Definition reloc-info.h:78
constexpr int kCodeTargetTag
Definition reloc-info.h:76
constexpr int kWasmStubCallTag
Definition reloc-info.h:77
constexpr int kTagBits
Definition reloc-info.h:71
constexpr int kSmallPCDeltaMask
Definition reloc-info.h:81
constexpr int kLongTagBits
Definition reloc-info.h:73
constexpr int kEmbeddedObjectTag
Definition reloc-info.h:75
constexpr int kSmallPCDeltaBits
Definition reloc-info.h:80
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
constexpr int kIntSize
Definition globals.h:400
constexpr int kBitsPerByte
Definition globals.h:682
const char * CodeKindToString(CodeKind kind)
Definition code-kind.cc:10
Tagged(T object) -> Tagged< T >
char const * DeoptimizeReasonToString(DeoptimizeReason reason)
constexpr JSDispatchHandle kNullJSDispatchHandle(0)
V8_EXPORT_PRIVATE FlagValues v8_flags
static constexpr Address kNullAddress
Definition v8-internal.h:53
constexpr bool is_uintn(int64_t x, unsigned n)
Definition utils.h:574
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_GE(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define CHECK_LT(lhs, rhs)
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define V8_EXPORT_PRIVATE
Definition macros.h:460