Bug Summary

File:out/../deps/v8/src/objects/code-inl.h
Warning:line 945, column 10
Value stored to 'value' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name api-arguments.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/inspector-generated-output-root -I ../deps/v8/third_party/inspector_protocol -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/v8/third_party/zlib -I ../deps/v8/third_party/zlib/google -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/api/api-arguments.cc
1// Copyright 2017 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#ifndef V8_OBJECTS_CODE_INL_H_
6#define V8_OBJECTS_CODE_INL_H_
7
8#include "src/base/memory.h"
9#include "src/baseline/bytecode-offset-iterator.h"
10#include "src/codegen/code-desc.h"
11#include "src/common/assert-scope.h"
12#include "src/common/globals.h"
13#include "src/execution/isolate.h"
14#include "src/heap/heap-inl.h"
15#include "src/interpreter/bytecode-register.h"
16#include "src/objects/code.h"
17#include "src/objects/dictionary.h"
18#include "src/objects/instance-type-inl.h"
19#include "src/objects/map-inl.h"
20#include "src/objects/maybe-object-inl.h"
21#include "src/objects/oddball.h"
22#include "src/objects/shared-function-info-inl.h"
23#include "src/objects/smi-inl.h"
24#include "src/utils/utils.h"
25
26// Has to be the last include (doesn't have include guards):
27#include "src/objects/object-macros.h"
28
29namespace v8 {
30namespace internal {
31
32#include "torque-generated/src/objects/code-tq-inl.inc"
33
34OBJECT_CONSTRUCTORS_IMPL(DeoptimizationData, FixedArray)
35TQ_OBJECT_CONSTRUCTORS_IMPL(BytecodeArray)
36OBJECT_CONSTRUCTORS_IMPL(AbstractCode, HeapObject)
37OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakArrayList)
38OBJECT_CONSTRUCTORS_IMPL(CodeDataContainer, HeapObject)
39NEVER_READ_ONLY_SPACE_IMPL(CodeDataContainer)
40
41NEVER_READ_ONLY_SPACE_IMPL(AbstractCode)
42
43CAST_ACCESSOR(AbstractCode)
44CAST_ACCESSOR(Code)
45CAST_ACCESSOR(CodeDataContainer)
46CAST_ACCESSOR(DependentCode)
47CAST_ACCESSOR(DeoptimizationData)
48CAST_ACCESSOR(DeoptimizationLiteralArray)
49
50int AbstractCode::raw_instruction_size() {
51 if (IsCode()) {
52 return GetCode().raw_instruction_size();
53 } else {
54 return GetBytecodeArray().length();
55 }
56}
57
58int AbstractCode::InstructionSize() {
59 if (IsCode()) {
60 return GetCode().InstructionSize();
61 } else {
62 return GetBytecodeArray().length();
63 }
64}
65
66ByteArray AbstractCode::SourcePositionTableInternal() {
67 if (IsCode()) {
68 DCHECK_NE(GetCode().kind(), CodeKind::BASELINE)((void) 0);
69 return GetCode().source_position_table();
70 } else {
71 return GetBytecodeArray().SourcePositionTable();
72 }
73}
74
75ByteArray AbstractCode::SourcePositionTable(SharedFunctionInfo sfi) {
76 if (IsCode()) {
77 return GetCode().SourcePositionTable(sfi);
78 } else {
79 return GetBytecodeArray().SourcePositionTable();
80 }
81}
82
83int AbstractCode::SizeIncludingMetadata() {
84 if (IsCode()) {
85 return GetCode().SizeIncludingMetadata();
86 } else {
87 return GetBytecodeArray().SizeIncludingMetadata();
88 }
89}
90
91Address AbstractCode::raw_instruction_start() {
92 if (IsCode()) {
93 return GetCode().raw_instruction_start();
94 } else {
95 return GetBytecodeArray().GetFirstBytecodeAddress();
96 }
97}
98
99Address AbstractCode::InstructionStart() {
100 if (IsCode()) {
101 return GetCode().InstructionStart();
102 } else {
103 return GetBytecodeArray().GetFirstBytecodeAddress();
104 }
105}
106
107Address AbstractCode::raw_instruction_end() {
108 if (IsCode()) {
109 return GetCode().raw_instruction_end();
110 } else {
111 return GetBytecodeArray().GetFirstBytecodeAddress() +
112 GetBytecodeArray().length();
113 }
114}
115
116Address AbstractCode::InstructionEnd() {
117 if (IsCode()) {
118 return GetCode().InstructionEnd();
119 } else {
120 return GetBytecodeArray().GetFirstBytecodeAddress() +
121 GetBytecodeArray().length();
122 }
123}
124
125bool AbstractCode::contains(Isolate* isolate, Address inner_pointer) {
126 PtrComprCageBase cage_base(isolate);
127 if (IsCode(cage_base)) {
128 return GetCode().contains(isolate, inner_pointer);
129 } else {
130 return (address() <= inner_pointer) &&
131 (inner_pointer <= address() + Size(cage_base));
132 }
133}
134
135CodeKind AbstractCode::kind() {
136 return IsCode() ? GetCode().kind() : CodeKind::INTERPRETED_FUNCTION;
137}
138
139Code AbstractCode::GetCode() { return Code::cast(*this); }
140
141BytecodeArray AbstractCode::GetBytecodeArray() {
142 return BytecodeArray::cast(*this);
143}
144
145OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
146NEVER_READ_ONLY_SPACE_IMPL(Code)
147
148INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset)
149INT_ACCESSORS(Code, raw_metadata_size, kMetadataSizeOffset)
150INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset)
151INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset)
152INT32_ACCESSORS(Code, unwinding_info_offset, kUnwindingInfoOffsetOffset)
153
154// Same as ACCESSORS_CHECKED2 macro but with Code as a host and using
155// main_cage_base() for computing the base.
156#define CODE_ACCESSORS_CHECKED2(name, type, offset, get_condition, \
157 set_condition) \
158 type Code::name() const { \
159 PtrComprCageBase cage_base = main_cage_base(); \
160 return Code::name(cage_base); \
161 } \
162 type Code::name(PtrComprCageBase cage_base) const { \
163 type value = TaggedField<type, offset>::load(cage_base, *this); \
164 DCHECK(get_condition)((void) 0); \
165 return value; \
166 } \
167 void Code::set_##name(type value, WriteBarrierMode mode) { \
168 DCHECK(set_condition)((void) 0); \
169 TaggedField<type, offset>::store(*this, value); \
170 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
171 }
172
173// Same as RELEASE_ACQUIRE_ACCESSORS_CHECKED2 macro but with Code as a host and
174// using main_cage_base(kRelaxedLoad) for computing the base.
175#define RELEASE_ACQUIRE_CODE_ACCESSORS_CHECKED2(name, type, offset, \
176 get_condition, set_condition) \
177 type Code::name(AcquireLoadTag tag) const { \
178 PtrComprCageBase cage_base = main_cage_base(kRelaxedLoad); \
179 return Code::name(cage_base, tag); \
180 } \
181 type Code::name(PtrComprCageBase cage_base, AcquireLoadTag) const { \
182 type value = TaggedField<type, offset>::Acquire_Load(cage_base, *this); \
183 DCHECK(get_condition)((void) 0); \
184 return value; \
185 } \
186 void Code::set_##name(type value, ReleaseStoreTag, WriteBarrierMode mode) { \
187 DCHECK(set_condition)((void) 0); \
188 TaggedField<type, offset>::Release_Store(*this, value); \
189 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); \
190 }
191
192#define CODE_ACCESSORS(name, type, offset) \
193 CODE_ACCESSORS_CHECKED2(name, type, offset, true, true)
194
195#define RELEASE_ACQUIRE_CODE_ACCESSORS(name, type, offset) \
196 RELEASE_ACQUIRE_CODE_ACCESSORS_CHECKED2(name, type, offset, \
197 !ObjectInYoungGeneration(value), \
198 !ObjectInYoungGeneration(value))
199
200CODE_ACCESSORS(relocation_info, ByteArray, kRelocationInfoOffset)
201
202CODE_ACCESSORS_CHECKED2(deoptimization_data, FixedArray,
203 kDeoptimizationDataOrInterpreterDataOffset,
204 kind() != CodeKind::BASELINE,
205 kind() != CodeKind::BASELINE &&
206 !ObjectInYoungGeneration(value))
207CODE_ACCESSORS_CHECKED2(bytecode_or_interpreter_data, HeapObject,
208 kDeoptimizationDataOrInterpreterDataOffset,
209 kind() == CodeKind::BASELINE,
210 kind() == CodeKind::BASELINE &&
211 !ObjectInYoungGeneration(value))
212
213CODE_ACCESSORS_CHECKED2(source_position_table, ByteArray, kPositionTableOffset,
214 kind() != CodeKind::BASELINE,
215 kind() != CodeKind::BASELINE &&
216 !ObjectInYoungGeneration(value))
217CODE_ACCESSORS_CHECKED2(bytecode_offset_table, ByteArray, kPositionTableOffset,
218 kind() == CodeKind::BASELINE,
219 kind() == CodeKind::BASELINE &&
220 !ObjectInYoungGeneration(value))
221
222// Concurrent marker needs to access kind specific flags in code data container.
223RELEASE_ACQUIRE_CODE_ACCESSORS(code_data_container, CodeDataContainer,
224 kCodeDataContainerOffset)
225#undef CODE_ACCESSORS
226#undef CODE_ACCESSORS_CHECKED2
227#undef RELEASE_ACQUIRE_CODE_ACCESSORS
228#undef RELEASE_ACQUIRE_CODE_ACCESSORS_CHECKED2
229
230PtrComprCageBase Code::main_cage_base() const {
231#ifdef V8_EXTERNAL_CODE_SPACE
232 Address cage_base_hi = ReadField<Tagged_t>(kMainCageBaseUpper32BitsOffset);
233 return PtrComprCageBase(cage_base_hi << 32);
234#else
235 return GetPtrComprCageBase(*this);
236#endif
237}
238
239PtrComprCageBase Code::main_cage_base(RelaxedLoadTag) const {
240#ifdef V8_EXTERNAL_CODE_SPACE
241 Address cage_base_hi =
242 Relaxed_ReadField<Tagged_t>(kMainCageBaseUpper32BitsOffset);
243 return PtrComprCageBase(cage_base_hi << 32);
244#else
245 return GetPtrComprCageBase(*this);
246#endif
247}
248
249void Code::set_main_cage_base(Address cage_base, RelaxedStoreTag) {
250#ifdef V8_EXTERNAL_CODE_SPACE
251 Tagged_t cage_base_hi = static_cast<Tagged_t>(cage_base >> 32);
252 Relaxed_WriteField<Tagged_t>(kMainCageBaseUpper32BitsOffset, cage_base_hi);
253#else
254 UNREACHABLE()V8_Fatal("unreachable code");
255#endif
256}
257
258CodeDataContainer Code::GCSafeCodeDataContainer(AcquireLoadTag) const {
259 PtrComprCageBase cage_base = main_cage_base(kRelaxedLoad);
260 HeapObject object =
261 TaggedField<HeapObject, kCodeDataContainerOffset>::Acquire_Load(cage_base,
262 *this);
263 DCHECK(!ObjectInYoungGeneration(object))((void) 0);
264 CodeDataContainer code_data_container =
265 ForwardingAddress(CodeDataContainer::unchecked_cast(object));
266 return code_data_container;
267}
268
269// Helper functions for converting Code objects to CodeDataContainer and back
270// when V8_EXTERNAL_CODE_SPACE is enabled.
271inline CodeT ToCodeT(Code code) {
272#ifdef V8_EXTERNAL_CODE_SPACE
273 return code.code_data_container(kAcquireLoad);
274#else
275 return code;
276#endif
277}
278
279inline Handle<CodeT> ToCodeT(Handle<Code> code, Isolate* isolate) {
280#ifdef V8_EXTERNAL_CODE_SPACE
281 return handle(ToCodeT(*code), isolate);
282#else
283 return code;
284#endif
285}
286
287inline MaybeHandle<CodeT> ToCodeT(MaybeHandle<Code> maybe_code,
288 Isolate* isolate) {
289#ifdef V8_EXTERNAL_CODE_SPACE
290 Handle<Code> code;
291 if (maybe_code.ToHandle(&code)) return ToCodeT(code, isolate);
292 return {};
293#else
294 return maybe_code;
295#endif
296}
297
298inline Code FromCodeT(CodeT code) {
299#ifdef V8_EXTERNAL_CODE_SPACE
300 return code.code();
301#else
302 return code;
303#endif
304}
305
306inline Code FromCodeT(CodeT code, RelaxedLoadTag) {
307#ifdef V8_EXTERNAL_CODE_SPACE
308 return code.code(kRelaxedLoad);
309#else
310 return code;
311#endif
312}
313
314inline Handle<Code> FromCodeT(Handle<CodeT> code, Isolate* isolate) {
315#ifdef V8_EXTERNAL_CODE_SPACE
316 return handle(FromCodeT(*code), isolate);
317#else
318 return code;
319#endif
320}
321
322inline Handle<AbstractCode> ToAbstractCode(Handle<CodeT> code,
323 Isolate* isolate) {
324 return Handle<AbstractCode>::cast(FromCodeT(code, isolate));
325}
326
327inline CodeDataContainer CodeDataContainerFromCodeT(CodeT code) {
328#ifdef V8_EXTERNAL_CODE_SPACE
329 return code;
330#else
331 return code.code_data_container(kAcquireLoad);
332#endif
333}
334
335void Code::WipeOutHeader() {
336 WRITE_FIELD(*this, kRelocationInfoOffset, Smi::FromInt(0));
337 WRITE_FIELD(*this, kDeoptimizationDataOrInterpreterDataOffset,
338 Smi::FromInt(0));
339 WRITE_FIELD(*this, kPositionTableOffset, Smi::FromInt(0));
340 WRITE_FIELD(*this, kCodeDataContainerOffset, Smi::FromInt(0));
341 if (V8_EXTERNAL_CODE_SPACE_BOOLfalse) {
342 set_main_cage_base(kNullAddress, kRelaxedStore);
343 }
344}
345
346void Code::clear_padding() {
347 // Clear the padding between the header and `raw_body_start`.
348 if (FIELD_SIZE(kOptionalPaddingOffset)(kOptionalPaddingOffsetEnd + 1 - kOptionalPaddingOffset) != 0) {
349 memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
350 FIELD_SIZE(kOptionalPaddingOffset)(kOptionalPaddingOffsetEnd + 1 - kOptionalPaddingOffset));
351 }
352
353 // Clear the padding after `raw_body_end`.
354 size_t trailing_padding_size =
355 CodeSize() - Code::kHeaderSize - raw_body_size();
356 memset(reinterpret_cast<void*>(raw_body_end()), 0, trailing_padding_size);
357}
358
359ByteArray Code::SourcePositionTable(SharedFunctionInfo sfi) const {
360 DisallowGarbageCollection no_gc;
361 if (kind() == CodeKind::BASELINE) {
362 return sfi.GetBytecodeArray(sfi.GetIsolate()).SourcePositionTable();
363 }
364 return source_position_table();
365}
366
367Object Code::next_code_link() const {
368 return code_data_container(kAcquireLoad).next_code_link();
369}
370
371void Code::set_next_code_link(Object value) {
372 code_data_container(kAcquireLoad).set_next_code_link(value);
373}
374
375Address Code::raw_body_start() const { return raw_instruction_start(); }
376
377Address Code::raw_body_end() const {
378 return raw_body_start() + raw_body_size();
379}
380
381int Code::raw_body_size() const {
382 return raw_instruction_size() + raw_metadata_size();
383}
384
385int Code::InstructionSize() const {
386 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
387 ? OffHeapInstructionSize(*this, builtin_id())
388 : raw_instruction_size();
389}
390
391Address Code::raw_instruction_start() const {
392 return field_address(kHeaderSize);
393}
394
395Address Code::InstructionStart() const {
396 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
397 ? i::OffHeapInstructionStart(*this, builtin_id())
398 : raw_instruction_start();
399}
400
401Address Code::raw_instruction_end() const {
402 return raw_instruction_start() + raw_instruction_size();
403}
404
405Address Code::InstructionEnd() const {
406 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
407 ? i::OffHeapInstructionEnd(*this, builtin_id())
408 : raw_instruction_end();
409}
410
411Address Code::raw_metadata_start() const {
412 return raw_instruction_start() + raw_instruction_size();
413}
414
415Address Code::InstructionStart(Isolate* isolate, Address pc) const {
416 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
417 ? OffHeapInstructionStart(isolate, pc)
418 : raw_instruction_start();
419}
420
421Address Code::InstructionEnd(Isolate* isolate, Address pc) const {
422 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
423 ? OffHeapInstructionEnd(isolate, pc)
424 : raw_instruction_end();
425}
426
427int Code::GetOffsetFromInstructionStart(Isolate* isolate, Address pc) const {
428 Address instruction_start = InstructionStart(isolate, pc);
429 Address offset = pc - instruction_start;
430 DCHECK_LE(offset, InstructionSize())((void) 0);
431 return static_cast<int>(offset);
432}
433
434Address Code::raw_metadata_end() const {
435 return raw_metadata_start() + raw_metadata_size();
436}
437
438int Code::MetadataSize() const {
439 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
440 ? OffHeapMetadataSize(*this, builtin_id())
441 : raw_metadata_size();
442}
443
444int Code::SizeIncludingMetadata() const {
445 int size = CodeSize();
446 size += relocation_info().Size();
447 if (kind() != CodeKind::BASELINE) {
448 size += deoptimization_data().Size();
449 }
450 return size;
451}
452
453Address Code::SafepointTableAddress() const {
454 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
455 ? OffHeapSafepointTableAddress(*this, builtin_id())
456 : raw_metadata_start() + safepoint_table_offset();
457}
458
459int Code::safepoint_table_size() const {
460 DCHECK_GE(handler_table_offset() - safepoint_table_offset(), 0)((void) 0);
461 return handler_table_offset() - safepoint_table_offset();
462}
463
464bool Code::has_safepoint_table() const { return safepoint_table_size() > 0; }
465
466Address Code::HandlerTableAddress() const {
467 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
468 ? OffHeapHandlerTableAddress(*this, builtin_id())
469 : raw_metadata_start() + handler_table_offset();
470}
471
472int Code::handler_table_size() const {
473 DCHECK_GE(constant_pool_offset() - handler_table_offset(), 0)((void) 0);
474 return constant_pool_offset() - handler_table_offset();
475}
476
477bool Code::has_handler_table() const { return handler_table_size() > 0; }
478
479int Code::constant_pool_size() const {
480 const int size = code_comments_offset() - constant_pool_offset();
481 DCHECK_IMPLIES(!FLAG_enable_embedded_constant_pool, size == 0)((void) 0);
482 DCHECK_GE(size, 0)((void) 0);
483 return size;
484}
485
486bool Code::has_constant_pool() const { return constant_pool_size() > 0; }
487
488int Code::code_comments_size() const {
489 DCHECK_GE(unwinding_info_offset() - code_comments_offset(), 0)((void) 0);
490 return unwinding_info_offset() - code_comments_offset();
491}
492
493bool Code::has_code_comments() const { return code_comments_size() > 0; }
494
495ByteArray Code::unchecked_relocation_info() const {
496 PtrComprCageBase cage_base = main_cage_base();
497 return ByteArray::unchecked_cast(
498 TaggedField<HeapObject, kRelocationInfoOffset>::load(cage_base, *this));
499}
500
501byte* Code::relocation_start() const {
502 return unchecked_relocation_info().GetDataStartAddress();
503}
504
505byte* Code::relocation_end() const {
506 return unchecked_relocation_info().GetDataEndAddress();
507}
508
509int Code::relocation_size() const {
510 return unchecked_relocation_info().length();
511}
512
513Address Code::entry() const { return raw_instruction_start(); }
514
515bool Code::contains(Isolate* isolate, Address inner_pointer) {
516 if (is_off_heap_trampoline()) {
517 if (OffHeapInstructionStart(isolate, inner_pointer) <= inner_pointer &&
518 inner_pointer < OffHeapInstructionEnd(isolate, inner_pointer)) {
519 return true;
520 }
521 }
522 return (address() <= inner_pointer) &&
523 (inner_pointer < address() + CodeSize());
524}
525
526// static
527void Code::CopyRelocInfoToByteArray(ByteArray dest, const CodeDesc& desc) {
528 DCHECK_EQ(dest.length(), desc.reloc_size)((void) 0);
529 CopyBytes(dest.GetDataStartAddress(),
530 desc.buffer + desc.buffer_size - desc.reloc_size,
531 static_cast<size_t>(desc.reloc_size));
532}
533
534int Code::CodeSize() const { return SizeFor(raw_body_size()); }
535
536DEF_GETTER(Code, Size, int) { return CodeSize(); }
537
538CodeKind Code::kind() const {
539 STATIC_ASSERT(FIELD_SIZE(kFlagsOffset) == kInt32Size)static_assert((kFlagsOffsetEnd + 1 - kFlagsOffset) == kInt32Size
, "FIELD_SIZE(kFlagsOffset) == kInt32Size")
;
540 const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset);
541 return KindField::decode(flags);
542}
543
544int Code::GetBytecodeOffsetForBaselinePC(Address baseline_pc,
545 BytecodeArray bytecodes) {
546 DisallowGarbageCollection no_gc;
547 CHECK(!is_baseline_trampoline_builtin())do { if ((__builtin_expect(!!(!(!is_baseline_trampoline_builtin
())), 0))) { V8_Fatal("Check failed: %s.", "!is_baseline_trampoline_builtin()"
); } } while (false)
;
548 if (is_baseline_leave_frame_builtin()) return kFunctionExitBytecodeOffset;
549 CHECK_EQ(kind(), CodeKind::BASELINE)do { bool _cmp = ::v8::base::CmpEQImpl< typename ::v8::base
::pass_value_or_ref<decltype(kind())>::type, typename ::
v8::base::pass_value_or_ref<decltype(CodeKind::BASELINE)>
::type>((kind()), (CodeKind::BASELINE)); do { if ((__builtin_expect
(!!(!(_cmp)), 0))) { V8_Fatal("Check failed: %s.", "kind()" " "
"==" " " "CodeKind::BASELINE"); } } while (false); } while (
false)
;
550 baseline::BytecodeOffsetIterator offset_iterator(
551 ByteArray::cast(bytecode_offset_table()), bytecodes);
552 Address pc = baseline_pc - InstructionStart();
553 offset_iterator.AdvanceToPCOffset(pc);
554 return offset_iterator.current_bytecode_offset();
555}
556
557uintptr_t Code::GetBaselinePCForBytecodeOffset(int bytecode_offset,
558 BytecodeToPCPosition position,
559 BytecodeArray bytecodes) {
560 DisallowGarbageCollection no_gc;
561 CHECK_EQ(kind(), CodeKind::BASELINE)do { bool _cmp = ::v8::base::CmpEQImpl< typename ::v8::base
::pass_value_or_ref<decltype(kind())>::type, typename ::
v8::base::pass_value_or_ref<decltype(CodeKind::BASELINE)>
::type>((kind()), (CodeKind::BASELINE)); do { if ((__builtin_expect
(!!(!(_cmp)), 0))) { V8_Fatal("Check failed: %s.", "kind()" " "
"==" " " "CodeKind::BASELINE"); } } while (false); } while (
false)
;
562 baseline::BytecodeOffsetIterator offset_iterator(
563 ByteArray::cast(bytecode_offset_table()), bytecodes);
564 offset_iterator.AdvanceToBytecodeOffset(bytecode_offset);
565 uintptr_t pc = 0;
566 if (position == kPcAtStartOfBytecode) {
567 pc = offset_iterator.current_pc_start_offset();
568 } else {
569 DCHECK_EQ(position, kPcAtEndOfBytecode)((void) 0);
570 pc = offset_iterator.current_pc_end_offset();
571 }
572 return pc;
573}
574
575uintptr_t Code::GetBaselineStartPCForBytecodeOffset(int bytecode_offset,
576 BytecodeArray bytecodes) {
577 return GetBaselinePCForBytecodeOffset(bytecode_offset, kPcAtStartOfBytecode,
578 bytecodes);
579}
580
581uintptr_t Code::GetBaselineEndPCForBytecodeOffset(int bytecode_offset,
582 BytecodeArray bytecodes) {
583 return GetBaselinePCForBytecodeOffset(bytecode_offset, kPcAtEndOfBytecode,
584 bytecodes);
585}
586
587uintptr_t Code::GetBaselinePCForNextExecutedBytecode(int bytecode_offset,
588 BytecodeArray bytecodes) {
589 DisallowGarbageCollection no_gc;
590 CHECK_EQ(kind(), CodeKind::BASELINE)do { bool _cmp = ::v8::base::CmpEQImpl< typename ::v8::base
::pass_value_or_ref<decltype(kind())>::type, typename ::
v8::base::pass_value_or_ref<decltype(CodeKind::BASELINE)>
::type>((kind()), (CodeKind::BASELINE)); do { if ((__builtin_expect
(!!(!(_cmp)), 0))) { V8_Fatal("Check failed: %s.", "kind()" " "
"==" " " "CodeKind::BASELINE"); } } while (false); } while (
false)
;
591 baseline::BytecodeOffsetIterator offset_iterator(
592 ByteArray::cast(bytecode_offset_table()), bytecodes);
593 Handle<BytecodeArray> bytecodes_handle(
594 reinterpret_cast<Address*>(&bytecodes));
595 interpreter::BytecodeArrayIterator bytecode_iterator(bytecodes_handle,
596 bytecode_offset);
597 interpreter::Bytecode bytecode = bytecode_iterator.current_bytecode();
598 if (bytecode == interpreter::Bytecode::kJumpLoop) {
599 return GetBaselineStartPCForBytecodeOffset(
600 bytecode_iterator.GetJumpTargetOffset(), bytecodes);
601 } else {
602 DCHECK(!interpreter::Bytecodes::IsJump(bytecode))((void) 0);
603 return GetBaselineEndPCForBytecodeOffset(bytecode_offset, bytecodes);
604 }
605}
606
607void Code::initialize_flags(CodeKind kind, bool is_turbofanned, int stack_slots,
608 bool is_off_heap_trampoline) {
609 CHECK(0 <= stack_slots && stack_slots < StackSlotsField::kMax)do { if ((__builtin_expect(!!(!(0 <= stack_slots &&
stack_slots < StackSlotsField::kMax)), 0))) { V8_Fatal("Check failed: %s."
, "0 <= stack_slots && stack_slots < StackSlotsField::kMax"
); } } while (false)
;
610 DCHECK(!CodeKindIsInterpretedJSFunction(kind))((void) 0);
611 uint32_t flags = KindField::encode(kind) |
612 IsTurbofannedField::encode(is_turbofanned) |
613 StackSlotsField::encode(stack_slots) |
614 IsOffHeapTrampoline::encode(is_off_heap_trampoline);
615 STATIC_ASSERT(FIELD_SIZE(kFlagsOffset) == kInt32Size)static_assert((kFlagsOffsetEnd + 1 - kFlagsOffset) == kInt32Size
, "FIELD_SIZE(kFlagsOffset) == kInt32Size")
;
616 RELAXED_WRITE_UINT32_FIELD(*this, kFlagsOffset, flags);
617 DCHECK_IMPLIES(stack_slots != 0, uses_safepoint_table())((void) 0);
618 DCHECK_IMPLIES(!uses_safepoint_table(), stack_slots == 0)((void) 0);
619}
620
621inline bool Code::is_interpreter_trampoline_builtin() const {
622 return IsInterpreterTrampolineBuiltin(builtin_id());
623}
624
625inline bool Code::is_baseline_trampoline_builtin() const {
626 return IsBaselineTrampolineBuiltin(builtin_id());
627}
628
629inline bool Code::is_baseline_leave_frame_builtin() const {
630 return builtin_id() == Builtin::kBaselineLeaveFrame;
631}
632
633#ifdef V8_EXTERNAL_CODE_SPACE
634// Note, must be in sync with Code::checks_tiering_state().
635inline bool CodeDataContainer::checks_tiering_state() const {
636 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
637 bool checks_state = (builtin_id() == Builtin::kCompileLazy ||
638 builtin_id() == Builtin::kInterpreterEntryTrampoline ||
639 CodeKindCanTierUp(kind()));
640 return checks_state ||
641 (CodeKindCanDeoptimize(kind()) && marked_for_deoptimization());
642}
643#endif // V8_EXTERNAL_CODE_SPACE
644
645// Note, must be in sync with CodeDataContainer::checks_tiering_state().
646inline bool Code::checks_tiering_state() const {
647 bool checks_state = (builtin_id() == Builtin::kCompileLazy ||
648 builtin_id() == Builtin::kInterpreterEntryTrampoline ||
649 CodeKindCanTierUp(kind()));
650 return checks_state ||
651 (CodeKindCanDeoptimize(kind()) && marked_for_deoptimization());
652}
653
654inline bool Code::has_tagged_outgoing_params() const {
655 return kind() != CodeKind::JS_TO_WASM_FUNCTION &&
656 kind() != CodeKind::C_WASM_ENTRY && kind() != CodeKind::WASM_FUNCTION;
657}
658
659inline bool Code::is_turbofanned() const {
660 const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset);
661 return IsTurbofannedField::decode(flags);
662}
663
664bool Code::is_maglevved() const { return kind() == CodeKind::MAGLEV; }
665
666inline bool Code::can_have_weak_objects() const {
667 DCHECK(CodeKindIsOptimizedJSFunction(kind()))((void) 0);
668 int32_t flags =
669 code_data_container(kAcquireLoad).kind_specific_flags(kRelaxedLoad);
670 return CanHaveWeakObjectsField::decode(flags);
671}
672
673inline void Code::set_can_have_weak_objects(bool value) {
674 DCHECK(CodeKindIsOptimizedJSFunction(kind()))((void) 0);
675 CodeDataContainer container = code_data_container(kAcquireLoad);
676 int32_t previous = container.kind_specific_flags(kRelaxedLoad);
677 int32_t updated = CanHaveWeakObjectsField::update(previous, value);
678 container.set_kind_specific_flags(updated, kRelaxedStore);
679}
680
681inline bool Code::is_promise_rejection() const {
682 DCHECK(kind() == CodeKind::BUILTIN)((void) 0);
683 int32_t flags =
684 code_data_container(kAcquireLoad).kind_specific_flags(kRelaxedLoad);
685 return IsPromiseRejectionField::decode(flags);
686}
687
688inline void Code::set_is_promise_rejection(bool value) {
689 DCHECK(kind() == CodeKind::BUILTIN)((void) 0);
690 CodeDataContainer container = code_data_container(kAcquireLoad);
691 int32_t previous = container.kind_specific_flags(kRelaxedLoad);
692 int32_t updated = IsPromiseRejectionField::update(previous, value);
693 container.set_kind_specific_flags(updated, kRelaxedStore);
694}
695
696inline bool Code::is_off_heap_trampoline() const {
697 const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset);
698 return IsOffHeapTrampoline::decode(flags);
699}
700
701inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() {
702 if (is_promise_rejection()) return HandlerTable::PROMISE;
703 return HandlerTable::UNCAUGHT;
704}
705
706Builtin Code::builtin_id() const {
707 int index = RELAXED_READ_INT_FIELD(*this, kBuiltinIndexOffset);
708 DCHECK(index == static_cast<int>(Builtin::kNoBuiltinId) ||((void) 0)
709 Builtins::IsBuiltinId(index))((void) 0);
710 return static_cast<Builtin>(index);
711}
712
713void Code::set_builtin_id(Builtin builtin) {
714 DCHECK(builtin == Builtin::kNoBuiltinId || Builtins::IsBuiltinId(builtin))((void) 0);
715 RELAXED_WRITE_INT_FIELD(*this, kBuiltinIndexOffset,
716 static_cast<int>(builtin));
717}
718
719bool Code::is_builtin() const { return builtin_id() != Builtin::kNoBuiltinId; }
720
721unsigned Code::inlined_bytecode_size() const {
722 unsigned size = RELAXED_READ_UINT_FIELD(*this, kInlinedBytecodeSizeOffset);
723 DCHECK(CodeKindIsOptimizedJSFunction(kind()) || size == 0)((void) 0);
724 return size;
725}
726
727void Code::set_inlined_bytecode_size(unsigned size) {
728 DCHECK(CodeKindIsOptimizedJSFunction(kind()) || size == 0)((void) 0);
729 RELAXED_WRITE_UINT_FIELD(*this, kInlinedBytecodeSizeOffset, size);
730}
731
732bool Code::uses_safepoint_table() const {
733 return is_turbofanned() || is_maglevved() || is_wasm_code();
734}
735
736int Code::stack_slots() const {
737 const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset);
738 const int slots = StackSlotsField::decode(flags);
739 DCHECK_IMPLIES(!uses_safepoint_table(), slots == 0)((void) 0);
740 return slots;
741}
742
743bool CodeDataContainer::marked_for_deoptimization() const {
744#ifdef V8_EXTERNAL_CODE_SPACE
745 // kind field is not available on CodeDataContainer when external code space
746 // is not enabled.
747 DCHECK(CodeKindCanDeoptimize(kind()))((void) 0);
748#endif // V8_EXTERNAL_CODE_SPACE
749 int32_t flags = kind_specific_flags(kRelaxedLoad);
750 return Code::MarkedForDeoptimizationField::decode(flags);
751}
752
753bool Code::marked_for_deoptimization() const {
754 DCHECK(CodeKindCanDeoptimize(kind()))((void) 0);
755 return code_data_container(kAcquireLoad).marked_for_deoptimization();
756}
757
758void CodeDataContainer::set_marked_for_deoptimization(bool flag) {
759#ifdef V8_EXTERNAL_CODE_SPACE
760 // kind field is not available on CodeDataContainer when external code space
761 // is not enabled.
762 DCHECK(CodeKindCanDeoptimize(kind()))((void) 0);
763#endif // V8_EXTERNAL_CODE_SPACE
764 DCHECK_IMPLIES(flag, AllowDeoptimization::IsAllowed(GetIsolate()))((void) 0);
765 int32_t previous = kind_specific_flags(kRelaxedLoad);
766 int32_t updated = Code::MarkedForDeoptimizationField::update(previous, flag);
767 set_kind_specific_flags(updated, kRelaxedStore);
768}
769
770void Code::set_marked_for_deoptimization(bool flag) {
771 code_data_container(kAcquireLoad).set_marked_for_deoptimization(flag);
772}
773
774bool Code::embedded_objects_cleared() const {
775 DCHECK(CodeKindIsOptimizedJSFunction(kind()))((void) 0);
776 int32_t flags =
777 code_data_container(kAcquireLoad).kind_specific_flags(kRelaxedLoad);
778 return EmbeddedObjectsClearedField::decode(flags);
779}
780
781void Code::set_embedded_objects_cleared(bool flag) {
782 DCHECK(CodeKindIsOptimizedJSFunction(kind()))((void) 0);
783 DCHECK_IMPLIES(flag, marked_for_deoptimization())((void) 0);
784 CodeDataContainer container = code_data_container(kAcquireLoad);
785 int32_t previous = container.kind_specific_flags(kRelaxedLoad);
786 int32_t updated = EmbeddedObjectsClearedField::update(previous, flag);
787 container.set_kind_specific_flags(updated, kRelaxedStore);
788}
789
790bool Code::is_optimized_code() const {
791 return CodeKindIsOptimizedJSFunction(kind());
792}
793
794bool Code::is_wasm_code() const { return kind() == CodeKind::WASM_FUNCTION; }
795
796int Code::constant_pool_offset() const {
797 if (!FLAG_enable_embedded_constant_pool) {
798 // Redirection needed since the field doesn't exist in this case.
799 return code_comments_offset();
800 }
801 return ReadField<int>(kConstantPoolOffsetOffset);
802}
803
804void Code::set_constant_pool_offset(int value) {
805 if (!FLAG_enable_embedded_constant_pool) {
806 // Redirection needed since the field doesn't exist in this case.
807 return;
808 }
809 DCHECK_LE(value, MetadataSize())((void) 0);
810 WriteField<int>(kConstantPoolOffsetOffset, value);
811}
812
813Address Code::constant_pool() const {
814 if (!has_constant_pool()) return kNullAddress;
815 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
816 ? OffHeapConstantPoolAddress(*this, builtin_id())
817 : raw_metadata_start() + constant_pool_offset();
818}
819
820Address Code::code_comments() const {
821 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
822 ? OffHeapCodeCommentsAddress(*this, builtin_id())
823 : raw_metadata_start() + code_comments_offset();
824}
825
826Address Code::unwinding_info_start() const {
827 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
828 ? OffHeapUnwindingInfoAddress(*this, builtin_id())
829 : raw_metadata_start() + unwinding_info_offset();
830}
831
832Address Code::unwinding_info_end() const {
833 return V8_UNLIKELY(is_off_heap_trampoline())(__builtin_expect(!!(is_off_heap_trampoline()), 0))
834 ? OffHeapMetadataEnd(*this, builtin_id())
835 : raw_metadata_end();
836}
837
838int Code::unwinding_info_size() const {
839 DCHECK_GE(unwinding_info_end(), unwinding_info_start())((void) 0);
840 return static_cast<int>(unwinding_info_end() - unwinding_info_start());
841}
842
843bool Code::has_unwinding_info() const { return unwinding_info_size() > 0; }
844
845Code Code::GetCodeFromTargetAddress(Address address) {
846 {
847 // TODO(jgruber,v8:6666): Support embedded builtins here. We'd need to pass
848 // in the current isolate.
849 Address start =
850 reinterpret_cast<Address>(Isolate::CurrentEmbeddedBlobCode());
851 Address end = start + Isolate::CurrentEmbeddedBlobCodeSize();
852 CHECK(address < start || address >= end)do { if ((__builtin_expect(!!(!(address < start || address
>= end)), 0))) { V8_Fatal("Check failed: %s.", "address < start || address >= end"
); } } while (false)
;
853 }
854
855 HeapObject code = HeapObject::FromAddress(address - Code::kHeaderSize);
856 // Unchecked cast because we can't rely on the map currently
857 // not being a forwarding pointer.
858 return Code::unchecked_cast(code);
859}
860
861Code Code::GetObjectFromEntryAddress(Address location_of_address) {
862 Address code_entry = base::Memory<Address>(location_of_address);
863 HeapObject code = HeapObject::FromAddress(code_entry - Code::kHeaderSize);
864 // Unchecked cast because we can't rely on the map currently
865 // not being a forwarding pointer.
866 return Code::unchecked_cast(code);
867}
868
869bool Code::CanContainWeakObjects() {
870 return is_optimized_code() && can_have_weak_objects();
871}
872
873bool Code::IsWeakObject(HeapObject object) {
874 return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object));
875}
876
877bool Code::IsWeakObjectInOptimizedCode(HeapObject object) {
878 Map map = object.map(kAcquireLoad);
879 InstanceType instance_type = map.instance_type();
880 if (InstanceTypeChecker::IsMap(instance_type)) {
881 return Map::cast(object).CanTransition();
882 }
883 return InstanceTypeChecker::IsPropertyCell(instance_type) ||
884 InstanceTypeChecker::IsJSReceiver(instance_type) ||
885 InstanceTypeChecker::IsContext(instance_type);
886}
887
888bool Code::IsWeakObjectInDeoptimizationLiteralArray(Object object) {
889 // Maps must be strong because they can be used as part of the description for
890 // how to materialize an object upon deoptimization, in which case it is
891 // possible to reach the code that requires the Map without anything else
892 // holding a strong pointer to that Map.
893 return object.IsHeapObject() && !object.IsMap() &&
894 Code::IsWeakObjectInOptimizedCode(HeapObject::cast(object));
895}
896
897bool Code::IsExecutable() {
898 return !Builtins::IsBuiltinId(builtin_id()) || !is_off_heap_trampoline() ||
899 Builtins::CodeObjectIsExecutable(builtin_id());
900}
901
902// This field has to have relaxed atomic accessors because it is accessed in the
903// concurrent marker.
904STATIC_ASSERT(FIELD_SIZE(CodeDataContainer::kKindSpecificFlagsOffset) ==static_assert((CodeDataContainer::kKindSpecificFlagsOffsetEnd
+ 1 - CodeDataContainer::kKindSpecificFlagsOffset) == kInt32Size
, "FIELD_SIZE(CodeDataContainer::kKindSpecificFlagsOffset) == kInt32Size"
)
905 kInt32Size)static_assert((CodeDataContainer::kKindSpecificFlagsOffsetEnd
+ 1 - CodeDataContainer::kKindSpecificFlagsOffset) == kInt32Size
, "FIELD_SIZE(CodeDataContainer::kKindSpecificFlagsOffset) == kInt32Size"
)
;
906RELAXED_INT32_ACCESSORS(CodeDataContainer, kind_specific_flags,
907 kKindSpecificFlagsOffset)
908
909#if defined(V8_TARGET_LITTLE_ENDIAN1)
910static_assert(!V8_EXTERNAL_CODE_SPACE_BOOLfalse ||
911 (CodeDataContainer::kCodeCageBaseUpper32BitsOffset ==
912 CodeDataContainer::kCodeOffset + kTaggedSize),
913 "CodeDataContainer::code field layout requires updating "
914 "for little endian architectures");
915#elif defined(V8_TARGET_BIG_ENDIAN)
916static_assert(!V8_EXTERNAL_CODE_SPACE_BOOLfalse,
917 "CodeDataContainer::code field layout requires updating "
918 "for big endian architectures");
919#endif
920
921Object CodeDataContainer::raw_code() const {
922 PtrComprCageBase cage_base = code_cage_base();
923 return CodeDataContainer::raw_code(cage_base);
924}
925
926Object CodeDataContainer::raw_code(PtrComprCageBase cage_base) const {
927 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
928 Object value = TaggedField<Object, kCodeOffset>::load(cage_base, *this);
929 return value;
930}
931
932void CodeDataContainer::set_raw_code(Object value, WriteBarrierMode mode) {
933 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
934 TaggedField<Object, kCodeOffset>::store(*this, value);
935 CONDITIONAL_WRITE_BARRIER(*this, kCodeOffset, value, mode);
936}
937
938Object CodeDataContainer::raw_code(RelaxedLoadTag tag) const {
939 PtrComprCageBase cage_base = code_cage_base(tag);
940 return CodeDataContainer::raw_code(cage_base, tag);
941}
942
943Object CodeDataContainer::raw_code(PtrComprCageBase cage_base,
944 RelaxedLoadTag) const {
945 Object value =
Value stored to 'value' during its initialization is never read
946 TaggedField<Object, kCodeOffset>::Relaxed_Load(cage_base, *this);
947 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
948 return value;
949}
950
951ACCESSORS(CodeDataContainer, next_code_link, Object, kNextCodeLinkOffset)
952
953PtrComprCageBase CodeDataContainer::code_cage_base() const {
954#ifdef V8_EXTERNAL_CODE_SPACE
955 // TODO(v8:10391): consider protecting this value with the sandbox.
956 Address code_cage_base_hi =
957 ReadField<Tagged_t>(kCodeCageBaseUpper32BitsOffset);
958 return PtrComprCageBase(code_cage_base_hi << 32);
959#else
960 return GetPtrComprCageBase(*this);
961#endif
962}
963
964void CodeDataContainer::set_code_cage_base(Address code_cage_base) {
965#ifdef V8_EXTERNAL_CODE_SPACE
966 Tagged_t code_cage_base_hi = static_cast<Tagged_t>(code_cage_base >> 32);
967 WriteField<Tagged_t>(kCodeCageBaseUpper32BitsOffset, code_cage_base_hi);
968#else
969 UNREACHABLE()V8_Fatal("unreachable code");
970#endif
971}
972
973PtrComprCageBase CodeDataContainer::code_cage_base(RelaxedLoadTag) const {
974#ifdef V8_EXTERNAL_CODE_SPACE
975 // TODO(v8:10391): consider protecting this value with the sandbox.
976 Address code_cage_base_hi =
977 Relaxed_ReadField<Tagged_t>(kCodeCageBaseUpper32BitsOffset);
978 return PtrComprCageBase(code_cage_base_hi << 32);
979#else
980 return GetPtrComprCageBase(*this);
981#endif
982}
983
984void CodeDataContainer::set_code_cage_base(Address code_cage_base,
985 RelaxedStoreTag) {
986#ifdef V8_EXTERNAL_CODE_SPACE
987 Tagged_t code_cage_base_hi = static_cast<Tagged_t>(code_cage_base >> 32);
988 Relaxed_WriteField<Tagged_t>(kCodeCageBaseUpper32BitsOffset,
989 code_cage_base_hi);
990#else
991 UNREACHABLE()V8_Fatal("unreachable code");
992#endif
993}
994
995void CodeDataContainer::AllocateExternalPointerEntries(Isolate* isolate) {
996 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
997 InitExternalPointerField(kCodeEntryPointOffset, isolate, kCodeEntryPointTag);
998}
999
1000Code CodeDataContainer::code() const {
1001 PtrComprCageBase cage_base = code_cage_base();
1002 return CodeDataContainer::code(cage_base);
1003}
1004Code CodeDataContainer::code(PtrComprCageBase cage_base) const {
1005 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1006 return Code::cast(raw_code(cage_base));
1007}
1008
1009Code CodeDataContainer::code(RelaxedLoadTag tag) const {
1010 PtrComprCageBase cage_base = code_cage_base(tag);
1011 return CodeDataContainer::code(cage_base, tag);
1012}
1013
1014Code CodeDataContainer::code(PtrComprCageBase cage_base,
1015 RelaxedLoadTag tag) const {
1016 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1017 return Code::cast(raw_code(cage_base, tag));
1018}
1019
1020DEF_GETTER(CodeDataContainer, code_entry_point, Address) {
1021 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1022 Isolate* isolate = GetIsolateForSandbox(*this);
1023 return ReadExternalPointerField(kCodeEntryPointOffset, isolate,
1024 kCodeEntryPointTag);
1025}
1026
1027void CodeDataContainer::set_code_entry_point(Isolate* isolate, Address value) {
1028 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1029 WriteExternalPointerField(kCodeEntryPointOffset, isolate, value,
1030 kCodeEntryPointTag);
1031}
1032
1033void CodeDataContainer::SetCodeAndEntryPoint(Isolate* isolate_for_sandbox,
1034 Code code, WriteBarrierMode mode) {
1035 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1036 set_raw_code(code, mode);
1037 set_code_entry_point(isolate_for_sandbox, code.InstructionStart());
1038}
1039
1040void CodeDataContainer::UpdateCodeEntryPoint(Isolate* isolate_for_sandbox,
1041 Code code) {
1042 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1043 DCHECK_EQ(raw_code(), code)((void) 0);
1044 set_code_entry_point(isolate_for_sandbox, code.InstructionStart());
1045}
1046
1047Address CodeDataContainer::InstructionStart() const {
1048 return code_entry_point();
1049}
1050
1051Address CodeDataContainer::raw_instruction_start() {
1052 return code_entry_point();
1053}
1054
1055Address CodeDataContainer::entry() const { return code_entry_point(); }
1056
1057void CodeDataContainer::clear_padding() {
1058 memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0,
1059 kSize - kUnalignedSize);
1060}
1061
1062RELAXED_UINT16_ACCESSORS(CodeDataContainer, flags, kFlagsOffset)
1063
1064// Ensure builtin_id field fits into int16_t, so that we can rely on sign
1065// extension to convert int16_t{-1} to kNoBuiltinId.
1066// If the asserts fail, update the code that use kBuiltinIdOffset below.
1067STATIC_ASSERT(static_cast<int>(Builtin::kNoBuiltinId) == -1)static_assert(static_cast<int>(Builtin::kNoBuiltinId) ==
-1, "static_cast<int>(Builtin::kNoBuiltinId) == -1")
;
1068STATIC_ASSERT(Builtins::kBuiltinCount < std::numeric_limits<int16_t>::max())static_assert(Builtins::kBuiltinCount < std::numeric_limits
<int16_t>::max(), "Builtins::kBuiltinCount < std::numeric_limits<int16_t>::max()"
)
;
1069
1070void CodeDataContainer::initialize_flags(CodeKind kind, Builtin builtin_id) {
1071 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1072 uint16_t value = KindField::encode(kind);
1073 set_flags(value, kRelaxedStore);
1074
1075 WriteField<int16_t>(kBuiltinIdOffset, static_cast<int16_t>(builtin_id));
1076}
1077
1078#ifdef V8_EXTERNAL_CODE_SPACE
1079
1080CodeKind CodeDataContainer::kind() const {
1081 return KindField::decode(flags(kRelaxedLoad));
1082}
1083
1084Builtin CodeDataContainer::builtin_id() const {
1085 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1086 // Rely on sign-extension when converting int16_t to int to preserve
1087 // kNoBuiltinId value.
1088 STATIC_ASSERT(static_cast<int>(static_cast<int16_t>(Builtin::kNoBuiltinId)) ==static_assert(static_cast<int>(static_cast<int16_t>
(Builtin::kNoBuiltinId)) == static_cast<int>(Builtin::kNoBuiltinId
), "static_cast<int>(static_cast<int16_t>(Builtin::kNoBuiltinId)) == static_cast<int>(Builtin::kNoBuiltinId)"
)
1089 static_cast<int>(Builtin::kNoBuiltinId))static_assert(static_cast<int>(static_cast<int16_t>
(Builtin::kNoBuiltinId)) == static_cast<int>(Builtin::kNoBuiltinId
), "static_cast<int>(static_cast<int16_t>(Builtin::kNoBuiltinId)) == static_cast<int>(Builtin::kNoBuiltinId)"
)
;
1090 int value = ReadField<int16_t>(kBuiltinIdOffset);
1091 return static_cast<Builtin>(value);
1092}
1093
1094bool CodeDataContainer::is_builtin() const {
1095 CHECK(V8_EXTERNAL_CODE_SPACE_BOOL)do { if ((__builtin_expect(!!(!(false)), 0))) { V8_Fatal("Check failed: %s."
, "V8_EXTERNAL_CODE_SPACE_BOOL"); } } while (false)
;
1096 return builtin_id() != Builtin::kNoBuiltinId;
1097}
1098
1099bool CodeDataContainer::is_optimized_code() const {
1100 return CodeKindIsOptimizedJSFunction(kind());
1101}
1102
1103inline bool CodeDataContainer::is_interpreter_trampoline_builtin() const {
1104 return IsInterpreterTrampolineBuiltin(builtin_id());
1105}
1106
1107//
1108// A collection of getters and predicates that forward queries to associated
1109// Code object.
1110//
1111
1112#define DEF_PRIMITIVE_FORWARDING_CDC_GETTER(name, type) \
1113 type CodeDataContainer::name() const { return FromCodeT(*this).name(); }
1114
1115#define DEF_FORWARDING_CDC_GETTER(name, type) \
1116 DEF_GETTER(CodeDataContainer, name, type) { \
1117 return FromCodeT(*this).name(cage_base); \
1118 }
1119
1120DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_maglevved, bool)
1121DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_turbofanned, bool)
1122DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_off_heap_trampoline, bool)
1123
1124DEF_FORWARDING_CDC_GETTER(deoptimization_data, FixedArray)
1125DEF_FORWARDING_CDC_GETTER(bytecode_or_interpreter_data, HeapObject)
1126DEF_FORWARDING_CDC_GETTER(source_position_table, ByteArray)
1127DEF_FORWARDING_CDC_GETTER(bytecode_offset_table, ByteArray)
1128
1129#undef DEF_PRIMITIVE_FORWARDING_CDC_GETTER
1130#undef DEF_FORWARDING_CDC_GETTER
1131
1132#endif // V8_EXTERNAL_CODE_SPACE
1133
1134byte BytecodeArray::get(int index) const {
1135 DCHECK(index >= 0 && index < this->length())((void) 0);
1136 return ReadField<byte>(kHeaderSize + index * kCharSize);
1137}
1138
1139void BytecodeArray::set(int index, byte value) {
1140 DCHECK(index >= 0 && index < this->length())((void) 0);
1141 WriteField<byte>(kHeaderSize + index * kCharSize, value);
1142}
1143
1144void BytecodeArray::set_frame_size(int32_t frame_size) {
1145 DCHECK_GE(frame_size, 0)((void) 0);
1146 DCHECK(IsAligned(frame_size, kSystemPointerSize))((void) 0);
1147 WriteField<int32_t>(kFrameSizeOffset, frame_size);
1148}
1149
1150int32_t BytecodeArray::frame_size() const {
1151 return ReadField<int32_t>(kFrameSizeOffset);
1152}
1153
1154int BytecodeArray::register_count() const {
1155 return static_cast<int>(frame_size()) / kSystemPointerSize;
1156}
1157
1158void BytecodeArray::set_parameter_count(int32_t number_of_parameters) {
1159 DCHECK_GE(number_of_parameters, 0)((void) 0);
1160 // Parameter count is stored as the size on stack of the parameters to allow
1161 // it to be used directly by generated code.
1162 WriteField<int32_t>(kParameterSizeOffset,
1163 (number_of_parameters << kSystemPointerSizeLog2));
1164}
1165
1166interpreter::Register BytecodeArray::incoming_new_target_or_generator_register()
1167 const {
1168 int32_t register_operand =
1169 ReadField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset);
1170 if (register_operand == 0) {
1171 return interpreter::Register::invalid_value();
1172 } else {
1173 return interpreter::Register::FromOperand(register_operand);
1174 }
1175}
1176
1177void BytecodeArray::set_incoming_new_target_or_generator_register(
1178 interpreter::Register incoming_new_target_or_generator_register) {
1179 if (!incoming_new_target_or_generator_register.is_valid()) {
1180 WriteField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset, 0);
1181 } else {
1182 DCHECK(incoming_new_target_or_generator_register.index() <((void) 0)
1183 register_count())((void) 0);
1184 DCHECK_NE(0, incoming_new_target_or_generator_register.ToOperand())((void) 0);
1185 WriteField<int32_t>(kIncomingNewTargetOrGeneratorRegisterOffset,
1186 incoming_new_target_or_generator_register.ToOperand());
1187 }
1188}
1189
1190int BytecodeArray::osr_urgency() const {
1191 return OsrUrgencyBits::decode(osr_urgency_and_install_target());
1192}
1193
1194void BytecodeArray::set_osr_urgency(int urgency) {
1195 DCHECK(0 <= urgency && urgency <= BytecodeArray::kMaxOsrUrgency)((void) 0);
1196 STATIC_ASSERT(BytecodeArray::kMaxOsrUrgency <= OsrUrgencyBits::kMax)static_assert(BytecodeArray::kMaxOsrUrgency <= OsrUrgencyBits
::kMax, "BytecodeArray::kMaxOsrUrgency <= OsrUrgencyBits::kMax"
)
;
1197 uint32_t value = osr_urgency_and_install_target();
1198 set_osr_urgency_and_install_target(OsrUrgencyBits::update(value, urgency));
1199}
1200
1201BytecodeArray::Age BytecodeArray::bytecode_age() const {
1202 // Bytecode is aged by the concurrent marker.
1203 static_assert(kBytecodeAgeSize == kUInt16Size);
1204 return static_cast<Age>(RELAXED_READ_INT16_FIELD(*this, kBytecodeAgeOffset));
1205}
1206
1207void BytecodeArray::reset_osr_urgency() { set_osr_urgency(0); }
1208
1209void BytecodeArray::RequestOsrAtNextOpportunity() {
1210 set_osr_urgency(kMaxOsrUrgency);
1211}
1212
1213int BytecodeArray::osr_install_target() {
1214 return OsrInstallTargetBits::decode(osr_urgency_and_install_target());
1215}
1216
1217void BytecodeArray::set_osr_install_target(BytecodeOffset jump_loop_offset) {
1218 DCHECK_LE(jump_loop_offset.ToInt(), length())((void) 0);
1219 set_osr_urgency_and_install_target(OsrInstallTargetBits::update(
1220 osr_urgency_and_install_target(), OsrInstallTargetFor(jump_loop_offset)));
1221}
1222
1223void BytecodeArray::reset_osr_install_target() {
1224 uint32_t value = osr_urgency_and_install_target();
1225 set_osr_urgency_and_install_target(
1226 OsrInstallTargetBits::update(value, kNoOsrInstallTarget));
1227}
1228
1229void BytecodeArray::reset_osr_urgency_and_install_target() {
1230 set_osr_urgency_and_install_target(OsrUrgencyBits::encode(0) |
1231 OsrInstallTargetBits::encode(0));
1232}
1233
1234void BytecodeArray::set_bytecode_age(BytecodeArray::Age age) {
1235 DCHECK_GE(age, kFirstBytecodeAge)((void) 0);
1236 DCHECK_LE(age, kLastBytecodeAge)((void) 0);
1237 static_assert(kLastBytecodeAge <= kMaxInt16);
1238 static_assert(kBytecodeAgeSize == kUInt16Size);
1239 // Bytecode is aged by the concurrent marker.
1240 RELAXED_WRITE_INT16_FIELD(*this, kBytecodeAgeOffset,
1241 static_cast<int16_t>(age));
1242}
1243
1244int32_t BytecodeArray::parameter_count() const {
1245 // Parameter count is stored as the size on stack of the parameters to allow
1246 // it to be used directly by generated code.
1247 return ReadField<int32_t>(kParameterSizeOffset) >> kSystemPointerSizeLog2;
1248}
1249
1250void BytecodeArray::clear_padding() {
1251 int data_size = kHeaderSize + length();
1252 memset(reinterpret_cast<void*>(address() + data_size), 0,
1253 SizeFor(length()) - data_size);
1254}
1255
1256Address BytecodeArray::GetFirstBytecodeAddress() {
1257 return ptr() - kHeapObjectTag + kHeaderSize;
1258}
1259
1260bool BytecodeArray::HasSourcePositionTable() const {
1261 Object maybe_table = source_position_table(kAcquireLoad);
1262 return !(maybe_table.IsUndefined() || DidSourcePositionGenerationFail());
1263}
1264
1265bool BytecodeArray::DidSourcePositionGenerationFail() const {
1266 return source_position_table(kAcquireLoad).IsException();
1267}
1268
1269void BytecodeArray::SetSourcePositionsFailedToCollect() {
1270 set_source_position_table(GetReadOnlyRoots().exception(), kReleaseStore);
1271}
1272
1273ByteArray BytecodeArray::SourcePositionTable() const {
1274 // WARNING: This function may be called from a background thread, hence
1275 // changes to how it accesses the heap can easily lead to bugs.
1276 Object maybe_table = source_position_table(kAcquireLoad);
1277 if (maybe_table.IsByteArray()) return ByteArray::cast(maybe_table);
1278 ReadOnlyRoots roots = GetReadOnlyRoots();
1279 DCHECK(maybe_table.IsUndefined(roots) || maybe_table.IsException(roots))((void) 0);
1280 return roots.empty_byte_array();
1281}
1282
1283int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); }
1284
1285int BytecodeArray::SizeIncludingMetadata() {
1286 int size = BytecodeArraySize();
1287 size += constant_pool().Size();
1288 size += handler_table().Size();
1289 ByteArray table = SourcePositionTable();
1290 if (table.length() != 0) {
1291 size += table.Size();
1292 }
1293 return size;
1294}
1295
1296DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, TranslationArray)
1297DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
1298DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, DeoptimizationLiteralArray)
1299DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
1300DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
1301DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
1302DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
1303DEFINE_DEOPT_ELEMENT_ACCESSORS(DeoptExitStart, Smi)
1304DEFINE_DEOPT_ELEMENT_ACCESSORS(EagerDeoptCount, Smi)
1305DEFINE_DEOPT_ELEMENT_ACCESSORS(LazyDeoptCount, Smi)
1306
1307DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
1308DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
1309DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
1310#ifdef DEBUG
1311DEFINE_DEOPT_ENTRY_ACCESSORS(NodeId, Smi)
1312#endif // DEBUG
1313
1314BytecodeOffset DeoptimizationData::GetBytecodeOffset(int i) {
1315 return BytecodeOffset(BytecodeOffsetRaw(i).value());
1316}
1317
1318void DeoptimizationData::SetBytecodeOffset(int i, BytecodeOffset value) {
1319 SetBytecodeOffsetRaw(i, Smi::FromInt(value.ToInt()));
1320}
1321
1322int DeoptimizationData::DeoptCount() {
1323 return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
1324}
1325
1326inline DeoptimizationLiteralArray::DeoptimizationLiteralArray(Address ptr)
1327 : WeakFixedArray(ptr) {
1328 // No type check is possible beyond that for WeakFixedArray.
1329}
1330
1331inline Object DeoptimizationLiteralArray::get(int index) const {
1332 return get(GetPtrComprCageBase(*this), index);
1333}
1334
1335inline Object DeoptimizationLiteralArray::get(PtrComprCageBase cage_base,
1336 int index) const {
1337 MaybeObject maybe = Get(cage_base, index);
1338
1339 // Slots in the DeoptimizationLiteralArray should only be cleared when there
1340 // is no possible code path that could need that slot. This works because the
1341 // weakly-held deoptimization literals are basically local variables that
1342 // TurboFan has decided not to keep on the stack. Thus, if the deoptimization
1343 // literal goes away, then whatever code needed it should be unreachable. The
1344 // exception is currently running Code: in that case, the deoptimization
1345 // literals array might be the only thing keeping the target object alive.
1346 // Thus, when a Code is running, we strongly mark all of its deoptimization
1347 // literals.
1348 CHECK(!maybe.IsCleared())do { if ((__builtin_expect(!!(!(!maybe.IsCleared())), 0))) { V8_Fatal
("Check failed: %s.", "!maybe.IsCleared()"); } } while (false
)
;
1349
1350 return maybe.GetHeapObjectOrSmi();
1351}
1352
1353inline void DeoptimizationLiteralArray::set(int index, Object value) {
1354 MaybeObject maybe = MaybeObject::FromObject(value);
1355 if (Code::IsWeakObjectInDeoptimizationLiteralArray(value)) {
1356 maybe = MaybeObject::MakeWeak(maybe);
1357 }
1358 Set(index, maybe);
1359}
1360
1361} // namespace internal
1362} // namespace v8
1363
1364#include "src/objects/object-macros-undef.h"
1365
1366#endif // V8_OBJECTS_CODE_INL_H_