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