Line data Source code
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_H_
6 : #define V8_OBJECTS_CODE_H_
7 :
8 : #include "src/contexts.h"
9 : #include "src/handler-table.h"
10 : #include "src/objects.h"
11 : #include "src/objects/fixed-array.h"
12 : #include "src/objects/heap-object.h"
13 : #include "src/objects/struct.h"
14 :
15 : // Has to be the last include (doesn't have include guards):
16 : #include "src/objects/object-macros.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 :
21 : class ByteArray;
22 : class BytecodeArray;
23 : class CodeDataContainer;
24 : class CodeDesc;
25 : class MaybeObject;
26 :
27 : namespace interpreter {
28 : class Register;
29 : }
30 :
31 : // Code describes objects with on-the-fly generated machine code.
32 : class Code : public HeapObject {
33 : public:
34 : NEVER_READ_ONLY_SPACE
35 : // Opaque data type for encapsulating code flags like kind, inline
36 : // cache state, and arguments count.
37 : using Flags = uint32_t;
38 :
39 : #define CODE_KIND_LIST(V) \
40 : V(OPTIMIZED_FUNCTION) \
41 : V(BYTECODE_HANDLER) \
42 : V(STUB) \
43 : V(BUILTIN) \
44 : V(REGEXP) \
45 : V(WASM_FUNCTION) \
46 : V(WASM_TO_JS_FUNCTION) \
47 : V(JS_TO_WASM_FUNCTION) \
48 : V(WASM_INTERPRETER_ENTRY) \
49 : V(C_WASM_ENTRY)
50 :
51 : enum Kind {
52 : #define DEFINE_CODE_KIND_ENUM(name) name,
53 : CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
54 : #undef DEFINE_CODE_KIND_ENUM
55 : NUMBER_OF_KINDS
56 : };
57 :
58 : static const char* Kind2String(Kind kind);
59 :
60 : #ifdef ENABLE_DISASSEMBLER
61 : const char* GetName(Isolate* isolate) const;
62 : V8_EXPORT_PRIVATE void Disassemble(const char* name, std::ostream& os,
63 : Address current_pc = kNullAddress);
64 : #endif
65 :
66 : // [instruction_size]: Size of the native instructions, including embedded
67 : // data such as the safepoints table.
68 : inline int raw_instruction_size() const;
69 : inline void set_raw_instruction_size(int value);
70 :
71 : // Returns the size of the native instructions, including embedded
72 : // data such as the safepoints table. For off-heap code objects
73 : // this may differ from instruction_size in that this will return the size of
74 : // the off-heap instruction stream rather than the on-heap trampoline located
75 : // at instruction_start.
76 : inline int InstructionSize() const;
77 : V8_EXPORT_PRIVATE int OffHeapInstructionSize() const;
78 :
79 : // [relocation_info]: Code relocation information
80 : DECL_ACCESSORS(relocation_info, ByteArray)
81 :
82 : // This function should be called only from GC.
83 : void ClearEmbeddedObjects(Heap* heap);
84 :
85 : // [deoptimization_data]: Array containing data for deopt.
86 : DECL_ACCESSORS(deoptimization_data, FixedArray)
87 :
88 : // [source_position_table]: ByteArray for the source positions table or
89 : // SourcePositionTableWithFrameCache.
90 : DECL_ACCESSORS(source_position_table, Object)
91 : inline ByteArray SourcePositionTable() const;
92 : inline ByteArray SourcePositionTableIfCollected() const;
93 :
94 : // [code_data_container]: A container indirection for all mutable fields.
95 : DECL_ACCESSORS(code_data_container, CodeDataContainer)
96 :
97 : // [next_code_link]: Link for lists of optimized or deoptimized code.
98 : // Note that this field is stored in the {CodeDataContainer} to be mutable.
99 : inline Object next_code_link() const;
100 : inline void set_next_code_link(Object value);
101 :
102 : // Unchecked accessors to be used during GC.
103 : inline ByteArray unchecked_relocation_info() const;
104 :
105 : inline int relocation_size() const;
106 :
107 : // [kind]: Access to specific code kind.
108 : inline Kind kind() const;
109 :
110 : inline bool is_optimized_code() const;
111 : inline bool is_wasm_code() const;
112 :
113 : // Testers for interpreter builtins.
114 : inline bool is_interpreter_trampoline_builtin() const;
115 :
116 : // Tells whether the code checks the optimization marker in the function's
117 : // feedback vector.
118 : inline bool checks_optimization_marker() const;
119 :
120 : // Tells whether the outgoing parameters of this code are tagged pointers.
121 : inline bool has_tagged_params() const;
122 :
123 : // [is_turbofanned]: For kind STUB or OPTIMIZED_FUNCTION, tells whether the
124 : // code object was generated by the TurboFan optimizing compiler.
125 : inline bool is_turbofanned() const;
126 :
127 : // [can_have_weak_objects]: For kind OPTIMIZED_FUNCTION, tells whether the
128 : // embedded objects in code should be treated weakly.
129 : inline bool can_have_weak_objects() const;
130 : inline void set_can_have_weak_objects(bool value);
131 :
132 : // [builtin_index]: For builtins, tells which builtin index the code object
133 : // has. The builtin index is a non-negative integer for builtins, and -1
134 : // otherwise.
135 : inline int builtin_index() const;
136 : inline void set_builtin_index(int id);
137 : inline bool is_builtin() const;
138 :
139 : inline bool has_safepoint_info() const;
140 :
141 : // [stack_slots]: If {has_safepoint_info()}, the number of stack slots
142 : // reserved in the code prologue.
143 : inline int stack_slots() const;
144 :
145 : // [safepoint_table_offset]: If {has_safepoint_info()}, the offset in the
146 : // instruction stream where the safepoint table starts.
147 : inline int safepoint_table_offset() const;
148 : inline void set_safepoint_table_offset(int offset);
149 : int safepoint_table_size() const;
150 : bool has_safepoint_table() const;
151 :
152 : // [handler_table_offset]: The offset in the instruction stream where the
153 : // exception handler table starts.
154 : inline int handler_table_offset() const;
155 : inline void set_handler_table_offset(int offset);
156 : int handler_table_size() const;
157 : bool has_handler_table() const;
158 :
159 : // [constant_pool offset]: Offset of the constant pool.
160 : // Valid for FLAG_enable_embedded_constant_pool only
161 : inline int constant_pool_offset() const;
162 : inline void set_constant_pool_offset(int offset);
163 : int constant_pool_size() const;
164 : bool has_constant_pool() const;
165 :
166 : // [code_comments_offset]: Offset of the code comment section.
167 : inline int code_comments_offset() const;
168 : inline void set_code_comments_offset(int offset);
169 : inline Address code_comments() const;
170 : V8_EXPORT_PRIVATE int code_comments_size() const;
171 : V8_EXPORT_PRIVATE bool has_code_comments() const;
172 :
173 : // The size of the executable instruction area, without embedded metadata.
174 : int ExecutableInstructionSize() const;
175 :
176 : // [marked_for_deoptimization]: For kind OPTIMIZED_FUNCTION tells whether
177 : // the code is going to be deoptimized.
178 : inline bool marked_for_deoptimization() const;
179 : inline void set_marked_for_deoptimization(bool flag);
180 :
181 : // [embedded_objects_cleared]: For kind OPTIMIZED_FUNCTION tells whether
182 : // the embedded objects in the code marked for deoptimization were cleared.
183 : // Note that embedded_objects_cleared() implies marked_for_deoptimization().
184 : inline bool embedded_objects_cleared() const;
185 : inline void set_embedded_objects_cleared(bool flag);
186 :
187 : // [deopt_already_counted]: For kind OPTIMIZED_FUNCTION tells whether
188 : // the code was already deoptimized.
189 : inline bool deopt_already_counted() const;
190 : inline void set_deopt_already_counted(bool flag);
191 :
192 : // [is_promise_rejection]: For kind BUILTIN tells whether the
193 : // exception thrown by the code will lead to promise rejection or
194 : // uncaught if both this and is_exception_caught is set.
195 : // Use GetBuiltinCatchPrediction to access this.
196 : inline void set_is_promise_rejection(bool flag);
197 :
198 : // [is_exception_caught]: For kind BUILTIN tells whether the
199 : // exception thrown by the code will be caught internally or
200 : // uncaught if both this and is_promise_rejection is set.
201 : // Use GetBuiltinCatchPrediction to access this.
202 : inline void set_is_exception_caught(bool flag);
203 :
204 : // [is_off_heap_trampoline]: For kind BUILTIN tells whether
205 : // this is a trampoline to an off-heap builtin.
206 : inline bool is_off_heap_trampoline() const;
207 :
208 : // [constant_pool]: The constant pool for this function.
209 : inline Address constant_pool() const;
210 :
211 : // Get the safepoint entry for the given pc.
212 : SafepointEntry GetSafepointEntry(Address pc);
213 :
214 : // The entire code object including its header is copied verbatim to the
215 : // snapshot so that it can be written in one, fast, memcpy during
216 : // deserialization. The deserializer will overwrite some pointers, rather
217 : // like a runtime linker, but the random allocation addresses used in the
218 : // mksnapshot process would still be present in the unlinked snapshot data,
219 : // which would make snapshot production non-reproducible. This method wipes
220 : // out the to-be-overwritten header data for reproducible snapshots.
221 : inline void WipeOutHeader();
222 :
223 : // Clear uninitialized padding space. This ensures that the snapshot content
224 : // is deterministic. Depending on the V8 build mode there could be no padding.
225 : inline void clear_padding();
226 : // Initialize the flags field. Similar to clear_padding above this ensure that
227 : // the snapshot content is deterministic.
228 : inline void initialize_flags(Kind kind, bool has_unwinding_info,
229 : bool is_turbofanned, int stack_slots,
230 : bool is_off_heap_trampoline);
231 :
232 : // Convert a target address into a code object.
233 : static inline Code GetCodeFromTargetAddress(Address address);
234 :
235 : // Convert an entry address into an object.
236 : static inline Code GetObjectFromEntryAddress(Address location_of_address);
237 :
238 : // Returns the address of the first instruction.
239 : inline Address raw_instruction_start() const;
240 :
241 : // Returns the address of the first instruction. For off-heap code objects
242 : // this differs from instruction_start (which would point to the off-heap
243 : // trampoline instead).
244 : inline Address InstructionStart() const;
245 : V8_EXPORT_PRIVATE Address OffHeapInstructionStart() const;
246 :
247 : // Returns the address right after the last instruction.
248 : inline Address raw_instruction_end() const;
249 :
250 : // Returns the address right after the last instruction. For off-heap code
251 : // objects this differs from instruction_end (which would point to the
252 : // off-heap trampoline instead).
253 : inline Address InstructionEnd() const;
254 : V8_EXPORT_PRIVATE Address OffHeapInstructionEnd() const;
255 :
256 : // Returns the size of the instructions, padding, relocation and unwinding
257 : // information.
258 : inline int body_size() const;
259 :
260 : // Returns the size of code and its metadata. This includes the size of code
261 : // relocation information, deoptimization data and handler table.
262 : inline int SizeIncludingMetadata() const;
263 :
264 : // Returns the address of the first relocation info (read backwards!).
265 : inline byte* relocation_start() const;
266 :
267 : // Returns the address right after the relocation info (read backwards!).
268 : inline byte* relocation_end() const;
269 :
270 : // [has_unwinding_info]: Whether this code object has unwinding information.
271 : // If it doesn't, unwinding_information_start() will point to invalid data.
272 : //
273 : // The body of all code objects has the following layout.
274 : //
275 : // +--------------------------+ <-- raw_instruction_start()
276 : // | instructions |
277 : // | ... |
278 : // +--------------------------+
279 : // | embedded metadata | <-- safepoint_table_offset()
280 : // | ... | <-- handler_table_offset()
281 : // | | <-- constant_pool_offset()
282 : // | | <-- code_comments_offset()
283 : // | |
284 : // +--------------------------+ <-- raw_instruction_end()
285 : //
286 : // If has_unwinding_info() is false, raw_instruction_end() points to the first
287 : // memory location after the end of the code object. Otherwise, the body
288 : // continues as follows:
289 : //
290 : // +--------------------------+
291 : // | padding to the next |
292 : // | 8-byte aligned address |
293 : // +--------------------------+ <-- raw_instruction_end()
294 : // | [unwinding_info_size] |
295 : // | as uint64_t |
296 : // +--------------------------+ <-- unwinding_info_start()
297 : // | unwinding info |
298 : // | ... |
299 : // +--------------------------+ <-- unwinding_info_end()
300 : //
301 : // and unwinding_info_end() points to the first memory location after the end
302 : // of the code object.
303 : //
304 : inline bool has_unwinding_info() const;
305 :
306 : // [unwinding_info_size]: Size of the unwinding information.
307 : inline int unwinding_info_size() const;
308 : inline void set_unwinding_info_size(int value);
309 :
310 : // Returns the address of the unwinding information, if any.
311 : inline Address unwinding_info_start() const;
312 :
313 : // Returns the address right after the end of the unwinding information.
314 : inline Address unwinding_info_end() const;
315 :
316 : // Code entry point.
317 : inline Address entry() const;
318 :
319 : // Returns true if pc is inside this object's instructions.
320 : inline bool contains(Address pc);
321 :
322 : // Relocate the code by delta bytes. Called to signal that this code
323 : // object has been moved by delta bytes.
324 : void Relocate(intptr_t delta);
325 :
326 : // Migrate code from desc without flushing the instruction cache.
327 : void CopyFromNoFlush(Heap* heap, const CodeDesc& desc);
328 :
329 : // Copy the RelocInfo portion of |desc| to |dest|. The ByteArray must be
330 : // exactly the same size as the RelocInfo in |desc|.
331 : static inline void CopyRelocInfoToByteArray(ByteArray dest,
332 : const CodeDesc& desc);
333 :
334 : // Flushes the instruction cache for the executable instructions of this code
335 : // object. Make sure to call this while the code is still writable.
336 : void FlushICache() const;
337 :
338 : // Returns the object size for a given body (used for allocation).
339 : static int SizeFor(int body_size) {
340 : DCHECK_SIZE_TAG_ALIGNED(body_size);
341 434548080 : return RoundUp(kHeaderSize + body_size, kCodeAlignment);
342 : }
343 :
344 : // Calculate the size of the code object to report for log events. This takes
345 : // the layout of the code object into account.
346 : inline int ExecutableSize() const;
347 :
348 : DECL_CAST(Code)
349 :
350 : // Dispatched behavior.
351 : inline int CodeSize() const;
352 :
353 : DECL_PRINTER(Code)
354 : DECL_VERIFIER(Code)
355 :
356 : void PrintDeoptLocation(FILE* out, const char* str, Address pc);
357 : bool CanDeoptAt(Address pc);
358 :
359 : void SetMarkedForDeoptimization(const char* reason);
360 :
361 : inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction();
362 :
363 : bool IsIsolateIndependent(Isolate* isolate);
364 :
365 : inline bool CanContainWeakObjects();
366 :
367 : inline bool IsWeakObject(HeapObject object);
368 :
369 : static inline bool IsWeakObjectInOptimizedCode(HeapObject object);
370 :
371 : // Return true if the function is inlined in the code.
372 : bool Inlines(SharedFunctionInfo sfi);
373 :
374 : class OptimizedCodeIterator;
375 :
376 : // Layout description.
377 : #define CODE_FIELDS(V) \
378 : V(kRelocationInfoOffset, kTaggedSize) \
379 : V(kDeoptimizationDataOffset, kTaggedSize) \
380 : V(kSourcePositionTableOffset, kTaggedSize) \
381 : V(kCodeDataContainerOffset, kTaggedSize) \
382 : /* Data or code not directly visited by GC directly starts here. */ \
383 : /* The serializer needs to copy bytes starting from here verbatim. */ \
384 : /* Objects embedded into code is visited via reloc info. */ \
385 : V(kDataStart, 0) \
386 : V(kInstructionSizeOffset, kIntSize) \
387 : V(kFlagsOffset, kIntSize) \
388 : V(kSafepointTableOffsetOffset, kIntSize) \
389 : V(kHandlerTableOffsetOffset, kIntSize) \
390 : V(kConstantPoolOffsetOffset, \
391 : FLAG_enable_embedded_constant_pool ? kIntSize : 0) \
392 : V(kCodeCommentsOffsetOffset, kIntSize) \
393 : V(kBuiltinIndexOffset, kIntSize) \
394 : V(kUnalignedHeaderSize, 0) \
395 : /* Add padding to align the instruction start following right after */ \
396 : /* the Code object header. */ \
397 : V(kOptionalPaddingOffset, CODE_POINTER_PADDING(kOptionalPaddingOffset)) \
398 : V(kHeaderSize, 0)
399 :
400 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CODE_FIELDS)
401 : #undef CODE_FIELDS
402 :
403 : // This documents the amount of free space we have in each Code object header
404 : // due to padding for code alignment.
405 : #if V8_TARGET_ARCH_ARM64
406 : static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 20 : 0;
407 : #elif V8_TARGET_ARCH_MIPS64
408 : static constexpr int kHeaderPaddingSize = 0;
409 : #elif V8_TARGET_ARCH_X64
410 : static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 20 : 0;
411 : #elif V8_TARGET_ARCH_ARM
412 : static constexpr int kHeaderPaddingSize = 20;
413 : #elif V8_TARGET_ARCH_IA32
414 : static constexpr int kHeaderPaddingSize = 20;
415 : #elif V8_TARGET_ARCH_MIPS
416 : static constexpr int kHeaderPaddingSize = 20;
417 : #elif V8_TARGET_ARCH_PPC64
418 : static constexpr int kHeaderPaddingSize =
419 : FLAG_enable_embedded_constant_pool ? 28 : 0;
420 : #elif V8_TARGET_ARCH_S390X
421 : static constexpr int kHeaderPaddingSize = 0;
422 : #else
423 : #error Unknown architecture.
424 : #endif
425 : STATIC_ASSERT(FIELD_SIZE(kOptionalPaddingOffset) == kHeaderPaddingSize);
426 :
427 : inline int GetUnwindingInfoSizeOffset() const;
428 :
429 : class BodyDescriptor;
430 :
431 : // Flags layout. BitField<type, shift, size>.
432 : #define CODE_FLAGS_BIT_FIELDS(V, _) \
433 : V(HasUnwindingInfoField, bool, 1, _) \
434 : V(KindField, Kind, 5, _) \
435 : V(IsTurbofannedField, bool, 1, _) \
436 : V(StackSlotsField, int, 24, _) \
437 : V(IsOffHeapTrampoline, bool, 1, _)
438 : DEFINE_BIT_FIELDS(CODE_FLAGS_BIT_FIELDS)
439 : #undef CODE_FLAGS_BIT_FIELDS
440 : static_assert(NUMBER_OF_KINDS <= KindField::kMax, "Code::KindField size");
441 : static_assert(IsOffHeapTrampoline::kNext <= 32,
442 : "Code::flags field exhausted");
443 :
444 : // KindSpecificFlags layout (STUB, BUILTIN and OPTIMIZED_FUNCTION)
445 : #define CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS(V, _) \
446 : V(MarkedForDeoptimizationField, bool, 1, _) \
447 : V(EmbeddedObjectsClearedField, bool, 1, _) \
448 : V(DeoptAlreadyCountedField, bool, 1, _) \
449 : V(CanHaveWeakObjectsField, bool, 1, _) \
450 : V(IsPromiseRejectionField, bool, 1, _) \
451 : V(IsExceptionCaughtField, bool, 1, _)
452 : DEFINE_BIT_FIELDS(CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS)
453 : #undef CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS
454 : static_assert(IsExceptionCaughtField::kNext <= 32, "KindSpecificFlags full");
455 :
456 : // The {marked_for_deoptimization} field is accessed from generated code.
457 : static const int kMarkedForDeoptimizationBit =
458 : MarkedForDeoptimizationField::kShift;
459 :
460 : static const int kArgumentsBits = 16;
461 : // Reserve one argument count value as the "don't adapt arguments" sentinel.
462 : static const int kMaxArguments = (1 << kArgumentsBits) - 2;
463 :
464 : private:
465 : friend class RelocIterator;
466 :
467 : bool is_promise_rejection() const;
468 : bool is_exception_caught() const;
469 :
470 131607 : OBJECT_CONSTRUCTORS(Code, HeapObject);
471 : };
472 :
473 : class Code::OptimizedCodeIterator {
474 : public:
475 : explicit OptimizedCodeIterator(Isolate* isolate);
476 : Code Next();
477 :
478 : private:
479 : Context next_context_;
480 : Code current_code_;
481 : Isolate* isolate_;
482 :
483 : DISALLOW_HEAP_ALLOCATION(no_gc)
484 : DISALLOW_COPY_AND_ASSIGN(OptimizedCodeIterator);
485 : };
486 :
487 : // CodeDataContainer is a container for all mutable fields associated with its
488 : // referencing {Code} object. Since {Code} objects reside on write-protected
489 : // pages within the heap, its header fields need to be immutable. There always
490 : // is a 1-to-1 relation between {Code} and {CodeDataContainer}, the referencing
491 : // field {Code::code_data_container} itself is immutable.
492 : class CodeDataContainer : public HeapObject {
493 : public:
494 : NEVER_READ_ONLY_SPACE
495 : DECL_ACCESSORS(next_code_link, Object)
496 : DECL_INT_ACCESSORS(kind_specific_flags)
497 :
498 : // Clear uninitialized padding space. This ensures that the snapshot content
499 : // is deterministic.
500 : inline void clear_padding();
501 :
502 : DECL_CAST(CodeDataContainer)
503 :
504 : // Dispatched behavior.
505 : DECL_PRINTER(CodeDataContainer)
506 : DECL_VERIFIER(CodeDataContainer)
507 :
508 : // Layout description.
509 : #define CODE_DATA_FIELDS(V) \
510 : /* Weak pointer fields. */ \
511 : V(kPointerFieldsStrongEndOffset, 0) \
512 : V(kNextCodeLinkOffset, kTaggedSize) \
513 : V(kPointerFieldsWeakEndOffset, 0) \
514 : /* Raw data fields. */ \
515 : V(kKindSpecificFlagsOffset, kIntSize) \
516 : V(kUnalignedSize, OBJECT_POINTER_PADDING(kUnalignedSize)) \
517 : /* Total size. */ \
518 : V(kSize, 0)
519 :
520 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CODE_DATA_FIELDS)
521 : #undef CODE_DATA_FIELDS
522 :
523 : class BodyDescriptor;
524 :
525 : OBJECT_CONSTRUCTORS(CodeDataContainer, HeapObject);
526 : };
527 :
528 : class AbstractCode : public HeapObject {
529 : public:
530 : NEVER_READ_ONLY_SPACE
531 : // All code kinds and INTERPRETED_FUNCTION.
532 : enum Kind {
533 : #define DEFINE_CODE_KIND_ENUM(name) name,
534 : CODE_KIND_LIST(DEFINE_CODE_KIND_ENUM)
535 : #undef DEFINE_CODE_KIND_ENUM
536 : INTERPRETED_FUNCTION,
537 : NUMBER_OF_KINDS
538 : };
539 :
540 : static const char* Kind2String(Kind kind);
541 :
542 : int SourcePosition(int offset);
543 : int SourceStatementPosition(int offset);
544 :
545 : // Returns the address of the first instruction.
546 : inline Address raw_instruction_start();
547 :
548 : // Returns the address of the first instruction. For off-heap code objects
549 : // this differs from instruction_start (which would point to the off-heap
550 : // trampoline instead).
551 : inline Address InstructionStart();
552 :
553 : // Returns the address right after the last instruction.
554 : inline Address raw_instruction_end();
555 :
556 : // Returns the address right after the last instruction. For off-heap code
557 : // objects this differs from instruction_end (which would point to the
558 : // off-heap trampoline instead).
559 : inline Address InstructionEnd();
560 :
561 : // Returns the size of the code instructions.
562 : inline int raw_instruction_size();
563 :
564 : // Returns the size of the native instructions, including embedded
565 : // data such as the safepoints table. For off-heap code objects
566 : // this may differ from instruction_size in that this will return the size of
567 : // the off-heap instruction stream rather than the on-heap trampoline located
568 : // at instruction_start.
569 : inline int InstructionSize();
570 :
571 : // Return the source position table.
572 : inline ByteArray source_position_table();
573 :
574 : inline Object stack_frame_cache();
575 : static void SetStackFrameCache(Handle<AbstractCode> abstract_code,
576 : Handle<SimpleNumberDictionary> cache);
577 : void DropStackFrameCache();
578 :
579 : // Returns the size of instructions and the metadata.
580 : inline int SizeIncludingMetadata();
581 :
582 : // Returns true if pc is inside this object's instructions.
583 : inline bool contains(Address pc);
584 :
585 : // Returns the AbstractCode::Kind of the code.
586 : inline Kind kind();
587 :
588 : // Calculate the size of the code object to report for log events. This takes
589 : // the layout of the code object into account.
590 : inline int ExecutableSize();
591 :
592 : DECL_CAST(AbstractCode)
593 : inline Code GetCode();
594 : inline BytecodeArray GetBytecodeArray();
595 :
596 : // Max loop nesting marker used to postpose OSR. We don't take loop
597 : // nesting that is deeper than 5 levels into account.
598 : static const int kMaxLoopNestingMarker = 6;
599 :
600 : OBJECT_CONSTRUCTORS(AbstractCode, HeapObject);
601 : };
602 :
603 : // Dependent code is a singly linked list of weak fixed arrays. Each array
604 : // contains weak pointers to code objects for one dependent group. The suffix of
605 : // the array can be filled with the undefined value if the number of codes is
606 : // less than the length of the array.
607 : //
608 : // +------+-----------------+--------+--------+-----+--------+-----------+-----+
609 : // | next | count & group 1 | code 1 | code 2 | ... | code n | undefined | ... |
610 : // +------+-----------------+--------+--------+-----+--------+-----------+-----+
611 : // |
612 : // V
613 : // +------+-----------------+--------+--------+-----+--------+-----------+-----+
614 : // | next | count & group 2 | code 1 | code 2 | ... | code m | undefined | ... |
615 : // +------+-----------------+--------+--------+-----+--------+-----------+-----+
616 : // |
617 : // V
618 : // empty_weak_fixed_array()
619 : //
620 : // The list of weak fixed arrays is ordered by dependency groups.
621 :
622 : class DependentCode : public WeakFixedArray {
623 : public:
624 : DECL_CAST(DependentCode)
625 :
626 : enum DependencyGroup {
627 : // Group of code that embed a transition to this map, and depend on being
628 : // deoptimized when the transition is replaced by a new version.
629 : kTransitionGroup,
630 : // Group of code that omit run-time prototype checks for prototypes
631 : // described by this map. The group is deoptimized whenever an object
632 : // described by this map changes shape (and transitions to a new map),
633 : // possibly invalidating the assumptions embedded in the code.
634 : kPrototypeCheckGroup,
635 : // Group of code that depends on global property values in property cells
636 : // not being changed.
637 : kPropertyCellChangedGroup,
638 : // Group of code that omit run-time checks for field(s) introduced by
639 : // this map, i.e. for the field type.
640 : kFieldOwnerGroup,
641 : // Group of code that omit run-time type checks for initial maps of
642 : // constructors.
643 : kInitialMapChangedGroup,
644 : // Group of code that depends on tenuring information in AllocationSites
645 : // not being changed.
646 : kAllocationSiteTenuringChangedGroup,
647 : // Group of code that depends on element transition information in
648 : // AllocationSites not being changed.
649 : kAllocationSiteTransitionChangedGroup
650 : };
651 :
652 : // Register a code dependency of {cell} on {object}.
653 : V8_EXPORT_PRIVATE static void InstallDependency(Isolate* isolate,
654 : const MaybeObjectHandle& code,
655 : Handle<HeapObject> object,
656 : DependencyGroup group);
657 :
658 : void DeoptimizeDependentCodeGroup(Isolate* isolate, DependencyGroup group);
659 :
660 : bool MarkCodeForDeoptimization(Isolate* isolate, DependencyGroup group);
661 :
662 : // The following low-level accessors are exposed only for tests.
663 : inline DependencyGroup group();
664 : inline MaybeObject object_at(int i);
665 : inline int count();
666 : inline DependentCode next_link();
667 :
668 : private:
669 : static const char* DependencyGroupName(DependencyGroup group);
670 :
671 : // Get/Set {object}'s {DependentCode}.
672 : static DependentCode GetDependentCode(Handle<HeapObject> object);
673 : static void SetDependentCode(Handle<HeapObject> object,
674 : Handle<DependentCode> dep);
675 :
676 : static Handle<DependentCode> New(Isolate* isolate, DependencyGroup group,
677 : const MaybeObjectHandle& object,
678 : Handle<DependentCode> next);
679 : static Handle<DependentCode> EnsureSpace(Isolate* isolate,
680 : Handle<DependentCode> entries);
681 : static Handle<DependentCode> InsertWeakCode(Isolate* isolate,
682 : Handle<DependentCode> entries,
683 : DependencyGroup group,
684 : const MaybeObjectHandle& code);
685 :
686 : // Compact by removing cleared weak cells and return true if there was
687 : // any cleared weak cell.
688 : bool Compact();
689 :
690 : static int Grow(int number_of_entries) {
691 59914 : if (number_of_entries < 5) return number_of_entries + 1;
692 21415 : return number_of_entries * 5 / 4;
693 : }
694 :
695 : static const int kGroupCount = kAllocationSiteTransitionChangedGroup + 1;
696 : static const int kNextLinkIndex = 0;
697 : static const int kFlagsIndex = 1;
698 : static const int kCodesStartIndex = 2;
699 :
700 : inline void set_next_link(DependentCode next);
701 : inline void set_count(int value);
702 : inline void set_object_at(int i, MaybeObject object);
703 : inline void clear_at(int i);
704 : inline void copy(int from, int to);
705 :
706 : inline int flags();
707 : inline void set_flags(int flags);
708 : class GroupField : public BitField<int, 0, 3> {};
709 : class CountField : public BitField<int, 3, 27> {};
710 : STATIC_ASSERT(kGroupCount <= GroupField::kMax + 1);
711 :
712 : OBJECT_CONSTRUCTORS(DependentCode, WeakFixedArray);
713 : };
714 :
715 : // BytecodeArray represents a sequence of interpreter bytecodes.
716 : class BytecodeArray : public FixedArrayBase {
717 : public:
718 : enum Age {
719 : kNoAgeBytecodeAge = 0,
720 : kQuadragenarianBytecodeAge,
721 : kQuinquagenarianBytecodeAge,
722 : kSexagenarianBytecodeAge,
723 : kSeptuagenarianBytecodeAge,
724 : kOctogenarianBytecodeAge,
725 : kAfterLastBytecodeAge,
726 : kFirstBytecodeAge = kNoAgeBytecodeAge,
727 : kLastBytecodeAge = kAfterLastBytecodeAge - 1,
728 : kBytecodeAgeCount = kAfterLastBytecodeAge - kFirstBytecodeAge - 1,
729 : kIsOldBytecodeAge = kSexagenarianBytecodeAge
730 : };
731 :
732 : static constexpr int SizeFor(int length) {
733 16570562 : return OBJECT_POINTER_ALIGN(kHeaderSize + length);
734 : }
735 :
736 : // Setter and getter
737 : inline byte get(int index) const;
738 : inline void set(int index, byte value);
739 :
740 : // Returns data start address.
741 : inline Address GetFirstBytecodeAddress();
742 :
743 : // Accessors for frame size.
744 : inline int frame_size() const;
745 : inline void set_frame_size(int frame_size);
746 :
747 : // Accessor for register count (derived from frame_size).
748 : inline int register_count() const;
749 :
750 : // Accessors for parameter count (including implicit 'this' receiver).
751 : inline int parameter_count() const;
752 : inline void set_parameter_count(int number_of_parameters);
753 :
754 : // Register used to pass the incoming new.target or generator object from the
755 : // fucntion call.
756 : inline interpreter::Register incoming_new_target_or_generator_register()
757 : const;
758 : inline void set_incoming_new_target_or_generator_register(
759 : interpreter::Register incoming_new_target_or_generator_register);
760 :
761 : // Accessors for OSR loop nesting level.
762 : inline int osr_loop_nesting_level() const;
763 : inline void set_osr_loop_nesting_level(int depth);
764 :
765 : // Accessors for bytecode's code age.
766 : inline Age bytecode_age() const;
767 : inline void set_bytecode_age(Age age);
768 :
769 : // Accessors for the constant pool.
770 : DECL_ACCESSORS(constant_pool, FixedArray)
771 :
772 : // Accessors for handler table containing offsets of exception handlers.
773 : DECL_ACCESSORS(handler_table, ByteArray)
774 :
775 : // Accessors for source position table. Can contain:
776 : // * undefined (initial value)
777 : // * empty_byte_array (for bytecode generated for functions that will never
778 : // have source positions, e.g. native functions).
779 : // * ByteArray (when source positions have been collected for the bytecode)
780 : // * SourcePositionTableWithFrameCache (as above but with a frame cache)
781 : // * exception (when an error occurred while explicitly collecting source
782 : // positions for pre-existing bytecode).
783 : DECL_ACCESSORS(source_position_table, Object)
784 :
785 : // This must only be called if source position collection has already been
786 : // attempted. (If it failed because of an exception then it will return
787 : // empty_byte_array).
788 : inline ByteArray SourcePositionTable() const;
789 : // If source positions have not been collected or an exception has been thrown
790 : // this will return empty_byte_array.
791 : inline ByteArray SourcePositionTableIfCollected() const;
792 : inline bool HasSourcePositionTable() const;
793 : inline bool DidSourcePositionGenerationFail() const;
794 : inline void ClearFrameCacheFromSourcePositionTable();
795 :
796 : // Indicates that an attempt was made to collect source positions, but that it
797 : // failed most likely due to stack exhaustion. When in this state
798 : // |SourcePositionTable| will return an empty byte array rather than crashing
799 : // as it would if no attempt was ever made to collect source positions.
800 : inline void SetSourcePositionsFailedToCollect();
801 :
802 : DECL_CAST(BytecodeArray)
803 :
804 : // Dispatched behavior.
805 : inline int BytecodeArraySize();
806 :
807 : inline int raw_instruction_size();
808 :
809 : // Returns the size of bytecode and its metadata. This includes the size of
810 : // bytecode, constant pool, source position table, and handler table.
811 : inline int SizeIncludingMetadata();
812 :
813 : DECL_PRINTER(BytecodeArray)
814 : DECL_VERIFIER(BytecodeArray)
815 :
816 : V8_EXPORT_PRIVATE void Disassemble(std::ostream& os);
817 :
818 : void CopyBytecodesTo(BytecodeArray to);
819 :
820 : // Bytecode aging
821 : V8_EXPORT_PRIVATE bool IsOld() const;
822 : V8_EXPORT_PRIVATE void MakeOlder();
823 :
824 : // Clear uninitialized padding space. This ensures that the snapshot content
825 : // is deterministic.
826 : inline void clear_padding();
827 :
828 : // Compares only the bytecode array but not any of the header fields.
829 : bool IsBytecodeEqual(const BytecodeArray other) const;
830 :
831 : // Layout description.
832 : #define BYTECODE_ARRAY_FIELDS(V) \
833 : /* Pointer fields. */ \
834 : V(kConstantPoolOffset, kTaggedSize) \
835 : V(kHandlerTableOffset, kTaggedSize) \
836 : V(kSourcePositionTableOffset, kTaggedSize) \
837 : V(kFrameSizeOffset, kIntSize) \
838 : V(kParameterSizeOffset, kIntSize) \
839 : V(kIncomingNewTargetOrGeneratorRegisterOffset, kIntSize) \
840 : V(kOSRNestingLevelOffset, kCharSize) \
841 : V(kBytecodeAgeOffset, kCharSize) \
842 : /* Total size. */ \
843 : V(kHeaderSize, 0)
844 :
845 : DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
846 : BYTECODE_ARRAY_FIELDS)
847 : #undef BYTECODE_ARRAY_FIELDS
848 :
849 : // InterpreterEntryTrampoline expects these fields to be next to each other
850 : // and writes a 16-bit value to reset them.
851 : STATIC_ASSERT(BytecodeArray::kBytecodeAgeOffset ==
852 : kOSRNestingLevelOffset + kCharSize);
853 :
854 : // Maximal memory consumption for a single BytecodeArray.
855 : static const int kMaxSize = 512 * MB;
856 : // Maximal length of a single BytecodeArray.
857 : static const int kMaxLength = kMaxSize - kHeaderSize;
858 :
859 : class BodyDescriptor;
860 :
861 : OBJECT_CONSTRUCTORS(BytecodeArray, FixedArrayBase);
862 : };
863 :
864 : // DeoptimizationData is a fixed array used to hold the deoptimization data for
865 : // optimized code. It also contains information about functions that were
866 : // inlined. If N different functions were inlined then the first N elements of
867 : // the literal array will contain these functions.
868 : //
869 : // It can be empty.
870 : class DeoptimizationData : public FixedArray {
871 : public:
872 : // Layout description. Indices in the array.
873 : static const int kTranslationByteArrayIndex = 0;
874 : static const int kInlinedFunctionCountIndex = 1;
875 : static const int kLiteralArrayIndex = 2;
876 : static const int kOsrBytecodeOffsetIndex = 3;
877 : static const int kOsrPcOffsetIndex = 4;
878 : static const int kOptimizationIdIndex = 5;
879 : static const int kSharedFunctionInfoIndex = 6;
880 : static const int kInliningPositionsIndex = 7;
881 : static const int kFirstDeoptEntryIndex = 8;
882 :
883 : // Offsets of deopt entry elements relative to the start of the entry.
884 : static const int kBytecodeOffsetRawOffset = 0;
885 : static const int kTranslationIndexOffset = 1;
886 : static const int kPcOffset = 2;
887 : static const int kDeoptEntrySize = 3;
888 :
889 : // Simple element accessors.
890 : #define DECL_ELEMENT_ACCESSORS(name, type) \
891 : inline type name() const; \
892 : inline void Set##name(type value);
893 :
894 : DECL_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
895 : DECL_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
896 : DECL_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
897 : DECL_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
898 : DECL_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
899 : DECL_ELEMENT_ACCESSORS(OptimizationId, Smi)
900 : DECL_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
901 : DECL_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
902 :
903 : #undef DECL_ELEMENT_ACCESSORS
904 :
905 : // Accessors for elements of the ith deoptimization entry.
906 : #define DECL_ENTRY_ACCESSORS(name, type) \
907 : inline type name(int i) const; \
908 : inline void Set##name(int i, type value);
909 :
910 : DECL_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
911 : DECL_ENTRY_ACCESSORS(TranslationIndex, Smi)
912 : DECL_ENTRY_ACCESSORS(Pc, Smi)
913 :
914 : #undef DECL_ENTRY_ACCESSORS
915 :
916 : inline BailoutId BytecodeOffset(int i);
917 :
918 : inline void SetBytecodeOffset(int i, BailoutId value);
919 :
920 : inline int DeoptCount();
921 :
922 : static const int kNotInlinedIndex = -1;
923 :
924 : // Returns the inlined function at the given position in LiteralArray, or the
925 : // outer function if index == kNotInlinedIndex.
926 : class SharedFunctionInfo GetInlinedFunction(int index);
927 :
928 : // Allocates a DeoptimizationData.
929 : static Handle<DeoptimizationData> New(Isolate* isolate, int deopt_entry_count,
930 : AllocationType allocation);
931 :
932 : // Return an empty DeoptimizationData.
933 : V8_EXPORT_PRIVATE static Handle<DeoptimizationData> Empty(Isolate* isolate);
934 :
935 : DECL_CAST(DeoptimizationData)
936 :
937 : #ifdef ENABLE_DISASSEMBLER
938 : void DeoptimizationDataPrint(std::ostream& os); // NOLINT
939 : #endif
940 :
941 : private:
942 : static int IndexForEntry(int i) {
943 5399703 : return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
944 : }
945 :
946 : static int LengthFor(int entry_count) { return IndexForEntry(entry_count); }
947 :
948 : OBJECT_CONSTRUCTORS(DeoptimizationData, FixedArray);
949 : };
950 :
951 : class SourcePositionTableWithFrameCache : public Tuple2 {
952 : public:
953 : DECL_ACCESSORS(source_position_table, ByteArray)
954 : DECL_ACCESSORS(stack_frame_cache, SimpleNumberDictionary)
955 :
956 : DECL_CAST(SourcePositionTableWithFrameCache)
957 :
958 : // Layout description.
959 : #define SOURCE_POSITION_TABLE_WITH_FRAME_FIELDS(V) \
960 : V(kSourcePositionTableIndex, kTaggedSize) \
961 : V(kStackFrameCacheIndex, kTaggedSize) \
962 : /* Total size. */ \
963 : V(kSize, 0)
964 :
965 : DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize,
966 : SOURCE_POSITION_TABLE_WITH_FRAME_FIELDS)
967 : #undef SOURCE_POSITION_TABLE_WITH_FRAME_FIELDS
968 :
969 : OBJECT_CONSTRUCTORS(SourcePositionTableWithFrameCache, Tuple2);
970 : };
971 :
972 : } // namespace internal
973 : } // namespace v8
974 :
975 : #include "src/objects/object-macros-undef.h"
976 :
977 : #endif // V8_OBJECTS_CODE_H_
|