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_SHARED_FUNCTION_INFO_INL_H_
6 #define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
7
8 #include "src/base/macros.h"
9 #include "src/handles/handles-inl.h"
10 #include "src/heap/heap-write-barrier-inl.h"
11 #include "src/heap/local-heap-inl.h"
12 #include "src/objects/debug-objects-inl.h"
13 #include "src/objects/feedback-vector-inl.h"
14 #include "src/objects/scope-info.h"
15 #include "src/objects/shared-function-info.h"
16 #include "src/objects/templates.h"
17 #include "src/wasm/wasm-objects-inl.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 #include "torque-generated/src/objects/shared-function-info-tq-inl.inc"
26
TQ_OBJECT_CONSTRUCTORS_IMPL(PreparseData)27 TQ_OBJECT_CONSTRUCTORS_IMPL(PreparseData)
28
29 int PreparseData::inner_start_offset() const {
30 return InnerOffset(data_length());
31 }
32
inner_data_start()33 ObjectSlot PreparseData::inner_data_start() const {
34 return RawField(inner_start_offset());
35 }
36
clear_padding()37 void PreparseData::clear_padding() {
38 int data_end_offset = kDataStartOffset + data_length();
39 int padding_size = inner_start_offset() - data_end_offset;
40 DCHECK_LE(0, padding_size);
41 if (padding_size == 0) return;
42 memset(reinterpret_cast<void*>(address() + data_end_offset), 0, padding_size);
43 }
44
get(int index)45 byte PreparseData::get(int index) const {
46 DCHECK_LE(0, index);
47 DCHECK_LT(index, data_length());
48 int offset = kDataStartOffset + index * kByteSize;
49 return ReadField<byte>(offset);
50 }
51
set(int index,byte value)52 void PreparseData::set(int index, byte value) {
53 DCHECK_LE(0, index);
54 DCHECK_LT(index, data_length());
55 int offset = kDataStartOffset + index * kByteSize;
56 WriteField<byte>(offset, value);
57 }
58
copy_in(int index,const byte * buffer,int length)59 void PreparseData::copy_in(int index, const byte* buffer, int length) {
60 DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
61 index + length <= this->data_length());
62 Address dst_addr = field_address(kDataStartOffset + index * kByteSize);
63 memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
64 }
65
get_child(int index)66 PreparseData PreparseData::get_child(int index) const {
67 return PreparseData::cast(get_child_raw(index));
68 }
69
get_child_raw(int index)70 Object PreparseData::get_child_raw(int index) const {
71 DCHECK_LE(0, index);
72 DCHECK_LT(index, this->children_length());
73 int offset = inner_start_offset() + index * kTaggedSize;
74 return RELAXED_READ_FIELD(*this, offset);
75 }
76
set_child(int index,PreparseData value,WriteBarrierMode mode)77 void PreparseData::set_child(int index, PreparseData value,
78 WriteBarrierMode mode) {
79 DCHECK_LE(0, index);
80 DCHECK_LT(index, this->children_length());
81 int offset = inner_start_offset() + index * kTaggedSize;
82 RELAXED_WRITE_FIELD(*this, offset, value);
83 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
84 }
85
86 TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledData)
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithoutPreparseData)87 TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithoutPreparseData)
88 TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithPreparseData)
89
90 OBJECT_CONSTRUCTORS_IMPL(InterpreterData, Struct)
91
92 CAST_ACCESSOR(InterpreterData)
93 ACCESSORS(InterpreterData, bytecode_array, BytecodeArray, kBytecodeArrayOffset)
94 ACCESSORS(InterpreterData, interpreter_trampoline, Code,
95 kInterpreterTrampolineOffset)
96
97 OBJECT_CONSTRUCTORS_IMPL(SharedFunctionInfo, HeapObject)
98 NEVER_READ_ONLY_SPACE_IMPL(SharedFunctionInfo)
99 CAST_ACCESSOR(SharedFunctionInfo)
100 DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
101
102 RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, function_data, Object,
103 kFunctionDataOffset)
104 RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
105 kNameOrScopeInfoOffset)
106 RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, script_or_debug_info, HeapObject,
107 kScriptOrDebugInfoOffset)
108
109 INT32_ACCESSORS(SharedFunctionInfo, function_literal_id,
110 kFunctionLiteralIdOffset)
111
112 #if V8_SFI_HAS_UNIQUE_ID
113 INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
114 #endif
115 UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
116 UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count,
117 kFormalParameterCountOffset)
118 UINT8_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
119 kExpectedNofPropertiesOffset)
120 UINT16_ACCESSORS(SharedFunctionInfo, raw_function_token_offset,
121 kFunctionTokenOffsetOffset)
122 RELAXED_INT32_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset)
123 UINT8_ACCESSORS(SharedFunctionInfo, flags2, kFlags2Offset)
124
125 bool SharedFunctionInfo::HasSharedName() const {
126 Object value = name_or_scope_info(kAcquireLoad);
127 if (value.IsScopeInfo()) {
128 return ScopeInfo::cast(value).HasSharedFunctionName();
129 }
130 return value != kNoSharedNameSentinel;
131 }
132
Name()133 String SharedFunctionInfo::Name() const {
134 if (!HasSharedName()) return GetReadOnlyRoots().empty_string();
135 Object value = name_or_scope_info(kAcquireLoad);
136 if (value.IsScopeInfo()) {
137 if (ScopeInfo::cast(value).HasFunctionName()) {
138 return String::cast(ScopeInfo::cast(value).FunctionName());
139 }
140 return GetReadOnlyRoots().empty_string();
141 }
142 return String::cast(value);
143 }
144
SetName(String name)145 void SharedFunctionInfo::SetName(String name) {
146 Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
147 if (maybe_scope_info.IsScopeInfo()) {
148 ScopeInfo::cast(maybe_scope_info).SetFunctionName(name);
149 } else {
150 DCHECK(maybe_scope_info.IsString() ||
151 maybe_scope_info == kNoSharedNameSentinel);
152 set_name_or_scope_info(name, kReleaseStore);
153 }
154 UpdateFunctionMapIndex();
155 }
156
is_script()157 bool SharedFunctionInfo::is_script() const {
158 return scope_info().is_script_scope() &&
159 Script::cast(script()).compilation_type() ==
160 Script::COMPILATION_TYPE_HOST;
161 }
162
needs_script_context()163 bool SharedFunctionInfo::needs_script_context() const {
164 return is_script() && scope_info().ContextLocalCount() > 0;
165 }
166
abstract_code()167 AbstractCode SharedFunctionInfo::abstract_code() {
168 if (HasBytecodeArray()) {
169 return AbstractCode::cast(GetBytecodeArray());
170 } else {
171 return AbstractCode::cast(GetCode());
172 }
173 }
174
function_token_position()175 int SharedFunctionInfo::function_token_position() const {
176 int offset = raw_function_token_offset();
177 if (offset == kFunctionTokenOutOfRange) {
178 return kNoSourcePosition;
179 } else {
180 return StartPosition() - offset;
181 }
182 }
183
BIT_FIELD_ACCESSORS(SharedFunctionInfo,flags2,class_scope_has_private_brand,SharedFunctionInfo::ClassScopeHasPrivateBrandBit)184 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, class_scope_has_private_brand,
185 SharedFunctionInfo::ClassScopeHasPrivateBrandBit)
186
187 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2,
188 has_static_private_methods_or_accessors,
189 SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit)
190
191 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, has_optimized_at_least_once,
192 SharedFunctionInfo::HasOptimizedAtLeastOnceBit)
193
194 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, may_have_cached_code,
195 SharedFunctionInfo::MayHaveCachedCodeBit)
196
197 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, syntax_kind,
198 SharedFunctionInfo::FunctionSyntaxKindBits)
199
200 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, allows_lazy_compilation,
201 SharedFunctionInfo::AllowLazyCompilationBit)
202 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_duplicate_parameters,
203 SharedFunctionInfo::HasDuplicateParametersBit)
204
205 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, native,
206 SharedFunctionInfo::IsNativeBit)
207 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken,
208 SharedFunctionInfo::IsAsmWasmBrokenBit)
209 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
210 requires_instance_members_initializer,
211 SharedFunctionInfo::RequiresInstanceMembersInitializerBit)
212
213 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous,
214 SharedFunctionInfo::NameShouldPrintAsAnonymousBit)
215 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_reported_binary_coverage,
216 SharedFunctionInfo::HasReportedBinaryCoverageBit)
217
218 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel,
219 SharedFunctionInfo::IsTopLevelBit)
220 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
221 is_oneshot_iife_or_properties_are_final,
222 SharedFunctionInfo::IsOneshotIifeOrPropertiesAreFinalBit)
223 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
224 private_name_lookup_skips_outer_class,
225 SharedFunctionInfo::PrivateNameLookupSkipsOuterClassBit)
226
227 bool SharedFunctionInfo::optimization_disabled() const {
228 return disable_optimization_reason() != BailoutReason::kNoReason;
229 }
230
disable_optimization_reason()231 BailoutReason SharedFunctionInfo::disable_optimization_reason() const {
232 return DisabledOptimizationReasonBits::decode(flags());
233 }
234
language_mode()235 LanguageMode SharedFunctionInfo::language_mode() const {
236 STATIC_ASSERT(LanguageModeSize == 2);
237 return construct_language_mode(IsStrictBit::decode(flags()));
238 }
239
set_language_mode(LanguageMode language_mode)240 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
241 STATIC_ASSERT(LanguageModeSize == 2);
242 // We only allow language mode transitions that set the same language mode
243 // again or go up in the chain:
244 DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode));
245 int hints = flags();
246 hints = IsStrictBit::update(hints, is_strict(language_mode));
247 set_flags(hints);
248 UpdateFunctionMapIndex();
249 }
250
kind()251 FunctionKind SharedFunctionInfo::kind() const {
252 STATIC_ASSERT(FunctionKindBits::kSize == kFunctionKindBitSize);
253 return FunctionKindBits::decode(flags());
254 }
255
set_kind(FunctionKind kind)256 void SharedFunctionInfo::set_kind(FunctionKind kind) {
257 int hints = flags();
258 hints = FunctionKindBits::update(hints, kind);
259 hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind));
260 set_flags(hints);
261 UpdateFunctionMapIndex();
262 }
263
is_wrapped()264 bool SharedFunctionInfo::is_wrapped() const {
265 return syntax_kind() == FunctionSyntaxKind::kWrapped;
266 }
267
needs_home_object()268 bool SharedFunctionInfo::needs_home_object() const {
269 return NeedsHomeObjectBit::decode(flags());
270 }
271
set_needs_home_object(bool value)272 void SharedFunctionInfo::set_needs_home_object(bool value) {
273 int hints = flags();
274 hints = NeedsHomeObjectBit::update(hints, value);
275 set_flags(hints);
276 UpdateFunctionMapIndex();
277 }
278
construct_as_builtin()279 bool SharedFunctionInfo::construct_as_builtin() const {
280 return ConstructAsBuiltinBit::decode(flags());
281 }
282
CalculateConstructAsBuiltin()283 void SharedFunctionInfo::CalculateConstructAsBuiltin() {
284 bool uses_builtins_construct_stub = false;
285 if (HasBuiltinId()) {
286 int id = builtin_id();
287 if (id != Builtins::kCompileLazy && id != Builtins::kEmptyFunction) {
288 uses_builtins_construct_stub = true;
289 }
290 } else if (IsApiFunction()) {
291 uses_builtins_construct_stub = true;
292 }
293
294 int f = flags();
295 f = ConstructAsBuiltinBit::update(f, uses_builtins_construct_stub);
296 set_flags(f);
297 }
298
function_map_index()299 int SharedFunctionInfo::function_map_index() const {
300 // Note: Must be kept in sync with the FastNewClosure builtin.
301 int index =
302 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::decode(flags());
303 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
304 return index;
305 }
306
set_function_map_index(int index)307 void SharedFunctionInfo::set_function_map_index(int index) {
308 STATIC_ASSERT(Context::LAST_FUNCTION_MAP_INDEX <=
309 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::kMax);
310 DCHECK_LE(Context::FIRST_FUNCTION_MAP_INDEX, index);
311 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
312 index -= Context::FIRST_FUNCTION_MAP_INDEX;
313 set_flags(FunctionMapIndexBits::update(flags(), index));
314 }
315
clear_padding()316 void SharedFunctionInfo::clear_padding() {
317 memset(reinterpret_cast<void*>(this->address() + kSize), 0,
318 kAlignedSize - kSize);
319 }
320
UpdateFunctionMapIndex()321 void SharedFunctionInfo::UpdateFunctionMapIndex() {
322 int map_index = Context::FunctionMapIndex(
323 language_mode(), kind(), HasSharedName(), needs_home_object());
324 set_function_map_index(map_index);
325 }
326
DontAdaptArguments()327 void SharedFunctionInfo::DontAdaptArguments() {
328 // TODO(leszeks): Revise this DCHECK now that the code field is gone.
329 DCHECK(!HasWasmExportedFunctionData());
330 set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel);
331 }
332
IsInterpreted()333 bool SharedFunctionInfo::IsInterpreted() const { return HasBytecodeArray(); }
334
scope_info()335 ScopeInfo SharedFunctionInfo::scope_info() const {
336 Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
337 if (maybe_scope_info.IsScopeInfo()) {
338 return ScopeInfo::cast(maybe_scope_info);
339 }
340 return GetReadOnlyRoots().empty_scope_info();
341 }
342
SetScopeInfo(ScopeInfo scope_info,WriteBarrierMode mode)343 void SharedFunctionInfo::SetScopeInfo(ScopeInfo scope_info,
344 WriteBarrierMode mode) {
345 // Move the existing name onto the ScopeInfo.
346 Object name = name_or_scope_info(kAcquireLoad);
347 if (name.IsScopeInfo()) {
348 name = ScopeInfo::cast(name).FunctionName();
349 }
350 DCHECK(name.IsString() || name == kNoSharedNameSentinel);
351 // Only set the function name for function scopes.
352 scope_info.SetFunctionName(name);
353 if (HasInferredName() && inferred_name().length() != 0) {
354 scope_info.SetInferredFunctionName(inferred_name());
355 }
356 set_name_or_scope_info(scope_info, kReleaseStore, mode);
357 }
358
set_raw_scope_info(ScopeInfo scope_info,WriteBarrierMode mode)359 void SharedFunctionInfo::set_raw_scope_info(ScopeInfo scope_info,
360 WriteBarrierMode mode) {
361 WRITE_FIELD(*this, kNameOrScopeInfoOffset, scope_info);
362 CONDITIONAL_WRITE_BARRIER(*this, kNameOrScopeInfoOffset, scope_info, mode);
363 }
364
ACCESSORS(SharedFunctionInfo,raw_outer_scope_info_or_feedback_metadata,HeapObject,kOuterScopeInfoOrFeedbackMetadataOffset)365 ACCESSORS(SharedFunctionInfo, raw_outer_scope_info_or_feedback_metadata,
366 HeapObject, kOuterScopeInfoOrFeedbackMetadataOffset)
367
368 HeapObject SharedFunctionInfo::outer_scope_info() const {
369 DCHECK(!is_compiled());
370 DCHECK(!HasFeedbackMetadata());
371 return raw_outer_scope_info_or_feedback_metadata();
372 }
373
HasOuterScopeInfo()374 bool SharedFunctionInfo::HasOuterScopeInfo() const {
375 ScopeInfo outer_info;
376 if (!is_compiled()) {
377 if (!outer_scope_info().IsScopeInfo()) return false;
378 outer_info = ScopeInfo::cast(outer_scope_info());
379 } else {
380 if (!scope_info().HasOuterScopeInfo()) return false;
381 outer_info = scope_info().OuterScopeInfo();
382 }
383 return outer_info.length() > 0;
384 }
385
GetOuterScopeInfo()386 ScopeInfo SharedFunctionInfo::GetOuterScopeInfo() const {
387 DCHECK(HasOuterScopeInfo());
388 if (!is_compiled()) return ScopeInfo::cast(outer_scope_info());
389 return scope_info().OuterScopeInfo();
390 }
391
set_outer_scope_info(HeapObject value,WriteBarrierMode mode)392 void SharedFunctionInfo::set_outer_scope_info(HeapObject value,
393 WriteBarrierMode mode) {
394 DCHECK(!is_compiled());
395 DCHECK(raw_outer_scope_info_or_feedback_metadata().IsTheHole());
396 DCHECK(value.IsScopeInfo() || value.IsTheHole());
397 set_raw_outer_scope_info_or_feedback_metadata(value, mode);
398 }
399
HasFeedbackMetadata()400 bool SharedFunctionInfo::HasFeedbackMetadata() const {
401 return raw_outer_scope_info_or_feedback_metadata().IsFeedbackMetadata();
402 }
403
feedback_metadata()404 FeedbackMetadata SharedFunctionInfo::feedback_metadata() const {
405 DCHECK(HasFeedbackMetadata());
406 return FeedbackMetadata::cast(raw_outer_scope_info_or_feedback_metadata());
407 }
408
set_feedback_metadata(FeedbackMetadata value,WriteBarrierMode mode)409 void SharedFunctionInfo::set_feedback_metadata(FeedbackMetadata value,
410 WriteBarrierMode mode) {
411 DCHECK(!HasFeedbackMetadata());
412 DCHECK(value.IsFeedbackMetadata());
413 set_raw_outer_scope_info_or_feedback_metadata(value, mode);
414 }
415
is_compiled()416 bool SharedFunctionInfo::is_compiled() const {
417 Object data = function_data(kAcquireLoad);
418 return data != Smi::FromEnum(Builtins::kCompileLazy) &&
419 !data.IsUncompiledData();
420 }
421
422 template <typename LocalIsolate>
is_compiled_scope(LocalIsolate * isolate)423 IsCompiledScope SharedFunctionInfo::is_compiled_scope(
424 LocalIsolate* isolate) const {
425 return IsCompiledScope(*this, isolate);
426 }
427
IsCompiledScope(const SharedFunctionInfo shared,Isolate * isolate)428 IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
429 Isolate* isolate)
430 : retain_bytecode_(shared.HasBytecodeArray()
431 ? handle(shared.GetBytecodeArray(), isolate)
432 : MaybeHandle<BytecodeArray>()),
433 is_compiled_(shared.is_compiled()) {
434 DCHECK_IMPLIES(!retain_bytecode_.is_null(), is_compiled());
435 }
436
IsCompiledScope(const SharedFunctionInfo shared,LocalIsolate * isolate)437 IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
438 LocalIsolate* isolate)
439 : retain_bytecode_(
440 shared.HasBytecodeArray()
441 ? isolate->heap()->NewPersistentHandle(shared.GetBytecodeArray())
442 : MaybeHandle<BytecodeArray>()),
443 is_compiled_(shared.is_compiled()) {
444 DCHECK_IMPLIES(!retain_bytecode_.is_null(), is_compiled());
445 }
446
has_simple_parameters()447 bool SharedFunctionInfo::has_simple_parameters() {
448 return scope_info().HasSimpleParameters();
449 }
450
IsApiFunction()451 bool SharedFunctionInfo::IsApiFunction() const {
452 return function_data(kAcquireLoad).IsFunctionTemplateInfo();
453 }
454
get_api_func_data()455 FunctionTemplateInfo SharedFunctionInfo::get_api_func_data() const {
456 DCHECK(IsApiFunction());
457 return FunctionTemplateInfo::cast(function_data(kAcquireLoad));
458 }
459
HasBytecodeArray()460 bool SharedFunctionInfo::HasBytecodeArray() const {
461 Object data = function_data(kAcquireLoad);
462 return data.IsBytecodeArray() || data.IsInterpreterData();
463 }
464
GetBytecodeArray()465 BytecodeArray SharedFunctionInfo::GetBytecodeArray() const {
466 DCHECK(HasBytecodeArray());
467 if (HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()) {
468 return GetDebugInfo().OriginalBytecodeArray();
469 }
470
471 Object data = function_data(kAcquireLoad);
472 if (data.IsBytecodeArray()) {
473 return BytecodeArray::cast(data);
474 } else {
475 DCHECK(data.IsInterpreterData());
476 return InterpreterData::cast(data).bytecode_array();
477 }
478 }
479
GetDebugBytecodeArray()480 BytecodeArray SharedFunctionInfo::GetDebugBytecodeArray() const {
481 DCHECK(HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray());
482
483 Object data = function_data(kAcquireLoad);
484 if (data.IsBytecodeArray()) {
485 return BytecodeArray::cast(data);
486 } else {
487 DCHECK(data.IsInterpreterData());
488 return InterpreterData::cast(data).bytecode_array();
489 }
490 }
491
SetDebugBytecodeArray(BytecodeArray bytecode)492 void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray bytecode) {
493 Object data = function_data(kAcquireLoad);
494 if (data.IsBytecodeArray()) {
495 set_function_data(bytecode, kReleaseStore);
496 } else {
497 DCHECK(data.IsInterpreterData());
498 interpreter_data().set_bytecode_array(bytecode);
499 }
500 }
501
set_bytecode_array(BytecodeArray bytecode)502 void SharedFunctionInfo::set_bytecode_array(BytecodeArray bytecode) {
503 DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
504 HasUncompiledData());
505 set_function_data(bytecode, kReleaseStore);
506 }
507
ShouldFlushBytecode(BytecodeFlushMode mode)508 bool SharedFunctionInfo::ShouldFlushBytecode(BytecodeFlushMode mode) {
509 if (mode == BytecodeFlushMode::kDoNotFlushBytecode) return false;
510
511 // TODO(rmcilroy): Enable bytecode flushing for resumable functions.
512 if (IsResumableFunction(kind()) || !allows_lazy_compilation()) {
513 return false;
514 }
515
516 // Get a snapshot of the function data field, and if it is a bytecode array,
517 // check if it is old. Note, this is done this way since this function can be
518 // called by the concurrent marker.
519 Object data = function_data(kAcquireLoad);
520 if (!data.IsBytecodeArray()) return false;
521
522 if (mode == BytecodeFlushMode::kStressFlushBytecode) return true;
523
524 BytecodeArray bytecode = BytecodeArray::cast(data);
525
526 return bytecode.IsOld();
527 }
528
InterpreterTrampoline()529 Code SharedFunctionInfo::InterpreterTrampoline() const {
530 DCHECK(HasInterpreterData());
531 return interpreter_data().interpreter_trampoline();
532 }
533
HasInterpreterData()534 bool SharedFunctionInfo::HasInterpreterData() const {
535 return function_data(kAcquireLoad).IsInterpreterData();
536 }
537
interpreter_data()538 InterpreterData SharedFunctionInfo::interpreter_data() const {
539 DCHECK(HasInterpreterData());
540 return InterpreterData::cast(function_data(kAcquireLoad));
541 }
542
set_interpreter_data(InterpreterData interpreter_data)543 void SharedFunctionInfo::set_interpreter_data(
544 InterpreterData interpreter_data) {
545 DCHECK(FLAG_interpreted_frames_native_stack);
546 set_function_data(interpreter_data, kReleaseStore);
547 }
548
HasAsmWasmData()549 bool SharedFunctionInfo::HasAsmWasmData() const {
550 return function_data(kAcquireLoad).IsAsmWasmData();
551 }
552
asm_wasm_data()553 AsmWasmData SharedFunctionInfo::asm_wasm_data() const {
554 DCHECK(HasAsmWasmData());
555 return AsmWasmData::cast(function_data(kAcquireLoad));
556 }
557
set_asm_wasm_data(AsmWasmData data)558 void SharedFunctionInfo::set_asm_wasm_data(AsmWasmData data) {
559 DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
560 HasUncompiledData() || HasAsmWasmData());
561 set_function_data(data, kReleaseStore);
562 }
563
HasBuiltinId()564 bool SharedFunctionInfo::HasBuiltinId() const {
565 return function_data(kAcquireLoad).IsSmi();
566 }
567
builtin_id()568 int SharedFunctionInfo::builtin_id() const {
569 DCHECK(HasBuiltinId());
570 int id = Smi::ToInt(function_data(kAcquireLoad));
571 DCHECK(Builtins::IsBuiltinId(id));
572 return id;
573 }
574
set_builtin_id(int builtin_id)575 void SharedFunctionInfo::set_builtin_id(int builtin_id) {
576 DCHECK(Builtins::IsBuiltinId(builtin_id));
577 set_function_data(Smi::FromInt(builtin_id), kReleaseStore,
578 SKIP_WRITE_BARRIER);
579 }
580
HasUncompiledData()581 bool SharedFunctionInfo::HasUncompiledData() const {
582 return function_data(kAcquireLoad).IsUncompiledData();
583 }
584
uncompiled_data()585 UncompiledData SharedFunctionInfo::uncompiled_data() const {
586 DCHECK(HasUncompiledData());
587 return UncompiledData::cast(function_data(kAcquireLoad));
588 }
589
set_uncompiled_data(UncompiledData uncompiled_data)590 void SharedFunctionInfo::set_uncompiled_data(UncompiledData uncompiled_data) {
591 DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy) ||
592 HasUncompiledData());
593 DCHECK(uncompiled_data.IsUncompiledData());
594 set_function_data(uncompiled_data, kReleaseStore);
595 }
596
HasUncompiledDataWithPreparseData()597 bool SharedFunctionInfo::HasUncompiledDataWithPreparseData() const {
598 return function_data(kAcquireLoad).IsUncompiledDataWithPreparseData();
599 }
600
601 UncompiledDataWithPreparseData
uncompiled_data_with_preparse_data()602 SharedFunctionInfo::uncompiled_data_with_preparse_data() const {
603 DCHECK(HasUncompiledDataWithPreparseData());
604 return UncompiledDataWithPreparseData::cast(function_data(kAcquireLoad));
605 }
606
set_uncompiled_data_with_preparse_data(UncompiledDataWithPreparseData uncompiled_data_with_preparse_data)607 void SharedFunctionInfo::set_uncompiled_data_with_preparse_data(
608 UncompiledDataWithPreparseData uncompiled_data_with_preparse_data) {
609 DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtins::kCompileLazy));
610 DCHECK(uncompiled_data_with_preparse_data.IsUncompiledDataWithPreparseData());
611 set_function_data(uncompiled_data_with_preparse_data, kReleaseStore);
612 }
613
HasUncompiledDataWithoutPreparseData()614 bool SharedFunctionInfo::HasUncompiledDataWithoutPreparseData() const {
615 return function_data(kAcquireLoad).IsUncompiledDataWithoutPreparseData();
616 }
617
ClearPreparseData()618 void SharedFunctionInfo::ClearPreparseData() {
619 DCHECK(HasUncompiledDataWithPreparseData());
620 UncompiledDataWithPreparseData data = uncompiled_data_with_preparse_data();
621
622 // Trim off the pre-parsed scope data from the uncompiled data by swapping the
623 // map, leaving only an uncompiled data without pre-parsed scope.
624 DisallowHeapAllocation no_gc;
625 Heap* heap = GetHeapFromWritableObject(data);
626
627 // Swap the map.
628 heap->NotifyObjectLayoutChange(data, no_gc);
629 STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize <
630 UncompiledDataWithPreparseData::kSize);
631 STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize ==
632 UncompiledData::kHeaderSize);
633 data.synchronized_set_map(
634 GetReadOnlyRoots().uncompiled_data_without_preparse_data_map());
635
636 // Fill the remaining space with filler.
637 heap->CreateFillerObjectAt(
638 data.address() + UncompiledDataWithoutPreparseData::kSize,
639 UncompiledDataWithPreparseData::kSize -
640 UncompiledDataWithoutPreparseData::kSize,
641 ClearRecordedSlots::kYes);
642
643 // Ensure that the clear was successful.
644 DCHECK(HasUncompiledDataWithoutPreparseData());
645 }
646
647 template <typename LocalIsolate>
Init(LocalIsolate * isolate,String inferred_name,int start_position,int end_position)648 void UncompiledData::Init(LocalIsolate* isolate, String inferred_name,
649 int start_position, int end_position) {
650 set_inferred_name(inferred_name);
651 set_start_position(start_position);
652 set_end_position(end_position);
653 }
654
InitAfterBytecodeFlush(String inferred_name,int start_position,int end_position,std::function<void (HeapObject object,ObjectSlot slot,HeapObject target)> gc_notify_updated_slot)655 void UncompiledData::InitAfterBytecodeFlush(
656 String inferred_name, int start_position, int end_position,
657 std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)>
658 gc_notify_updated_slot) {
659 set_inferred_name(inferred_name);
660 gc_notify_updated_slot(*this, RawField(UncompiledData::kInferredNameOffset),
661 inferred_name);
662 set_start_position(start_position);
663 set_end_position(end_position);
664 }
665
666 template <typename LocalIsolate>
Init(LocalIsolate * isolate,String inferred_name,int start_position,int end_position,PreparseData scope_data)667 void UncompiledDataWithPreparseData::Init(LocalIsolate* isolate,
668 String inferred_name,
669 int start_position, int end_position,
670 PreparseData scope_data) {
671 this->UncompiledData::Init(isolate, inferred_name, start_position,
672 end_position);
673 set_preparse_data(scope_data);
674 }
675
HasWasmExportedFunctionData()676 bool SharedFunctionInfo::HasWasmExportedFunctionData() const {
677 return function_data(kAcquireLoad).IsWasmExportedFunctionData();
678 }
679
HasWasmJSFunctionData()680 bool SharedFunctionInfo::HasWasmJSFunctionData() const {
681 return function_data(kAcquireLoad).IsWasmJSFunctionData();
682 }
683
HasWasmCapiFunctionData()684 bool SharedFunctionInfo::HasWasmCapiFunctionData() const {
685 return function_data(kAcquireLoad).IsWasmCapiFunctionData();
686 }
687
script()688 HeapObject SharedFunctionInfo::script() const {
689 HeapObject maybe_script = script_or_debug_info(kAcquireLoad);
690 if (maybe_script.IsDebugInfo()) {
691 return DebugInfo::cast(maybe_script).script();
692 }
693 return maybe_script;
694 }
695
set_script(HeapObject script)696 void SharedFunctionInfo::set_script(HeapObject script) {
697 HeapObject maybe_debug_info = script_or_debug_info(kAcquireLoad);
698 if (maybe_debug_info.IsDebugInfo()) {
699 DebugInfo::cast(maybe_debug_info).set_script(script);
700 } else {
701 set_script_or_debug_info(script, kReleaseStore);
702 }
703 }
704
is_repl_mode()705 bool SharedFunctionInfo::is_repl_mode() const {
706 return script().IsScript() && Script::cast(script()).is_repl_mode();
707 }
708
HasDebugInfo()709 bool SharedFunctionInfo::HasDebugInfo() const {
710 return script_or_debug_info(kAcquireLoad).IsDebugInfo();
711 }
712
GetDebugInfo()713 DebugInfo SharedFunctionInfo::GetDebugInfo() const {
714 auto debug_info = script_or_debug_info(kAcquireLoad);
715 DCHECK(debug_info.IsDebugInfo());
716 return DebugInfo::cast(debug_info);
717 }
718
SetDebugInfo(DebugInfo debug_info)719 void SharedFunctionInfo::SetDebugInfo(DebugInfo debug_info) {
720 DCHECK(!HasDebugInfo());
721 DCHECK_EQ(debug_info.script(), script_or_debug_info(kAcquireLoad));
722 set_script_or_debug_info(debug_info, kReleaseStore);
723 }
724
HasInferredName()725 bool SharedFunctionInfo::HasInferredName() {
726 Object scope_info = name_or_scope_info(kAcquireLoad);
727 if (scope_info.IsScopeInfo()) {
728 return ScopeInfo::cast(scope_info).HasInferredFunctionName();
729 }
730 return HasUncompiledData();
731 }
732
inferred_name()733 String SharedFunctionInfo::inferred_name() {
734 Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
735 if (maybe_scope_info.IsScopeInfo()) {
736 ScopeInfo scope_info = ScopeInfo::cast(maybe_scope_info);
737 if (scope_info.HasInferredFunctionName()) {
738 Object name = scope_info.InferredFunctionName();
739 if (name.IsString()) return String::cast(name);
740 }
741 } else if (HasUncompiledData()) {
742 return uncompiled_data().inferred_name();
743 }
744 return GetReadOnlyRoots().empty_string();
745 }
746
IsUserJavaScript()747 bool SharedFunctionInfo::IsUserJavaScript() const {
748 Object script_obj = script();
749 if (script_obj.IsUndefined()) return false;
750 Script script = Script::cast(script_obj);
751 return script.IsUserJavaScript();
752 }
753
IsSubjectToDebugging()754 bool SharedFunctionInfo::IsSubjectToDebugging() const {
755 return IsUserJavaScript() && !HasAsmWasmData();
756 }
757
CanDiscardCompiled()758 bool SharedFunctionInfo::CanDiscardCompiled() const {
759 bool can_decompile = (HasBytecodeArray() || HasAsmWasmData() ||
760 HasUncompiledDataWithPreparseData());
761 return can_decompile;
762 }
763
is_class_constructor()764 bool SharedFunctionInfo::is_class_constructor() const {
765 return IsClassConstructorBit::decode(flags());
766 }
767
is_oneshot_iife()768 bool SharedFunctionInfo::is_oneshot_iife() const {
769 bool bit = is_oneshot_iife_or_properties_are_final();
770 return bit && !is_class_constructor();
771 }
772
set_is_oneshot_iife(bool value)773 void SharedFunctionInfo::set_is_oneshot_iife(bool value) {
774 DCHECK(!value || !is_class_constructor());
775 if (!is_class_constructor()) {
776 set_is_oneshot_iife_or_properties_are_final(value);
777 }
778 }
779
set_are_properties_final(bool value)780 void SharedFunctionInfo::set_are_properties_final(bool value) {
781 if (is_class_constructor()) {
782 set_is_oneshot_iife_or_properties_are_final(value);
783 }
784 }
785
are_properties_final()786 bool SharedFunctionInfo::are_properties_final() const {
787 bool bit = is_oneshot_iife_or_properties_are_final();
788 return bit && is_class_constructor();
789 }
790
791 } // namespace internal
792 } // namespace v8
793
794 #include "src/objects/object-macros-undef.h"
795
796 #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
797