• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/base/bit-field.h"
9 #include "src/builtins/builtins.h"
10 #include "src/codegen/handler-table.h"
11 #include "src/deoptimizer/translation-array.h"
12 #include "src/objects/code-kind.h"
13 #include "src/objects/contexts.h"
14 #include "src/objects/fixed-array.h"
15 #include "src/objects/heap-object.h"
16 #include "src/objects/objects.h"
17 #include "src/objects/shared-function-info.h"
18 #include "src/objects/struct.h"
19 
20 // Has to be the last include (doesn't have include guards):
21 #include "src/objects/object-macros.h"
22 
23 namespace v8 {
24 namespace internal {
25 
26 class ByteArray;
27 class BytecodeArray;
28 class CodeDataContainer;
29 class CodeDesc;
30 
31 class LocalFactory;
32 template <typename Impl>
33 class FactoryBase;
34 
35 namespace interpreter {
36 class Register;
37 }  // namespace interpreter
38 
39 #include "torque-generated/src/objects/code-tq.inc"
40 
41 // CodeDataContainer is a container for all mutable fields associated with its
42 // referencing {Code} object. Since {Code} objects reside on write-protected
43 // pages within the heap, its header fields need to be immutable. There always
44 // is a 1-to-1 relation between {Code} and {CodeDataContainer}, the referencing
45 // field {Code::code_data_container} itself is immutable.
46 class CodeDataContainer : public HeapObject {
47  public:
48   NEVER_READ_ONLY_SPACE
49   DECL_ACCESSORS(next_code_link, Object)
50   DECL_RELAXED_INT32_ACCESSORS(kind_specific_flags)
51 
52   // Clear uninitialized padding space. This ensures that the snapshot content
53   // is deterministic.
54   inline void clear_padding();
55 
56   //
57   // A collection of getters and predicates that are used by respective methods
58   // on Code object. They are defined here mostly because they operate on the
59   // writable state of the respective Code object.
60   //
61 
62   inline bool can_have_weak_objects() const;
63   inline void set_can_have_weak_objects(bool value);
64 
65   inline bool marked_for_deoptimization() const;
66   inline void set_marked_for_deoptimization(bool flag);
67 
68   // Back-reference to the Code object.
69   // Available only when V8_EXTERNAL_CODE_SPACE is defined.
70   DECL_GETTER(code, Code)
71   DECL_RELAXED_GETTER(code, Code)
72 
73   // When V8_EXTERNAL_CODE_SPACE is enabled, Code objects are allocated in
74   // a separate pointer compression cage instead of the cage where all the
75   // other objects are allocated.
76   // This field contains code cage base value which is used for decompressing
77   // the reference to respective Code. Basically, |code_cage_base| and |code|
78   // fields together form a full pointer. The reason why they are split is that
79   // the code field must also support atomic access and the word alignment of
80   // the full value is not guaranteed.
81   inline PtrComprCageBase code_cage_base() const;
82   inline void set_code_cage_base(Address code_cage_base);
83   inline PtrComprCageBase code_cage_base(RelaxedLoadTag) const;
84   inline void set_code_cage_base(Address code_cage_base, RelaxedStoreTag);
85 
86   // Cached value of code().InstructionStart().
87   // Available only when V8_EXTERNAL_CODE_SPACE is defined.
88   DECL_GETTER(code_entry_point, Address)
89 
90   inline void SetCodeAndEntryPoint(
91       Isolate* isolate_for_sandbox, Code code,
92       WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
93   // Updates the value of the code entry point. The code must be equal to
94   // the code() value.
95   inline void UpdateCodeEntryPoint(Isolate* isolate_for_sandbox, Code code);
96 
97   inline void AllocateExternalPointerEntries(Isolate* isolate);
98 
99   // Initializes internal flags field which stores cached values of some
100   // properties of the respective Code object.
101   // Available only when V8_EXTERNAL_CODE_SPACE is enabled.
102   inline void initialize_flags(CodeKind kind, Builtin builtin_id);
103 
104   // Alias for code_entry_point to make it API compatible with Code.
105   inline Address InstructionStart() const;
106 
107   // Alias for code_entry_point to make it API compatible with Code.
108   inline Address raw_instruction_start();
109 
110   // Alias for code_entry_point to make it API compatible with Code.
111   inline Address entry() const;
112 
113 #ifdef V8_EXTERNAL_CODE_SPACE
114   //
115   // A collection of getters and predicates that forward queries to associated
116   // Code object.
117   //
118 
119   inline CodeKind kind() const;
120   inline Builtin builtin_id() const;
121   inline bool is_builtin() const;
122 
123   inline bool is_optimized_code() const;
124   inline bool is_wasm_code() const;
125 
126   // Testers for interpreter builtins.
127   inline bool is_interpreter_trampoline_builtin() const;
128 
129   // Testers for baseline builtins.
130   inline bool is_baseline_trampoline_builtin() const;
131   inline bool is_baseline_leave_frame_builtin() const;
132 
133   // Tells whether the code checks the tiering state in the function's
134   // feedback vector.
135   inline bool checks_tiering_state() const;
136 
137   // Tells whether the outgoing parameters of this code are tagged pointers.
138   inline bool has_tagged_outgoing_params() const;
139 
140   // [is_maglevved]: Tells whether the code object was generated by the
141   // Maglev optimizing compiler.
142   inline bool is_maglevved() const;
143 
144   // [is_turbofanned]: Tells whether the code object was generated by the
145   // TurboFan optimizing compiler.
146   inline bool is_turbofanned() const;
147 
148   // [is_off_heap_trampoline]: For kind BUILTIN tells whether
149   // this is a trampoline to an off-heap builtin.
150   inline bool is_off_heap_trampoline() const;
151 
152   DECL_GETTER(deoptimization_data, FixedArray)
153   DECL_GETTER(bytecode_or_interpreter_data, HeapObject)
154   DECL_GETTER(source_position_table, ByteArray)
155   DECL_GETTER(bytecode_offset_table, ByteArray)
156 
157 #endif  // V8_EXTERNAL_CODE_SPACE
158 
159   DECL_CAST(CodeDataContainer)
160 
161   // Dispatched behavior.
162   DECL_PRINTER(CodeDataContainer)
163   DECL_VERIFIER(CodeDataContainer)
164 
165 // Layout description.
166 #define CODE_DATA_FIELDS(V)                                         \
167   /* Strong pointer fields. */                                      \
168   V(kPointerFieldsStrongEndOffset, 0)                               \
169   /* Weak pointer fields. */                                        \
170   V(kNextCodeLinkOffset, kTaggedSize)                               \
171   V(kPointerFieldsWeakEndOffset, 0)                                 \
172   /* Strong Code pointer fields. */                                 \
173   V(kCodeOffset, V8_EXTERNAL_CODE_SPACE_BOOL ? kTaggedSize : 0)     \
174   V(kCodePointerFieldsStrongEndOffset, 0)                           \
175   /* Raw data fields. */                                            \
176   V(kCodeCageBaseUpper32BitsOffset,                                 \
177     V8_EXTERNAL_CODE_SPACE_BOOL ? kTaggedSize : 0)                  \
178   V(kCodeEntryPointOffset,                                          \
179     V8_EXTERNAL_CODE_SPACE_BOOL ? kExternalPointerSize : 0)         \
180   V(kFlagsOffset, V8_EXTERNAL_CODE_SPACE_BOOL ? kUInt16Size : 0)    \
181   V(kBuiltinIdOffset, V8_EXTERNAL_CODE_SPACE_BOOL ? kInt16Size : 0) \
182   V(kKindSpecificFlagsOffset, kInt32Size)                           \
183   V(kUnalignedSize, OBJECT_POINTER_PADDING(kUnalignedSize))         \
184   /* Total size. */                                                 \
185   V(kSize, 0)
186 
187   DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CODE_DATA_FIELDS)
188 #undef CODE_DATA_FIELDS
189 
190   class BodyDescriptor;
191 
192   // Flags layout.
193 #define FLAGS_BIT_FIELDS(V, _) \
194   V(KindField, CodeKind, 4, _) \
195   /* The other 12 bits are still free. */
196 
197   DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
198 #undef FLAGS_BIT_FIELDS
199   STATIC_ASSERT(FLAGS_BIT_FIELDS_Ranges::kBitsCount == 4);
200   STATIC_ASSERT(!V8_EXTERNAL_CODE_SPACE_BOOL ||
201                 (FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
202                  FIELD_SIZE(CodeDataContainer::kFlagsOffset) * kBitsPerByte));
203 
204  private:
205   DECL_ACCESSORS(raw_code, Object)
206   DECL_RELAXED_GETTER(raw_code, Object)
207   inline void set_code_entry_point(Isolate* isolate, Address value);
208 
209   // When V8_EXTERNAL_CODE_SPACE is enabled the flags field contains cached
210   // values of some flags of the from the respective Code object.
211   DECL_RELAXED_UINT16_ACCESSORS(flags)
212 
213   friend Factory;
214   friend FactoryBase<Factory>;
215   friend FactoryBase<LocalFactory>;
216 
217   OBJECT_CONSTRUCTORS(CodeDataContainer, HeapObject);
218 };
219 
220 // Code describes objects with on-the-fly generated machine code.
221 class Code : public HeapObject {
222  public:
223   NEVER_READ_ONLY_SPACE
224   // Opaque data type for encapsulating code flags like kind, inline
225   // cache state, and arguments count.
226   using Flags = uint32_t;
227 
228   // All Code objects have the following layout:
229   //
230   //  +--------------------------+
231   //  |          header          |
232   //  | padded to code alignment |
233   //  +--------------------------+  <-- raw_body_start()
234   //  |       instructions       |   == raw_instruction_start()
235   //  |           ...            |
236   //  | padded to meta alignment |      see kMetadataAlignment
237   //  +--------------------------+  <-- raw_instruction_end()
238   //  |         metadata         |   == raw_metadata_start() (MS)
239   //  |           ...            |
240   //  |                          |  <-- MS + handler_table_offset()
241   //  |                          |  <-- MS + constant_pool_offset()
242   //  |                          |  <-- MS + code_comments_offset()
243   //  |                          |  <-- MS + unwinding_info_offset()
244   //  | padded to obj alignment  |
245   //  +--------------------------+  <-- raw_metadata_end() == raw_body_end()
246   //  | padded to code alignment |
247   //  +--------------------------+
248   //
249   // In other words, the variable-size 'body' consists of 'instructions' and
250   // 'metadata'.
251   //
252   // Note the accessor functions below may be prefixed with 'raw'. In this case,
253   // raw accessors (e.g. raw_instruction_start) always refer to the on-heap
254   // Code object, while camel-case accessors (e.g. InstructionStart) may refer
255   // to an off-heap area in the case of embedded builtins.
256   //
257   // Embedded builtins are on-heap Code objects, with an out-of-line body
258   // section. The on-heap Code object contains an essentially empty body
259   // section, while accessors, as mentioned above, redirect to the off-heap
260   // area. Metadata table offsets remain relative to MetadataStart(), i.e. they
261   // point into the off-heap metadata section. The off-heap layout is described
262   // in detail in the EmbeddedData class, but at a high level one can assume a
263   // dedicated, out-of-line, instruction and metadata section for each embedded
264   // builtin *in addition* to the on-heap Code object:
265   //
266   //  +--------------------------+  <-- InstructionStart()
267   //  |   off-heap instructions  |
268   //  |           ...            |
269   //  +--------------------------+  <-- InstructionEnd()
270   //
271   //  +--------------------------+  <-- MetadataStart() (MS)
272   //  |    off-heap metadata     |
273   //  |           ...            |  <-- MS + handler_table_offset()
274   //  |                          |  <-- MS + constant_pool_offset()
275   //  |                          |  <-- MS + code_comments_offset()
276   //  |                          |  <-- MS + unwinding_info_offset()
277   //  +--------------------------+  <-- MetadataEnd()
278 
279   // Constants for use in static asserts, stating whether the body is adjacent,
280   // i.e. instructions and metadata areas are adjacent.
281   static constexpr bool kOnHeapBodyIsContiguous = true;
282   static constexpr bool kOffHeapBodyIsContiguous = false;
283   static constexpr bool kBodyIsContiguous =
284       kOnHeapBodyIsContiguous && kOffHeapBodyIsContiguous;
285 
286   inline Address raw_body_start() const;
287   inline Address raw_body_end() const;
288   inline int raw_body_size() const;
289 
290   inline Address raw_instruction_start() const;
291   inline Address InstructionStart() const;
292 
293   inline Address raw_instruction_end() const;
294   inline Address InstructionEnd() const;
295 
296   // When builtins un-embedding is enabled for the Isolate
297   // (see Isolate::is_short_builtin_calls_enabled()) then both embedded and
298   // un-embedded builtins might be exeuted and thus two kinds of |pc|s might
299   // appear on the stack.
300   // Unlike the paremeterless versions of the functions above the below variants
301   // ensure that the instruction start correspond to the given |pc| value.
302   // Thus for off-heap trampoline Code objects the result might be the
303   // instruction start/end of the embedded code stream or of un-embedded one.
304   // For normal Code objects these functions just return the
305   // raw_instruction_start/end() values.
306   // TODO(11527): remove these versions once the full solution is ready.
307   inline Address InstructionStart(Isolate* isolate, Address pc) const;
308   V8_EXPORT_PRIVATE Address OffHeapInstructionStart(Isolate* isolate,
309                                                     Address pc) const;
310   inline Address InstructionEnd(Isolate* isolate, Address pc) const;
311   V8_EXPORT_PRIVATE Address OffHeapInstructionEnd(Isolate* isolate,
312                                                   Address pc) const;
313 
314   // Computes offset of the |pc| from the instruction start. The |pc| must
315   // belong to this code.
316   inline int GetOffsetFromInstructionStart(Isolate* isolate, Address pc) const;
317 
318   inline int raw_instruction_size() const;
319   inline void set_raw_instruction_size(int value);
320   inline int InstructionSize() const;
321 
322   inline Address raw_metadata_start() const;
323   inline Address raw_metadata_end() const;
324   inline int raw_metadata_size() const;
325   inline void set_raw_metadata_size(int value);
326   inline int MetadataSize() const;
327 
328   // The metadata section is aligned to this value.
329   static constexpr int kMetadataAlignment = kIntSize;
330 
331   // [safepoint_table_offset]: The offset where the safepoint table starts.
safepoint_table_offset()332   inline int safepoint_table_offset() const { return 0; }
333   inline Address SafepointTableAddress() const;
334   inline int safepoint_table_size() const;
335   inline bool has_safepoint_table() const;
336 
337   // [handler_table_offset]: The offset where the exception handler table
338   // starts.
339   inline int handler_table_offset() const;
340   inline void set_handler_table_offset(int offset);
341   inline Address HandlerTableAddress() const;
342   inline int handler_table_size() const;
343   inline bool has_handler_table() const;
344 
345   // [constant_pool offset]: Offset of the constant pool.
346   inline int constant_pool_offset() const;
347   inline void set_constant_pool_offset(int offset);
348   inline Address constant_pool() const;
349   inline int constant_pool_size() const;
350   inline bool has_constant_pool() const;
351 
352   // [code_comments_offset]: Offset of the code comment section.
353   inline int code_comments_offset() const;
354   inline void set_code_comments_offset(int offset);
355   inline Address code_comments() const;
356   inline int code_comments_size() const;
357   inline bool has_code_comments() const;
358 
359   // [unwinding_info_offset]: Offset of the unwinding info section.
360   inline int32_t unwinding_info_offset() const;
361   inline void set_unwinding_info_offset(int32_t offset);
362   inline Address unwinding_info_start() const;
363   inline Address unwinding_info_end() const;
364   inline int unwinding_info_size() const;
365   inline bool has_unwinding_info() const;
366 
367 #ifdef ENABLE_DISASSEMBLER
368   const char* GetName(Isolate* isolate) const;
369   V8_EXPORT_PRIVATE void Disassemble(const char* name, std::ostream& os,
370                                      Isolate* isolate,
371                                      Address current_pc = kNullAddress);
372 #endif
373 
374   // [relocation_info]: Code relocation information
375   DECL_ACCESSORS(relocation_info, ByteArray)
376 
377   // This function should be called only from GC.
378   void ClearEmbeddedObjects(Heap* heap);
379 
380   // [deoptimization_data]: Array containing data for deopt for non-baseline
381   // code.
382   DECL_ACCESSORS(deoptimization_data, FixedArray)
383   // [bytecode_or_interpreter_data]: BytecodeArray or InterpreterData for
384   // baseline code.
385   DECL_ACCESSORS(bytecode_or_interpreter_data, HeapObject)
386 
387   // [source_position_table]: ByteArray for the source positions table for
388   // non-baseline code.
389   DECL_ACCESSORS(source_position_table, ByteArray)
390   // [bytecode_offset_table]: ByteArray for the bytecode offset for baseline
391   // code.
392   DECL_ACCESSORS(bytecode_offset_table, ByteArray)
393 
394   // If source positions have not been collected or an exception has been thrown
395   // this will return empty_byte_array.
396   inline ByteArray SourcePositionTable(SharedFunctionInfo sfi) const;
397 
398   // [code_data_container]: A container indirection for all mutable fields.
399   DECL_RELEASE_ACQUIRE_ACCESSORS(code_data_container, CodeDataContainer)
400 
401   // [next_code_link]: Link for lists of optimized or deoptimized code.
402   // Note that this field is stored in the {CodeDataContainer} to be mutable.
403   inline Object next_code_link() const;
404   inline void set_next_code_link(Object value);
405 
406   // Unchecked accessors to be used during GC.
407   inline ByteArray unchecked_relocation_info() const;
408 
409   inline int relocation_size() const;
410 
411   // [kind]: Access to specific code kind.
412   inline CodeKind kind() const;
413 
414   inline bool is_optimized_code() const;
415   inline bool is_wasm_code() const;
416 
417   // Testers for interpreter builtins.
418   inline bool is_interpreter_trampoline_builtin() const;
419 
420   // Testers for baseline builtins.
421   inline bool is_baseline_trampoline_builtin() const;
422   inline bool is_baseline_leave_frame_builtin() const;
423 
424   // Tells whether the code checks the tiering state in the function's
425   // feedback vector.
426   inline bool checks_tiering_state() const;
427 
428   // Tells whether the outgoing parameters of this code are tagged pointers.
429   inline bool has_tagged_outgoing_params() const;
430 
431   // [is_turbofanned]: Tells whether the code object was generated by the
432   // TurboFan optimizing compiler.
433   inline bool is_turbofanned() const;
434 
435   // TODO(jgruber): Reconsider these predicates; we should probably merge them
436   // and rename to something appropriate.
437   inline bool is_maglevved() const;
438 
439   // [can_have_weak_objects]: If CodeKindIsOptimizedJSFunction(kind), tells
440   // whether the embedded objects in code should be treated weakly.
441   inline bool can_have_weak_objects() const;
442   inline void set_can_have_weak_objects(bool value);
443 
444   // [builtin]: For builtins, tells which builtin index the code object
445   // has. The builtin index is a non-negative integer for builtins, and
446   // Builtin::kNoBuiltinId (-1) otherwise.
447   inline Builtin builtin_id() const;
448   inline void set_builtin_id(Builtin builtin);
449   inline bool is_builtin() const;
450 
451   inline unsigned inlined_bytecode_size() const;
452   inline void set_inlined_bytecode_size(unsigned size);
453 
454   // [uses_safepoint_table]: Whether this Code object uses safepoint tables
455   // (note the table may still be empty, see has_safepoint_table).
456   inline bool uses_safepoint_table() const;
457 
458   // [stack_slots]: If {uses_safepoint_table()}, the number of stack slots
459   // reserved in the code prologue; otherwise 0.
460   inline int stack_slots() const;
461 
462   // [marked_for_deoptimization]: If CodeKindCanDeoptimize(kind), tells whether
463   // the code is going to be deoptimized.
464   inline bool marked_for_deoptimization() const;
465   inline void set_marked_for_deoptimization(bool flag);
466 
467   // [embedded_objects_cleared]: If CodeKindIsOptimizedJSFunction(kind), tells
468   // whether the embedded objects in the code marked for deoptimization were
469   // cleared. Note that embedded_objects_cleared() implies
470   // marked_for_deoptimization().
471   inline bool embedded_objects_cleared() const;
472   inline void set_embedded_objects_cleared(bool flag);
473 
474   // [is_promise_rejection]: For kind BUILTIN tells whether the
475   // exception thrown by the code will lead to promise rejection or
476   // uncaught if both this and is_exception_caught is set.
477   // Use GetBuiltinCatchPrediction to access this.
478   inline void set_is_promise_rejection(bool flag);
479 
480   // [is_off_heap_trampoline]: For kind BUILTIN tells whether
481   // this is a trampoline to an off-heap builtin.
482   inline bool is_off_heap_trampoline() const;
483 
484   // Get the safepoint entry for the given pc.
485   SafepointEntry GetSafepointEntry(Isolate* isolate, Address pc);
486 
487   // The entire code object including its header is copied verbatim to the
488   // snapshot so that it can be written in one, fast, memcpy during
489   // deserialization. The deserializer will overwrite some pointers, rather
490   // like a runtime linker, but the random allocation addresses used in the
491   // mksnapshot process would still be present in the unlinked snapshot data,
492   // which would make snapshot production non-reproducible. This method wipes
493   // out the to-be-overwritten header data for reproducible snapshots.
494   inline void WipeOutHeader();
495 
496   // When V8_EXTERNAL_CODE_SPACE is enabled, Code objects are allocated in
497   // a separate pointer compression cage instead of the cage where all the
498   // other objects are allocated.
499   // This field contains cage base value which is used for decompressing
500   // the references to non-Code objects (map, deoptimization_data, etc.).
501   inline PtrComprCageBase main_cage_base() const;
502   inline PtrComprCageBase main_cage_base(RelaxedLoadTag) const;
503   inline void set_main_cage_base(Address cage_base, RelaxedStoreTag);
504 
505   // Clear uninitialized padding space. This ensures that the snapshot content
506   // is deterministic. Depending on the V8 build mode there could be no padding.
507   inline void clear_padding();
508   // Initialize the flags field. Similar to clear_padding above this ensure that
509   // the snapshot content is deterministic.
510   inline void initialize_flags(CodeKind kind, bool is_turbofanned,
511                                int stack_slots, bool is_off_heap_trampoline);
512 
513   // Convert a target address into a code object.
514   static inline Code GetCodeFromTargetAddress(Address address);
515 
516   // Convert an entry address into an object.
517   static inline Code GetObjectFromEntryAddress(Address location_of_address);
518 
519   // Returns the size of code and its metadata. This includes the size of code
520   // relocation information, deoptimization data.
521   inline int SizeIncludingMetadata() const;
522 
523   // Returns the address of the first relocation info (read backwards!).
524   inline byte* relocation_start() const;
525 
526   // Returns the address right after the relocation info (read backwards!).
527   inline byte* relocation_end() const;
528 
529   // Code entry point.
530   inline Address entry() const;
531 
532   // Returns true if pc is inside this object's instructions.
533   inline bool contains(Isolate* isolate, Address pc);
534 
535   // Relocate the code by delta bytes. Called to signal that this code
536   // object has been moved by delta bytes.
537   void Relocate(intptr_t delta);
538 
539   // Migrate code from desc without flushing the instruction cache.
540   void CopyFromNoFlush(ByteArray reloc_info, Heap* heap, const CodeDesc& desc);
541   void RelocateFromDesc(ByteArray reloc_info, Heap* heap, const CodeDesc& desc);
542 
543   // Copy the RelocInfo portion of |desc| to |dest|. The ByteArray must be
544   // exactly the same size as the RelocInfo in |desc|.
545   static inline void CopyRelocInfoToByteArray(ByteArray dest,
546                                               const CodeDesc& desc);
547 
548   inline uintptr_t GetBaselineStartPCForBytecodeOffset(int bytecode_offset,
549                                                        BytecodeArray bytecodes);
550 
551   inline uintptr_t GetBaselineEndPCForBytecodeOffset(int bytecode_offset,
552                                                      BytecodeArray bytecodes);
553 
554   // Returns the PC of the next bytecode in execution order.
555   // If the bytecode at the given offset is JumpLoop, the PC of the jump target
556   // is returned. Other jumps are not allowed.
557   // For other bytecodes this is equivalent to
558   // GetBaselineEndPCForBytecodeOffset.
559   inline uintptr_t GetBaselinePCForNextExecutedBytecode(
560       int bytecode_offset, BytecodeArray bytecodes);
561 
562   inline int GetBytecodeOffsetForBaselinePC(Address baseline_pc,
563                                             BytecodeArray bytecodes);
564 
565   // Flushes the instruction cache for the executable instructions of this code
566   // object. Make sure to call this while the code is still writable.
567   void FlushICache() const;
568 
569   // Returns the object size for a given body (used for allocation).
SizeFor(int body_size)570   static int SizeFor(int body_size) {
571     return RoundUp(kHeaderSize + body_size, kCodeAlignment);
572   }
573 
574   inline int CodeSize() const;
575 
576   // Hides HeapObject::Size(...) and redirects queries to CodeSize().
577   DECL_GETTER(Size, int)
578 
579   DECL_CAST(Code)
580 
581   // Dispatched behavior.
582   DECL_PRINTER(Code)
583   DECL_VERIFIER(Code)
584 
585   bool CanDeoptAt(Isolate* isolate, Address pc);
586 
587   void SetMarkedForDeoptimization(const char* reason);
588 
589   inline HandlerTable::CatchPrediction GetBuiltinCatchPrediction();
590 
591   bool IsIsolateIndependent(Isolate* isolate);
592 
593   inline bool CanContainWeakObjects();
594 
595   inline bool IsWeakObject(HeapObject object);
596 
597   static inline bool IsWeakObjectInOptimizedCode(HeapObject object);
598 
599   static inline bool IsWeakObjectInDeoptimizationLiteralArray(Object object);
600 
601   // Returns false if this is an embedded builtin Code object that's in
602   // read_only_space and hence doesn't have execute permissions.
603   inline bool IsExecutable();
604 
605   // Returns true if the function is inlined in the code.
606   bool Inlines(SharedFunctionInfo sfi);
607 
608   class OptimizedCodeIterator;
609 
610   // Layout description.
611 #define CODE_FIELDS(V)                                                        \
612   V(kRelocationInfoOffset, kTaggedSize)                                       \
613   V(kDeoptimizationDataOrInterpreterDataOffset, kTaggedSize)                  \
614   V(kPositionTableOffset, kTaggedSize)                                        \
615   V(kCodeDataContainerOffset, kTaggedSize)                                    \
616   /* Data or code not directly visited by GC directly starts here. */         \
617   /* The serializer needs to copy bytes starting from here verbatim. */       \
618   /* Objects embedded into code is visited via reloc info. */                 \
619   V(kDataStart, 0)                                                            \
620   V(kMainCageBaseUpper32BitsOffset,                                           \
621     V8_EXTERNAL_CODE_SPACE_BOOL ? kTaggedSize : 0)                            \
622   V(kInstructionSizeOffset, kIntSize)                                         \
623   V(kMetadataSizeOffset, kIntSize)                                            \
624   V(kFlagsOffset, kInt32Size)                                                 \
625   V(kBuiltinIndexOffset, kIntSize)                                            \
626   V(kInlinedBytecodeSizeOffset, kIntSize)                                     \
627   /* Offsets describing inline metadata tables, relative to MetadataStart. */ \
628   V(kHandlerTableOffsetOffset, kIntSize)                                      \
629   V(kConstantPoolOffsetOffset,                                                \
630     FLAG_enable_embedded_constant_pool ? kIntSize : 0)                        \
631   V(kCodeCommentsOffsetOffset, kIntSize)                                      \
632   V(kUnwindingInfoOffsetOffset, kInt32Size)                                   \
633   V(kUnalignedHeaderSize, 0)                                                  \
634   /* Add padding to align the instruction start following right after */      \
635   /* the Code object header. */                                               \
636   V(kOptionalPaddingOffset, CODE_POINTER_PADDING(kOptionalPaddingOffset))     \
637   V(kHeaderSize, 0)
638 
639   DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CODE_FIELDS)
640 #undef CODE_FIELDS
641 
642   // This documents the amount of free space we have in each Code object header
643   // due to padding for code alignment.
644 #if V8_TARGET_ARCH_ARM64
645   static constexpr int kHeaderPaddingSize =
646       V8_EXTERNAL_CODE_SPACE_BOOL ? 8 : (COMPRESS_POINTERS_BOOL ? 12 : 24);
647 #elif V8_TARGET_ARCH_MIPS64
648   static constexpr int kHeaderPaddingSize = 24;
649 #elif V8_TARGET_ARCH_LOONG64
650   static constexpr int kHeaderPaddingSize = 24;
651 #elif V8_TARGET_ARCH_X64
652   static constexpr int kHeaderPaddingSize =
653       V8_EXTERNAL_CODE_SPACE_BOOL ? 8 : (COMPRESS_POINTERS_BOOL ? 12 : 56);
654 #elif V8_TARGET_ARCH_ARM
655   static constexpr int kHeaderPaddingSize = 12;
656 #elif V8_TARGET_ARCH_IA32
657   static constexpr int kHeaderPaddingSize = 12;
658 #elif V8_TARGET_ARCH_MIPS
659   static constexpr int kHeaderPaddingSize = 12;
660 #elif V8_TARGET_ARCH_PPC64
661   static constexpr int kHeaderPaddingSize =
662       FLAG_enable_embedded_constant_pool ? (COMPRESS_POINTERS_BOOL ? 8 : 52)
663                                          : (COMPRESS_POINTERS_BOOL ? 12 : 56);
664 #elif V8_TARGET_ARCH_S390X
665   static constexpr int kHeaderPaddingSize = COMPRESS_POINTERS_BOOL ? 12 : 24;
666 #elif V8_TARGET_ARCH_RISCV64
667   static constexpr int kHeaderPaddingSize = (COMPRESS_POINTERS_BOOL ? 12 : 24);
668 #else
669 #error Unknown architecture.
670 #endif
671   STATIC_ASSERT(FIELD_SIZE(kOptionalPaddingOffset) == kHeaderPaddingSize);
672 
673   class BodyDescriptor;
674 
675   // Flags layout.  base::BitField<type, shift, size>.
676 #define CODE_FLAGS_BIT_FIELDS(V, _)    \
677   V(KindField, CodeKind, 4, _)         \
678   V(IsTurbofannedField, bool, 1, _)    \
679   V(StackSlotsField, int, 24, _)       \
680   V(IsOffHeapTrampoline, bool, 1, _)
681   DEFINE_BIT_FIELDS(CODE_FLAGS_BIT_FIELDS)
682 #undef CODE_FLAGS_BIT_FIELDS
683   STATIC_ASSERT(kCodeKindCount <= KindField::kNumValues);
684   STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 30);
685   STATIC_ASSERT(CODE_FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
686                 FIELD_SIZE(kFlagsOffset) * kBitsPerByte);
687 
688   // KindSpecificFlags layout.
689 #define CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS(V, _) \
690   V(MarkedForDeoptimizationField, bool, 1, _)     \
691   V(EmbeddedObjectsClearedField, bool, 1, _)      \
692   V(CanHaveWeakObjectsField, bool, 1, _)          \
693   V(IsPromiseRejectionField, bool, 1, _)
694   DEFINE_BIT_FIELDS(CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS)
695 #undef CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS
696   STATIC_ASSERT(CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS_Ranges::kBitsCount == 4);
697   STATIC_ASSERT(CODE_KIND_SPECIFIC_FLAGS_BIT_FIELDS_Ranges::kBitsCount <=
698                 FIELD_SIZE(CodeDataContainer::kKindSpecificFlagsOffset) *
699                     kBitsPerByte);
700 
701   // The {marked_for_deoptimization} field is accessed from generated code.
702   static const int kMarkedForDeoptimizationBit =
703       MarkedForDeoptimizationField::kShift;
704 
705   static const int kArgumentsBits = 16;
706   // Reserve one argument count value as the "don't adapt arguments" sentinel.
707   static const int kMaxArguments = (1 << kArgumentsBits) - 2;
708 
709  private:
710   friend class RelocIterator;
711   friend class EvacuateVisitorBase;
712 
713   inline CodeDataContainer GCSafeCodeDataContainer(AcquireLoadTag) const;
714 
715   bool is_promise_rejection() const;
716 
717   enum BytecodeToPCPosition {
718     kPcAtStartOfBytecode,
719     // End of bytecode equals the start of the next bytecode.
720     // We need it when we deoptimize to the next bytecode (lazy deopt or deopt
721     // of non-topmost frame).
722     kPcAtEndOfBytecode
723   };
724   inline uintptr_t GetBaselinePCForBytecodeOffset(int bytecode_offset,
725                                                   BytecodeToPCPosition position,
726                                                   BytecodeArray bytecodes);
727 
728   OBJECT_CONSTRUCTORS(Code, HeapObject);
729 };
730 
731 // TODO(v8:11880): move these functions to CodeDataContainer once they are no
732 // longer used from Code.
733 V8_EXPORT_PRIVATE Address OffHeapInstructionStart(HeapObject code,
734                                                   Builtin builtin);
735 V8_EXPORT_PRIVATE Address OffHeapInstructionEnd(HeapObject code,
736                                                 Builtin builtin);
737 V8_EXPORT_PRIVATE int OffHeapInstructionSize(HeapObject code, Builtin builtin);
738 
739 V8_EXPORT_PRIVATE Address OffHeapMetadataStart(HeapObject code,
740                                                Builtin builtin);
741 V8_EXPORT_PRIVATE Address OffHeapMetadataEnd(HeapObject code, Builtin builtin);
742 V8_EXPORT_PRIVATE int OffHeapMetadataSize(HeapObject code, Builtin builtin);
743 
744 V8_EXPORT_PRIVATE Address OffHeapSafepointTableAddress(HeapObject code,
745                                                        Builtin builtin);
746 V8_EXPORT_PRIVATE int OffHeapSafepointTableSize(HeapObject code,
747                                                 Builtin builtin);
748 V8_EXPORT_PRIVATE Address OffHeapHandlerTableAddress(HeapObject code,
749                                                      Builtin builtin);
750 V8_EXPORT_PRIVATE int OffHeapHandlerTableSize(HeapObject code, Builtin builtin);
751 V8_EXPORT_PRIVATE Address OffHeapConstantPoolAddress(HeapObject code,
752                                                      Builtin builtin);
753 V8_EXPORT_PRIVATE int OffHeapConstantPoolSize(HeapObject code, Builtin builtin);
754 V8_EXPORT_PRIVATE Address OffHeapCodeCommentsAddress(HeapObject code,
755                                                      Builtin builtin);
756 V8_EXPORT_PRIVATE int OffHeapCodeCommentsSize(HeapObject code, Builtin builtin);
757 V8_EXPORT_PRIVATE Address OffHeapUnwindingInfoAddress(HeapObject code,
758                                                       Builtin builtin);
759 V8_EXPORT_PRIVATE int OffHeapUnwindingInfoSize(HeapObject code,
760                                                Builtin builtin);
761 
762 class Code::OptimizedCodeIterator {
763  public:
764   explicit OptimizedCodeIterator(Isolate* isolate);
765   OptimizedCodeIterator(const OptimizedCodeIterator&) = delete;
766   OptimizedCodeIterator& operator=(const OptimizedCodeIterator&) = delete;
767   Code Next();
768 
769  private:
770   NativeContext next_context_;
771   Code current_code_;
772   Isolate* isolate_;
773 
774   DISALLOW_GARBAGE_COLLECTION(no_gc)
775 };
776 
777 // Helper functions for converting Code objects to CodeDataContainer and back
778 // when V8_EXTERNAL_CODE_SPACE is enabled.
779 inline CodeT ToCodeT(Code code);
780 inline Handle<CodeT> ToCodeT(Handle<Code> code, Isolate* isolate);
781 inline Code FromCodeT(CodeT code);
782 inline Code FromCodeT(CodeT code, RelaxedLoadTag);
783 inline Code FromCodeT(CodeT code, AcquireLoadTag);
784 inline Code FromCodeT(CodeT code, PtrComprCageBase);
785 inline Code FromCodeT(CodeT code, PtrComprCageBase, RelaxedLoadTag);
786 inline Code FromCodeT(CodeT code, PtrComprCageBase, AcquireLoadTag);
787 inline Handle<CodeT> FromCodeT(Handle<Code> code, Isolate* isolate);
788 inline CodeDataContainer CodeDataContainerFromCodeT(CodeT code);
789 
790 class AbstractCode : public HeapObject {
791  public:
792   NEVER_READ_ONLY_SPACE
793 
794   int SourcePosition(int offset);
795   int SourceStatementPosition(int offset);
796 
797   // Returns the address of the first instruction.
798   inline Address raw_instruction_start();
799 
800   // Returns the address of the first instruction. For off-heap code objects
801   // this differs from instruction_start (which would point to the off-heap
802   // trampoline instead).
803   inline Address InstructionStart();
804 
805   // Returns the address right after the last instruction.
806   inline Address raw_instruction_end();
807 
808   // Returns the address right after the last instruction. For off-heap code
809   // objects this differs from instruction_end (which would point to the
810   // off-heap trampoline instead).
811   inline Address InstructionEnd();
812 
813   // Returns the size of the code instructions.
814   inline int raw_instruction_size();
815 
816   // Returns the size of the native instructions, including embedded
817   // data such as the safepoints table. For off-heap code objects
818   // this may differ from instruction_size in that this will return the size of
819   // the off-heap instruction stream rather than the on-heap trampoline located
820   // at instruction_start.
821   inline int InstructionSize();
822 
823   // Return the source position table for interpreter code.
824   inline ByteArray SourcePositionTable(SharedFunctionInfo sfi);
825 
826   void DropStackFrameCache();
827 
828   // Returns the size of instructions and the metadata.
829   inline int SizeIncludingMetadata();
830 
831   // Returns true if pc is inside this object's instructions.
832   inline bool contains(Isolate* isolate, Address pc);
833 
834   // Returns the kind of the code.
835   inline CodeKind kind();
836 
837   DECL_CAST(AbstractCode)
838   inline Code GetCode();
839   inline BytecodeArray GetBytecodeArray();
840 
841   OBJECT_CONSTRUCTORS(AbstractCode, HeapObject);
842 
843  private:
844   inline ByteArray SourcePositionTableInternal();
845 };
846 
847 // Dependent code is conceptually the list of {Code, DependencyGroup} tuples
848 // associated with an object, where the dependency group is a reason that could
849 // lead to a deopt of the corresponding code.
850 //
851 // Implementation details: DependentCode is a weak array list containing
852 // entries, where each entry consists of a (weak) Code object and the
853 // DependencyGroups bitset as a Smi.
854 //
855 // Note the underlying weak array list currently never shrinks physically (the
856 // contents may shrink).
857 // TODO(jgruber): Consider adding physical shrinking.
858 class DependentCode : public WeakArrayList {
859  public:
860   DECL_CAST(DependentCode)
861 
862   enum DependencyGroup {
863     // Group of code objects that embed a transition to this map, and depend on
864     // being deoptimized when the transition is replaced by a new version.
865     kTransitionGroup = 1 << 0,
866     // Group of code objects that omit run-time prototype checks for prototypes
867     // described by this map. The group is deoptimized whenever the following
868     // conditions hold, possibly invalidating the assumptions embedded in the
869     // code:
870     // a) A fast-mode object described by this map changes shape (and
871     // transitions to a new map), or
872     // b) A dictionary-mode prototype described by this map changes shape, the
873     // const-ness of one of its properties changes, or its [[Prototype]]
874     // changes (only the latter causes a transition).
875     kPrototypeCheckGroup = 1 << 1,
876     // Group of code objects that depends on global property values in property
877     // cells not being changed.
878     kPropertyCellChangedGroup = 1 << 2,
879     // Group of code objects that omit run-time checks for field(s) introduced
880     // by this map, i.e. for the field type.
881     kFieldTypeGroup = 1 << 3,
882     kFieldConstGroup = 1 << 4,
883     kFieldRepresentationGroup = 1 << 5,
884     // Group of code objects that omit run-time type checks for initial maps of
885     // constructors.
886     kInitialMapChangedGroup = 1 << 6,
887     // Group of code objects that depends on tenuring information in
888     // AllocationSites not being changed.
889     kAllocationSiteTenuringChangedGroup = 1 << 7,
890     // Group of code objects that depends on element transition information in
891     // AllocationSites not being changed.
892     kAllocationSiteTransitionChangedGroup = 1 << 8,
893     // IMPORTANT: The last bit must fit into a Smi, i.e. into 31 bits.
894   };
895   using DependencyGroups = base::Flags<DependencyGroup, uint32_t>;
896 
897   static const char* DependencyGroupName(DependencyGroup group);
898 
899   // Register a dependency of {code} on {object}, of the kinds given by
900   // {groups}.
901   V8_EXPORT_PRIVATE static void InstallDependency(Isolate* isolate,
902                                                   Handle<Code> code,
903                                                   Handle<HeapObject> object,
904                                                   DependencyGroups groups);
905 
906   void DeoptimizeDependentCodeGroup(Isolate* isolate, DependencyGroups groups);
907 
908   bool MarkCodeForDeoptimization(DependencyGroups deopt_groups);
909 
910   V8_EXPORT_PRIVATE static DependentCode empty_dependent_code(
911       const ReadOnlyRoots& roots);
912   static constexpr RootIndex kEmptyDependentCode =
913       RootIndex::kEmptyWeakArrayList;
914 
915   // Constants exposed for tests.
916   static constexpr int kSlotsPerEntry = 2;  // {code: weak Code, groups: Smi}.
917   static constexpr int kCodeSlotOffset = 0;
918   static constexpr int kGroupsSlotOffset = 1;
919 
920  private:
921   // Get/Set {object}'s {DependentCode}.
922   static DependentCode GetDependentCode(Handle<HeapObject> object);
923   static void SetDependentCode(Handle<HeapObject> object,
924                                Handle<DependentCode> dep);
925 
926   static Handle<DependentCode> New(Isolate* isolate, DependencyGroups groups,
927                                    Handle<Code> code);
928   static Handle<DependentCode> InsertWeakCode(Isolate* isolate,
929                                               Handle<DependentCode> entries,
930                                               DependencyGroups groups,
931                                               Handle<Code> code);
932 
933   // The callback is called for all non-cleared entries, and should return true
934   // iff the current entry should be cleared.
935   using IterateAndCompactFn = std::function<bool(CodeT, DependencyGroups)>;
936   void IterateAndCompact(const IterateAndCompactFn& fn);
937 
938   // Fills the given entry with the last non-cleared entry in this list, and
939   // returns the new length after the last non-cleared entry has been moved.
940   int FillEntryFromBack(int index, int length);
941 
LengthFor(int number_of_entries)942   static constexpr int LengthFor(int number_of_entries) {
943     return number_of_entries * kSlotsPerEntry;
944   }
945 
946   OBJECT_CONSTRUCTORS(DependentCode, WeakArrayList);
947 };
948 
DEFINE_OPERATORS_FOR_FLAGS(DependentCode::DependencyGroups)949 DEFINE_OPERATORS_FOR_FLAGS(DependentCode::DependencyGroups)
950 
951 // BytecodeArray represents a sequence of interpreter bytecodes.
952 class BytecodeArray
953     : public TorqueGeneratedBytecodeArray<BytecodeArray, FixedArrayBase> {
954  public:
955   DEFINE_TORQUE_GENERATED_OSRURGENCY_AND_INSTALL_TARGET()
956 
957   enum Age {
958     kNoAgeBytecodeAge = 0,
959     kQuadragenarianBytecodeAge,
960     kQuinquagenarianBytecodeAge,
961     kSexagenarianBytecodeAge,
962     kSeptuagenarianBytecodeAge,
963     kOctogenarianBytecodeAge,
964     kAfterLastBytecodeAge,
965     kFirstBytecodeAge = kNoAgeBytecodeAge,
966     kLastBytecodeAge = kAfterLastBytecodeAge - 1,
967     kBytecodeAgeCount = kAfterLastBytecodeAge - kFirstBytecodeAge - 1,
968     kIsOldBytecodeAge = kSexagenarianBytecodeAge
969   };
970 
971   static constexpr int SizeFor(int length) {
972     return OBJECT_POINTER_ALIGN(kHeaderSize + length);
973   }
974 
975   inline byte get(int index) const;
976   inline void set(int index, byte value);
977 
978   inline Address GetFirstBytecodeAddress();
979 
980   inline int32_t frame_size() const;
981   inline void set_frame_size(int32_t frame_size);
982 
983   // Note: The register count is derived from frame_size.
984   inline int register_count() const;
985 
986   // Note: the parameter count includes the implicit 'this' receiver.
987   inline int32_t parameter_count() const;
988   inline void set_parameter_count(int32_t number_of_parameters);
989 
990   inline interpreter::Register incoming_new_target_or_generator_register()
991       const;
992   inline void set_incoming_new_target_or_generator_register(
993       interpreter::Register incoming_new_target_or_generator_register);
994 
995   // The [osr_urgency] controls when OSR is attempted, and is incremented as
996   // the function becomes hotter. When the current loop depth is less than the
997   // osr_urgency, JumpLoop calls into runtime to attempt OSR optimization.
998   static constexpr int kMaxOsrUrgency = 6;
999   STATIC_ASSERT(kMaxOsrUrgency <= OsrUrgencyBits::kMax);
1000   inline int osr_urgency() const;
1001   inline void set_osr_urgency(int urgency);
1002   inline void reset_osr_urgency();
1003   inline void RequestOsrAtNextOpportunity();
1004 
1005   // The [osr_install_target] is used upon finishing concurrent OSR
1006   // compilation; instead of bumping the osr_urgency (which would target all
1007   // JumpLoops of appropriate loop_depth), we target a specific JumpLoop at the
1008   // given bytecode offset.
1009   static constexpr int kNoOsrInstallTarget = 0;
1010   static constexpr int OsrInstallTargetFor(BytecodeOffset offset) {
1011     // Any set `osr_install_target` must be non-zero since zero is the 'unset'
1012     // value and is ignored by generated code. For branchless code (both here
1013     // and in generated code), we simply OR in a 1.
1014     STATIC_ASSERT(kNoOsrInstallTarget == 0);
1015     return (offset.ToInt() | 1) &
1016            (OsrInstallTargetBits::kMask >> OsrInstallTargetBits::kShift);
1017   }
1018 
1019   inline int osr_install_target();
1020   inline void set_osr_install_target(BytecodeOffset jump_loop_offset);
1021   inline void reset_osr_install_target();
1022 
1023   inline void reset_osr_urgency_and_install_target();
1024 
1025   static constexpr int kBytecodeAgeSize = kUInt16Size;
1026   static_assert(kBytecodeAgeOffset + kBytecodeAgeSize - 1 ==
1027                 kBytecodeAgeOffsetEnd);
1028 
1029   // InterpreterEntryTrampoline and other builtins expect these fields to be
1030   // next to each other and fill 32 bits in total, since they write a 32-bit
1031   // value to reset them.
1032   static constexpr bool kOsrStateAndBytecodeAgeAreContiguous32Bits =
1033       kBytecodeAgeOffset == kOsrUrgencyAndInstallTargetOffset + kUInt16Size &&
1034       kBytecodeAgeSize == kUInt16Size;
1035   static_assert(kOsrStateAndBytecodeAgeAreContiguous32Bits);
1036 
1037   inline Age bytecode_age() const;
1038   inline void set_bytecode_age(Age age);
1039 
1040   inline bool HasSourcePositionTable() const;
1041   inline bool DidSourcePositionGenerationFail() const;
1042 
1043   // If source positions have not been collected or an exception has been thrown
1044   // this will return empty_byte_array.
1045   inline ByteArray SourcePositionTable() const;
1046 
1047   // Indicates that an attempt was made to collect source positions, but that it
1048   // failed most likely due to stack exhaustion. When in this state
1049   // |SourcePositionTable| will return an empty byte array rather than crashing
1050   // as it would if no attempt was ever made to collect source positions.
1051   inline void SetSourcePositionsFailedToCollect();
1052 
1053   inline int BytecodeArraySize();
1054 
1055   // Returns the size of bytecode and its metadata. This includes the size of
1056   // bytecode, constant pool, source position table, and handler table.
1057   inline int SizeIncludingMetadata();
1058 
1059   DECL_PRINTER(BytecodeArray)
1060   DECL_VERIFIER(BytecodeArray)
1061 
1062   V8_EXPORT_PRIVATE void Disassemble(std::ostream& os);
1063 
1064   void CopyBytecodesTo(BytecodeArray to);
1065 
1066   // Bytecode aging
1067   V8_EXPORT_PRIVATE bool IsOld() const;
1068   V8_EXPORT_PRIVATE void MakeOlder();
1069 
1070   // Clear uninitialized padding space. This ensures that the snapshot content
1071   // is deterministic.
1072   inline void clear_padding();
1073 
1074   // Maximal memory consumption for a single BytecodeArray.
1075   static const int kMaxSize = 512 * MB;
1076   // Maximal length of a single BytecodeArray.
1077   static const int kMaxLength = kMaxSize - kHeaderSize;
1078 
1079   class BodyDescriptor;
1080 
1081  private:
1082   // Hide accessors inherited from generated class. Use parameter_count instead.
1083   DECL_INT_ACCESSORS(parameter_size)
1084 
1085   TQ_OBJECT_CONSTRUCTORS(BytecodeArray)
1086 };
1087 
1088 // This class holds data required during deoptimization. It does not have its
1089 // own instance type.
1090 class DeoptimizationLiteralArray : public WeakFixedArray {
1091  public:
1092   // Getters for literals. These include runtime checks that the pointer was not
1093   // cleared, if the literal was held weakly.
1094   inline Object get(int index) const;
1095   inline Object get(PtrComprCageBase cage_base, int index) const;
1096 
1097   // Setter for literals. This will set the object as strong or weak depending
1098   // on Code::IsWeakObjectInOptimizedCode.
1099   inline void set(int index, Object value);
1100 
1101   DECL_CAST(DeoptimizationLiteralArray)
1102 
1103   OBJECT_CONSTRUCTORS(DeoptimizationLiteralArray, WeakFixedArray);
1104 };
1105 
1106 // DeoptimizationData is a fixed array used to hold the deoptimization data for
1107 // optimized code.  It also contains information about functions that were
1108 // inlined.  If N different functions were inlined then the first N elements of
1109 // the literal array will contain these functions.
1110 //
1111 // It can be empty.
1112 class DeoptimizationData : public FixedArray {
1113  public:
1114   // Layout description.  Indices in the array.
1115   static const int kTranslationByteArrayIndex = 0;
1116   static const int kInlinedFunctionCountIndex = 1;
1117   static const int kLiteralArrayIndex = 2;
1118   static const int kOsrBytecodeOffsetIndex = 3;
1119   static const int kOsrPcOffsetIndex = 4;
1120   static const int kOptimizationIdIndex = 5;
1121   static const int kSharedFunctionInfoIndex = 6;
1122   static const int kInliningPositionsIndex = 7;
1123   static const int kDeoptExitStartIndex = 8;
1124   static const int kEagerDeoptCountIndex = 9;
1125   static const int kLazyDeoptCountIndex = 10;
1126   static const int kFirstDeoptEntryIndex = 11;
1127 
1128   // Offsets of deopt entry elements relative to the start of the entry.
1129   static const int kBytecodeOffsetRawOffset = 0;
1130   static const int kTranslationIndexOffset = 1;
1131   static const int kPcOffset = 2;
1132 #ifdef DEBUG
1133   static const int kNodeIdOffset = 3;
1134   static const int kDeoptEntrySize = 4;
1135 #else   // DEBUG
1136   static const int kDeoptEntrySize = 3;
1137 #endif  // DEBUG
1138 
1139 // Simple element accessors.
1140 #define DECL_ELEMENT_ACCESSORS(name, type) \
1141   inline type name() const;                \
1142   inline void Set##name(type value);
1143 
1144   DECL_ELEMENT_ACCESSORS(TranslationByteArray, TranslationArray)
1145   DECL_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
1146   DECL_ELEMENT_ACCESSORS(LiteralArray, DeoptimizationLiteralArray)
1147   DECL_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
1148   DECL_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
1149   DECL_ELEMENT_ACCESSORS(OptimizationId, Smi)
1150   DECL_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
1151   DECL_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
1152   DECL_ELEMENT_ACCESSORS(DeoptExitStart, Smi)
1153   DECL_ELEMENT_ACCESSORS(EagerDeoptCount, Smi)
1154   DECL_ELEMENT_ACCESSORS(LazyDeoptCount, Smi)
1155 
1156 #undef DECL_ELEMENT_ACCESSORS
1157 
1158 // Accessors for elements of the ith deoptimization entry.
1159 #define DECL_ENTRY_ACCESSORS(name, type) \
1160   inline type name(int i) const;         \
1161   inline void Set##name(int i, type value);
1162 
1163   DECL_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
1164   DECL_ENTRY_ACCESSORS(TranslationIndex, Smi)
1165   DECL_ENTRY_ACCESSORS(Pc, Smi)
1166 #ifdef DEBUG
1167   DECL_ENTRY_ACCESSORS(NodeId, Smi)
1168 #endif  // DEBUG
1169 
1170 #undef DECL_ENTRY_ACCESSORS
1171 
1172   inline BytecodeOffset GetBytecodeOffset(int i);
1173 
1174   inline void SetBytecodeOffset(int i, BytecodeOffset value);
1175 
1176   inline int DeoptCount();
1177 
1178   static const int kNotInlinedIndex = -1;
1179 
1180   // Returns the inlined function at the given position in LiteralArray, or the
1181   // outer function if index == kNotInlinedIndex.
1182   class SharedFunctionInfo GetInlinedFunction(int index);
1183 
1184   // Allocates a DeoptimizationData.
1185   static Handle<DeoptimizationData> New(Isolate* isolate, int deopt_entry_count,
1186                                         AllocationType allocation);
1187 
1188   // Return an empty DeoptimizationData.
1189   V8_EXPORT_PRIVATE static Handle<DeoptimizationData> Empty(Isolate* isolate);
1190 
1191   DECL_CAST(DeoptimizationData)
1192 
1193 #ifdef ENABLE_DISASSEMBLER
1194   void DeoptimizationDataPrint(std::ostream& os);
1195 #endif
1196 
1197  private:
IndexForEntry(int i)1198   static int IndexForEntry(int i) {
1199     return kFirstDeoptEntryIndex + (i * kDeoptEntrySize);
1200   }
1201 
LengthFor(int entry_count)1202   static int LengthFor(int entry_count) { return IndexForEntry(entry_count); }
1203 
1204   OBJECT_CONSTRUCTORS(DeoptimizationData, FixedArray);
1205 };
1206 
1207 }  // namespace internal
1208 }  // namespace v8
1209 
1210 #include "src/objects/object-macros-undef.h"
1211 
1212 #endif  // V8_OBJECTS_CODE_H_
1213