• 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/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