File: | out/../deps/v8/src/objects/code-inl.h |
Warning: | line 945, column 10 Value stored to 'value' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
29 | namespace v8 { |
30 | namespace internal { |
31 | |
32 | #include "torque-generated/src/objects/code-tq-inl.inc" |
33 | |
34 | OBJECT_CONSTRUCTORS_IMPL(DeoptimizationData, FixedArray) |
35 | TQ_OBJECT_CONSTRUCTORS_IMPL(BytecodeArray) |
36 | OBJECT_CONSTRUCTORS_IMPL(AbstractCode, HeapObject) |
37 | OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakArrayList) |
38 | OBJECT_CONSTRUCTORS_IMPL(CodeDataContainer, HeapObject) |
39 | NEVER_READ_ONLY_SPACE_IMPL(CodeDataContainer) |
40 | |
41 | NEVER_READ_ONLY_SPACE_IMPL(AbstractCode) |
42 | |
43 | CAST_ACCESSOR(AbstractCode) |
44 | CAST_ACCESSOR(Code) |
45 | CAST_ACCESSOR(CodeDataContainer) |
46 | CAST_ACCESSOR(DependentCode) |
47 | CAST_ACCESSOR(DeoptimizationData) |
48 | CAST_ACCESSOR(DeoptimizationLiteralArray) |
49 | |
50 | int AbstractCode::raw_instruction_size() { |
51 | if (IsCode()) { |
52 | return GetCode().raw_instruction_size(); |
53 | } else { |
54 | return GetBytecodeArray().length(); |
55 | } |
56 | } |
57 | |
58 | int AbstractCode::InstructionSize() { |
59 | if (IsCode()) { |
60 | return GetCode().InstructionSize(); |
61 | } else { |
62 | return GetBytecodeArray().length(); |
63 | } |
64 | } |
65 | |
66 | ByteArray 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 | |
75 | ByteArray AbstractCode::SourcePositionTable(SharedFunctionInfo sfi) { |
76 | if (IsCode()) { |
77 | return GetCode().SourcePositionTable(sfi); |
78 | } else { |
79 | return GetBytecodeArray().SourcePositionTable(); |
80 | } |
81 | } |
82 | |
83 | int AbstractCode::SizeIncludingMetadata() { |
84 | if (IsCode()) { |
85 | return GetCode().SizeIncludingMetadata(); |
86 | } else { |
87 | return GetBytecodeArray().SizeIncludingMetadata(); |
88 | } |
89 | } |
90 | |
91 | Address AbstractCode::raw_instruction_start() { |
92 | if (IsCode()) { |
93 | return GetCode().raw_instruction_start(); |
94 | } else { |
95 | return GetBytecodeArray().GetFirstBytecodeAddress(); |
96 | } |
97 | } |
98 | |
99 | Address AbstractCode::InstructionStart() { |
100 | if (IsCode()) { |
101 | return GetCode().InstructionStart(); |
102 | } else { |
103 | return GetBytecodeArray().GetFirstBytecodeAddress(); |
104 | } |
105 | } |
106 | |
107 | Address 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 | |
116 | Address AbstractCode::InstructionEnd() { |
117 | if (IsCode()) { |
118 | return GetCode().InstructionEnd(); |
119 | } else { |
120 | return GetBytecodeArray().GetFirstBytecodeAddress() + |
121 | GetBytecodeArray().length(); |
122 | } |
123 | } |
124 | |
125 | bool 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 | |
135 | CodeKind AbstractCode::kind() { |
136 | return IsCode() ? GetCode().kind() : CodeKind::INTERPRETED_FUNCTION; |
137 | } |
138 | |
139 | Code AbstractCode::GetCode() { return Code::cast(*this); } |
140 | |
141 | BytecodeArray AbstractCode::GetBytecodeArray() { |
142 | return BytecodeArray::cast(*this); |
143 | } |
144 | |
145 | OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject) |
146 | NEVER_READ_ONLY_SPACE_IMPL(Code) |
147 | |
148 | INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset) |
149 | INT_ACCESSORS(Code, raw_metadata_size, kMetadataSizeOffset) |
150 | INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset) |
151 | INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset) |
152 | INT32_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 | |
200 | CODE_ACCESSORS(relocation_info, ByteArray, kRelocationInfoOffset) |
201 | |
202 | CODE_ACCESSORS_CHECKED2(deoptimization_data, FixedArray, |
203 | kDeoptimizationDataOrInterpreterDataOffset, |
204 | kind() != CodeKind::BASELINE, |
205 | kind() != CodeKind::BASELINE && |
206 | !ObjectInYoungGeneration(value)) |
207 | CODE_ACCESSORS_CHECKED2(bytecode_or_interpreter_data, HeapObject, |
208 | kDeoptimizationDataOrInterpreterDataOffset, |
209 | kind() == CodeKind::BASELINE, |
210 | kind() == CodeKind::BASELINE && |
211 | !ObjectInYoungGeneration(value)) |
212 | |
213 | CODE_ACCESSORS_CHECKED2(source_position_table, ByteArray, kPositionTableOffset, |
214 | kind() != CodeKind::BASELINE, |
215 | kind() != CodeKind::BASELINE && |
216 | !ObjectInYoungGeneration(value)) |
217 | CODE_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. |
223 | RELEASE_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 | |
230 | PtrComprCageBase 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 | |
239 | PtrComprCageBase 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 | |
249 | void 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 | |
258 | CodeDataContainer 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. |
271 | inline 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 | |
279 | inline 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 | |
287 | inline 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 | |
298 | inline Code FromCodeT(CodeT code) { |
299 | #ifdef V8_EXTERNAL_CODE_SPACE |
300 | return code.code(); |
301 | #else |
302 | return code; |
303 | #endif |
304 | } |
305 | |
306 | inline 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 | |
314 | inline 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 | |
322 | inline Handle<AbstractCode> ToAbstractCode(Handle<CodeT> code, |
323 | Isolate* isolate) { |
324 | return Handle<AbstractCode>::cast(FromCodeT(code, isolate)); |
325 | } |
326 | |
327 | inline 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 | |
335 | void 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 | |
346 | void 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 | |
359 | ByteArray 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 | |
367 | Object Code::next_code_link() const { |
368 | return code_data_container(kAcquireLoad).next_code_link(); |
369 | } |
370 | |
371 | void Code::set_next_code_link(Object value) { |
372 | code_data_container(kAcquireLoad).set_next_code_link(value); |
373 | } |
374 | |
375 | Address Code::raw_body_start() const { return raw_instruction_start(); } |
376 | |
377 | Address Code::raw_body_end() const { |
378 | return raw_body_start() + raw_body_size(); |
379 | } |
380 | |
381 | int Code::raw_body_size() const { |
382 | return raw_instruction_size() + raw_metadata_size(); |
383 | } |
384 | |
385 | int 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 | |
391 | Address Code::raw_instruction_start() const { |
392 | return field_address(kHeaderSize); |
393 | } |
394 | |
395 | Address 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 | |
401 | Address Code::raw_instruction_end() const { |
402 | return raw_instruction_start() + raw_instruction_size(); |
403 | } |
404 | |
405 | Address 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 | |
411 | Address Code::raw_metadata_start() const { |
412 | return raw_instruction_start() + raw_instruction_size(); |
413 | } |
414 | |
415 | Address 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 | |
421 | Address 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 | |
427 | int 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 | |
434 | Address Code::raw_metadata_end() const { |
435 | return raw_metadata_start() + raw_metadata_size(); |
436 | } |
437 | |
438 | int 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 | |
444 | int 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 | |
453 | Address 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 | |
459 | int 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 | |
464 | bool Code::has_safepoint_table() const { return safepoint_table_size() > 0; } |
465 | |
466 | Address 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 | |
472 | int 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 | |
477 | bool Code::has_handler_table() const { return handler_table_size() > 0; } |
478 | |
479 | int 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 | |
486 | bool Code::has_constant_pool() const { return constant_pool_size() > 0; } |
487 | |
488 | int 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 | |
493 | bool Code::has_code_comments() const { return code_comments_size() > 0; } |
494 | |
495 | ByteArray 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 | |
501 | byte* Code::relocation_start() const { |
502 | return unchecked_relocation_info().GetDataStartAddress(); |
503 | } |
504 | |
505 | byte* Code::relocation_end() const { |
506 | return unchecked_relocation_info().GetDataEndAddress(); |
507 | } |
508 | |
509 | int Code::relocation_size() const { |
510 | return unchecked_relocation_info().length(); |
511 | } |
512 | |
513 | Address Code::entry() const { return raw_instruction_start(); } |
514 | |
515 | bool 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 |
527 | void 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 | |
534 | int Code::CodeSize() const { return SizeFor(raw_body_size()); } |
535 | |
536 | DEF_GETTER(Code, Size, int) { return CodeSize(); } |
537 | |
538 | CodeKind 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 | |
544 | int 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 | |
557 | uintptr_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 | |
575 | uintptr_t Code::GetBaselineStartPCForBytecodeOffset(int bytecode_offset, |
576 | BytecodeArray bytecodes) { |
577 | return GetBaselinePCForBytecodeOffset(bytecode_offset, kPcAtStartOfBytecode, |
578 | bytecodes); |
579 | } |
580 | |
581 | uintptr_t Code::GetBaselineEndPCForBytecodeOffset(int bytecode_offset, |
582 | BytecodeArray bytecodes) { |
583 | return GetBaselinePCForBytecodeOffset(bytecode_offset, kPcAtEndOfBytecode, |
584 | bytecodes); |
585 | } |
586 | |
587 | uintptr_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 | |
607 | void 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 | |
621 | inline bool Code::is_interpreter_trampoline_builtin() const { |
622 | return IsInterpreterTrampolineBuiltin(builtin_id()); |
623 | } |
624 | |
625 | inline bool Code::is_baseline_trampoline_builtin() const { |
626 | return IsBaselineTrampolineBuiltin(builtin_id()); |
627 | } |
628 | |
629 | inline 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(). |
635 | inline 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(). |
646 | inline 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 | |
654 | inline 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 | |
659 | inline bool Code::is_turbofanned() const { |
660 | const uint32_t flags = RELAXED_READ_UINT32_FIELD(*this, kFlagsOffset); |
661 | return IsTurbofannedField::decode(flags); |
662 | } |
663 | |
664 | bool Code::is_maglevved() const { return kind() == CodeKind::MAGLEV; } |
665 | |
666 | inline 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 | |
673 | inline 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 | |
681 | inline 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 | |
688 | inline 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 | |
696 | inline 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 | |
701 | inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() { |
702 | if (is_promise_rejection()) return HandlerTable::PROMISE; |
703 | return HandlerTable::UNCAUGHT; |
704 | } |
705 | |
706 | Builtin 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 | |
713 | void 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 | |
719 | bool Code::is_builtin() const { return builtin_id() != Builtin::kNoBuiltinId; } |
720 | |
721 | unsigned 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 | |
727 | void 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 | |
732 | bool Code::uses_safepoint_table() const { |
733 | return is_turbofanned() || is_maglevved() || is_wasm_code(); |
734 | } |
735 | |
736 | int 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 | |
743 | bool 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 | |
753 | bool Code::marked_for_deoptimization() const { |
754 | DCHECK(CodeKindCanDeoptimize(kind()))((void) 0); |
755 | return code_data_container(kAcquireLoad).marked_for_deoptimization(); |
756 | } |
757 | |
758 | void 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 | |
770 | void Code::set_marked_for_deoptimization(bool flag) { |
771 | code_data_container(kAcquireLoad).set_marked_for_deoptimization(flag); |
772 | } |
773 | |
774 | bool 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 | |
781 | void 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 | |
790 | bool Code::is_optimized_code() const { |
791 | return CodeKindIsOptimizedJSFunction(kind()); |
792 | } |
793 | |
794 | bool Code::is_wasm_code() const { return kind() == CodeKind::WASM_FUNCTION; } |
795 | |
796 | int 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 | |
804 | void 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 | |
813 | Address 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 | |
820 | Address 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 | |
826 | Address 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 | |
832 | Address 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 | |
838 | int 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 | |
843 | bool Code::has_unwinding_info() const { return unwinding_info_size() > 0; } |
844 | |
845 | Code 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 | |
861 | Code 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 | |
869 | bool Code::CanContainWeakObjects() { |
870 | return is_optimized_code() && can_have_weak_objects(); |
871 | } |
872 | |
873 | bool Code::IsWeakObject(HeapObject object) { |
874 | return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object)); |
875 | } |
876 | |
877 | bool 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 | |
888 | bool 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 | |
897 | bool 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. |
904 | STATIC_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" ); |
906 | RELAXED_INT32_ACCESSORS(CodeDataContainer, kind_specific_flags, |
907 | kKindSpecificFlagsOffset) |
908 | |
909 | #if defined(V8_TARGET_LITTLE_ENDIAN1) |
910 | static_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) |
916 | static_assert(!V8_EXTERNAL_CODE_SPACE_BOOLfalse, |
917 | "CodeDataContainer::code field layout requires updating " |
918 | "for big endian architectures"); |
919 | #endif |
920 | |
921 | Object CodeDataContainer::raw_code() const { |
922 | PtrComprCageBase cage_base = code_cage_base(); |
923 | return CodeDataContainer::raw_code(cage_base); |
924 | } |
925 | |
926 | Object 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 | |
932 | void 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 | |
938 | Object CodeDataContainer::raw_code(RelaxedLoadTag tag) const { |
939 | PtrComprCageBase cage_base = code_cage_base(tag); |
940 | return CodeDataContainer::raw_code(cage_base, tag); |
941 | } |
942 | |
943 | Object 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 | |
951 | ACCESSORS(CodeDataContainer, next_code_link, Object, kNextCodeLinkOffset) |
952 | |
953 | PtrComprCageBase 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 | |
964 | void 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 | |
973 | PtrComprCageBase 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 | |
984 | void 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 | |
995 | void 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 | |
1000 | Code CodeDataContainer::code() const { |
1001 | PtrComprCageBase cage_base = code_cage_base(); |
1002 | return CodeDataContainer::code(cage_base); |
1003 | } |
1004 | Code 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 | |
1009 | Code CodeDataContainer::code(RelaxedLoadTag tag) const { |
1010 | PtrComprCageBase cage_base = code_cage_base(tag); |
1011 | return CodeDataContainer::code(cage_base, tag); |
1012 | } |
1013 | |
1014 | Code 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 | |
1020 | DEF_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 | |
1027 | void 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 | |
1033 | void 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 | |
1040 | void 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 | |
1047 | Address CodeDataContainer::InstructionStart() const { |
1048 | return code_entry_point(); |
1049 | } |
1050 | |
1051 | Address CodeDataContainer::raw_instruction_start() { |
1052 | return code_entry_point(); |
1053 | } |
1054 | |
1055 | Address CodeDataContainer::entry() const { return code_entry_point(); } |
1056 | |
1057 | void CodeDataContainer::clear_padding() { |
1058 | memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0, |
1059 | kSize - kUnalignedSize); |
1060 | } |
1061 | |
1062 | RELAXED_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. |
1067 | STATIC_ASSERT(static_cast<int>(Builtin::kNoBuiltinId) == -1)static_assert(static_cast<int>(Builtin::kNoBuiltinId) == -1, "static_cast<int>(Builtin::kNoBuiltinId) == -1"); |
1068 | STATIC_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 | |
1070 | void 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 | |
1080 | CodeKind CodeDataContainer::kind() const { |
1081 | return KindField::decode(flags(kRelaxedLoad)); |
1082 | } |
1083 | |
1084 | Builtin 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 | |
1094 | bool 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 | |
1099 | bool CodeDataContainer::is_optimized_code() const { |
1100 | return CodeKindIsOptimizedJSFunction(kind()); |
1101 | } |
1102 | |
1103 | inline 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 | |
1120 | DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_maglevved, bool) |
1121 | DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_turbofanned, bool) |
1122 | DEF_PRIMITIVE_FORWARDING_CDC_GETTER(is_off_heap_trampoline, bool) |
1123 | |
1124 | DEF_FORWARDING_CDC_GETTER(deoptimization_data, FixedArray) |
1125 | DEF_FORWARDING_CDC_GETTER(bytecode_or_interpreter_data, HeapObject) |
1126 | DEF_FORWARDING_CDC_GETTER(source_position_table, ByteArray) |
1127 | DEF_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 | |
1134 | byte BytecodeArray::get(int index) const { |
1135 | DCHECK(index >= 0 && index < this->length())((void) 0); |
1136 | return ReadField<byte>(kHeaderSize + index * kCharSize); |
1137 | } |
1138 | |
1139 | void BytecodeArray::set(int index, byte value) { |
1140 | DCHECK(index >= 0 && index < this->length())((void) 0); |
1141 | WriteField<byte>(kHeaderSize + index * kCharSize, value); |
1142 | } |
1143 | |
1144 | void 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 | |
1150 | int32_t BytecodeArray::frame_size() const { |
1151 | return ReadField<int32_t>(kFrameSizeOffset); |
1152 | } |
1153 | |
1154 | int BytecodeArray::register_count() const { |
1155 | return static_cast<int>(frame_size()) / kSystemPointerSize; |
1156 | } |
1157 | |
1158 | void 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 | |
1166 | interpreter::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 | |
1177 | void 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 | |
1190 | int BytecodeArray::osr_urgency() const { |
1191 | return OsrUrgencyBits::decode(osr_urgency_and_install_target()); |
1192 | } |
1193 | |
1194 | void 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 | |
1201 | BytecodeArray::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 | |
1207 | void BytecodeArray::reset_osr_urgency() { set_osr_urgency(0); } |
1208 | |
1209 | void BytecodeArray::RequestOsrAtNextOpportunity() { |
1210 | set_osr_urgency(kMaxOsrUrgency); |
1211 | } |
1212 | |
1213 | int BytecodeArray::osr_install_target() { |
1214 | return OsrInstallTargetBits::decode(osr_urgency_and_install_target()); |
1215 | } |
1216 | |
1217 | void 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 | |
1223 | void 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 | |
1229 | void BytecodeArray::reset_osr_urgency_and_install_target() { |
1230 | set_osr_urgency_and_install_target(OsrUrgencyBits::encode(0) | |
1231 | OsrInstallTargetBits::encode(0)); |
1232 | } |
1233 | |
1234 | void 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 | |
1244 | int32_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 | |
1250 | void 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 | |
1256 | Address BytecodeArray::GetFirstBytecodeAddress() { |
1257 | return ptr() - kHeapObjectTag + kHeaderSize; |
1258 | } |
1259 | |
1260 | bool BytecodeArray::HasSourcePositionTable() const { |
1261 | Object maybe_table = source_position_table(kAcquireLoad); |
1262 | return !(maybe_table.IsUndefined() || DidSourcePositionGenerationFail()); |
1263 | } |
1264 | |
1265 | bool BytecodeArray::DidSourcePositionGenerationFail() const { |
1266 | return source_position_table(kAcquireLoad).IsException(); |
1267 | } |
1268 | |
1269 | void BytecodeArray::SetSourcePositionsFailedToCollect() { |
1270 | set_source_position_table(GetReadOnlyRoots().exception(), kReleaseStore); |
1271 | } |
1272 | |
1273 | ByteArray 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 | |
1283 | int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); } |
1284 | |
1285 | int 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 | |
1296 | DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, TranslationArray) |
1297 | DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi) |
1298 | DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, DeoptimizationLiteralArray) |
1299 | DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi) |
1300 | DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi) |
1301 | DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi) |
1302 | DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>) |
1303 | DEFINE_DEOPT_ELEMENT_ACCESSORS(DeoptExitStart, Smi) |
1304 | DEFINE_DEOPT_ELEMENT_ACCESSORS(EagerDeoptCount, Smi) |
1305 | DEFINE_DEOPT_ELEMENT_ACCESSORS(LazyDeoptCount, Smi) |
1306 | |
1307 | DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi) |
1308 | DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi) |
1309 | DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi) |
1310 | #ifdef DEBUG |
1311 | DEFINE_DEOPT_ENTRY_ACCESSORS(NodeId, Smi) |
1312 | #endif // DEBUG |
1313 | |
1314 | BytecodeOffset DeoptimizationData::GetBytecodeOffset(int i) { |
1315 | return BytecodeOffset(BytecodeOffsetRaw(i).value()); |
1316 | } |
1317 | |
1318 | void DeoptimizationData::SetBytecodeOffset(int i, BytecodeOffset value) { |
1319 | SetBytecodeOffsetRaw(i, Smi::FromInt(value.ToInt())); |
1320 | } |
1321 | |
1322 | int DeoptimizationData::DeoptCount() { |
1323 | return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize; |
1324 | } |
1325 | |
1326 | inline DeoptimizationLiteralArray::DeoptimizationLiteralArray(Address ptr) |
1327 | : WeakFixedArray(ptr) { |
1328 | // No type check is possible beyond that for WeakFixedArray. |
1329 | } |
1330 | |
1331 | inline Object DeoptimizationLiteralArray::get(int index) const { |
1332 | return get(GetPtrComprCageBase(*this), index); |
1333 | } |
1334 | |
1335 | inline 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 | |
1353 | inline 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_ |