v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
code.cc
Go to the documentation of this file.
1// Copyright 2019 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#include "src/objects/code.h"
6
7#include <iomanip>
8
16
17#ifdef ENABLE_DISASSEMBLER
20#endif
21
22namespace v8 {
23namespace internal {
24
26 return RawProtectedPointerField(kDeoptimizationDataOrInterpreterDataOffset)
27 .load();
28}
29
31 return RawProtectedPointerField(kPositionTableOffset).load();
32}
33
36 Tagged<HeapObject> undefined = ReadOnlyRoots(heap).undefined_value();
38 int mode_mask = RelocInfo::EmbeddedObjectModeMask();
39#ifdef V8_ENABLE_LEAPTIERING
41#endif
42 {
44 istream->address(), istream->Size(),
46 for (WritableRelocIterator it(jit_allocation, istream, constant_pool(),
47 mode_mask);
48 !it.done(); it.next()) {
49 const auto mode = it.rinfo()->rmode();
51 it.rinfo()->set_target_object(istream, undefined, SKIP_WRITE_BARRIER);
52#ifdef V8_ENABLE_LEAPTIERING
53 } else {
54 it.rinfo()->set_js_dispatch_handle(istream, kNullJSDispatchHandle,
56#endif // V8_ENABLE_LEAPTIERING
57 }
58 }
59 }
61}
62
63void Code::FlushICache() const {
64 FlushInstructionCache(instruction_start(), instruction_size());
65}
66
68 CHECK_NE(kind(), CodeKind::BASELINE);
69
70 // Subtract one because the current PC is one instruction after the call site.
71 offset--;
72
73 int position = 0;
76 source_position_table(),
79 !it.done() && it.code_offset() <= offset; it.Advance()) {
80 position = it.source_position().ScriptOffset();
81 }
82 return position;
83}
84
86 CHECK_NE(kind(), CodeKind::BASELINE);
87
88 // Subtract one because the current PC is one instruction after the call site.
89 offset--;
90
91 int position = 0;
93 for (SourcePositionTableIterator it(source_position_table());
94 !it.done() && it.code_offset() <= offset; it.Advance()) {
95 if (it.is_statement()) {
96 position = it.source_position().ScriptOffset();
97 }
98 }
99 return position;
100}
101
104 SafepointTable table(isolate, pc, *this);
105 return table.FindEntry(pc);
106}
107
109 Address pc) {
111 MaglevSafepointTable table(isolate, pc, *this);
112 return table.FindEntry(pc);
113}
114
116 static constexpr int kModeMask =
123 static_assert(kModeMask ==
135
136#if defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_MIPS64)
137 return RelocIterator(*this, kModeMask).done();
138#elif defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
139 defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_S390X) || \
140 defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_RISCV64) || \
141 defined(V8_TARGET_ARCH_LOONG64) || defined(V8_TARGET_ARCH_RISCV32)
142 for (RelocIterator it(*this, kModeMask); !it.done(); it.next()) {
143 // On these platforms we emit relative builtin-to-builtin
144 // jumps for isolate independent builtins in the snapshot. They are later
145 // rewritten as pc-relative jumps to the off-heap instruction stream and are
146 // thus process-independent. See also: FinalizeEmbeddedCodeTargets.
147 if (RelocInfo::IsCodeTargetMode(it.rinfo()->rmode())) {
148 Address target_address = it.rinfo()->target_address();
149 if (OffHeapInstructionStream::PcIsOffHeap(isolate, target_address))
150 continue;
151
152 Tagged<Code> target = Code::FromTargetAddress(target_address);
154 continue;
155 }
156 }
157 return false;
158 }
159 return true;
160#else
161#error Unsupported architecture.
162#endif
163}
164
166 // We can only check for inlining for optimized code.
169 Tagged<DeoptimizationData> const data =
170 Cast<DeoptimizationData>(deoptimization_data());
171 if (data->length() == 0) return false;
172 if (data->GetSharedFunctionInfo() == sfi) return true;
173 Tagged<DeoptimizationLiteralArray> const literals = data->LiteralArray();
174 int const inlined_count = data->InlinedFunctionCount().value();
175 for (int i = 0; i < inlined_count; ++i) {
176 if (Cast<SharedFunctionInfo>(literals->get(i)) == sfi) return true;
177 }
178 return false;
179}
180
181#ifdef ENABLE_DISASSEMBLER
182
183namespace {
184
185void DisassembleCodeRange(Isolate* isolate, std::ostream& os, Tagged<Code> code,
186 Address begin, size_t size, Address current_pc,
187 size_t range_limit = 0) {
188 Address end = begin + size;
189 AllowHandleAllocation allow_handles;
191 HandleScope handle_scope(isolate);
192 Disassembler::Decode(isolate, os, reinterpret_cast<uint8_t*>(begin),
193 reinterpret_cast<uint8_t*>(end),
194 CodeReference(handle(code, isolate)), current_pc,
195 range_limit);
196}
197
198void DisassembleOnlyCode(const char* name, std::ostream& os, Isolate* isolate,
199 Tagged<Code> code, Address current_pc,
200 size_t range_limit) {
201 int code_size = code->instruction_size();
202 DisassembleCodeRange(isolate, os, code, code->instruction_start(), code_size,
203 current_pc, range_limit);
204}
205
206void Disassemble(const char* name, std::ostream& os, Isolate* isolate,
207 Tagged<Code> code, Address current_pc) {
208 CodeKind kind = code->kind();
209 os << "kind = " << CodeKindToString(kind) << "\n";
210 if (name == nullptr && code->is_builtin()) {
211 name = Builtins::name(code->builtin_id());
212 }
213 if ((name != nullptr) && (name[0] != '\0')) {
214 os << "name = " << name << "\n";
215 }
216 os << "compiler = "
217 << (code->is_turbofanned() ? "turbofan"
218 : code->is_maglevved() ? "maglev"
219 : kind == CodeKind::BASELINE ? "baseline"
220 : "unknown")
221 << "\n";
222 os << "address = " << reinterpret_cast<void*>(code.ptr()) << "\n\n";
223
224 {
225 int code_size = code->instruction_size();
226 os << "Instructions (size = " << code_size << ")\n";
227 DisassembleCodeRange(isolate, os, code, code->instruction_start(),
228 code_size, current_pc);
229
230 if (int pool_size = code->constant_pool_size()) {
231 DCHECK_EQ(pool_size & kPointerAlignmentMask, 0);
232 os << "\nConstant Pool (size = " << pool_size << ")\n";
233 base::Vector<char> buf = base::Vector<char>::New(50);
234 intptr_t* ptr = reinterpret_cast<intptr_t*>(code->constant_pool());
235 for (int i = 0; i < pool_size; i += kSystemPointerSize, ptr++) {
236 SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
237 os << static_cast<const void*>(ptr) << " " << buf.begin() << "\n";
238 }
239 }
240 }
241 os << "\n";
242
243 // TODO(cbruni): add support for baseline code.
244 if (code->has_source_position_table()) {
245 {
246 SourcePositionTableIterator it(
247 code->source_position_table(),
249 if (!it.done()) {
250 os << "Source positions:\n pc offset position\n";
251 for (; !it.done(); it.Advance()) {
252 os << std::setw(10) << std::hex << it.code_offset() << std::dec
253 << std::setw(10) << it.source_position().ScriptOffset()
254 << (it.is_statement() ? " statement" : "") << "\n";
255 }
256 os << "\n";
257 }
258 }
259
260 {
261 SourcePositionTableIterator it(
262 code->source_position_table(),
264 if (!it.done()) {
265 os << "External Source positions:\n pc offset fileid line\n";
266 for (; !it.done(); it.Advance()) {
267 DCHECK(it.source_position().IsExternal());
268 os << std::setw(10) << std::hex << it.code_offset() << std::dec
269 << std::setw(10) << it.source_position().ExternalFileId()
270 << std::setw(10) << it.source_position().ExternalLine() << "\n";
271 }
272 os << "\n";
273 }
274 }
275 }
276
277 if (code->uses_deoptimization_data()) {
279 Cast<DeoptimizationData>(code->deoptimization_data());
280 data->PrintDeoptimizationData(os);
281 }
282 os << "\n";
283
284 if (code->uses_safepoint_table()) {
285 if (code->is_maglevved()) {
286 MaglevSafepointTable table(isolate, current_pc, code);
287 table.Print(os);
288 } else {
289 SafepointTable table(isolate, current_pc, code);
290 table.Print(os);
291 }
292 os << "\n";
293 }
294
295 if (code->has_handler_table()) {
296 HandlerTable table(code);
297 os << "Handler Table (size = " << table.NumberOfReturnEntries() << ")\n";
299 table.HandlerTableReturnPrint(os);
300 }
301 os << "\n";
302 }
303
304 os << "RelocInfo (size = " << code->relocation_size() << ")\n";
305 if (code->has_instruction_stream()) {
306 for (RelocIterator it(code); !it.done(); it.next()) {
307 it.rinfo()->Print(isolate, os);
308 }
309 }
310 os << "\n";
311
312 if (code->has_unwinding_info()) {
313 os << "UnwindingInfo (size = " << code->unwinding_info_size() << ")\n";
314 EhFrameDisassembler eh_frame_disassembler(
315 reinterpret_cast<uint8_t*>(code->unwinding_info_start()),
316 reinterpret_cast<uint8_t*>(code->unwinding_info_end()));
317 eh_frame_disassembler.DisassembleToStream(os);
318 os << "\n";
319 }
320}
321
322} // namespace
323
324void Code::Disassemble(const char* name, std::ostream& os, Isolate* isolate,
325 Address current_pc) {
326 i::Disassemble(name, os, isolate, *this, current_pc);
327}
328
329void Code::DisassembleOnlyCode(const char* name, std::ostream& os,
330 Isolate* isolate, Address current_pc,
331 size_t range_limit) {
332 i::DisassembleOnlyCode(name, os, isolate, *this, current_pc, range_limit);
333}
334
335#endif // ENABLE_DISASSEMBLER
336
341
342} // namespace internal
343} // namespace v8
Builtins::Kind kind
Definition builtins.cc:40
static Vector< T > New(size_t length)
Definition vector.h:35
static bool IsIsolateIndependentBuiltin(Tagged< Code > code)
Definition builtins.cc:372
static V8_EXPORT_PRIVATE const char * name(Builtin builtin)
Definition builtins.cc:226
SafepointEntry GetSafepointEntry(Isolate *isolate, Address pc)
Definition code.cc:102
bool has_source_position_table() const
Definition code-inl.h:179
Tagged< InstructionStream > unchecked_instruction_stream() const
Definition code-inl.h:777
void TraceMarkForDeoptimization(Isolate *isolate, LazyDeoptimizeReason reason)
Definition code.cc:337
void set_embedded_objects_cleared(bool flag)
Definition code-inl.h:578
static Tagged< Code > FromTargetAddress(Address address)
Definition code-inl.h:671
Tagged< Object > raw_deoptimization_data_or_interpreter_data() const
Definition code.cc:25
CodeKind kind() const
Definition code-inl.h:332
bool Inlines(Tagged< SharedFunctionInfo > sfi)
Definition code.cc:165
Address constant_pool() const
Definition code-inl.h:614
int SourcePosition(int offset) const
Definition code.cc:67
bool is_optimized_code() const
Definition code-inl.h:916
MaglevSafepointEntry GetMaglevSafepointEntry(Isolate *isolate, Address pc)
Definition code.cc:108
void FlushICache() const
Definition code.cc:63
int SourceStatementPosition(int offset) const
Definition code.cc:85
bool is_maglevved() const
Definition code-inl.h:441
Tagged< Object > raw_position_table() const
Definition code.cc:30
bool IsIsolateIndependent(Isolate *isolate)
Definition code.cc:115
void ClearEmbeddedObjectsAndJSDispatchHandles(Heap *heap)
Definition code.cc:34
static void TraceMarkForDeoptimization(Isolate *isolate, Tagged< Code > code, LazyDeoptimizeReason reason)
static V8_EXPORT_PRIVATE int Decode(Isolate *isolate, std::ostream &os, uint8_t *begin, uint8_t *end, CodeReference code={}, Address current_pc=kNullAddress, size_t range_limit=0)
Tagged< Object > load() const
Definition slots-inl.h:48
static bool PcIsOffHeap(Isolate *isolate, Address pc)
static constexpr bool IsCodeTargetMode(Mode mode)
Definition reloc-info.h:197
static constexpr int AllRealModesMask()
Definition reloc-info.h:371
static constexpr int ModeMask(Mode mode)
Definition reloc-info.h:272
static constexpr bool IsEmbeddedObjectMode(Mode mode)
Definition reloc-info.h:209
static int JSDispatchHandleModeMask()
Definition reloc-info.h:383
static int EmbeddedObjectModeMask()
Definition reloc-info.h:378
static WritableJitAllocation LookupJitAllocation(Address addr, size_t size, JitAllocationType type, bool enforce_write_api=false)
ProtectedPointerSlot RawProtectedPointerField(int byte_offset) const
int end
int32_t offset
int position
Definition liveedit.cc:290
int SNPrintF(Vector< char > str, const char *format,...)
Definition strings.cc:20
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind)
Definition code-kind.h:66
@ SKIP_WRITE_BARRIER
Definition objects.h:52
const char * CodeKindToString(CodeKind kind)
Definition code-kind.cc:10
Tagged(T object) -> Tagged< T >
void FlushInstructionCache(void *start, size_t size)
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr JSDispatchHandle kNullJSDispatchHandle(0)
constexpr intptr_t kPointerAlignmentMask
Definition globals.h:946
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
#define CHECK_NE(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8PRIxPTR
Definition macros.h:331