shared-function-info-inl.h 33.1 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_
#define V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_

8
#include "src/base/macros.h"
9
#include "src/base/platform/mutex.h"
10
#include "src/codegen/optimized-compilation-info.h"
11
#include "src/common/globals.h"
12
#include "src/handles/handles-inl.h"
13
#include "src/heap/heap-write-barrier-inl.h"
14
#include "src/objects/debug-objects-inl.h"
15
#include "src/objects/feedback-vector-inl.h"
16 17
#include "src/objects/scope-info-inl.h"
#include "src/objects/script-inl.h"
18
#include "src/objects/shared-function-info.h"
19
#include "src/objects/templates-inl.h"
20 21

#if V8_ENABLE_WEBASSEMBLY
22
#include "src/wasm/wasm-module.h"
23
#include "src/wasm/wasm-objects.h"
24
#endif  // V8_ENABLE_WEBASSEMBLY
25 26 27 28 29 30 31

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

32 33
#include "torque-generated/src/objects/shared-function-info-tq-inl.inc"

34
TQ_OBJECT_CONSTRUCTORS_IMPL(PreparseData)
35

36 37
int PreparseData::inner_start_offset() const {
  return InnerOffset(data_length());
38 39
}

40 41
ObjectSlot PreparseData::inner_data_start() const {
  return RawField(inner_start_offset());
42 43
}

44 45 46 47 48 49
void PreparseData::clear_padding() {
  int data_end_offset = kDataStartOffset + data_length();
  int padding_size = inner_start_offset() - data_end_offset;
  DCHECK_LE(0, padding_size);
  if (padding_size == 0) return;
  memset(reinterpret_cast<void*>(address() + data_end_offset), 0, padding_size);
50 51
}

52 53 54 55
byte PreparseData::get(int index) const {
  DCHECK_LE(0, index);
  DCHECK_LT(index, data_length());
  int offset = kDataStartOffset + index * kByteSize;
56
  return ReadField<byte>(offset);
57 58 59 60 61 62
}

void PreparseData::set(int index, byte value) {
  DCHECK_LE(0, index);
  DCHECK_LT(index, data_length());
  int offset = kDataStartOffset + index * kByteSize;
63
  WriteField<byte>(offset, value);
64 65 66 67 68
}

void PreparseData::copy_in(int index, const byte* buffer, int length) {
  DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
         index + length <= this->data_length());
69
  Address dst_addr = field_address(kDataStartOffset + index * kByteSize);
70
  memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
}

PreparseData PreparseData::get_child(int index) const {
  return PreparseData::cast(get_child_raw(index));
}

Object PreparseData::get_child_raw(int index) const {
  DCHECK_LE(0, index);
  DCHECK_LT(index, this->children_length());
  int offset = inner_start_offset() + index * kTaggedSize;
  return RELAXED_READ_FIELD(*this, offset);
}

void PreparseData::set_child(int index, PreparseData value,
                             WriteBarrierMode mode) {
  DCHECK_LE(0, index);
  DCHECK_LT(index, this->children_length());
  int offset = inner_start_offset() + index * kTaggedSize;
  RELAXED_WRITE_FIELD(*this, offset, value);
  CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
91
}
92

93 94 95
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledData)
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithoutPreparseData)
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithPreparseData)
96 97
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithoutPreparseDataWithJob)
TQ_OBJECT_CONSTRUCTORS_IMPL(UncompiledDataWithPreparseDataAndJob)
98

99
TQ_OBJECT_CONSTRUCTORS_IMPL(InterpreterData)
100
TQ_OBJECT_CONSTRUCTORS_IMPL(SharedFunctionInfo)
101
NEVER_READ_ONLY_SPACE_IMPL(SharedFunctionInfo)
102 103
DEFINE_DEOPT_ELEMENT_ACCESSORS(SharedFunctionInfo, Object)

104 105
RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, function_data, Object,
                          kFunctionDataOffset)
106 107
RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
                          kNameOrScopeInfoOffset)
108 109
RELEASE_ACQUIRE_ACCESSORS(SharedFunctionInfo, script_or_debug_info, HeapObject,
                          kScriptOrDebugInfoOffset)
110

111 112 113
RENAME_TORQUE_ACCESSORS(SharedFunctionInfo,
                        raw_outer_scope_info_or_feedback_metadata,
                        outer_scope_info_or_feedback_metadata, HeapObject)
114 115 116 117 118 119 120 121
DEF_ACQUIRE_GETTER(SharedFunctionInfo,
                   raw_outer_scope_info_or_feedback_metadata, HeapObject) {
  HeapObject value =
      TaggedField<HeapObject, kOuterScopeInfoOrFeedbackMetadataOffset>::
          Acquire_Load(cage_base, *this);
  return value;
}

122 123
uint16_t SharedFunctionInfo::internal_formal_parameter_count_with_receiver()
    const {
124
  const uint16_t param_count = TorqueGeneratedClass::formal_parameter_count();
125
  if (param_count == kDontAdaptArgumentsSentinel) return param_count;
126
  return param_count + (kJSArgcIncludesReceiver ? 0 : 1);
127 128 129 130
}

uint16_t SharedFunctionInfo::internal_formal_parameter_count_without_receiver()
    const {
131 132 133
  const uint16_t param_count = TorqueGeneratedClass::formal_parameter_count();
  if (param_count == kDontAdaptArgumentsSentinel) return param_count;
  return param_count - kJSArgcReceiverSlots;
134 135 136 137
}

void SharedFunctionInfo::set_internal_formal_parameter_count(int value) {
  DCHECK_EQ(value, static_cast<uint16_t>(value));
138
  DCHECK_GE(value, kJSArgcReceiverSlots);
139 140 141
  TorqueGeneratedClass::set_formal_parameter_count(value);
}

142 143 144
RENAME_UINT16_TORQUE_ACCESSORS(SharedFunctionInfo, raw_function_token_offset,
                               function_token_offset)

145 146 147 148 149 150 151 152
RELAXED_INT32_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset)
int32_t SharedFunctionInfo::relaxed_flags() const {
  return flags(kRelaxedLoad);
}
void SharedFunctionInfo::set_relaxed_flags(int32_t flags) {
  return set_flags(flags, kRelaxedStore);
}

153
UINT8_ACCESSORS(SharedFunctionInfo, flags2, kFlags2Offset)
154

155
bool SharedFunctionInfo::HasSharedName() const {
156
  Object value = name_or_scope_info(kAcquireLoad);
157 158
  if (value.IsScopeInfo()) {
    return ScopeInfo::cast(value).HasSharedFunctionName();
159 160
  }
  return value != kNoSharedNameSentinel;
161 162
}

163
String SharedFunctionInfo::Name() const {
164
  if (!HasSharedName()) return GetReadOnlyRoots().empty_string();
165
  Object value = name_or_scope_info(kAcquireLoad);
166 167 168
  if (value.IsScopeInfo()) {
    if (ScopeInfo::cast(value).HasFunctionName()) {
      return String::cast(ScopeInfo::cast(value).FunctionName());
169
    }
170
    return GetReadOnlyRoots().empty_string();
171 172
  }
  return String::cast(value);
173 174
}

175
void SharedFunctionInfo::SetName(String name) {
176
  Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
177 178
  if (maybe_scope_info.IsScopeInfo()) {
    ScopeInfo::cast(maybe_scope_info).SetFunctionName(name);
179
  } else {
180
    DCHECK(maybe_scope_info.IsString() ||
181
           maybe_scope_info == kNoSharedNameSentinel);
182
    set_name_or_scope_info(name, kReleaseStore);
183
  }
184 185 186
  UpdateFunctionMapIndex();
}

187
bool SharedFunctionInfo::is_script() const {
188
  return scope_info(kAcquireLoad).is_script_scope() &&
189 190 191 192 193
         Script::cast(script()).compilation_type() ==
             Script::COMPILATION_TYPE_HOST;
}

bool SharedFunctionInfo::needs_script_context() const {
194
  return is_script() && scope_info(kAcquireLoad).ContextLocalCount() > 0;
195 196
}

197 198
template <typename IsolateT>
AbstractCode SharedFunctionInfo::abstract_code(IsolateT* isolate) {
199 200
  // TODO(v8:11429): Decide if this return bytecode or baseline code, when the
  // latter is present.
201
  if (HasBytecodeArray()) {
202
    return AbstractCode::cast(GetBytecodeArray(isolate));
203
  } else {
204
    return AbstractCode::cast(FromCodeT(GetCode()));
205 206 207
  }
}

208 209 210 211 212 213 214 215 216
int SharedFunctionInfo::function_token_position() const {
  int offset = raw_function_token_offset();
  if (offset == kFunctionTokenOutOfRange) {
    return kNoSourcePosition;
  } else {
    return StartPosition() - offset;
  }
}

217 218
template <typename IsolateT>
bool SharedFunctionInfo::AreSourcePositionsAvailable(IsolateT* isolate) const {
219 220 221 222 223 224 225
  if (FLAG_enable_lazy_source_positions) {
    return !HasBytecodeArray() ||
           GetBytecodeArray(isolate).HasSourcePositionTable();
  }
  return true;
}

226
template <typename IsolateT>
227
SharedFunctionInfo::Inlineability SharedFunctionInfo::GetInlineability(
228
    IsolateT* isolate, bool is_turboprop) const {
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
  if (!script().IsScript()) return kHasNoScript;

  if (GetIsolate()->is_precise_binary_code_coverage() &&
      !has_reported_binary_coverage()) {
    // We may miss invocations if this function is inlined.
    return kNeedsBinaryCoverage;
  }

  // Built-in functions are handled by the JSCallReducer.
  if (HasBuiltinId()) return kIsBuiltin;

  if (!IsUserJavaScript()) return kIsNotUserCode;

  // If there is no bytecode array, it is either not compiled or it is compiled
  // with WebAssembly for the asm.js pipeline. In either case we don't want to
  // inline.
  if (!HasBytecodeArray()) return kHasNoBytecode;

247 248 249 250 251
  int max_inlined_size = FLAG_max_inlined_bytecode_size;
  if (is_turboprop) {
    max_inlined_size = max_inlined_size / FLAG_turboprop_inline_scaling_factor;
  }
  if (GetBytecodeArray(isolate).length() > max_inlined_size) {
252 253 254 255 256
    return kExceedsBytecodeLimit;
  }

  if (HasBreakInfo()) return kMayContainBreakPoints;

Georg Neis's avatar
Georg Neis committed
257 258
  if (optimization_disabled()) return kHasOptimizationDisabled;

259 260 261
  return kIsInlineable;
}

262
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, class_scope_has_private_brand,
263 264
                    SharedFunctionInfo::ClassScopeHasPrivateBrandBit)

265
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2,
266 267 268
                    has_static_private_methods_or_accessors,
                    SharedFunctionInfo::HasStaticPrivateMethodsOrAccessorsBit)

269
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, syntax_kind,
270 271
                    SharedFunctionInfo::FunctionSyntaxKindBits)

272
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, allows_lazy_compilation,
273
                    SharedFunctionInfo::AllowLazyCompilationBit)
274
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, has_duplicate_parameters,
275 276
                    SharedFunctionInfo::HasDuplicateParametersBit)

277
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, native,
278
                    SharedFunctionInfo::IsNativeBit)
279
#if V8_ENABLE_WEBASSEMBLY
280
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, is_asm_wasm_broken,
281
                    SharedFunctionInfo::IsAsmWasmBrokenBit)
282
#endif  // V8_ENABLE_WEBASSEMBLY
283
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags,
284
                    requires_instance_members_initializer,
285
                    SharedFunctionInfo::RequiresInstanceMembersInitializerBit)
286

287 288
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags,
                    name_should_print_as_anonymous,
289
                    SharedFunctionInfo::NameShouldPrintAsAnonymousBit)
290 291
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags,
                    has_reported_binary_coverage,
292 293
                    SharedFunctionInfo::HasReportedBinaryCoverageBit)

294
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, is_toplevel,
295
                    SharedFunctionInfo::IsTopLevelBit)
296
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, properties_are_final,
297
                    SharedFunctionInfo::PropertiesAreFinalBit)
298
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags,
299 300
                    private_name_lookup_skips_outer_class,
                    SharedFunctionInfo::PrivateNameLookupSkipsOuterClassBit)
301

302
bool SharedFunctionInfo::optimization_disabled() const {
303
  return disabled_optimization_reason() != BailoutReason::kNoReason;
304 305
}

306
BailoutReason SharedFunctionInfo::disabled_optimization_reason() const {
307
  return DisabledOptimizationReasonBits::decode(flags(kRelaxedLoad));
308
}
309

310
LanguageMode SharedFunctionInfo::language_mode() const {
311
  STATIC_ASSERT(LanguageModeSize == 2);
312
  return construct_language_mode(IsStrictBit::decode(flags(kRelaxedLoad)));
313 314 315
}

void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
316
  STATIC_ASSERT(LanguageModeSize == 2);
317 318 319
  // We only allow language mode transitions that set the same language mode
  // again or go up in the chain:
  DCHECK(is_sloppy(this->language_mode()) || is_strict(language_mode));
320
  int hints = flags(kRelaxedLoad);
321
  hints = IsStrictBit::update(hints, is_strict(language_mode));
322
  set_flags(hints, kRelaxedStore);
323
  UpdateFunctionMapIndex();
324 325 326
}

FunctionKind SharedFunctionInfo::kind() const {
327
  STATIC_ASSERT(FunctionKindBits::kSize == kFunctionKindBitSize);
328
  return FunctionKindBits::decode(flags(kRelaxedLoad));
329 330 331
}

void SharedFunctionInfo::set_kind(FunctionKind kind) {
332
  int hints = flags(kRelaxedLoad);
333
  hints = FunctionKindBits::update(hints, kind);
334
  hints = IsClassConstructorBit::update(hints, IsClassConstructor(kind));
335
  set_flags(hints, kRelaxedStore);
336 337 338
  UpdateFunctionMapIndex();
}

339 340 341 342
bool SharedFunctionInfo::is_wrapped() const {
  return syntax_kind() == FunctionSyntaxKind::kWrapped;
}

343
bool SharedFunctionInfo::construct_as_builtin() const {
344
  return ConstructAsBuiltinBit::decode(flags(kRelaxedLoad));
345 346 347 348 349
}

void SharedFunctionInfo::CalculateConstructAsBuiltin() {
  bool uses_builtins_construct_stub = false;
  if (HasBuiltinId()) {
350
    Builtin id = builtin_id();
351
    if (id != Builtin::kCompileLazy && id != Builtin::kEmptyFunction) {
352 353 354 355 356 357
      uses_builtins_construct_stub = true;
    }
  } else if (IsApiFunction()) {
    uses_builtins_construct_stub = true;
  }

358
  int f = flags(kRelaxedLoad);
359
  f = ConstructAsBuiltinBit::update(f, uses_builtins_construct_stub);
360
  set_flags(f, kRelaxedStore);
361 362
}

363
int SharedFunctionInfo::function_map_index() const {
364
  // Note: Must be kept in sync with the FastNewClosure builtin.
365 366
  int index = Context::FIRST_FUNCTION_MAP_INDEX +
              FunctionMapIndexBits::decode(flags(kRelaxedLoad));
367 368 369 370 371 372 373 374 375 376
  DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
  return index;
}

void SharedFunctionInfo::set_function_map_index(int index) {
  STATIC_ASSERT(Context::LAST_FUNCTION_MAP_INDEX <=
                Context::FIRST_FUNCTION_MAP_INDEX + FunctionMapIndexBits::kMax);
  DCHECK_LE(Context::FIRST_FUNCTION_MAP_INDEX, index);
  DCHECK_LE(index, Context::LAST_FUNCTION_MAP_INDEX);
  index -= Context::FIRST_FUNCTION_MAP_INDEX;
377 378
  set_flags(FunctionMapIndexBits::update(flags(kRelaxedLoad), index),
            kRelaxedStore);
379 380
}

381
void SharedFunctionInfo::clear_padding() {
382 383
  memset(reinterpret_cast<void*>(this->address() + kSize), 0,
         kAlignedSize - kSize);
384 385
}

386
void SharedFunctionInfo::UpdateFunctionMapIndex() {
387 388
  int map_index =
      Context::FunctionMapIndex(language_mode(), kind(), HasSharedName());
389
  set_function_map_index(map_index);
390 391 392
}

void SharedFunctionInfo::DontAdaptArguments() {
393
#if V8_ENABLE_WEBASSEMBLY
394
  // TODO(leszeks): Revise this DCHECK now that the code field is gone.
395
  DCHECK(!HasWasmExportedFunctionData());
396
#endif  // V8_ENABLE_WEBASSEMBLY
397
  TorqueGeneratedClass::set_formal_parameter_count(kDontAdaptArgumentsSentinel);
398 399
}

400 401 402 403 404
bool SharedFunctionInfo::IsDontAdaptArguments() const {
  return TorqueGeneratedClass::formal_parameter_count() ==
         kDontAdaptArgumentsSentinel;
}

405
bool SharedFunctionInfo::IsInterpreted() const { return HasBytecodeArray(); }
406

407 408 409
DEF_ACQUIRE_GETTER(SharedFunctionInfo, scope_info, ScopeInfo) {
  Object maybe_scope_info = name_or_scope_info(cage_base, kAcquireLoad);
  if (maybe_scope_info.IsScopeInfo(cage_base)) {
410 411
    return ScopeInfo::cast(maybe_scope_info);
  }
412
  return GetReadOnlyRoots().empty_scope_info();
413 414
}

415 416
DEF_GETTER(SharedFunctionInfo, scope_info, ScopeInfo) {
  return scope_info(cage_base, kAcquireLoad);
417 418
}

419 420
void SharedFunctionInfo::SetScopeInfo(ScopeInfo scope_info,
                                      WriteBarrierMode mode) {
421
  // Move the existing name onto the ScopeInfo.
422
  Object name = name_or_scope_info(kAcquireLoad);
423 424
  if (name.IsScopeInfo()) {
    name = ScopeInfo::cast(name).FunctionName();
425
  }
426
  DCHECK(name.IsString() || name == kNoSharedNameSentinel);
427
  // Only set the function name for function scopes.
428 429 430
  scope_info.SetFunctionName(name);
  if (HasInferredName() && inferred_name().length() != 0) {
    scope_info.SetInferredFunctionName(inferred_name());
431
  }
432
  set_name_or_scope_info(scope_info, kReleaseStore, mode);
433 434 435 436
}

void SharedFunctionInfo::set_raw_scope_info(ScopeInfo scope_info,
                                            WriteBarrierMode mode) {
437 438
  WRITE_FIELD(*this, kNameOrScopeInfoOffset, scope_info);
  CONDITIONAL_WRITE_BARRIER(*this, kNameOrScopeInfoOffset, scope_info, mode);
439 440
}

441
HeapObject SharedFunctionInfo::outer_scope_info() const {
442 443 444 445 446 447
  DCHECK(!is_compiled());
  DCHECK(!HasFeedbackMetadata());
  return raw_outer_scope_info_or_feedback_metadata();
}

bool SharedFunctionInfo::HasOuterScopeInfo() const {
448
  ScopeInfo outer_info;
449
  if (!is_compiled()) {
450
    if (!outer_scope_info().IsScopeInfo()) return false;
451 452
    outer_info = ScopeInfo::cast(outer_scope_info());
  } else {
453 454 455
    ScopeInfo info = scope_info(kAcquireLoad);
    if (!info.HasOuterScopeInfo()) return false;
    outer_info = info.OuterScopeInfo();
456
  }
457
  return !outer_info.IsEmpty();
458 459
}

460
ScopeInfo SharedFunctionInfo::GetOuterScopeInfo() const {
461 462
  DCHECK(HasOuterScopeInfo());
  if (!is_compiled()) return ScopeInfo::cast(outer_scope_info());
463
  return scope_info(kAcquireLoad).OuterScopeInfo();
464 465
}

466
void SharedFunctionInfo::set_outer_scope_info(HeapObject value,
467 468
                                              WriteBarrierMode mode) {
  DCHECK(!is_compiled());
469 470
  DCHECK(raw_outer_scope_info_or_feedback_metadata().IsTheHole());
  DCHECK(value.IsScopeInfo() || value.IsTheHole());
471
  set_raw_outer_scope_info_or_feedback_metadata(value, mode);
472 473 474
}

bool SharedFunctionInfo::HasFeedbackMetadata() const {
475
  return raw_outer_scope_info_or_feedback_metadata().IsFeedbackMetadata();
476 477
}

478 479 480 481
bool SharedFunctionInfo::HasFeedbackMetadata(AcquireLoadTag tag) const {
  return raw_outer_scope_info_or_feedback_metadata(tag).IsFeedbackMetadata();
}

482
FeedbackMetadata SharedFunctionInfo::feedback_metadata() const {
483 484 485 486
  DCHECK(HasFeedbackMetadata());
  return FeedbackMetadata::cast(raw_outer_scope_info_or_feedback_metadata());
}

487 488 489 490 491 492
RELEASE_ACQUIRE_ACCESSORS_CHECKED2(SharedFunctionInfo, feedback_metadata,
                                   FeedbackMetadata,
                                   kOuterScopeInfoOrFeedbackMetadataOffset,
                                   HasFeedbackMetadata(kAcquireLoad),
                                   !HasFeedbackMetadata(kAcquireLoad) &&
                                       value.IsFeedbackMetadata())
493 494

bool SharedFunctionInfo::is_compiled() const {
495
  Object data = function_data(kAcquireLoad);
496
  return data != Smi::FromEnum(Builtin::kCompileLazy) &&
497
         !data.IsUncompiledData();
498 499
}

500 501
template <typename IsolateT>
IsCompiledScope SharedFunctionInfo::is_compiled_scope(IsolateT* isolate) const {
502
  return IsCompiledScope(*this, isolate);
503 504 505
}

IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
506
                                 Isolate* isolate)
507
    : is_compiled_(shared.is_compiled()) {
508 509
  if (shared.HasBaselineCode()) {
    retain_code_ = handle(shared.baseline_code(kAcquireLoad), isolate);
510 511
  } else if (shared.HasBytecodeArray()) {
    retain_code_ = handle(shared.GetBytecodeArray(isolate), isolate);
512 513 514 515 516
  } else {
    retain_code_ = MaybeHandle<HeapObject>();
  }

  DCHECK_IMPLIES(!retain_code_.is_null(), is_compiled());
517 518 519 520
}

IsCompiledScope::IsCompiledScope(const SharedFunctionInfo shared,
                                 LocalIsolate* isolate)
521
    : is_compiled_(shared.is_compiled()) {
522 523 524
  if (shared.HasBaselineCode()) {
    retain_code_ = isolate->heap()->NewPersistentHandle(
        shared.baseline_code(kAcquireLoad));
525
  } else if (shared.HasBytecodeArray()) {
526 527 528 529 530 531 532
    retain_code_ =
        isolate->heap()->NewPersistentHandle(shared.GetBytecodeArray(isolate));
  } else {
    retain_code_ = MaybeHandle<HeapObject>();
  }

  DCHECK_IMPLIES(!retain_code_.is_null(), is_compiled());
533 534
}

535
bool SharedFunctionInfo::has_simple_parameters() {
536
  return scope_info(kAcquireLoad).HasSimpleParameters();
537 538
}

539 540 541 542 543
bool SharedFunctionInfo::CanCollectSourcePosition(Isolate* isolate) {
  return FLAG_enable_lazy_source_positions && HasBytecodeArray() &&
         !GetBytecodeArray(isolate).HasSourcePositionTable();
}

544
bool SharedFunctionInfo::IsApiFunction() const {
545
  return function_data(kAcquireLoad).IsFunctionTemplateInfo();
546 547
}

548
FunctionTemplateInfo SharedFunctionInfo::get_api_func_data() const {
549
  DCHECK(IsApiFunction());
550
  return FunctionTemplateInfo::cast(function_data(kAcquireLoad));
551 552 553
}

bool SharedFunctionInfo::HasBytecodeArray() const {
554
  Object data = function_data(kAcquireLoad);
555
  return data.IsBytecodeArray() || data.IsInterpreterData() || data.IsCodeT();
556 557
}

558 559 560
template <typename IsolateT>
BytecodeArray SharedFunctionInfo::GetBytecodeArray(IsolateT* isolate) const {
  SharedMutexGuardIfOffThread<IsolateT, base::kShared> mutex_guard(
561 562
      GetIsolate()->shared_function_info_access(), isolate);

563
  DCHECK(HasBytecodeArray());
564 565
  if (HasDebugInfo() && GetDebugInfo().HasInstrumentedBytecodeArray()) {
    return GetDebugInfo().OriginalBytecodeArray();
566 567
  }

568 569 570
  return GetActiveBytecodeArray();
}

571
BytecodeArray SharedFunctionInfo::GetActiveBytecodeArray() const {
572
  Object data = function_data(kAcquireLoad);
573
  if (data.IsCodeT()) {
574
    CodeT baseline_code = CodeT::cast(data);
575 576
    data = baseline_code.bytecode_or_interpreter_data();
  }
577 578
  if (data.IsBytecodeArray()) {
    return BytecodeArray::cast(data);
579
  } else {
580 581
    DCHECK(data.IsInterpreterData());
    return InterpreterData::cast(data).bytecode_array();
582
  }
583 584
}

585
void SharedFunctionInfo::SetActiveBytecodeArray(BytecodeArray bytecode) {
586 587 588 589
  // We don't allow setting the active bytecode array on baseline-optimized
  // functions. They should have been flushed earlier.
  DCHECK(!HasBaselineCode());

590 591 592
  Object data = function_data(kAcquireLoad);
  if (data.IsBytecodeArray()) {
    set_function_data(bytecode, kReleaseStore);
593
  } else {
594
    DCHECK(data.IsInterpreterData());
595
    interpreter_data().set_bytecode_array(bytecode);
596 597 598
  }
}

599
void SharedFunctionInfo::set_bytecode_array(BytecodeArray bytecode) {
600
  DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtin::kCompileLazy) ||
601
         HasUncompiledData());
602
  set_function_data(bytecode, kReleaseStore);
603 604
}

605
bool SharedFunctionInfo::ShouldFlushCode(
606 607
    base::EnumSet<CodeFlushMode> code_flush_mode) {
  if (IsFlushingDisabled(code_flush_mode)) return false;
608

609 610
  // TODO(rmcilroy): Enable bytecode flushing for resumable functions.
  if (IsResumableFunction(kind()) || !allows_lazy_compilation()) {
611 612 613 614 615 616
    return false;
  }

  // Get a snapshot of the function data field, and if it is a bytecode array,
  // check if it is old. Note, this is done this way since this function can be
  // called by the concurrent marker.
617
  Object data = function_data(kAcquireLoad);
618
  if (data.IsCodeT()) {
619
    CodeT baseline_code = CodeT::cast(data);
620
    DCHECK_EQ(baseline_code.kind(), CodeKind::BASELINE);
621 622
    // If baseline code flushing isn't enabled and we have baseline data on SFI
    // we cannot flush baseline / bytecode.
623
    if (!IsBaselineCodeFlushingEnabled(code_flush_mode)) return false;
624
    data = baseline_code.bytecode_or_interpreter_data();
625 626 627 628
  } else if (!IsByteCodeFlushingEnabled(code_flush_mode)) {
    // If bytecode flushing isn't enabled and there is no baseline code there is
    // nothing to flush.
    return false;
629
  }
630
  if (!data.IsBytecodeArray()) return false;
631

632
  if (IsStressFlushingEnabled(code_flush_mode)) return true;
633 634 635

  BytecodeArray bytecode = BytecodeArray::cast(data);

636
  return bytecode.IsOld();
637 638
}

639
CodeT SharedFunctionInfo::InterpreterTrampoline() const {
640
  DCHECK(HasInterpreterData());
641
  return interpreter_data().interpreter_trampoline();
642 643 644
}

bool SharedFunctionInfo::HasInterpreterData() const {
645
  Object data = function_data(kAcquireLoad);
646
  if (data.IsCodeT()) {
647
    CodeT baseline_code = CodeT::cast(data);
648 649 650
    DCHECK_EQ(baseline_code.kind(), CodeKind::BASELINE);
    data = baseline_code.bytecode_or_interpreter_data();
  }
651
  return data.IsInterpreterData();
652 653
}

654
InterpreterData SharedFunctionInfo::interpreter_data() const {
655
  DCHECK(HasInterpreterData());
656
  Object data = function_data(kAcquireLoad);
657
  if (data.IsCodeT()) {
658
    CodeT baseline_code = CodeT::cast(data);
659 660 661
    DCHECK_EQ(baseline_code.kind(), CodeKind::BASELINE);
    data = baseline_code.bytecode_or_interpreter_data();
  }
662
  return InterpreterData::cast(data);
663 664 665
}

void SharedFunctionInfo::set_interpreter_data(
666
    InterpreterData interpreter_data) {
667
  DCHECK(FLAG_interpreted_frames_native_stack);
668
  DCHECK(!HasBaselineCode());
669
  set_function_data(interpreter_data, kReleaseStore);
670 671
}

672 673 674
bool SharedFunctionInfo::HasBaselineCode() const {
  Object data = function_data(kAcquireLoad);
  if (data.IsCodeT()) {
675
    DCHECK_EQ(CodeT::cast(data).kind(), CodeKind::BASELINE);
676 677 678
    return true;
  }
  return false;
679 680
}

681
CodeT SharedFunctionInfo::baseline_code(AcquireLoadTag) const {
682
  DCHECK(HasBaselineCode());
683
  return CodeT::cast(function_data(kAcquireLoad));
684 685
}

686
void SharedFunctionInfo::set_baseline_code(CodeT baseline_code,
687 688
                                           ReleaseStoreTag) {
  DCHECK_EQ(baseline_code.kind(), CodeKind::BASELINE);
689
  set_function_data(baseline_code, kReleaseStore);
690 691
}

692 693 694 695
void SharedFunctionInfo::FlushBaselineCode() {
  DCHECK(HasBaselineCode());
  set_function_data(baseline_code(kAcquireLoad).bytecode_or_interpreter_data(),
                    kReleaseStore);
696 697
}

698
#if V8_ENABLE_WEBASSEMBLY
699
bool SharedFunctionInfo::HasAsmWasmData() const {
700
  return function_data(kAcquireLoad).IsAsmWasmData();
701 702
}

703 704 705 706 707 708 709 710 711 712 713 714
bool SharedFunctionInfo::HasWasmExportedFunctionData() const {
  return function_data(kAcquireLoad).IsWasmExportedFunctionData();
}

bool SharedFunctionInfo::HasWasmJSFunctionData() const {
  return function_data(kAcquireLoad).IsWasmJSFunctionData();
}

bool SharedFunctionInfo::HasWasmCapiFunctionData() const {
  return function_data(kAcquireLoad).IsWasmCapiFunctionData();
}

715
AsmWasmData SharedFunctionInfo::asm_wasm_data() const {
716
  DCHECK(HasAsmWasmData());
717
  return AsmWasmData::cast(function_data(kAcquireLoad));
718 719
}

720
void SharedFunctionInfo::set_asm_wasm_data(AsmWasmData data) {
721
  DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtin::kCompileLazy) ||
722
         HasUncompiledData() || HasAsmWasmData());
723
  set_function_data(data, kReleaseStore);
724 725
}

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
const wasm::WasmModule* SharedFunctionInfo::wasm_module() const {
  if (!HasWasmExportedFunctionData()) return nullptr;
  const WasmExportedFunctionData& function_data = wasm_exported_function_data();
  const WasmInstanceObject& wasm_instance = function_data.instance();
  const WasmModuleObject& wasm_module_object = wasm_instance.module_object();
  return wasm_module_object.module();
}

const wasm::FunctionSig* SharedFunctionInfo::wasm_function_signature() const {
  const wasm::WasmModule* module = wasm_module();
  if (!module) return nullptr;
  const WasmExportedFunctionData& function_data = wasm_exported_function_data();
  DCHECK_LT(function_data.function_index(), module->functions.size());
  return module->functions[function_data.function_index()].sig;
}
#endif  // V8_ENABLE_WEBASSEMBLY

743
bool SharedFunctionInfo::HasBuiltinId() const {
744
  return function_data(kAcquireLoad).IsSmi();
745 746
}

747
Builtin SharedFunctionInfo::builtin_id() const {
748
  DCHECK(HasBuiltinId());
749
  int id = Smi::ToInt(function_data(kAcquireLoad));
750
  DCHECK(Builtins::IsBuiltinId(id));
751
  return Builtins::FromInt(id);
752 753
}

754 755 756
void SharedFunctionInfo::set_builtin_id(Builtin builtin) {
  DCHECK(Builtins::IsBuiltinId(builtin));
  set_function_data(Smi::FromInt(static_cast<int>(builtin)), kReleaseStore,
757
                    SKIP_WRITE_BARRIER);
758 759
}

760
bool SharedFunctionInfo::HasUncompiledData() const {
761
  return function_data(kAcquireLoad).IsUncompiledData();
762 763
}

764
UncompiledData SharedFunctionInfo::uncompiled_data() const {
765
  DCHECK(HasUncompiledData());
766
  return UncompiledData::cast(function_data(kAcquireLoad));
767 768
}

769
void SharedFunctionInfo::set_uncompiled_data(UncompiledData uncompiled_data) {
770
  DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtin::kCompileLazy) ||
771
         HasUncompiledData());
772
  DCHECK(uncompiled_data.IsUncompiledData());
773
  set_function_data(uncompiled_data, kReleaseStore);
774 775
}

776
bool SharedFunctionInfo::HasUncompiledDataWithPreparseData() const {
777
  return function_data(kAcquireLoad).IsUncompiledDataWithPreparseData();
778 779
}

780 781 782
UncompiledDataWithPreparseData
SharedFunctionInfo::uncompiled_data_with_preparse_data() const {
  DCHECK(HasUncompiledDataWithPreparseData());
783
  return UncompiledDataWithPreparseData::cast(function_data(kAcquireLoad));
784 785
}

786 787
void SharedFunctionInfo::set_uncompiled_data_with_preparse_data(
    UncompiledDataWithPreparseData uncompiled_data_with_preparse_data) {
788
  DCHECK(function_data(kAcquireLoad) == Smi::FromEnum(Builtin::kCompileLazy));
789
  DCHECK(uncompiled_data_with_preparse_data.IsUncompiledDataWithPreparseData());
790
  set_function_data(uncompiled_data_with_preparse_data, kReleaseStore);
791 792
}

793
bool SharedFunctionInfo::HasUncompiledDataWithoutPreparseData() const {
794
  return function_data(kAcquireLoad).IsUncompiledDataWithoutPreparseData();
795 796
}

797 798 799 800 801 802 803 804 805 806 807
void SharedFunctionInfo::ClearUncompiledDataJobPointer() {
  UncompiledData uncompiled_data = this->uncompiled_data();
  if (uncompiled_data.IsUncompiledDataWithPreparseDataAndJob()) {
    UncompiledDataWithPreparseDataAndJob::cast(uncompiled_data)
        .set_job(kNullAddress);
  } else if (uncompiled_data.IsUncompiledDataWithoutPreparseDataWithJob()) {
    UncompiledDataWithoutPreparseDataWithJob::cast(uncompiled_data)
        .set_job(kNullAddress);
  }
}

808 809 810
void SharedFunctionInfo::ClearPreparseData() {
  DCHECK(HasUncompiledDataWithPreparseData());
  UncompiledDataWithPreparseData data = uncompiled_data_with_preparse_data();
811 812 813

  // Trim off the pre-parsed scope data from the uncompiled data by swapping the
  // map, leaving only an uncompiled data without pre-parsed scope.
814
  DisallowGarbageCollection no_gc;
815
  Heap* heap = GetHeapFromWritableObject(data);
816 817

  // Swap the map.
818
  heap->NotifyObjectLayoutChange(data, no_gc);
819 820 821
  STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize <
                UncompiledDataWithPreparseData::kSize);
  STATIC_ASSERT(UncompiledDataWithoutPreparseData::kSize ==
822
                UncompiledData::kHeaderSize);
823 824
  data.set_map(GetReadOnlyRoots().uncompiled_data_without_preparse_data_map(),
               kReleaseStore);
825 826 827

  // Fill the remaining space with filler.
  heap->CreateFillerObjectAt(
828
      data.address() + UncompiledDataWithoutPreparseData::kSize,
829
      UncompiledDataWithPreparseData::kSize -
830
          UncompiledDataWithoutPreparseData::kSize,
831
      ClearRecordedSlots::kYes);
832 833

  // Ensure that the clear was successful.
834
  DCHECK(HasUncompiledDataWithoutPreparseData());
835 836
}

837
void UncompiledData::InitAfterBytecodeFlush(
838
    String inferred_name, int start_position, int end_position,
839
    std::function<void(HeapObject object, ObjectSlot slot, HeapObject target)>
840
        gc_notify_updated_slot) {
841 842 843 844 845
  set_inferred_name(inferred_name);
  gc_notify_updated_slot(*this, RawField(UncompiledData::kInferredNameOffset),
                         inferred_name);
  set_start_position(start_position);
  set_end_position(end_position);
846 847
}

848 849 850
DEF_GETTER(SharedFunctionInfo, script, HeapObject) {
  HeapObject maybe_script = script_or_debug_info(cage_base, kAcquireLoad);
  if (maybe_script.IsDebugInfo(cage_base)) {
851
    return DebugInfo::cast(maybe_script).script();
852 853 854 855
  }
  return maybe_script;
}

856
void SharedFunctionInfo::set_script(HeapObject script) {
857
  HeapObject maybe_debug_info = script_or_debug_info(kAcquireLoad);
858 859
  if (maybe_debug_info.IsDebugInfo()) {
    DebugInfo::cast(maybe_debug_info).set_script(script);
860
  } else {
861
    set_script_or_debug_info(script, kReleaseStore);
862 863 864
  }
}

Simon Zünd's avatar
Simon Zünd committed
865 866 867 868
bool SharedFunctionInfo::is_repl_mode() const {
  return script().IsScript() && Script::cast(script()).is_repl_mode();
}

869
bool SharedFunctionInfo::HasDebugInfo() const {
870
  return script_or_debug_info(kAcquireLoad).IsDebugInfo();
871 872
}

873
DebugInfo SharedFunctionInfo::GetDebugInfo() const {
874 875 876
  auto debug_info = script_or_debug_info(kAcquireLoad);
  DCHECK(debug_info.IsDebugInfo());
  return DebugInfo::cast(debug_info);
877 878
}

879
void SharedFunctionInfo::SetDebugInfo(DebugInfo debug_info) {
880
  DCHECK(!HasDebugInfo());
881 882
  DCHECK_EQ(debug_info.script(), script_or_debug_info(kAcquireLoad));
  set_script_or_debug_info(debug_info, kReleaseStore);
883 884
}

885
bool SharedFunctionInfo::HasInferredName() {
886
  Object scope_info = name_or_scope_info(kAcquireLoad);
887 888
  if (scope_info.IsScopeInfo()) {
    return ScopeInfo::cast(scope_info).HasInferredFunctionName();
889 890
  }
  return HasUncompiledData();
891 892
}

893
String SharedFunctionInfo::inferred_name() {
894
  Object maybe_scope_info = name_or_scope_info(kAcquireLoad);
895
  if (maybe_scope_info.IsScopeInfo()) {
896
    ScopeInfo scope_info = ScopeInfo::cast(maybe_scope_info);
897 898 899
    if (scope_info.HasInferredFunctionName()) {
      Object name = scope_info.InferredFunctionName();
      if (name.IsString()) return String::cast(name);
900 901
    }
  } else if (HasUncompiledData()) {
902
    return uncompiled_data().inferred_name();
903
  }
904
  return GetReadOnlyRoots().empty_string();
905 906
}

907
bool SharedFunctionInfo::IsUserJavaScript() const {
908
  Object script_obj = script();
909
  if (script_obj.IsUndefined()) return false;
910
  Script script = Script::cast(script_obj);
911
  return script.IsUserJavaScript();
912 913
}

914
bool SharedFunctionInfo::IsSubjectToDebugging() const {
915 916 917 918
#if V8_ENABLE_WEBASSEMBLY
  if (HasAsmWasmData()) return false;
#endif  // V8_ENABLE_WEBASSEMBLY
  return IsUserJavaScript();
919 920
}

921
bool SharedFunctionInfo::CanDiscardCompiled() const {
922 923 924 925
#if V8_ENABLE_WEBASSEMBLY
  if (HasAsmWasmData()) return true;
#endif  // V8_ENABLE_WEBASSEMBLY
  return HasBytecodeArray() || HasUncompiledDataWithPreparseData() ||
926
         HasBaselineCode();
927 928
}

929
bool SharedFunctionInfo::is_class_constructor() const {
930
  return IsClassConstructorBit::decode(flags(kRelaxedLoad));
931 932 933 934
}

void SharedFunctionInfo::set_are_properties_final(bool value) {
  if (is_class_constructor()) {
935
    set_properties_are_final(value);
936 937 938 939
  }
}

bool SharedFunctionInfo::are_properties_final() const {
940
  bool bit = properties_are_final();
941 942 943
  return bit && is_class_constructor();
}

944 945 946
}  // namespace internal
}  // namespace v8

947
#include "src/base/platform/wrappers.h"
948 949 950
#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_SHARED_FUNCTION_INFO_INL_H_