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/code-desc.h"
11 : #include "src/interpreter/bytecode-register.h"
12 : #include "src/isolate.h"
13 : #include "src/objects/dictionary.h"
14 : #include "src/objects/instance-type-inl.h"
15 : #include "src/objects/map-inl.h"
16 : #include "src/objects/maybe-object-inl.h"
17 : #include "src/objects/oddball.h"
18 : #include "src/objects/smi-inl.h"
19 : #include "src/v8memory.h"
20 :
21 : // Has to be the last include (doesn't have include guards):
22 : #include "src/objects/object-macros.h"
23 :
24 : namespace v8 {
25 : namespace internal {
26 :
27 : OBJECT_CONSTRUCTORS_IMPL(DeoptimizationData, FixedArray)
28 : OBJECT_CONSTRUCTORS_IMPL(BytecodeArray, FixedArrayBase)
29 111384 : OBJECT_CONSTRUCTORS_IMPL(AbstractCode, HeapObject)
30 2912 : OBJECT_CONSTRUCTORS_IMPL(DependentCode, WeakFixedArray)
31 1680 : OBJECT_CONSTRUCTORS_IMPL(CodeDataContainer, HeapObject)
32 : OBJECT_CONSTRUCTORS_IMPL(SourcePositionTableWithFrameCache, Tuple2)
33 :
34 : NEVER_READ_ONLY_SPACE_IMPL(AbstractCode)
35 :
36 111384 : CAST_ACCESSOR(AbstractCode)
37 : CAST_ACCESSOR(BytecodeArray)
38 1635690 : CAST_ACCESSOR(Code)
39 1680 : CAST_ACCESSOR(CodeDataContainer)
40 2912 : CAST_ACCESSOR(DependentCode)
41 : CAST_ACCESSOR(DeoptimizationData)
42 : CAST_ACCESSOR(SourcePositionTableWithFrameCache)
43 :
44 269568 : ACCESSORS(SourcePositionTableWithFrameCache, source_position_table, ByteArray,
45 : kSourcePositionTableIndex)
46 98647 : ACCESSORS(SourcePositionTableWithFrameCache, stack_frame_cache,
47 : SimpleNumberDictionary, kStackFrameCacheIndex)
48 :
49 : int AbstractCode::raw_instruction_size() {
50 : if (IsCode()) {
51 : return GetCode()->raw_instruction_size();
52 : } else {
53 : return GetBytecodeArray()->length();
54 : }
55 : }
56 :
57 660766 : int AbstractCode::InstructionSize() {
58 1321532 : if (IsCode()) {
59 315334 : return GetCode()->InstructionSize();
60 : } else {
61 : return GetBytecodeArray()->length();
62 : }
63 : }
64 :
65 2140404 : ByteArray AbstractCode::source_position_table() {
66 4280808 : if (IsCode()) {
67 103249 : return GetCode()->SourcePositionTable();
68 : } else {
69 2037155 : return GetBytecodeArray()->SourcePositionTable();
70 : }
71 : }
72 :
73 72305 : Object AbstractCode::stack_frame_cache() {
74 : Object maybe_table;
75 144610 : if (IsCode()) {
76 : maybe_table = GetCode()->source_position_table();
77 : } else {
78 : maybe_table = GetBytecodeArray()->source_position_table();
79 : }
80 72305 : if (maybe_table->IsSourcePositionTableWithFrameCache()) {
81 : return SourcePositionTableWithFrameCache::cast(maybe_table)
82 55907 : ->stack_frame_cache();
83 : }
84 16398 : return Smi::kZero;
85 : }
86 :
87 0 : int AbstractCode::SizeIncludingMetadata() {
88 0 : if (IsCode()) {
89 0 : return GetCode()->SizeIncludingMetadata();
90 : } else {
91 0 : return GetBytecodeArray()->SizeIncludingMetadata();
92 : }
93 : }
94 10 : int AbstractCode::ExecutableSize() {
95 20 : if (IsCode()) {
96 : return GetCode()->ExecutableSize();
97 : } else {
98 : return GetBytecodeArray()->BytecodeArraySize();
99 : }
100 : }
101 :
102 24 : Address AbstractCode::raw_instruction_start() {
103 48 : if (IsCode()) {
104 : return GetCode()->raw_instruction_start();
105 : } else {
106 : return GetBytecodeArray()->GetFirstBytecodeAddress();
107 : }
108 : }
109 :
110 1292907 : Address AbstractCode::InstructionStart() {
111 2585814 : if (IsCode()) {
112 572138 : return GetCode()->InstructionStart();
113 : } else {
114 : return GetBytecodeArray()->GetFirstBytecodeAddress();
115 : }
116 : }
117 :
118 15 : Address AbstractCode::raw_instruction_end() {
119 30 : if (IsCode()) {
120 : return GetCode()->raw_instruction_end();
121 : } else {
122 12 : return GetBytecodeArray()->GetFirstBytecodeAddress() +
123 12 : GetBytecodeArray()->length();
124 : }
125 : }
126 :
127 : Address AbstractCode::InstructionEnd() {
128 : if (IsCode()) {
129 : return GetCode()->InstructionEnd();
130 : } else {
131 : return GetBytecodeArray()->GetFirstBytecodeAddress() +
132 : GetBytecodeArray()->length();
133 : }
134 : }
135 :
136 : bool AbstractCode::contains(Address inner_pointer) {
137 20 : return (address() <= inner_pointer) && (inner_pointer <= address() + Size());
138 : }
139 :
140 89310 : AbstractCode::Kind AbstractCode::kind() {
141 178620 : if (IsCode()) {
142 : return static_cast<AbstractCode::Kind>(GetCode()->kind());
143 : } else {
144 : return INTERPRETED_FUNCTION;
145 : }
146 : }
147 :
148 : Code AbstractCode::GetCode() { return Code::cast(*this); }
149 :
150 : BytecodeArray AbstractCode::GetBytecodeArray() {
151 : return BytecodeArray::cast(*this);
152 : }
153 :
154 : DependentCode DependentCode::next_link() {
155 : return DependentCode::cast(Get(kNextLinkIndex)->GetHeapObjectAssumeStrong());
156 : }
157 :
158 : void DependentCode::set_next_link(DependentCode next) {
159 93383 : Set(kNextLinkIndex, HeapObjectReference::Strong(next));
160 : }
161 :
162 : int DependentCode::flags() { return Smi::ToInt(Get(kFlagsIndex)->ToSmi()); }
163 :
164 : void DependentCode::set_flags(int flags) {
165 329923 : Set(kFlagsIndex, MaybeObject::FromObject(Smi::FromInt(flags)));
166 : }
167 :
168 547070 : int DependentCode::count() { return CountField::decode(flags()); }
169 :
170 246619 : void DependentCode::set_count(int value) {
171 493238 : set_flags(CountField::update(flags(), value));
172 246619 : }
173 :
174 : DependentCode::DependencyGroup DependentCode::group() {
175 9 : return static_cast<DependencyGroup>(GroupField::decode(flags()));
176 : }
177 :
178 : void DependentCode::set_object_at(int i, MaybeObject object) {
179 274059 : Set(kCodesStartIndex + i, object);
180 : }
181 :
182 : MaybeObject DependentCode::object_at(int i) {
183 : return Get(kCodesStartIndex + i);
184 : }
185 :
186 11272 : void DependentCode::clear_at(int i) {
187 11272 : Set(kCodesStartIndex + i,
188 22544 : HeapObjectReference::Strong(GetReadOnlyRoots().undefined_value()));
189 11272 : }
190 :
191 2300 : void DependentCode::copy(int from, int to) {
192 2300 : Set(kCodesStartIndex + to, Get(kCodesStartIndex + from));
193 2300 : }
194 :
195 3101700 : OBJECT_CONSTRUCTORS_IMPL(Code, HeapObject)
196 : NEVER_READ_ONLY_SPACE_IMPL(Code)
197 :
198 463663185 : INT_ACCESSORS(Code, raw_instruction_size, kInstructionSizeOffset)
199 4846333 : INT_ACCESSORS(Code, safepoint_table_offset, kSafepointTableOffsetOffset)
200 6652314 : INT_ACCESSORS(Code, handler_table_offset, kHandlerTableOffsetOffset)
201 6056866 : INT_ACCESSORS(Code, code_comments_offset, kCodeCommentsOffsetOffset)
202 : #define CODE_ACCESSORS(name, type, offset) \
203 : ACCESSORS_CHECKED2(Code, name, type, offset, true, \
204 : !ObjectInYoungGeneration(value))
205 : #define SYNCHRONIZED_CODE_ACCESSORS(name, type, offset) \
206 : SYNCHRONIZED_ACCESSORS_CHECKED2(Code, name, type, offset, true, \
207 : !ObjectInYoungGeneration(value))
208 :
209 10758737 : CODE_ACCESSORS(relocation_info, ByteArray, kRelocationInfoOffset)
210 14215950 : CODE_ACCESSORS(deoptimization_data, FixedArray, kDeoptimizationDataOffset)
211 10995598 : CODE_ACCESSORS(source_position_table, Object, kSourcePositionTableOffset)
212 : // Concurrent marker needs to access kind specific flags in code data container.
213 45863039 : SYNCHRONIZED_CODE_ACCESSORS(code_data_container, CodeDataContainer,
214 : kCodeDataContainerOffset)
215 : #undef CODE_ACCESSORS
216 : #undef SYNCHRONIZED_CODE_ACCESSORS
217 :
218 396205 : void Code::WipeOutHeader() {
219 396205 : WRITE_FIELD(*this, kRelocationInfoOffset, Smi::FromInt(0));
220 396205 : WRITE_FIELD(*this, kDeoptimizationDataOffset, Smi::FromInt(0));
221 396205 : WRITE_FIELD(*this, kSourcePositionTableOffset, Smi::FromInt(0));
222 396205 : WRITE_FIELD(*this, kCodeDataContainerOffset, Smi::FromInt(0));
223 396205 : }
224 :
225 1903466 : void Code::clear_padding() {
226 : if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
227 1903466 : memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
228 : FIELD_SIZE(kOptionalPaddingOffset));
229 : }
230 : Address data_end =
231 1903466 : has_unwinding_info() ? unwinding_info_end() : raw_instruction_end();
232 3806932 : memset(reinterpret_cast<void*>(data_end), 0,
233 1903466 : CodeSize() - (data_end - address()));
234 1903466 : }
235 :
236 107032 : ByteArray Code::SourcePositionTable() const {
237 : Object maybe_table = source_position_table();
238 107032 : if (maybe_table->IsByteArray()) return ByteArray::cast(maybe_table);
239 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
240 : return SourcePositionTableWithFrameCache::cast(maybe_table)
241 : ->source_position_table();
242 : }
243 :
244 9565400 : Object Code::next_code_link() const {
245 9565400 : return code_data_container()->next_code_link();
246 : }
247 :
248 741309 : void Code::set_next_code_link(Object value) {
249 741309 : code_data_container()->set_next_code_link(value);
250 741308 : }
251 :
252 : int Code::InstructionSize() const {
253 166101 : if (is_off_heap_trampoline()) {
254 : DCHECK(FLAG_embedded_builtins);
255 64581 : return OffHeapInstructionSize();
256 : }
257 : return raw_instruction_size();
258 : }
259 :
260 475664 : Address Code::raw_instruction_start() const {
261 291922436 : return FIELD_ADDR(*this, kHeaderSize);
262 : }
263 :
264 : Address Code::InstructionStart() const {
265 160511431 : if (is_off_heap_trampoline()) {
266 : DCHECK(FLAG_embedded_builtins);
267 151363577 : return OffHeapInstructionStart();
268 : }
269 : return raw_instruction_start();
270 : }
271 :
272 : Address Code::raw_instruction_end() const {
273 1903702 : return raw_instruction_start() + raw_instruction_size();
274 : }
275 :
276 255 : Address Code::InstructionEnd() const {
277 255 : if (is_off_heap_trampoline()) {
278 : DCHECK(FLAG_embedded_builtins);
279 0 : return OffHeapInstructionEnd();
280 : }
281 255 : return raw_instruction_end();
282 : }
283 :
284 : int Code::GetUnwindingInfoSizeOffset() const {
285 : DCHECK(has_unwinding_info());
286 119 : return RoundUp(kHeaderSize + raw_instruction_size(), kInt64Size);
287 : }
288 :
289 : int Code::unwinding_info_size() const {
290 : DCHECK(has_unwinding_info());
291 : return static_cast<int>(
292 130 : READ_UINT64_FIELD(*this, GetUnwindingInfoSizeOffset()));
293 : }
294 :
295 27 : void Code::set_unwinding_info_size(int value) {
296 : DCHECK(has_unwinding_info());
297 54 : WRITE_UINT64_FIELD(*this, GetUnwindingInfoSizeOffset(), value);
298 27 : }
299 :
300 : Address Code::unwinding_info_start() const {
301 : DCHECK(has_unwinding_info());
302 92 : return FIELD_ADDR(*this, GetUnwindingInfoSizeOffset()) + kInt64Size;
303 : }
304 :
305 : Address Code::unwinding_info_end() const {
306 : DCHECK(has_unwinding_info());
307 65 : return unwinding_info_start() + unwinding_info_size();
308 : }
309 :
310 456017489 : int Code::body_size() const {
311 : int unpadded_body_size =
312 : has_unwinding_info()
313 : ? static_cast<int>(unwinding_info_end() - raw_instruction_start())
314 456017555 : : raw_instruction_size();
315 456017489 : return RoundUp(unpadded_body_size, kObjectAlignment);
316 : }
317 :
318 0 : int Code::SizeIncludingMetadata() const {
319 : int size = CodeSize();
320 0 : size += relocation_info()->Size();
321 0 : size += deoptimization_data()->Size();
322 0 : return size;
323 : }
324 :
325 : ByteArray Code::unchecked_relocation_info() const {
326 214354754 : return ByteArray::unchecked_cast(READ_FIELD(*this, kRelocationInfoOffset));
327 : }
328 :
329 : byte* Code::relocation_start() const {
330 : return unchecked_relocation_info()->GetDataStartAddress();
331 : }
332 :
333 0 : byte* Code::relocation_end() const {
334 0 : return unchecked_relocation_info()->GetDataEndAddress();
335 : }
336 :
337 85593 : int Code::relocation_size() const {
338 85593 : return unchecked_relocation_info()->length();
339 : }
340 :
341 : Address Code::entry() const { return raw_instruction_start(); }
342 :
343 11575084 : bool Code::contains(Address inner_pointer) {
344 11575084 : if (is_off_heap_trampoline()) {
345 : DCHECK(FLAG_embedded_builtins);
346 1040078 : if (OffHeapInstructionStart() <= inner_pointer &&
347 359612 : inner_pointer < OffHeapInstructionEnd()) {
348 : return true;
349 : }
350 : }
351 11225984 : return (address() <= inner_pointer) && (inner_pointer < address() + Size());
352 : }
353 :
354 : int Code::ExecutableSize() const {
355 : // Check that the assumptions about the layout of the code object holds.
356 : DCHECK_EQ(static_cast<int>(raw_instruction_start() - address()),
357 : Code::kHeaderSize);
358 2 : return raw_instruction_size() + Code::kHeaderSize;
359 : }
360 :
361 : // static
362 : void Code::CopyRelocInfoToByteArray(ByteArray dest, const CodeDesc& desc) {
363 : DCHECK_EQ(dest->length(), desc.reloc_size);
364 3807040 : CopyBytes(dest->GetDataStartAddress(),
365 1903520 : desc.buffer + desc.buffer_size - desc.reloc_size,
366 : static_cast<size_t>(desc.reloc_size));
367 : }
368 :
369 455847115 : int Code::CodeSize() const { return SizeFor(body_size()); }
370 :
371 : Code::Kind Code::kind() const {
372 67925403 : return KindField::decode(READ_UINT32_FIELD(*this, kFlagsOffset));
373 : }
374 :
375 1988306 : void Code::initialize_flags(Kind kind, bool has_unwinding_info,
376 : bool is_turbofanned, int stack_slots,
377 : bool is_off_heap_trampoline) {
378 1988306 : CHECK(0 <= stack_slots && stack_slots < StackSlotsField::kMax);
379 : static_assert(Code::NUMBER_OF_KINDS <= KindField::kMax + 1, "field overflow");
380 1988306 : uint32_t flags = HasUnwindingInfoField::encode(has_unwinding_info) |
381 1988306 : KindField::encode(kind) |
382 1988306 : IsTurbofannedField::encode(is_turbofanned) |
383 : StackSlotsField::encode(stack_slots) |
384 1988306 : IsOffHeapTrampoline::encode(is_off_heap_trampoline);
385 1988306 : WRITE_UINT32_FIELD(*this, kFlagsOffset, flags);
386 : DCHECK_IMPLIES(stack_slots != 0, has_safepoint_info());
387 1988306 : }
388 :
389 : inline bool Code::is_interpreter_trampoline_builtin() const {
390 : bool is_interpreter_trampoline =
391 1614944 : (builtin_index() == Builtins::kInterpreterEntryTrampoline ||
392 29584650 : builtin_index() == Builtins::kInterpreterEnterBytecodeAdvance ||
393 : builtin_index() == Builtins::kInterpreterEnterBytecodeDispatch);
394 : return is_interpreter_trampoline;
395 : }
396 :
397 : inline bool Code::checks_optimization_marker() const {
398 : bool checks_marker =
399 : (builtin_index() == Builtins::kCompileLazy ||
400 : builtin_index() == Builtins::kInterpreterEntryTrampoline);
401 : return checks_marker ||
402 : (kind() == OPTIMIZED_FUNCTION && marked_for_deoptimization());
403 : }
404 :
405 : inline bool Code::has_tagged_params() const {
406 881804 : return kind() != JS_TO_WASM_FUNCTION && kind() != C_WASM_ENTRY &&
407 : kind() != WASM_FUNCTION;
408 : }
409 :
410 : inline bool Code::has_unwinding_info() const {
411 457920969 : return HasUnwindingInfoField::decode(READ_UINT32_FIELD(*this, kFlagsOffset));
412 : }
413 :
414 : inline bool Code::is_turbofanned() const {
415 222140 : return IsTurbofannedField::decode(READ_UINT32_FIELD(*this, kFlagsOffset));
416 : }
417 :
418 458541 : inline bool Code::can_have_weak_objects() const {
419 : DCHECK(kind() == OPTIMIZED_FUNCTION);
420 : int32_t flags = code_data_container()->kind_specific_flags();
421 458529 : return CanHaveWeakObjectsField::decode(flags);
422 : }
423 :
424 460320 : inline void Code::set_can_have_weak_objects(bool value) {
425 : DCHECK(kind() == OPTIMIZED_FUNCTION);
426 : int32_t previous = code_data_container()->kind_specific_flags();
427 : int32_t updated = CanHaveWeakObjectsField::update(previous, value);
428 : code_data_container()->set_kind_specific_flags(updated);
429 460320 : }
430 :
431 7025 : inline bool Code::is_promise_rejection() const {
432 : DCHECK(kind() == BUILTIN);
433 : int32_t flags = code_data_container()->kind_specific_flags();
434 7025 : return IsPromiseRejectionField::decode(flags);
435 : }
436 :
437 784 : inline void Code::set_is_promise_rejection(bool value) {
438 : DCHECK(kind() == BUILTIN);
439 784 : int32_t previous = code_data_container()->kind_specific_flags();
440 784 : int32_t updated = IsPromiseRejectionField::update(previous, value);
441 784 : code_data_container()->set_kind_specific_flags(updated);
442 784 : }
443 :
444 5212 : inline bool Code::is_exception_caught() const {
445 : DCHECK(kind() == BUILTIN);
446 : int32_t flags = code_data_container()->kind_specific_flags();
447 5212 : return IsExceptionCaughtField::decode(flags);
448 : }
449 :
450 56 : inline void Code::set_is_exception_caught(bool value) {
451 : DCHECK(kind() == BUILTIN);
452 56 : int32_t previous = code_data_container()->kind_specific_flags();
453 56 : int32_t updated = IsExceptionCaughtField::update(previous, value);
454 56 : code_data_container()->set_kind_specific_flags(updated);
455 56 : }
456 :
457 : inline bool Code::is_off_heap_trampoline() const {
458 169481941 : return IsOffHeapTrampoline::decode(READ_UINT32_FIELD(*this, kFlagsOffset));
459 : }
460 :
461 7025 : inline HandlerTable::CatchPrediction Code::GetBuiltinCatchPrediction() {
462 7025 : if (is_promise_rejection()) return HandlerTable::PROMISE;
463 5212 : if (is_exception_caught()) return HandlerTable::CAUGHT;
464 5144 : return HandlerTable::UNCAUGHT;
465 : }
466 :
467 804832 : int Code::builtin_index() const {
468 193723344 : int index = READ_INT_FIELD(*this, kBuiltinIndexOffset);
469 : DCHECK(index == -1 || Builtins::IsBuiltinId(index));
470 804832 : return index;
471 : }
472 :
473 : void Code::set_builtin_index(int index) {
474 : DCHECK(index == -1 || Builtins::IsBuiltinId(index));
475 1988305 : WRITE_INT_FIELD(*this, kBuiltinIndexOffset, index);
476 : }
477 :
478 402416 : bool Code::is_builtin() const { return builtin_index() != -1; }
479 :
480 : bool Code::has_safepoint_info() const {
481 104969 : return is_turbofanned() || is_wasm_code();
482 : }
483 :
484 : int Code::stack_slots() const {
485 : DCHECK(has_safepoint_info());
486 6838850 : return StackSlotsField::decode(READ_UINT32_FIELD(*this, kFlagsOffset));
487 : }
488 :
489 5041408 : bool Code::marked_for_deoptimization() const {
490 : DCHECK(kind() == OPTIMIZED_FUNCTION);
491 : int32_t flags = code_data_container()->kind_specific_flags();
492 5041408 : return MarkedForDeoptimizationField::decode(flags);
493 : }
494 :
495 278039 : void Code::set_marked_for_deoptimization(bool flag) {
496 : DCHECK(kind() == OPTIMIZED_FUNCTION);
497 : DCHECK_IMPLIES(flag, AllowDeoptimization::IsAllowed(GetIsolate()));
498 : int32_t previous = code_data_container()->kind_specific_flags();
499 : int32_t updated = MarkedForDeoptimizationField::update(previous, flag);
500 : code_data_container()->set_kind_specific_flags(updated);
501 278039 : }
502 :
503 852 : bool Code::embedded_objects_cleared() const {
504 : DCHECK(kind() == OPTIMIZED_FUNCTION);
505 : int32_t flags = code_data_container()->kind_specific_flags();
506 852 : return EmbeddedObjectsClearedField::decode(flags);
507 : }
508 :
509 278 : void Code::set_embedded_objects_cleared(bool flag) {
510 : DCHECK(kind() == OPTIMIZED_FUNCTION);
511 : DCHECK_IMPLIES(flag, marked_for_deoptimization());
512 : int32_t previous = code_data_container()->kind_specific_flags();
513 : int32_t updated = EmbeddedObjectsClearedField::update(previous, flag);
514 : code_data_container()->set_kind_specific_flags(updated);
515 278 : }
516 :
517 87074 : bool Code::deopt_already_counted() const {
518 : DCHECK(kind() == OPTIMIZED_FUNCTION);
519 : int32_t flags = code_data_container()->kind_specific_flags();
520 87074 : return DeoptAlreadyCountedField::decode(flags);
521 : }
522 :
523 61761 : void Code::set_deopt_already_counted(bool flag) {
524 : DCHECK(kind() == OPTIMIZED_FUNCTION);
525 : DCHECK_IMPLIES(flag, AllowDeoptimization::IsAllowed(GetIsolate()));
526 : int32_t previous = code_data_container()->kind_specific_flags();
527 : int32_t updated = DeoptAlreadyCountedField::update(previous, flag);
528 : code_data_container()->set_kind_specific_flags(updated);
529 61761 : }
530 :
531 : bool Code::is_optimized_code() const { return kind() == OPTIMIZED_FUNCTION; }
532 : bool Code::is_wasm_code() const { return kind() == WASM_FUNCTION; }
533 :
534 : int Code::constant_pool_offset() const {
535 : if (!FLAG_enable_embedded_constant_pool) return code_comments_offset();
536 : return READ_INT_FIELD(*this, kConstantPoolOffsetOffset);
537 : }
538 :
539 : void Code::set_constant_pool_offset(int value) {
540 : if (!FLAG_enable_embedded_constant_pool) return;
541 : DCHECK_LE(value, InstructionSize());
542 : WRITE_INT_FIELD(*this, kConstantPoolOffsetOffset, value);
543 : }
544 :
545 213241074 : Address Code::constant_pool() const {
546 213241074 : if (!has_constant_pool()) return kNullAddress;
547 0 : return InstructionStart() + constant_pool_offset();
548 : }
549 :
550 8 : Address Code::code_comments() const {
551 8 : if (!has_code_comments()) return kNullAddress;
552 8 : return InstructionStart() + code_comments_offset();
553 : }
554 :
555 3269739 : Code Code::GetCodeFromTargetAddress(Address address) {
556 : {
557 : // TODO(jgruber,v8:6666): Support embedded builtins here. We'd need to pass
558 : // in the current isolate.
559 3269739 : Address start = reinterpret_cast<Address>(Isolate::CurrentEmbeddedBlob());
560 3269717 : Address end = start + Isolate::CurrentEmbeddedBlobSize();
561 3269695 : CHECK(address < start || address >= end);
562 : }
563 :
564 402416 : HeapObject code = HeapObject::FromAddress(address - Code::kHeaderSize);
565 : // Unchecked cast because we can't rely on the map currently
566 : // not being a forwarding pointer.
567 3269695 : return Code::unchecked_cast(code);
568 : }
569 :
570 : Code Code::GetObjectFromEntryAddress(Address location_of_address) {
571 0 : Address code_entry = Memory<Address>(location_of_address);
572 : HeapObject code = HeapObject::FromAddress(code_entry - Code::kHeaderSize);
573 : // Unchecked cast because we can't rely on the map currently
574 : // not being a forwarding pointer.
575 : return Code::unchecked_cast(code);
576 : }
577 :
578 459782 : bool Code::CanContainWeakObjects() {
579 459782 : return is_optimized_code() && can_have_weak_objects();
580 : }
581 :
582 459782 : bool Code::IsWeakObject(HeapObject object) {
583 459782 : return (CanContainWeakObjects() && IsWeakObjectInOptimizedCode(object));
584 : }
585 :
586 5589681 : bool Code::IsWeakObjectInOptimizedCode(HeapObject object) {
587 : Map map = object->synchronized_map();
588 : InstanceType instance_type = map->instance_type();
589 5589681 : if (InstanceTypeChecker::IsMap(instance_type)) {
590 : return Map::cast(object)->CanTransition();
591 : }
592 5396211 : return InstanceTypeChecker::IsPropertyCell(instance_type) ||
593 10637074 : InstanceTypeChecker::IsJSReceiver(instance_type) ||
594 : InstanceTypeChecker::IsContext(instance_type);
595 : }
596 :
597 : // This field has to have relaxed atomic accessors because it is accessed in the
598 : // concurrent marker.
599 9275786 : RELAXED_INT32_ACCESSORS(CodeDataContainer, kind_specific_flags,
600 : kKindSpecificFlagsOffset)
601 16398620 : ACCESSORS(CodeDataContainer, next_code_link, Object, kNextCodeLinkOffset)
602 :
603 : void CodeDataContainer::clear_padding() {
604 1903496 : memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0,
605 : kSize - kUnalignedSize);
606 : }
607 :
608 : byte BytecodeArray::get(int index) const {
609 : DCHECK(index >= 0 && index < this->length());
610 284255141 : return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
611 : }
612 :
613 : void BytecodeArray::set(int index, byte value) {
614 : DCHECK(index >= 0 && index < this->length());
615 14273286 : WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize, value);
616 : }
617 :
618 : void BytecodeArray::set_frame_size(int frame_size) {
619 : DCHECK_GE(frame_size, 0);
620 : DCHECK(IsAligned(frame_size, kSystemPointerSize));
621 2102862 : WRITE_INT_FIELD(*this, kFrameSizeOffset, frame_size);
622 : }
623 :
624 : int BytecodeArray::frame_size() const {
625 31016874 : return READ_INT_FIELD(*this, kFrameSizeOffset);
626 : }
627 :
628 : int BytecodeArray::register_count() const {
629 31003931 : return frame_size() / kSystemPointerSize;
630 : }
631 :
632 : void BytecodeArray::set_parameter_count(int number_of_parameters) {
633 : DCHECK_GE(number_of_parameters, 0);
634 : // Parameter count is stored as the size on stack of the parameters to allow
635 : // it to be used directly by generated code.
636 4205724 : WRITE_INT_FIELD(*this, kParameterSizeOffset,
637 4205724 : (number_of_parameters << kSystemPointerSizeLog2));
638 : }
639 :
640 : interpreter::Register BytecodeArray::incoming_new_target_or_generator_register()
641 : const {
642 : int register_operand =
643 539645 : READ_INT_FIELD(*this, kIncomingNewTargetOrGeneratorRegisterOffset);
644 539645 : if (register_operand == 0) {
645 : return interpreter::Register::invalid_value();
646 : } else {
647 : return interpreter::Register::FromOperand(register_operand);
648 : }
649 : }
650 :
651 : void BytecodeArray::set_incoming_new_target_or_generator_register(
652 : interpreter::Register incoming_new_target_or_generator_register) {
653 115716 : if (!incoming_new_target_or_generator_register.is_valid()) {
654 2102289 : WRITE_INT_FIELD(*this, kIncomingNewTargetOrGeneratorRegisterOffset, 0);
655 : } else {
656 : DCHECK(incoming_new_target_or_generator_register.index() <
657 : register_count());
658 : DCHECK_NE(0, incoming_new_target_or_generator_register.ToOperand());
659 105697 : WRITE_INT_FIELD(*this, kIncomingNewTargetOrGeneratorRegisterOffset,
660 211394 : incoming_new_target_or_generator_register.ToOperand());
661 : }
662 : }
663 :
664 : int BytecodeArray::interrupt_budget() const {
665 10597 : return READ_INT_FIELD(*this, kInterruptBudgetOffset);
666 : }
667 :
668 : void BytecodeArray::set_interrupt_budget(int interrupt_budget) {
669 : DCHECK_GE(interrupt_budget, 0);
670 2103587 : WRITE_INT_FIELD(*this, kInterruptBudgetOffset, interrupt_budget);
671 : }
672 :
673 : int BytecodeArray::osr_loop_nesting_level() const {
674 41187 : return READ_INT8_FIELD(*this, kOSRNestingLevelOffset);
675 : }
676 :
677 : void BytecodeArray::set_osr_loop_nesting_level(int depth) {
678 : DCHECK(0 <= depth && depth <= AbstractCode::kMaxLoopNestingMarker);
679 : STATIC_ASSERT(AbstractCode::kMaxLoopNestingMarker < kMaxInt8);
680 2146188 : WRITE_INT8_FIELD(*this, kOSRNestingLevelOffset, depth);
681 : }
682 :
683 : BytecodeArray::Age BytecodeArray::bytecode_age() const {
684 : // Bytecode is aged by the concurrent marker.
685 5159851 : return static_cast<Age>(RELAXED_READ_INT8_FIELD(*this, kBytecodeAgeOffset));
686 : }
687 :
688 : void BytecodeArray::set_bytecode_age(BytecodeArray::Age age) {
689 : DCHECK_GE(age, kFirstBytecodeAge);
690 : DCHECK_LE(age, kLastBytecodeAge);
691 : STATIC_ASSERT(kLastBytecodeAge <= kMaxInt8);
692 : // Bytecode is aged by the concurrent marker.
693 2102853 : RELAXED_WRITE_INT8_FIELD(*this, kBytecodeAgeOffset, static_cast<int8_t>(age));
694 : }
695 :
696 : int BytecodeArray::parameter_count() const {
697 : // Parameter count is stored as the size on stack of the parameters to allow
698 : // it to be used directly by generated code.
699 1745389 : return READ_INT_FIELD(*this, kParameterSizeOffset) >> kSystemPointerSizeLog2;
700 : }
701 :
702 15773040 : ACCESSORS(BytecodeArray, constant_pool, FixedArray, kConstantPoolOffset)
703 60345081 : ACCESSORS(BytecodeArray, handler_table, ByteArray, kHandlerTableOffset)
704 27892779 : ACCESSORS(BytecodeArray, source_position_table, Object,
705 : kSourcePositionTableOffset)
706 :
707 2092267 : void BytecodeArray::clear_padding() {
708 2092267 : int data_size = kHeaderSize + length();
709 4184534 : memset(reinterpret_cast<void*>(address() + data_size), 0,
710 2092267 : SizeFor(length()) - data_size);
711 2092267 : }
712 :
713 : Address BytecodeArray::GetFirstBytecodeAddress() {
714 35155416 : return ptr() - kHeapObjectTag + kHeaderSize;
715 : }
716 :
717 10 : bool BytecodeArray::HasSourcePositionTable() {
718 : Object maybe_table = source_position_table();
719 10 : return !maybe_table->IsUndefined();
720 : }
721 :
722 6778126 : ByteArray BytecodeArray::SourcePositionTable() {
723 : Object maybe_table = source_position_table();
724 6778131 : if (maybe_table->IsByteArray()) return ByteArray::cast(maybe_table);
725 : ReadOnlyRoots roots = GetReadOnlyRoots();
726 228578 : if (maybe_table->IsUndefined(roots)) return roots.empty_byte_array();
727 :
728 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
729 : return SourcePositionTableWithFrameCache::cast(maybe_table)
730 : ->source_position_table();
731 : }
732 :
733 1529 : void BytecodeArray::ClearFrameCacheFromSourcePositionTable() {
734 : Object maybe_table = source_position_table();
735 3058 : if (maybe_table->IsUndefined() || maybe_table->IsByteArray()) return;
736 : DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
737 : set_source_position_table(SourcePositionTableWithFrameCache::cast(maybe_table)
738 0 : ->source_position_table());
739 : }
740 :
741 : int BytecodeArray::BytecodeArraySize() { return SizeFor(this->length()); }
742 :
743 2072805 : int BytecodeArray::SizeIncludingMetadata() {
744 : int size = BytecodeArraySize();
745 2072805 : size += constant_pool()->Size();
746 2072799 : size += handler_table()->Size();
747 4145597 : size += SourcePositionTable()->Size();
748 2072798 : return size;
749 : }
750 :
751 463633 : DEFINE_DEOPT_ELEMENT_ACCESSORS(TranslationByteArray, ByteArray)
752 : DEFINE_DEOPT_ELEMENT_ACCESSORS(InlinedFunctionCount, Smi)
753 463633 : DEFINE_DEOPT_ELEMENT_ACCESSORS(LiteralArray, FixedArray)
754 : DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrBytecodeOffset, Smi)
755 9368 : DEFINE_DEOPT_ELEMENT_ACCESSORS(OsrPcOffset, Smi)
756 : DEFINE_DEOPT_ELEMENT_ACCESSORS(OptimizationId, Smi)
757 463812 : DEFINE_DEOPT_ELEMENT_ACCESSORS(InliningPositions, PodArray<InliningPosition>)
758 :
759 104424 : DEFINE_DEOPT_ENTRY_ACCESSORS(BytecodeOffsetRaw, Smi)
760 4224828 : DEFINE_DEOPT_ENTRY_ACCESSORS(TranslationIndex, Smi)
761 450330 : DEFINE_DEOPT_ENTRY_ACCESSORS(Pc, Smi)
762 :
763 : BailoutId DeoptimizationData::BytecodeOffset(int i) {
764 104424 : return BailoutId(BytecodeOffsetRaw(i)->value());
765 : }
766 :
767 : void DeoptimizationData::SetBytecodeOffset(int i, BailoutId value) {
768 : SetBytecodeOffsetRaw(i, Smi::FromInt(value.ToInt()));
769 : }
770 :
771 : int DeoptimizationData::DeoptCount() {
772 88137 : return (length() - kFirstDeoptEntryIndex) / kDeoptEntrySize;
773 : }
774 :
775 : } // namespace internal
776 : } // namespace v8
777 :
778 : #include "src/objects/object-macros-undef.h"
779 :
780 : #endif // V8_OBJECTS_CODE_INL_H_
|