• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_OBJECTS_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