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/handles-inl.h"
11 #include "src/heap/heap-inl.h"
12 #include "src/objects/debug-objects-inl.h"
13 #include "src/objects/scope-info.h"
14 #include "src/objects/templates.h"
15
16 // Has to be the last include (doesn't have include guards):
17 #include "src/objects/object-macros.h"
18
19 namespace v8 {
20 namespace internal {
21
22 CAST_ACCESSOR(PreParsedScopeData)
ACCESSORS(PreParsedScopeData,scope_data,PodArray<uint8_t>,kScopeDataOffset)23 ACCESSORS(PreParsedScopeData, scope_data, PodArray<uint8_t>, kScopeDataOffset)
24 INT_ACCESSORS(PreParsedScopeData, length, kLengthOffset)
25
26 Object* PreParsedScopeData::child_data(int index) const {
27 DCHECK_GE(index, 0);
28 DCHECK_LT(index, this->length());
29 int offset = kChildDataStartOffset + index * kPointerSize;
30 return RELAXED_READ_FIELD(this, offset);
31 }
32
set_child_data(int index,Object * value,WriteBarrierMode mode)33 void PreParsedScopeData::set_child_data(int index, Object* value,
34 WriteBarrierMode mode) {
35 DCHECK_GE(index, 0);
36 DCHECK_LT(index, this->length());
37 int offset = kChildDataStartOffset + index * kPointerSize;
38 RELAXED_WRITE_FIELD(this, offset, value);
39 CONDITIONAL_WRITE_BARRIER(this, offset, value, mode);
40 }
41
child_data_start()42 Object** PreParsedScopeData::child_data_start() const {
43 return HeapObject::RawField(this, kChildDataStartOffset);
44 }
45
clear_padding()46 void PreParsedScopeData::clear_padding() {
47 // For archs where kIntSize < kPointerSize, there will be padding between the
48 // length field and the start of the child data.
49 if (kUnalignedChildDataStartOffset < kChildDataStartOffset) {
50 memset(reinterpret_cast<void*>(address() + kUnalignedChildDataStartOffset),
51 0, kChildDataStartOffset - kUnalignedChildDataStartOffset);
52 }
53 }
54
55 CAST_ACCESSOR(UncompiledData)
ACCESSORS(UncompiledData,inferred_name,String,kInferredNameOffset)56 ACCESSORS(UncompiledData, inferred_name, String, kInferredNameOffset)
57 INT32_ACCESSORS(UncompiledData, start_position, kStartPositionOffset)
58 INT32_ACCESSORS(UncompiledData, end_position, kEndPositionOffset)
59 INT32_ACCESSORS(UncompiledData, function_literal_id, kFunctionLiteralIdOffset)
60
61 void UncompiledData::clear_padding() {
62 // For archs where kIntSize < kPointerSize, there will be padding at the end
63 // of the data.
64 if (kUnalignedSize < kSize) {
65 memset(reinterpret_cast<void*>(address() + kUnalignedSize), 0,
66 kSize - kUnalignedSize);
67 }
68 }
69
70 CAST_ACCESSOR(UncompiledDataWithoutPreParsedScope)
71
CAST_ACCESSOR(UncompiledDataWithPreParsedScope)72 CAST_ACCESSOR(UncompiledDataWithPreParsedScope)
73 ACCESSORS(UncompiledDataWithPreParsedScope, pre_parsed_scope_data,
74 PreParsedScopeData, kPreParsedScopeDataOffset)
75
76 CAST_ACCESSOR(InterpreterData)
77 ACCESSORS(InterpreterData, bytecode_array, BytecodeArray, kBytecodeArrayOffset)
78 ACCESSORS(InterpreterData, interpreter_trampoline, Code,
79 kInterpreterTrampolineOffset)
80
81 CAST_ACCESSOR(SharedFunctionInfo)
82 DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)
83
84 ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
85 kNameOrScopeInfoOffset)
86 ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
87 ACCESSORS(SharedFunctionInfo, script_or_debug_info, Object,
88 kScriptOrDebugInfoOffset)
89
90 #if V8_SFI_HAS_UNIQUE_ID
91 INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
92 #endif
93 UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
94 UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count,
95 kFormalParameterCountOffset)
96 UINT8_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
97 kExpectedNofPropertiesOffset)
98 UINT8_ACCESSORS(SharedFunctionInfo, raw_builtin_function_id, kBuiltinFunctionId)
99 UINT16_ACCESSORS(SharedFunctionInfo, raw_function_token_offset,
100 kFunctionTokenOffsetOffset)
101 INT_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset)
102
103 bool SharedFunctionInfo::HasSharedName() const {
104 Object* value = name_or_scope_info();
105 if (value->IsScopeInfo()) {
106 return ScopeInfo::cast(value)->HasSharedFunctionName();
107 }
108 return value != kNoSharedNameSentinel;
109 }
110
Name()111 String* SharedFunctionInfo::Name() const {
112 if (!HasSharedName()) return GetReadOnlyRoots().empty_string();
113 Object* value = name_or_scope_info();
114 if (value->IsScopeInfo()) {
115 if (ScopeInfo::cast(value)->HasFunctionName()) {
116 return String::cast(ScopeInfo::cast(value)->FunctionName());
117 }
118 return GetReadOnlyRoots().empty_string();
119 }
120 return String::cast(value);
121 }
122
SetName(String * name)123 void SharedFunctionInfo::SetName(String* name) {
124 Object* maybe_scope_info = name_or_scope_info();
125 if (maybe_scope_info->IsScopeInfo()) {
126 ScopeInfo::cast(maybe_scope_info)->SetFunctionName(name);
127 } else {
128 DCHECK(maybe_scope_info->IsString() ||
129 maybe_scope_info == kNoSharedNameSentinel);
130 set_name_or_scope_info(name);
131 }
132 UpdateFunctionMapIndex();
133 }
134
abstract_code()135 AbstractCode* SharedFunctionInfo::abstract_code() {
136 if (HasBytecodeArray()) {
137 return AbstractCode::cast(GetBytecodeArray());
138 } else {
139 return AbstractCode::cast(GetCode());
140 }
141 }
142
function_token_position()143 int SharedFunctionInfo::function_token_position() const {
144 int offset = raw_function_token_offset();
145 if (offset == kFunctionTokenOutOfRange) {
146 return kNoSourcePosition;
147 } else {
148 return StartPosition() - offset;
149 }
150 }
151
BIT_FIELD_ACCESSORS(SharedFunctionInfo,flags,is_wrapped,SharedFunctionInfo::IsWrappedBit)152 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_wrapped,
153 SharedFunctionInfo::IsWrappedBit)
154 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, allows_lazy_compilation,
155 SharedFunctionInfo::AllowLazyCompilationBit)
156 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_duplicate_parameters,
157 SharedFunctionInfo::HasDuplicateParametersBit)
158 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_declaration,
159 SharedFunctionInfo::IsDeclarationBit)
160
161 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, native,
162 SharedFunctionInfo::IsNativeBit)
163 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken,
164 SharedFunctionInfo::IsAsmWasmBrokenBit)
165 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
166 requires_instance_fields_initializer,
167 SharedFunctionInfo::RequiresInstanceFieldsInitializer)
168
169 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous,
170 SharedFunctionInfo::NameShouldPrintAsAnonymousBit)
171 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_anonymous_expression,
172 SharedFunctionInfo::IsAnonymousExpressionBit)
173 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, deserialized,
174 SharedFunctionInfo::IsDeserializedBit)
175 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, has_reported_binary_coverage,
176 SharedFunctionInfo::HasReportedBinaryCoverageBit)
177
178 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_named_expression,
179 SharedFunctionInfo::IsNamedExpressionBit)
180 BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel,
181 SharedFunctionInfo::IsTopLevelBit)
182
183 bool SharedFunctionInfo::optimization_disabled() const {
184 return disable_optimization_reason() != BailoutReason::kNoReason;
185 }
186
disable_optimization_reason()187 BailoutReason SharedFunctionInfo::disable_optimization_reason() const {
188 return DisabledOptimizationReasonBits::decode(flags());
189 }
190
language_mode()191 LanguageMode SharedFunctionInfo::language_mode() const {
192 STATIC_ASSERT(LanguageModeSize == 2);
193 return construct_language_mode(IsStrictBit::decode(flags()));
194 }
195
set_language_mode(LanguageMode language_mode)196 void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
197 STATIC_ASSERT(LanguageModeSize == 2);
198 // We only allow language mode transitions that set the same language mode
199 // again or go up in the chain:
200 DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode));
201 int hints = flags();
202 hints = IsStrictBit::update(hints, is_strict(language_mode));
203 set_flags(hints);
204 UpdateFunctionMapIndex();
205 }
206
kind()207 FunctionKind SharedFunctionInfo::kind() const {
208 return FunctionKindBits::decode(flags());
209 }
210
set_kind(FunctionKind kind)211 void SharedFunctionInfo::set_kind(FunctionKind kind) {
212 int hints = flags();
213 hints = FunctionKindBits::update(hints, kind);
214 hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind));
215 hints = IsDerivedConstructorBit::update(hints, IsDerivedConstructor(kind));
216 set_flags(hints);
217 UpdateFunctionMapIndex();
218 }
219
needs_home_object()220 bool SharedFunctionInfo::needs_home_object() const {
221 return NeedsHomeObjectBit::decode(flags());
222 }
223
set_needs_home_object(bool value)224 void SharedFunctionInfo::set_needs_home_object(bool value) {
225 int hints = flags();
226 hints = NeedsHomeObjectBit::update(hints, value);
227 set_flags(hints);
228 UpdateFunctionMapIndex();
229 }
230
construct_as_builtin()231 bool SharedFunctionInfo::construct_as_builtin() const {
232 return ConstructAsBuiltinBit::decode(flags());
233 }
234
CalculateConstructAsBuiltin()235 void SharedFunctionInfo::CalculateConstructAsBuiltin() {
236 bool uses_builtins_construct_stub = false;
237 if (HasBuiltinId()) {
238 int id = builtin_id();
239 if (id != Builtins::kCompileLazy && id != Builtins::kEmptyFunction) {
240 uses_builtins_construct_stub = true;
241 }
242 } else if (IsApiFunction()) {
243 uses_builtins_construct_stub = true;
244 }
245
246 int f = flags();
247 f = ConstructAsBuiltinBit::update(f, uses_builtins_construct_stub);
248 set_flags(f);
249 }
250
function_map_index()251 int SharedFunctionInfo::function_map_index() const {
252 // Note: Must be kept in sync with the FastNewClosure builtin.
253 int index =
254 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::decode(flags());
255 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
256 return index;
257 }
258
set_function_map_index(int index)259 void SharedFunctionInfo::set_function_map_index(int index) {
260 STATIC_ASSERT(Context::LAST_FUNCTION_MAP_INDEX <=
261 Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::kMax);
262 DCHECK_LE(Context::FIRST_FUNCTION_MAP_INDEX, index);
263 DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
264 index -= Context::FIRST_FUNCTION_MAP_INDEX;
265 set_flags(FunctionMapIndexBits::update(flags(), index));
266 }
267
clear_padding()268 void SharedFunctionInfo::clear_padding() {
269 memset(reinterpret_cast<void*>(this->address() + kSize), 0,
270 kAlignedSize - kSize);
271 }
272
UpdateFunctionMapIndex()273 void SharedFunctionInfo::UpdateFunctionMapIndex() {
274 int map_index = Context::FunctionMapIndex(
275 language_mode(), kind(), true, HasSharedName(), needs_home_object());
276 set_function_map_index(map_index);
277 }
278
DontAdaptArguments()279 void SharedFunctionInfo::DontAdaptArguments() {
280 // TODO(leszeks): Revise this DCHECK now that the code field is gone.
281 DCHECK(!HasWasmExportedFunctionData());
282 set_internal_formal_parameter_count(kDontAdaptArgumentsSentinel);
283 }
284
StartPosition()285 int SharedFunctionInfo::StartPosition() const {
286 Object* maybe_scope_info = name_or_scope_info();
287 if (maybe_scope_info->IsScopeInfo()) {
288 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info);
289 if (info->HasPositionInfo()) {
290 return info->StartPosition();
291 }
292 } else if (HasUncompiledData()) {
293 // Works with or without scope.
294 return uncompiled_data()->start_position();
295 } else if (IsApiFunction() || HasBuiltinId()) {
296 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
297 return 0;
298 }
299 return kNoSourcePosition;
300 }
301
EndPosition()302 int SharedFunctionInfo::EndPosition() const {
303 Object* maybe_scope_info = name_or_scope_info();
304 if (maybe_scope_info->IsScopeInfo()) {
305 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info);
306 if (info->HasPositionInfo()) {
307 return info->EndPosition();
308 }
309 } else if (HasUncompiledData()) {
310 // Works with or without scope.
311 return uncompiled_data()->end_position();
312 } else if (IsApiFunction() || HasBuiltinId()) {
313 DCHECK_IMPLIES(HasBuiltinId(), builtin_id() != Builtins::kCompileLazy);
314 return 0;
315 }
316 return kNoSourcePosition;
317 }
318
SetPosition(int start_position,int end_position)319 void SharedFunctionInfo::SetPosition(int start_position, int end_position) {
320 Object* maybe_scope_info = name_or_scope_info();
321 if (maybe_scope_info->IsScopeInfo()) {
322 ScopeInfo* info = ScopeInfo::cast(maybe_scope_info);
323 if (info->HasPositionInfo()) {
324 info->SetPositionInfo(start_position, end_position);
325 }
326 } else if (HasUncompiledData()) {
327 if (HasUncompiledDataWithPreParsedScope()) {
328 // Clear out preparsed scope data, since the position setter invalidates
329 // any scope data.
330 ClearPreParsedScopeData();
331 }
332 uncompiled_data()->set_start_position(start_position);
333 uncompiled_data()->set_end_position(end_position);
334 } else {
335 UNREACHABLE();
336 }
337 }
338
IsInterpreted()339 bool SharedFunctionInfo::IsInterpreted() const { return HasBytecodeArray(); }
340
scope_info()341 ScopeInfo* SharedFunctionInfo::scope_info() const {
342 Object* maybe_scope_info = name_or_scope_info();
343 if (maybe_scope_info->IsScopeInfo()) {
344 return ScopeInfo::cast(maybe_scope_info);
345 }
346 return ScopeInfo::Empty(GetIsolate());
347 }
348
set_scope_info(ScopeInfo * scope_info,WriteBarrierMode mode)349 void SharedFunctionInfo::set_scope_info(ScopeInfo* scope_info,
350 WriteBarrierMode mode) {
351 // Move the existing name onto the ScopeInfo.
352 Object* name = name_or_scope_info();
353 if (name->IsScopeInfo()) {
354 name = ScopeInfo::cast(name)->FunctionName();
355 }
356 DCHECK(name->IsString() || name == kNoSharedNameSentinel);
357 // Only set the function name for function scopes.
358 scope_info->SetFunctionName(name);
359 if (HasInferredName() && inferred_name()->length() != 0) {
360 scope_info->SetInferredFunctionName(inferred_name());
361 }
362 WRITE_FIELD(this, kNameOrScopeInfoOffset,
363 reinterpret_cast<Object*>(scope_info));
364 CONDITIONAL_WRITE_BARRIER(this, kNameOrScopeInfoOffset,
365 reinterpret_cast<Object*>(scope_info), mode);
366 }
367
ACCESSORS(SharedFunctionInfo,raw_outer_scope_info_or_feedback_metadata,HeapObject,kOuterScopeInfoOrFeedbackMetadataOffset)368 ACCESSORS(SharedFunctionInfo, raw_outer_scope_info_or_feedback_metadata,
369 HeapObject, kOuterScopeInfoOrFeedbackMetadataOffset)
370
371 HeapObject* SharedFunctionInfo::outer_scope_info() const {
372 DCHECK(!is_compiled());
373 DCHECK(!HasFeedbackMetadata());
374 return raw_outer_scope_info_or_feedback_metadata();
375 }
376
HasOuterScopeInfo()377 bool SharedFunctionInfo::HasOuterScopeInfo() const {
378 ScopeInfo* outer_info = nullptr;
379 if (!is_compiled()) {
380 if (!outer_scope_info()->IsScopeInfo()) return false;
381 outer_info = ScopeInfo::cast(outer_scope_info());
382 } else {
383 if (!scope_info()->HasOuterScopeInfo()) return false;
384 outer_info = scope_info()->OuterScopeInfo();
385 }
386 return outer_info->length() > 0;
387 }
388
GetOuterScopeInfo()389 ScopeInfo* SharedFunctionInfo::GetOuterScopeInfo() const {
390 DCHECK(HasOuterScopeInfo());
391 if (!is_compiled()) return ScopeInfo::cast(outer_scope_info());
392 return scope_info()->OuterScopeInfo();
393 }
394
set_outer_scope_info(HeapObject * value,WriteBarrierMode mode)395 void SharedFunctionInfo::set_outer_scope_info(HeapObject* value,
396 WriteBarrierMode mode) {
397 DCHECK(!is_compiled());
398 DCHECK(raw_outer_scope_info_or_feedback_metadata()->IsTheHole());
399 DCHECK(value->IsScopeInfo() || value->IsTheHole());
400 return set_raw_outer_scope_info_or_feedback_metadata(value, mode);
401 }
402
HasFeedbackMetadata()403 bool SharedFunctionInfo::HasFeedbackMetadata() const {
404 return raw_outer_scope_info_or_feedback_metadata()->IsFeedbackMetadata();
405 }
406
feedback_metadata()407 FeedbackMetadata* SharedFunctionInfo::feedback_metadata() const {
408 DCHECK(HasFeedbackMetadata());
409 return FeedbackMetadata::cast(raw_outer_scope_info_or_feedback_metadata());
410 }
411
set_feedback_metadata(FeedbackMetadata * value,WriteBarrierMode mode)412 void SharedFunctionInfo::set_feedback_metadata(FeedbackMetadata* value,
413 WriteBarrierMode mode) {
414 DCHECK(!HasFeedbackMetadata());
415 DCHECK(value->IsFeedbackMetadata());
416 return set_raw_outer_scope_info_or_feedback_metadata(value, mode);
417 }
418
is_compiled()419 bool SharedFunctionInfo::is_compiled() const {
420 Object* data = function_data();
421 return data != Smi::FromEnum(Builtins::kCompileLazy) &&
422 !data->IsUncompiledData();
423 }
424
GetLength()425 uint16_t SharedFunctionInfo::GetLength() const {
426 DCHECK(is_compiled());
427 DCHECK(HasLength());
428 return length();
429 }
430
HasLength()431 bool SharedFunctionInfo::HasLength() const {
432 return length() != kInvalidLength;
433 }
434
has_simple_parameters()435 bool SharedFunctionInfo::has_simple_parameters() {
436 return scope_info()->HasSimpleParameters();
437 }
438
IsApiFunction()439 bool SharedFunctionInfo::IsApiFunction() const {
440 return function_data()->IsFunctionTemplateInfo();
441 }
442
get_api_func_data()443 FunctionTemplateInfo* SharedFunctionInfo::get_api_func_data() {
444 DCHECK(IsApiFunction());
445 return FunctionTemplateInfo::cast(function_data());
446 }
447
HasBytecodeArray()448 bool SharedFunctionInfo::HasBytecodeArray() const {
449 return function_data()->IsBytecodeArray() ||
450 function_data()->IsInterpreterData();
451 }
452
GetBytecodeArray()453 BytecodeArray* SharedFunctionInfo::GetBytecodeArray() const {
454 DCHECK(HasBytecodeArray());
455 if (HasDebugInfo() && GetDebugInfo()->HasInstrumentedBytecodeArray()) {
456 return GetDebugInfo()->OriginalBytecodeArray();
457 } else if (function_data()->IsBytecodeArray()) {
458 return BytecodeArray::cast(function_data());
459 } else {
460 DCHECK(function_data()->IsInterpreterData());
461 return InterpreterData::cast(function_data())->bytecode_array();
462 }
463 }
464
GetDebugBytecodeArray()465 BytecodeArray* SharedFunctionInfo::GetDebugBytecodeArray() const {
466 DCHECK(HasBytecodeArray());
467 DCHECK(HasDebugInfo() && GetDebugInfo()->HasInstrumentedBytecodeArray());
468 if (function_data()->IsBytecodeArray()) {
469 return BytecodeArray::cast(function_data());
470 } else {
471 DCHECK(function_data()->IsInterpreterData());
472 return InterpreterData::cast(function_data())->bytecode_array();
473 }
474 }
475
SetDebugBytecodeArray(BytecodeArray * bytecode)476 void SharedFunctionInfo::SetDebugBytecodeArray(BytecodeArray* bytecode) {
477 DCHECK(HasBytecodeArray());
478 if (function_data()->IsBytecodeArray()) {
479 set_function_data(bytecode);
480 } else {
481 DCHECK(function_data()->IsInterpreterData());
482 interpreter_data()->set_bytecode_array(bytecode);
483 }
484 }
485
set_bytecode_array(BytecodeArray * bytecode)486 void SharedFunctionInfo::set_bytecode_array(BytecodeArray* bytecode) {
487 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) ||
488 HasUncompiledData());
489 set_function_data(bytecode);
490 }
491
InterpreterTrampoline()492 Code* SharedFunctionInfo::InterpreterTrampoline() const {
493 DCHECK(HasInterpreterData());
494 return interpreter_data()->interpreter_trampoline();
495 }
496
HasInterpreterData()497 bool SharedFunctionInfo::HasInterpreterData() const {
498 return function_data()->IsInterpreterData();
499 }
500
interpreter_data()501 InterpreterData* SharedFunctionInfo::interpreter_data() const {
502 DCHECK(HasInterpreterData());
503 return InterpreterData::cast(function_data());
504 }
505
set_interpreter_data(InterpreterData * interpreter_data)506 void SharedFunctionInfo::set_interpreter_data(
507 InterpreterData* interpreter_data) {
508 DCHECK(FLAG_interpreted_frames_native_stack);
509 set_function_data(interpreter_data);
510 }
511
HasAsmWasmData()512 bool SharedFunctionInfo::HasAsmWasmData() const {
513 return function_data()->IsFixedArray();
514 }
515
asm_wasm_data()516 FixedArray* SharedFunctionInfo::asm_wasm_data() const {
517 DCHECK(HasAsmWasmData());
518 return FixedArray::cast(function_data());
519 }
520
set_asm_wasm_data(FixedArray * data)521 void SharedFunctionInfo::set_asm_wasm_data(FixedArray* data) {
522 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy) ||
523 HasUncompiledData() || HasAsmWasmData());
524 set_function_data(data);
525 }
526
HasBuiltinId()527 bool SharedFunctionInfo::HasBuiltinId() const {
528 return function_data()->IsSmi();
529 }
530
builtin_id()531 int SharedFunctionInfo::builtin_id() const {
532 DCHECK(HasBuiltinId());
533 int id = Smi::ToInt(function_data());
534 DCHECK(Builtins::IsBuiltinId(id));
535 return id;
536 }
537
set_builtin_id(int builtin_id)538 void SharedFunctionInfo::set_builtin_id(int builtin_id) {
539 DCHECK(Builtins::IsBuiltinId(builtin_id));
540 DCHECK_NE(builtin_id, Builtins::kDeserializeLazy);
541 set_function_data(Smi::FromInt(builtin_id), SKIP_WRITE_BARRIER);
542 }
543
HasUncompiledData()544 bool SharedFunctionInfo::HasUncompiledData() const {
545 return function_data()->IsUncompiledData();
546 }
547
uncompiled_data()548 UncompiledData* SharedFunctionInfo::uncompiled_data() const {
549 DCHECK(HasUncompiledData());
550 return UncompiledData::cast(function_data());
551 }
552
set_uncompiled_data(UncompiledData * uncompiled_data)553 void SharedFunctionInfo::set_uncompiled_data(UncompiledData* uncompiled_data) {
554 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy));
555 DCHECK(uncompiled_data->IsUncompiledData());
556 set_function_data(uncompiled_data);
557 }
558
HasUncompiledDataWithPreParsedScope()559 bool SharedFunctionInfo::HasUncompiledDataWithPreParsedScope() const {
560 return function_data()->IsUncompiledDataWithPreParsedScope();
561 }
562
563 UncompiledDataWithPreParsedScope*
uncompiled_data_with_pre_parsed_scope()564 SharedFunctionInfo::uncompiled_data_with_pre_parsed_scope() const {
565 DCHECK(HasUncompiledDataWithPreParsedScope());
566 return UncompiledDataWithPreParsedScope::cast(function_data());
567 }
568
set_uncompiled_data_with_pre_parsed_scope(UncompiledDataWithPreParsedScope * uncompiled_data_with_pre_parsed_scope)569 void SharedFunctionInfo::set_uncompiled_data_with_pre_parsed_scope(
570 UncompiledDataWithPreParsedScope* uncompiled_data_with_pre_parsed_scope) {
571 DCHECK(function_data() == Smi::FromEnum(Builtins::kCompileLazy));
572 DCHECK(uncompiled_data_with_pre_parsed_scope
573 ->IsUncompiledDataWithPreParsedScope());
574 set_function_data(uncompiled_data_with_pre_parsed_scope);
575 }
576
HasUncompiledDataWithoutPreParsedScope()577 bool SharedFunctionInfo::HasUncompiledDataWithoutPreParsedScope() const {
578 return function_data()->IsUncompiledDataWithoutPreParsedScope();
579 }
580
ClearPreParsedScopeData()581 void SharedFunctionInfo::ClearPreParsedScopeData() {
582 DCHECK(HasUncompiledDataWithPreParsedScope());
583 UncompiledDataWithPreParsedScope* data =
584 uncompiled_data_with_pre_parsed_scope();
585
586 // Trim off the pre-parsed scope data from the uncompiled data by swapping the
587 // map, leaving only an uncompiled data without pre-parsed scope.
588 DisallowHeapAllocation no_gc;
589 Heap* heap = Heap::FromWritableHeapObject(data);
590
591 // Swap the map.
592 heap->NotifyObjectLayoutChange(data, UncompiledDataWithPreParsedScope::kSize,
593 no_gc);
594 STATIC_ASSERT(UncompiledDataWithoutPreParsedScope::kSize <
595 UncompiledDataWithPreParsedScope::kSize);
596 STATIC_ASSERT(UncompiledDataWithoutPreParsedScope::kSize ==
597 UncompiledData::kSize);
598 data->synchronized_set_map(
599 GetReadOnlyRoots().uncompiled_data_without_pre_parsed_scope_map());
600
601 // Fill the remaining space with filler.
602 heap->CreateFillerObjectAt(
603 data->address() + UncompiledDataWithoutPreParsedScope::kSize,
604 UncompiledDataWithPreParsedScope::kSize -
605 UncompiledDataWithoutPreParsedScope::kSize,
606 ClearRecordedSlots::kNo);
607
608 // Ensure that the clear was successful.
609 DCHECK(HasUncompiledDataWithoutPreParsedScope());
610 }
611
HasWasmExportedFunctionData()612 bool SharedFunctionInfo::HasWasmExportedFunctionData() const {
613 return function_data()->IsWasmExportedFunctionData();
614 }
615
FunctionLiteralId(Isolate * isolate)616 int SharedFunctionInfo::FunctionLiteralId(Isolate* isolate) const {
617 // Fast path for the common case when the SFI is uncompiled and so the
618 // function literal id is already in the uncompiled data.
619 if (HasUncompiledData()) {
620 int id = uncompiled_data()->function_literal_id();
621 // Make sure the id is what we should have found with the slow path.
622 DCHECK_EQ(id, FindIndexInScript(isolate));
623 return id;
624 }
625
626 // Otherwise, search for the function in the SFI's script's function list,
627 // and return its index in that list.e
628 return FindIndexInScript(isolate);
629 }
630
script()631 Object* SharedFunctionInfo::script() const {
632 Object* maybe_script = script_or_debug_info();
633 if (maybe_script->IsDebugInfo()) {
634 return DebugInfo::cast(maybe_script)->script();
635 }
636 return maybe_script;
637 }
638
set_script(Object * script)639 void SharedFunctionInfo::set_script(Object* script) {
640 Object* maybe_debug_info = script_or_debug_info();
641 if (maybe_debug_info->IsDebugInfo()) {
642 DebugInfo::cast(maybe_debug_info)->set_script(script);
643 } else {
644 set_script_or_debug_info(script);
645 }
646 }
647
HasDebugInfo()648 bool SharedFunctionInfo::HasDebugInfo() const {
649 return script_or_debug_info()->IsDebugInfo();
650 }
651
GetDebugInfo()652 DebugInfo* SharedFunctionInfo::GetDebugInfo() const {
653 DCHECK(HasDebugInfo());
654 return DebugInfo::cast(script_or_debug_info());
655 }
656
SetDebugInfo(DebugInfo * debug_info)657 void SharedFunctionInfo::SetDebugInfo(DebugInfo* debug_info) {
658 DCHECK(!HasDebugInfo());
659 DCHECK_EQ(debug_info->script(), script_or_debug_info());
660 set_script_or_debug_info(debug_info);
661 }
662
HasBuiltinFunctionId()663 bool SharedFunctionInfo::HasBuiltinFunctionId() {
664 return builtin_function_id() != BuiltinFunctionId::kInvalidBuiltinFunctionId;
665 }
666
builtin_function_id()667 BuiltinFunctionId SharedFunctionInfo::builtin_function_id() {
668 return static_cast<BuiltinFunctionId>(raw_builtin_function_id());
669 }
670
set_builtin_function_id(BuiltinFunctionId id)671 void SharedFunctionInfo::set_builtin_function_id(BuiltinFunctionId id) {
672 set_raw_builtin_function_id(static_cast<uint8_t>(id));
673 }
674
HasInferredName()675 bool SharedFunctionInfo::HasInferredName() {
676 Object* scope_info = name_or_scope_info();
677 if (scope_info->IsScopeInfo()) {
678 return ScopeInfo::cast(scope_info)->HasInferredFunctionName();
679 }
680 return HasUncompiledData();
681 }
682
inferred_name()683 String* SharedFunctionInfo::inferred_name() {
684 Object* maybe_scope_info = name_or_scope_info();
685 if (maybe_scope_info->IsScopeInfo()) {
686 ScopeInfo* scope_info = ScopeInfo::cast(maybe_scope_info);
687 if (scope_info->HasInferredFunctionName()) {
688 Object* name = ScopeInfo::cast(maybe_scope_info)->InferredFunctionName();
689 if (name->IsString()) return String::cast(name);
690 }
691 } else if (HasUncompiledData()) {
692 return uncompiled_data()->inferred_name();
693 }
694 return GetReadOnlyRoots().empty_string();
695 }
696
IsUserJavaScript()697 bool SharedFunctionInfo::IsUserJavaScript() {
698 Object* script_obj = script();
699 if (script_obj->IsUndefined()) return false;
700 Script* script = Script::cast(script_obj);
701 return script->IsUserJavaScript();
702 }
703
IsSubjectToDebugging()704 bool SharedFunctionInfo::IsSubjectToDebugging() {
705 return IsUserJavaScript() && !HasAsmWasmData();
706 }
707
CanDiscardCompiled()708 bool SharedFunctionInfo::CanDiscardCompiled() const {
709 bool can_decompile = (HasBytecodeArray() || HasAsmWasmData() ||
710 HasUncompiledDataWithPreParsedScope());
711 return can_decompile;
712 }
713
714 // static
DiscardCompiled(Isolate * isolate,Handle<SharedFunctionInfo> shared_info)715 void SharedFunctionInfo::DiscardCompiled(
716 Isolate* isolate, Handle<SharedFunctionInfo> shared_info) {
717 DCHECK(shared_info->CanDiscardCompiled());
718
719 int start_position = shared_info->StartPosition();
720 int end_position = shared_info->EndPosition();
721 int function_literal_id = shared_info->FunctionLiteralId(isolate);
722
723 if (shared_info->is_compiled()) {
724 DisallowHeapAllocation no_gc;
725
726 HeapObject* outer_scope_info;
727 if (shared_info->scope_info()->HasOuterScopeInfo()) {
728 outer_scope_info = shared_info->scope_info()->OuterScopeInfo();
729 } else {
730 outer_scope_info = ReadOnlyRoots(isolate).the_hole_value();
731 }
732 // Raw setter to avoid validity checks, since we're performing the unusual
733 // task of decompiling.
734 shared_info->set_raw_outer_scope_info_or_feedback_metadata(
735 outer_scope_info);
736 } else {
737 DCHECK(shared_info->outer_scope_info()->IsScopeInfo() ||
738 shared_info->outer_scope_info()->IsTheHole());
739 }
740
741 if (shared_info->HasUncompiledDataWithPreParsedScope()) {
742 // If this is uncompiled data with a pre-parsed scope data, we can just
743 // clear out the scope data and keep the uncompiled data.
744 shared_info->ClearPreParsedScopeData();
745 } else {
746 // Create a new UncompiledData, without pre-parsed scope, and update the
747 // function data to point to it. Use the raw function data setter to avoid
748 // validity checks, since we're performing the unusual task of decompiling.
749 Handle<UncompiledData> data =
750 isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
751 handle(shared_info->inferred_name(), isolate), start_position,
752 end_position, function_literal_id);
753 shared_info->set_function_data(*data);
754 }
755 }
756
757 } // namespace internal
758 } // namespace v8
759
760 #include "src/objects/object-macros-undef.h"
761
762 #endif // V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
763