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_INL_H_
6 : #define V8_OBJECTS_CODE_INL_H_
7 :
8 : #include "src/objects/code.h"
9 :
10 : #include "src/interpreter/bytecode-register.h"
11 : #include "src/isolate.h"
12 : #include "src/objects/dictionary.h"
13 : #include "src/objects/instance-type-inl.h"
14 : #include "src/objects/map-inl.h"
15 : #include "src/objects/maybe-object-inl.h"
16 : #include "src/objects/smi-inl.h"
17 : #include "src/v8memory.h"
18 :
19 : // Has to be the last include (doesn't have include guards):
20 : #include "src/objects/object-macros.h"
21 :
22 : namespace v8 {
23 : namespace internal {
24 :
25 10026358 : OBJECT_CONSTRUCTORS_IMPL(DeoptimizationData, FixedArray)
26 336957336 : OBJECT_CONSTRUCTORS_IMPL(BytecodeArray, FixedArrayBase)
27 32782758 : OBJECT_CONSTRUCTORS_IMPL(AbstractCode, HeapObject)
28 121184480 : OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakFixedArray)
29 294403074 : OBJECT_CONSTRUCTORS_IMPL(CodeDataContainer, HeapObject)
30 672892 : OBJECT_CONSTRUCTORS_IMPL(SourcePositionTableWithFrameCache, Tuple2)
31 :
32 : NEVER_READ_ONLY_SPACE_IMPL(AbstractCode)
33 :
34 13728886 : CAST_ACCESSOR(AbstractCode)
35 168496496 : CAST_ACCESSOR(BytecodeArray)
36 443429471 : CAST_ACCESSOR(Code)
37 147207280 : CAST_ACCESSOR(CodeDataContainer)
38 60592278 : CAST_ACCESSOR(DependentCode)
39 5013177 : CAST_ACCESSOR(DeoptimizationData)
40 336446 : CAST_ACCESSOR(SourcePositionTableWithFrameCache)
41 :
42 844275 : ACCESSORS(SourcePositionTableWithFrameCache, source_position_table, ByteArray,
43 : kSourcePositionTableIndex)
44 226751 : ACCESSORS(SourcePositionTableWithFrameCache, stack_frame_cache,
45 : SimpleNumberDictionary, kStackFrameCacheIndex)
46 :
47 : int AbstractCode::raw_instruction_size() {
48 : if (IsCode()) {
49 : return GetCode()->raw_instruction_size();
50 : } else {
51 : return GetBytecodeArray()->length();
52 : }
53 : }
54 :
55 661138 : int AbstractCode::InstructionSize() {
56 1322276 : if (IsCode()) {
57 158264 : return GetCode()->InstructionSize();
58 : } else {
59 1005748 : return GetBytecodeArray()->length();
60 : }
61 : }
62 :
63 2191504 : ByteArray AbstractCode::source_position_table() {
64 4383008 : if (IsCode()) {
65 103042 : return GetCode()->SourcePositionTable();
66 : } else {
67 2088462 : return GetBytecodeArray()->SourcePositionTable();
68 : }
69 : }
70 :
71 66151 : Object AbstractCode::stack_frame_cache() {
72 66151 : Object maybe_table;
73 132302 : if (IsCode()) {
74 0 : maybe_table = GetCode()->source_position_table();
75 : } else {
76 66151 : maybe_table = GetBytecodeArray()->source_position_table();
77 : }
78 66151 : if (maybe_table->IsSourcePositionTableWithFrameCache()) {
79 : return SourcePositionTableWithFrameCache::cast(maybe_table)
80 58027 : ->stack_frame_cache();
81 : }
82 8124 : return Smi::kZero;
83 : }
84 :
85 0 : int AbstractCode::SizeIncludingMetadata() {
86 0 : if (IsCode()) {
87 0 : return GetCode()->SizeIncludingMetadata();
88 : } else {
89 0 : return GetBytecodeArray()->SizeIncludingMetadata();
90 : }
91 : }
92 10 : int AbstractCode::ExecutableSize() {
93 20 : if (IsCode()) {
94 4 : return GetCode()->ExecutableSize();
95 : } else {
96 8 : return GetBytecodeArray()->BytecodeArraySize();
97 : }
98 : }
99 :
100 25 : Address AbstractCode::raw_instruction_start() {
101 50 : if (IsCode()) {
102 16 : return GetCode()->raw_instruction_start();
103 : } else {
104 34 : return GetBytecodeArray()->GetFirstBytecodeAddress();
105 : }
106 : }
107 :
108 1292665 : Address AbstractCode::InstructionStart() {
109 2585330 : if (IsCode()) {
110 286293 : return GetCode()->InstructionStart();
111 : } else {
112 2012744 : return GetBytecodeArray()->GetFirstBytecodeAddress();
113 : }
114 : }
115 :
116 15 : Address AbstractCode::raw_instruction_end() {
117 30 : if (IsCode()) {
118 6 : return GetCode()->raw_instruction_end();
119 : } else {
120 36 : return GetBytecodeArray()->GetFirstBytecodeAddress() +
121 24 : GetBytecodeArray()->length();
122 : }
123 : }
124 :
125 : Address AbstractCode::InstructionEnd() {
126 : if (IsCode()) {
127 : return GetCode()->InstructionEnd();
128 : } else {
129 : return GetBytecodeArray()->GetFirstBytecodeAddress() +
130 : GetBytecodeArray()->length();
131 : }
132 : }
133 :
134 20 : bool AbstractCode::contains(Address inner_pointer) {
135 20 : return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
136 : }
137 :
138 92225 : AbstractCode::Kind AbstractCode::kind() {
139 184450 : if (IsCode()) {
140 177976 : return static_cast<AbstractCode::Kind>(GetCode()->kind());
141 : } else {
142 : return INTERPRETED_FUNCTION;
143 : }
144 : }
145 :
146 3171560 : Code AbstractCode::GetCode() { return Code::cast(*this); }
147 :
148 3677562 : BytecodeArray AbstractCode::GetBytecodeArray() {
149 3677562 : return BytecodeArray::cast(*this);
150 : }
151 :
152 685 : DependentCode DependentCode::next_link() {
153 1370 : return DependentCode::cast(Get(kNextLinkIndex)->GetHeapObjectAssumeStrong());
154 : }
155 :
156 : void DependentCode::set_next_link(DependentCode next) {
157 219704 : Set(kNextLinkIndex, HeapObjectReference::Strong(next));
158 : }
159 :
160 2665965 : int DependentCode::flags() { return Smi::ToInt(Get(kFlagsIndex)->ToSmi()); }
161 :
162 : void DependentCode::set_flags(int flags) {
163 625114 : Set(kFlagsIndex, MaybeObject::FromObject(Smi::FromInt(flags)));
164 : }
165 :
166 950411 : int DependentCode::count() { return CountField::decode(flags()); }
167 :
168 405712 : void DependentCode::set_count(int value) {
169 811424 : set_flags(CountField::update(flags(), value));
170 405711 : }
171 :
172 : DependentCode::DependencyGroup DependentCode::group() {
173 1309852 : return static_cast<DependencyGroup>(GroupField::decode(flags()));
174 : }
175 :
176 : void DependentCode::set_object_at(int i, MaybeObject object) {
177 520296 : Set(kCodesStartIndex + i, object);
178 : }
179 :
180 : MaybeObject DependentCode::object_at(int i) {
181 84360436 : return Get(kCodesStartIndex + i);
182 : }
183 :
184 58103 : void DependentCode::clear_at(int i) {
185 : Set(kCodesStartIndex + i,
186 116206 : HeapObjectReference::Strong(GetReadOnlyRoots().undefined_value()));
187 58103 : }
188 :
189 12396 : void DependentCode::copy(int from, int to) {
190 12396 : Set(kCodesStartIndex + to, Get(kCodesStartIndex + from));
191 12396 : }
192 :
193 883725560 : OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
194 : NEVER_READ_ONLY_SPACE_IMPL(Code)
195 :
196 545301132 : INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset)
197 44651040 : INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset)
198 : #define CODE_ACCESSORS(name, type, offset) \
199 : ACCESSORS_CHECKED2(Code, name, type, offset, true, !Heap::InNewSpace(value))
200 : #define SYNCHRONIZED_CODE_ACCESSORS(name, type, offset) \
201 : SYNCHRONIZED_ACCESSORS_CHECKED2(Code, name, type, offset, true, \
202 : !Heap::InNewSpace(value))
203 :
204 15739235 : CODE_ACCESSORS(relocation_info, ByteArray, kRelocationInfoOffset)
205 24635641 : CODE_ACCESSORS(deoptimization_data, FixedArray, kDeoptimizationDataOffset)
206 132294041 : CODE_ACCESSORS(source_position_table, Object, kSourcePositionTableOffset)
207 : // Concurrent marker needs to access kind specific flags in code data container.
208 67898271 : SYNCHRONIZED_CODE_ACCESSORS(code_data_container, CodeDataContainer,
209 : kCodeDataContainerOffset)
210 : #undef CODE_ACCESSORS
211 : #undef SYNCHRONIZED_CODE_ACCESSORS
212 :
213 379269 : void Code::WipeOutHeader() {
214 379269 : WRITE_FIELD(this, kRelocationInfoOffset, Smi::FromInt(0));
215 379269 : WRITE_FIELD(this, kDeoptimizationDataOffset, Smi::FromInt(0));
216 379269 : WRITE_FIELD(this, kSourcePositionTableOffset, Smi::FromInt(0));
217 379269 : WRITE_FIELD(this, kCodeDataContainerOffset, Smi::FromInt(0));
218 379269 : }
219 :
220 2200279 : void Code::clear_padding() {
221 2200279 : memset(reinterpret_cast<void*>(address() + kHeaderPaddingStart), 0,
222 2200279 : kHeaderSize - kHeaderPaddingStart);
223 : Address data_end =
224 2200279 : has_unwinding_info() ? unwinding_info_end() : raw_instruction_end();
225 : memset(reinterpret_cast<void*>(data_end), 0,
226 4400558 : CodeSize() - (data_end - address()));
227 2200279 : }
228 :
229 38347932 : ByteArray Code::SourcePositionTable() const {
230 38347932 : Object maybe_table = source_position_table();
231 38347934 : if (maybe_table->IsByteArray()) return ByteArray::cast(maybe_table);
232 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
233 : return SourcePositionTableWithFrameCache::cast(maybe_table)
234 0 : ->source_position_table();
235 : }
236 :
237 : Object Code::next_code_link() const {
238 9490039 : return code_data_container()->next_code_link();
239 : }
240 :
241 785414 : void Code::set_next_code_link(Object value) {
242 785414 : code_data_container()->set_next_code_link(value);
243 785414 : }
244 :
245 38410815 : int Code::InstructionSize() const {
246 38410815 : if (is_off_heap_trampoline()) {
247 : DCHECK(FLAG_embedded_builtins);
248 38309337 : return OffHeapInstructionSize();
249 : }
250 101478 : return raw_instruction_size();
251 : }
252 :
253 : Address Code::raw_instruction_start() const {
254 266829419 : return FIELD_ADDR(this, kHeaderSize);
255 : }
256 :
257 245139968 : Address Code::InstructionStart() const {
258 245139968 : if (is_off_heap_trampoline()) {
259 : DCHECK(FLAG_embedded_builtins);
260 235276716 : return OffHeapInstructionStart();
261 : }
262 9863252 : return raw_instruction_start();
263 : }
264 :
265 : Address Code::raw_instruction_end() const {
266 2200565 : return raw_instruction_start() + raw_instruction_size();
267 : }
268 :
269 306 : Address Code::InstructionEnd() const {
270 306 : if (is_off_heap_trampoline()) {
271 : DCHECK(FLAG_embedded_builtins);
272 0 : return OffHeapInstructionEnd();
273 : }
274 306 : return raw_instruction_end();
275 : }
276 :
277 : int Code::GetUnwindingInfoSizeOffset() const {
278 : DCHECK(has_unwinding_info());
279 140 : return RoundUp(kHeaderSize + raw_instruction_size(), kInt64Size);
280 : }
281 :
282 : int Code::unwinding_info_size() const {
283 : DCHECK(has_unwinding_info());
284 : return static_cast<int>(
285 74 : READ_UINT64_FIELD(this, GetUnwindingInfoSizeOffset()));
286 : }
287 :
288 : void Code::set_unwinding_info_size(int value) {
289 : DCHECK(has_unwinding_info());
290 28 : WRITE_UINT64_FIELD(this, GetUnwindingInfoSizeOffset(), value);
291 : }
292 :
293 : Address Code::unwinding_info_start() const {
294 : DCHECK(has_unwinding_info());
295 107 : return FIELD_ADDR(this, GetUnwindingInfoSizeOffset()) + kInt64Size;
296 : }
297 :
298 : Address Code::unwinding_info_end() const {
299 : DCHECK(has_unwinding_info());
300 69 : return unwinding_info_start() + unwinding_info_size();
301 : }
302 :
303 536424274 : int Code::body_size() const {
304 : int unpadded_body_size =
305 : has_unwinding_info()
306 : ? static_cast<int>(unwinding_info_end() - raw_instruction_start())
307 536424346 : : raw_instruction_size();
308 536424274 : return RoundUp(unpadded_body_size, kObjectAlignment);
309 : }
310 :
311 0 : int Code::SizeIncludingMetadata() const {
312 : int size = CodeSize();
313 0 : size += relocation_info()->Size();
314 0 : size += deoptimization_data()->Size();
315 0 : return size;
316 : }
317 :
318 : ByteArray Code::unchecked_relocation_info() const {
319 210360681 : return ByteArray::unchecked_cast(READ_FIELD(this, kRelocationInfoOffset));
320 : }
321 :
322 : byte* Code::relocation_start() const {
323 : return unchecked_relocation_info()->GetDataStartAddress();
324 : }
325 :
326 : byte* Code::relocation_end() const {
327 0 : return unchecked_relocation_info()->GetDataEndAddress();
328 : }
329 :
330 85557 : int Code::relocation_size() const {
331 85557 : return unchecked_relocation_info()->length();
332 : }
333 :
334 : Address Code::entry() const { return raw_instruction_start(); }
335 :
336 11192493 : bool Code::contains(Address inner_pointer) {
337 11192493 : if (is_off_heap_trampoline()) {
338 : DCHECK(FLAG_embedded_builtins);
339 429452 : if (OffHeapInstructionStart() <= inner_pointer &&
340 96694 : inner_pointer < OffHeapInstructionEnd()) {
341 : return true;
342 : }
343 : }
344 11108462 : return (address() <= inner_pointer) && (inner_pointer < address() + Size());
345 : }
346 :
347 : int Code::ExecutableSize() const {
348 : // Check that the assumptions about the layout of the code object holds.
349 : DCHECK_EQ(static_cast<int>(raw_instruction_start() - address()),
350 : Code::kHeaderSize);
351 2 : return raw_instruction_size() + Code::kHeaderSize;
352 : }
353 :
354 : // static
355 : void Code::CopyRelocInfoToByteArray(ByteArray dest, const CodeDesc& desc) {
356 : DCHECK_EQ(dest->length(), desc.reloc_size);
357 : CopyBytes(dest->GetDataStartAddress(),
358 2200327 : desc.buffer + desc.buffer_size - desc.reloc_size,
359 6600981 : static_cast<size_t>(desc.reloc_size));
360 : }
361 :
362 536200770 : int Code::CodeSize() const { return SizeFor(body_size()); }
363 :
364 4948 : Code::Kind Code::kind() const {
365 68708135 : return KindField::decode(READ_UINT32_FIELD(this, kFlagsOffset));
366 : }
367 :
368 2284895 : void Code::initialize_flags(Kind kind, bool has_unwinding_info,
369 : bool is_turbofanned, int stack_slots,
370 : bool is_off_heap_trampoline) {
371 2284895 : CHECK(0 <= stack_slots && stack_slots < StackSlotsField::kMax);
372 : static_assert(Code::NUMBER_OF_KINDS <= KindField::kMax + 1, "field overflow");
373 2284895 : uint32_t flags = HasUnwindingInfoField::encode(has_unwinding_info) |
374 2284895 : KindField::encode(kind) |
375 2284895 : IsTurbofannedField::encode(is_turbofanned) |
376 : StackSlotsField::encode(stack_slots) |
377 2284895 : IsOffHeapTrampoline::encode(is_off_heap_trampoline);
378 2284895 : WRITE_UINT32_FIELD(this, kFlagsOffset, flags);
379 : DCHECK_IMPLIES(stack_slots != 0, has_safepoint_info());
380 2284895 : }
381 :
382 : inline bool Code::is_interpreter_trampoline_builtin() const {
383 : bool is_interpreter_trampoline =
384 1703871 : (builtin_index() == Builtins::kInterpreterEntryTrampoline ||
385 28608633 : builtin_index() == Builtins::kInterpreterEnterBytecodeAdvance ||
386 : builtin_index() == Builtins::kInterpreterEnterBytecodeDispatch);
387 : return is_interpreter_trampoline;
388 : }
389 :
390 : inline bool Code::checks_optimization_marker() const {
391 : bool checks_marker =
392 : (builtin_index() == Builtins::kCompileLazy ||
393 : builtin_index() == Builtins::kInterpreterEntryTrampoline);
394 : return checks_marker ||
395 : (kind() == OPTIMIZED_FUNCTION && marked_for_deoptimization());
396 : }
397 :
398 : inline bool Code::has_tagged_params() const {
399 1267064 : return kind() != JS_TO_WASM_FUNCTION && kind() != C_WASM_ENTRY &&
400 : kind() != WASM_FUNCTION;
401 : }
402 :
403 : inline bool Code::has_unwinding_info() const {
404 538709184 : return HasUnwindingInfoField::decode(READ_UINT32_FIELD(this, kFlagsOffset));
405 : }
406 :
407 5653 : inline bool Code::is_turbofanned() const {
408 76755848 : return IsTurbofannedField::decode(READ_UINT32_FIELD(this, kFlagsOffset));
409 : }
410 :
411 644315 : inline bool Code::can_have_weak_objects() const {
412 : DCHECK(kind() == OPTIMIZED_FUNCTION);
413 1288636 : int32_t flags = code_data_container()->kind_specific_flags();
414 644321 : return CanHaveWeakObjectsField::decode(flags);
415 : }
416 :
417 451810 : inline void Code::set_can_have_weak_objects(bool value) {
418 : DCHECK(kind() == OPTIMIZED_FUNCTION);
419 903620 : int32_t previous = code_data_container()->kind_specific_flags();
420 : int32_t updated = CanHaveWeakObjectsField::update(previous, value);
421 903620 : code_data_container()->set_kind_specific_flags(updated);
422 451810 : }
423 :
424 7005 : inline bool Code::is_promise_rejection() const {
425 : DCHECK(kind() == BUILTIN);
426 14010 : int32_t flags = code_data_container()->kind_specific_flags();
427 7005 : return IsPromiseRejectionField::decode(flags);
428 : }
429 :
430 784 : inline void Code::set_is_promise_rejection(bool value) {
431 : DCHECK(kind() == BUILTIN);
432 1568 : int32_t previous = code_data_container()->kind_specific_flags();
433 : int32_t updated = IsPromiseRejectionField::update(previous, value);
434 1568 : code_data_container()->set_kind_specific_flags(updated);
435 784 : }
436 :
437 5192 : inline bool Code::is_exception_caught() const {
438 : DCHECK(kind() == BUILTIN);
439 10384 : int32_t flags = code_data_container()->kind_specific_flags();
440 5192 : return IsExceptionCaughtField::decode(flags);
441 : }
442 :
443 56 : inline void Code::set_is_exception_caught(bool value) {
444 : DCHECK(kind() == BUILTIN);
445 112 : int32_t previous = code_data_container()->kind_specific_flags();
446 : int32_t updated = IsExceptionCaughtField::update(previous, value);
447 112 : code_data_container()->set_kind_specific_flags(updated);
448 56 : }
449 :
450 : inline bool Code::is_off_heap_trampoline() const {
451 332988475 : return IsOffHeapTrampoline::decode(READ_UINT32_FIELD(this, kFlagsOffset));
452 : }
453 :
454 7005 : inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() {
455 7005 : if (is_promise_rejection()) return HandlerTable::PROMISE;
456 5192 : if (is_exception_caught()) return HandlerTable::CAUGHT;
457 5124 : return HandlerTable::UNCAUGHT;
458 : }
459 :
460 : int Code::builtin_index() const {
461 309955951 : int index = READ_INT_FIELD(this, kBuiltinIndexOffset);
462 : DCHECK(index == -1 || Builtins::IsBuiltinId(index));
463 : return index;
464 : }
465 :
466 : void Code::set_builtin_index(int index) {
467 : DCHECK(index == -1 || Builtins::IsBuiltinId(index));
468 2284895 : WRITE_INT_FIELD(this, kBuiltinIndexOffset, index);
469 : }
470 :
471 : bool Code::is_builtin() const { return builtin_index() != -1; }
472 :
473 : bool Code::has_safepoint_info() const {
474 79763860 : return is_turbofanned() || is_wasm_code();
475 : }
476 :
477 : int Code::stack_slots() const {
478 : DCHECK(has_safepoint_info());
479 44288534 : return StackSlotsField::decode(READ_UINT32_FIELD(this, kFlagsOffset));
480 : }
481 :
482 : int Code::safepoint_table_offset() const {
483 : DCHECK(has_safepoint_info());
484 39799843 : return READ_INT32_FIELD(this, kSafepointTableOffsetOffset);
485 : }
486 :
487 2265240 : void Code::set_safepoint_table_offset(int offset) {
488 2265240 : CHECK_LE(0, offset);
489 : DCHECK(has_safepoint_info() || offset == 0); // Allow zero initialization.
490 : DCHECK(IsAligned(offset, static_cast<unsigned>(kIntSize)));
491 2265240 : WRITE_INT32_FIELD(this, kSafepointTableOffsetOffset, offset);
492 2265240 : }
493 :
494 5419944 : bool Code::marked_for_deoptimization() const {
495 : DCHECK(kind() == OPTIMIZED_FUNCTION);
496 10839889 : int32_t flags = code_data_container()->kind_specific_flags();
497 5419945 : return MarkedForDeoptimizationField::decode(flags);
498 : }
499 :
500 328405 : void Code::set_marked_for_deoptimization(bool flag) {
501 : DCHECK(kind() == OPTIMIZED_FUNCTION);
502 : DCHECK_IMPLIES(flag, AllowDeoptimization::IsAllowed(GetIsolate()));
503 656810 : int32_t previous = code_data_container()->kind_specific_flags();
504 : int32_t updated = MarkedForDeoptimizationField::update(previous, flag);
505 656810 : code_data_container()->set_kind_specific_flags(updated);
506 328405 : }
507 :
508 808 : bool Code::embedded_objects_cleared() const {
509 : DCHECK(kind() == OPTIMIZED_FUNCTION);
510 1616 : int32_t flags = code_data_container()->kind_specific_flags();
511 808 : return EmbeddedObjectsClearedField::decode(flags);
512 : }
513 :
514 282 : void Code::set_embedded_objects_cleared(bool flag) {
515 : DCHECK(kind() == OPTIMIZED_FUNCTION);
516 : DCHECK_IMPLIES(flag, marked_for_deoptimization());
517 564 : int32_t previous = code_data_container()->kind_specific_flags();
518 : int32_t updated = EmbeddedObjectsClearedField::update(previous, flag);
519 564 : code_data_container()->set_kind_specific_flags(updated);
520 282 : }
521 :
522 180381 : bool Code::deopt_already_counted() const {
523 : DCHECK(kind() == OPTIMIZED_FUNCTION);
524 360762 : int32_t flags = code_data_container()->kind_specific_flags();
525 180381 : return DeoptAlreadyCountedField::decode(flags);
526 : }
527 :
528 157611 : void Code::set_deopt_already_counted(bool flag) {
529 : DCHECK(kind() == OPTIMIZED_FUNCTION);
530 : DCHECK_IMPLIES(flag, AllowDeoptimization::IsAllowed(GetIsolate()));
531 315222 : int32_t previous = code_data_container()->kind_specific_flags();
532 : int32_t updated = DeoptAlreadyCountedField::update(previous, flag);
533 315222 : code_data_container()->set_kind_specific_flags(updated);
534 157611 : }
535 :
536 : bool Code::is_optimized_code() const { return kind() == OPTIMIZED_FUNCTION; }
537 : bool Code::is_wasm_code() const { return kind() == WASM_FUNCTION; }
538 :
539 : int Code::constant_pool_offset() const {
540 : if (!FLAG_enable_embedded_constant_pool) return code_comments_offset();
541 : return READ_INT_FIELD(this, kConstantPoolOffset);
542 : }
543 :
544 : void Code::set_constant_pool_offset(int value) {
545 : if (!FLAG_enable_embedded_constant_pool) return;
546 : DCHECK_LE(value, InstructionSize());
547 : WRITE_INT_FIELD(this, kConstantPoolOffset, value);
548 : }
549 :
550 : int Code::constant_pool_size() const {
551 : if (!FLAG_enable_embedded_constant_pool) return 0;
552 : return code_comments_offset() - constant_pool_offset();
553 : }
554 : Address Code::constant_pool() const {
555 : if (FLAG_enable_embedded_constant_pool) {
556 : int offset = constant_pool_offset();
557 : if (offset < code_comments_offset()) {
558 : return InstructionStart() + offset;
559 : }
560 : }
561 : return kNullAddress;
562 : }
563 :
564 : int Code::code_comments_offset() const {
565 76574410 : int offset = READ_INT_FIELD(this, kCodeCommentsOffset);
566 : DCHECK_LE(0, offset);
567 : DCHECK_LE(offset, InstructionSize());
568 : return offset;
569 : }
570 :
571 : void Code::set_code_comments_offset(int offset) {
572 : DCHECK_LE(0, offset);
573 : DCHECK_LE(offset, InstructionSize());
574 2284894 : WRITE_INT_FIELD(this, kCodeCommentsOffset, offset);
575 : }
576 :
577 10 : Address Code::code_comments() const {
578 : int offset = code_comments_offset();
579 10 : if (offset < InstructionSize()) {
580 10 : return InstructionStart() + offset;
581 : }
582 : return kNullAddress;
583 : }
584 :
585 3525006 : Code Code::GetCodeFromTargetAddress(Address address) {
586 : {
587 : // TODO(jgruber,v8:6666): Support embedded builtins here. We'd need to pass
588 : // in the current isolate.
589 3525006 : Address start = reinterpret_cast<Address>(Isolate::CurrentEmbeddedBlob());
590 3525002 : Address end = start + Isolate::CurrentEmbeddedBlobSize();
591 3525005 : CHECK(address < start || address >= end);
592 : }
593 :
594 : HeapObject code = HeapObject::FromAddress(address - Code::kHeaderSize);
595 : // Unchecked cast because we can't rely on the map currently
596 : // not being a forwarding pointer.
597 3525005 : return Code::unchecked_cast(code);
598 : }
599 :
600 : Code Code::GetObjectFromEntryAddress(Address location_of_address) {
601 0 : Address code_entry = Memory<Address>(location_of_address);
602 : HeapObject code = HeapObject::FromAddress(code_entry - Code::kHeaderSize);
603 : // Unchecked cast because we can't rely on the map currently
604 : // not being a forwarding pointer.
605 : return Code::unchecked_cast(code);
606 : }
607 :
608 646444 : bool Code::CanContainWeakObjects() {
609 646444 : return is_optimized_code() && can_have_weak_objects();
610 : }
611 :
612 646444 : bool Code::IsWeakObject(HeapObject object) {
613 646444 : return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object));
614 : }
615 :
616 5190103 : bool Code::IsWeakObjectInOptimizedCode(HeapObject object) {
617 : Map map = object->synchronized_map();
618 : InstanceType instance_type = map->instance_type();
619 5190103 : if (InstanceTypeChecker::IsMap(instance_type)) {
620 : return Map::cast(object)->CanTransition();
621 : }
622 4916371 : return InstanceTypeChecker::IsPropertyCell(instance_type) ||
623 9104363 : InstanceTypeChecker::IsJSReceiver(instance_type) ||
624 5017752 : InstanceTypeChecker::IsContext(instance_type);
625 : }
626 :
627 : // This field has to have relaxed atomic accessors because it is accessed in the
628 : // concurrent marker.
629 10505249 : RELAXED_INT32_ACCESSORS(CodeDataContainer, kind_specific_flags,
630 : kKindSpecificFlagsOffset)
631 40317030 : ACCESSORS(CodeDataContainer, next_code_link, Object, kNextCodeLinkOffset)
632 :
633 2200371 : void CodeDataContainer::clear_padding() {
634 2200371 : memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0,
635 2200371 : kSize - kUnalignedSize);
636 2200371 : }
637 :
638 66688 : byte BytecodeArray::get(int index) {
639 : DCHECK(index >= 0 && index < this->length());
640 301160664 : return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
641 : }
642 :
643 : void BytecodeArray::set(int index, byte value) {
644 : DCHECK(index >= 0 && index < this->length());
645 14301404 : WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
646 : }
647 :
648 : void BytecodeArray::set_frame_size(int frame_size) {
649 : DCHECK_GE(frame_size, 0);
650 : DCHECK(IsAligned(frame_size, kSystemPointerSize));
651 2116378 : WRITE_INT_FIELD(this, kFrameSizeOffset, frame_size);
652 : }
653 :
654 : int BytecodeArray::frame_size() const {
655 29799480 : return READ_INT_FIELD(this, kFrameSizeOffset);
656 : }
657 :
658 8619 : int BytecodeArray::register_count() const {
659 29786596 : return frame_size() / kSystemPointerSize;
660 : }
661 :
662 : void BytecodeArray::set_parameter_count(int number_of_parameters) {
663 : DCHECK_GE(number_of_parameters, 0);
664 : // Parameter count is stored as the size on stack of the parameters to allow
665 : // it to be used directly by generated code.
666 4232742 : WRITE_INT_FIELD(this, kParameterSizeOffset,
667 4232742 : (number_of_parameters << kSystemPointerSizeLog2));
668 : }
669 :
670 : interpreter::Register BytecodeArray::incoming_new_target_or_generator_register()
671 : const {
672 : int register_operand =
673 533670 : READ_INT_FIELD(this, kIncomingNewTargetOrGeneratorRegisterOffset);
674 533670 : if (register_operand == 0) {
675 : return interpreter::Register::invalid_value();
676 : } else {
677 : return interpreter::Register::FromOperand(register_operand);
678 : }
679 : }
680 :
681 : void BytecodeArray::set_incoming_new_target_or_generator_register(
682 : interpreter::Register incoming_new_target_or_generator_register) {
683 116684 : if (!incoming_new_target_or_generator_register.is_valid()) {
684 2115790 : WRITE_INT_FIELD(this, kIncomingNewTargetOrGeneratorRegisterOffset, 0);
685 : } else {
686 : DCHECK(incoming_new_target_or_generator_register.index() <
687 : register_count());
688 : DCHECK_NE(0, incoming_new_target_or_generator_register.ToOperand());
689 106719 : WRITE_INT_FIELD(this, kIncomingNewTargetOrGeneratorRegisterOffset,
690 213438 : incoming_new_target_or_generator_register.ToOperand());
691 : }
692 : }
693 :
694 : int BytecodeArray::interrupt_budget() const {
695 10543 : return READ_INT_FIELD(this, kInterruptBudgetOffset);
696 : }
697 :
698 : void BytecodeArray::set_interrupt_budget(int interrupt_budget) {
699 : DCHECK_GE(interrupt_budget, 0);
700 2117117 : WRITE_INT_FIELD(this, kInterruptBudgetOffset, interrupt_budget);
701 : }
702 :
703 : int BytecodeArray::osr_loop_nesting_level() const {
704 42249 : return READ_INT8_FIELD(this, kOSRNestingLevelOffset);
705 : }
706 :
707 : void BytecodeArray::set_osr_loop_nesting_level(int depth) {
708 : DCHECK(0 <= depth && depth <= AbstractCode::kMaxLoopNestingMarker);
709 : STATIC_ASSERT(AbstractCode::kMaxLoopNestingMarker < kMaxInt8);
710 2161054 : WRITE_INT8_FIELD(this, kOSRNestingLevelOffset, depth);
711 : }
712 :
713 : BytecodeArray::Age BytecodeArray::bytecode_age() const {
714 : // Bytecode is aged by the concurrent marker.
715 10513318 : return static_cast<Age>(RELAXED_READ_INT8_FIELD(this, kBytecodeAgeOffset));
716 : }
717 :
718 : void BytecodeArray::set_bytecode_age(BytecodeArray::Age age) {
719 : DCHECK_GE(age, kFirstBytecodeAge);
720 : DCHECK_LE(age, kLastBytecodeAge);
721 : STATIC_ASSERT(kLastBytecodeAge <= kMaxInt8);
722 : // Bytecode is aged by the concurrent marker.
723 2116376 : RELAXED_WRITE_INT8_FIELD(this, kBytecodeAgeOffset, static_cast<int8_t>(age));
724 : }
725 :
726 : int BytecodeArray::parameter_count() const {
727 : // Parameter count is stored as the size on stack of the parameters to allow
728 : // it to be used directly by generated code.
729 1716325 : return READ_INT_FIELD(this, kParameterSizeOffset) >> kSystemPointerSizeLog2;
730 : }
731 :
732 26254994 : ACCESSORS(BytecodeArray, constant_pool, FixedArray, kConstantPoolOffset)
733 134997084 : ACCESSORS(BytecodeArray, handler_table, ByteArray, kHandlerTableOffset)
734 41940668 : ACCESSORS(BytecodeArray, source_position_table, Object,
735 : kSourcePositionTableOffset)
736 :
737 2105830 : void BytecodeArray::clear_padding() {
738 2105837 : int data_size = kHeaderSize + length();
739 2105841 : memset(reinterpret_cast<void*>(address() + data_size), 0,
740 4211682 : SizeFor(length()) - data_size);
741 2105841 : }
742 :
743 : Address BytecodeArray::GetFirstBytecodeAddress() {
744 34569987 : return ptr() - kHeapObjectTag + kHeaderSize;
745 : }
746 :
747 6838682 : ByteArray BytecodeArray::SourcePositionTable() {
748 6838682 : Object maybe_table = source_position_table();
749 6838701 : if (maybe_table->IsByteArray()) return ByteArray::cast(maybe_table);
750 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
751 : return SourcePositionTableWithFrameCache::cast(maybe_table)
752 267865 : ->source_position_table();
753 : }
754 :
755 1485 : void BytecodeArray::ClearFrameCacheFromSourcePositionTable() {
756 1485 : Object maybe_table = source_position_table();
757 2970 : if (maybe_table->IsByteArray()) return;
758 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
759 : set_source_position_table(SourcePositionTableWithFrameCache::cast(maybe_table)
760 0 : ->source_position_table());
761 : }
762 :
763 4172771 : int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); }
764 :
765 2086370 : int BytecodeArray::SizeIncludingMetadata() {
766 2086370 : int size = BytecodeArraySize();
767 2086376 : size += constant_pool()->Size();
768 2086373 : size += handler_table()->Size();
769 2086383 : size += SourcePositionTable()->Size();
770 2086387 : return size;
771 : }
772 :
773 : BailoutId DeoptimizationData::BytecodeOffset(int i) {
774 299254 : return BailoutId(BytecodeOffsetRaw(i)->value());
775 : }
776 :
777 : void DeoptimizationData::SetBytecodeOffset(int i, BailoutId value) {
778 2702441 : SetBytecodeOffsetRaw(i, Smi::FromInt(value.ToInt()));
779 : }
780 :
781 92656 : int DeoptimizationData::DeoptCount() {
782 92656 : return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
783 : }
784 :
785 : } // namespace internal
786 : } // namespace v8
787 :
788 : #include "src/objects/object-macros-undef.h"
789 :
790 : #endif // V8_OBJECTS_CODE_INL_H_
|