%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/objects/
Upload File :
Create Path :
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/objects/js-function.cc

// Copyright 2020 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.

#include "src/objects/js-function.h"

#include "src/base/optional.h"
#include "src/baseline/baseline-batch-compiler.h"
#include "src/codegen/compiler.h"
#include "src/common/globals.h"
#include "src/diagnostics/code-tracer.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/tiering-manager.h"
#include "src/heap/heap-inl.h"
#include "src/ic/ic.h"
#include "src/init/bootstrapper.h"
#include "src/objects/feedback-cell-inl.h"
#include "src/strings/string-builder-inl.h"

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

namespace v8 {
namespace internal {

CodeKinds JSFunction::GetAttachedCodeKinds() const {
  const CodeKind kind = code()->kind();
  if (!CodeKindIsJSFunction(kind)) return {};
  if (CodeKindIsOptimizedJSFunction(kind) &&
      code()->marked_for_deoptimization()) {
    return {};
  }
  return CodeKindToCodeKindFlag(kind);
}

CodeKinds JSFunction::GetAvailableCodeKinds() const {
  CodeKinds result = GetAttachedCodeKinds();

  if ((result & CodeKindFlag::INTERPRETED_FUNCTION) == 0) {
    // The SharedFunctionInfo could have attached bytecode.
    if (shared()->HasBytecodeArray()) {
      result |= CodeKindFlag::INTERPRETED_FUNCTION;
    }
  }

  if ((result & CodeKindFlag::BASELINE) == 0) {
    // The SharedFunctionInfo could have attached baseline code.
    if (shared()->HasBaselineCode()) {
      result |= CodeKindFlag::BASELINE;
    }
  }

  // Check the optimized code cache.
  if (has_feedback_vector() && feedback_vector()->has_optimized_code() &&
      !feedback_vector()->optimized_code()->marked_for_deoptimization()) {
    Tagged<Code> code = feedback_vector()->optimized_code();
    DCHECK(CodeKindIsOptimizedJSFunction(code->kind()));
    result |= CodeKindToCodeKindFlag(code->kind());
  }

  DCHECK_EQ((result & ~kJSFunctionCodeKindsMask), 0);
  return result;
}

bool JSFunction::HasAttachedOptimizedCode() const {
  CodeKinds result = GetAttachedCodeKinds();
  return (result & kOptimizedJSFunctionCodeKindsMask) != 0;
}

bool JSFunction::HasAvailableHigherTierCodeThan(CodeKind kind) const {
  return HasAvailableHigherTierCodeThanWithFilter(kind,
                                                  kJSFunctionCodeKindsMask);
}

bool JSFunction::HasAvailableHigherTierCodeThanWithFilter(
    CodeKind kind, CodeKinds filter_mask) const {
  const int kind_as_int_flag = static_cast<int>(CodeKindToCodeKindFlag(kind));
  DCHECK(base::bits::IsPowerOfTwo(kind_as_int_flag));
  // Smear right - any higher present bit means we have a higher tier available.
  const int mask = kind_as_int_flag | (kind_as_int_flag - 1);
  const CodeKinds masked_available_kinds =
      GetAvailableCodeKinds() & filter_mask;
  return (masked_available_kinds & static_cast<CodeKinds>(~mask)) != 0;
}

bool JSFunction::HasAvailableOptimizedCode() const {
  CodeKinds result = GetAvailableCodeKinds();
  return (result & kOptimizedJSFunctionCodeKindsMask) != 0;
}

bool JSFunction::HasAttachedCodeKind(CodeKind kind) const {
  CodeKinds result = GetAttachedCodeKinds();
  return (result & CodeKindToCodeKindFlag(kind)) != 0;
}

bool JSFunction::HasAvailableCodeKind(CodeKind kind) const {
  CodeKinds result = GetAvailableCodeKinds();
  return (result & CodeKindToCodeKindFlag(kind)) != 0;
}

namespace {

// Returns false if no highest tier exists (i.e. the function is not compiled),
// otherwise returns true and sets highest_tier.
V8_WARN_UNUSED_RESULT bool HighestTierOf(CodeKinds kinds,
                                         CodeKind* highest_tier) {
  DCHECK_EQ((kinds & ~kJSFunctionCodeKindsMask), 0);
  // Higher tiers > lower tiers.
  static_assert(CodeKind::TURBOFAN > CodeKind::INTERPRETED_FUNCTION);
  if (kinds == 0) return false;
  const int highest_tier_log2 =
      31 - base::bits::CountLeadingZeros(static_cast<uint32_t>(kinds));
  DCHECK(CodeKindIsJSFunction(static_cast<CodeKind>(highest_tier_log2)));
  *highest_tier = static_cast<CodeKind>(highest_tier_log2);
  return true;
}

}  // namespace

base::Optional<CodeKind> JSFunction::GetActiveTier() const {
#if V8_ENABLE_WEBASSEMBLY
  // Asm/Wasm functions are currently not supported. For simplicity, this
  // includes invalid asm.js functions whose code hasn't yet been updated to
  // CompileLazy but is still the InstantiateAsmJs builtin.
  if (shared()->HasAsmWasmData() ||
      code()->builtin_id() == Builtin::kInstantiateAsmJs) {
    return {};
  }
#endif  // V8_ENABLE_WEBASSEMBLY

  CodeKind highest_tier;
  if (!HighestTierOf(GetAvailableCodeKinds(), &highest_tier)) return {};

#ifdef DEBUG
  CHECK(highest_tier == CodeKind::TURBOFAN ||
        highest_tier == CodeKind::BASELINE ||
        highest_tier == CodeKind::MAGLEV ||
        highest_tier == CodeKind::INTERPRETED_FUNCTION);

  if (highest_tier == CodeKind::INTERPRETED_FUNCTION) {
    CHECK(code()->is_interpreter_trampoline_builtin() ||
          (CodeKindIsOptimizedJSFunction(code()->kind()) &&
           code()->marked_for_deoptimization()) ||
          (code()->builtin_id() == Builtin::kCompileLazy &&
           shared()->HasBytecodeArray() && !shared()->HasBaselineCode()));
  }
#endif  // DEBUG

  return highest_tier;
}

bool JSFunction::ActiveTierIsIgnition() const {
  return GetActiveTier() == CodeKind::INTERPRETED_FUNCTION;
}

bool JSFunction::ActiveTierIsBaseline() const {
  return GetActiveTier() == CodeKind::BASELINE;
}

bool JSFunction::ActiveTierIsMaglev() const {
  return GetActiveTier() == CodeKind::MAGLEV;
}

bool JSFunction::ActiveTierIsTurbofan() const {
  return GetActiveTier() == CodeKind::TURBOFAN;
}

bool JSFunction::CanDiscardCompiled() const {
  // Essentially, what we are asking here is, has this function been compiled
  // from JS code? We can currently tell only indirectly, by looking at
  // available code kinds. If any JS code kind exists, we can discard.
  //
  // Attached optimized code that is marked for deoptimization will not show up
  // in the list of available code kinds, thus we must check for it manually.
  //
  // Note that when the function has not yet been compiled we also return
  // false; that's fine, since nothing must be discarded in that case.
  if (CodeKindIsOptimizedJSFunction(code()->kind())) return true;
  CodeKinds result = GetAvailableCodeKinds();
  return (result & kJSFunctionCodeKindsMask) != 0;
}

namespace {

constexpr TieringState TieringStateFor(CodeKind target_kind,
                                       ConcurrencyMode mode) {
  DCHECK(target_kind == CodeKind::MAGLEV || target_kind == CodeKind::TURBOFAN);
  return target_kind == CodeKind::MAGLEV
             ? (IsConcurrent(mode) ? TieringState::kRequestMaglev_Concurrent
                                   : TieringState::kRequestMaglev_Synchronous)
             : (IsConcurrent(mode)
                    ? TieringState::kRequestTurbofan_Concurrent
                    : TieringState::kRequestTurbofan_Synchronous);
}

}  // namespace

void JSFunction::MarkForOptimization(Isolate* isolate, CodeKind target_kind,
                                     ConcurrencyMode mode) {
  if (!isolate->concurrent_recompilation_enabled() ||
      isolate->bootstrapper()->IsActive()) {
    mode = ConcurrencyMode::kSynchronous;
  }

  DCHECK(CodeKindIsOptimizedJSFunction(target_kind));
  DCHECK(!is_compiled() || ActiveTierIsIgnition() || ActiveTierIsBaseline() ||
         ActiveTierIsMaglev());
  DCHECK(!ActiveTierIsTurbofan());
  DCHECK(shared()->HasBytecodeArray());
  DCHECK(shared()->allows_lazy_compilation() ||
         !shared()->optimization_disabled());

  if (IsConcurrent(mode)) {
    if (IsInProgress(tiering_state())) {
      if (v8_flags.trace_concurrent_recompilation) {
        PrintF("  ** Not marking ");
        ShortPrint(*this);
        PrintF(" -- already in optimization queue.\n");
      }
      return;
    }
    if (v8_flags.trace_concurrent_recompilation) {
      PrintF("  ** Marking ");
      ShortPrint(*this);
      PrintF(" for concurrent %s recompilation.\n",
             CodeKindToString(target_kind));
    }
  }

  set_tiering_state(TieringStateFor(target_kind, mode));
}

void JSFunction::SetInterruptBudget(
    Isolate* isolate, base::Optional<CodeKind> override_active_tier) {
  raw_feedback_cell()->set_interrupt_budget(
      TieringManager::InterruptBudgetFor(isolate, *this, override_active_tier));
}

// static
Maybe<bool> JSFunctionOrBoundFunctionOrWrappedFunction::CopyNameAndLength(
    Isolate* isolate,
    Handle<JSFunctionOrBoundFunctionOrWrappedFunction> function,
    Handle<JSReceiver> target, Handle<String> prefix, int arg_count) {
  // Setup the "length" property based on the "length" of the {target}.
  // If the targets length is the default JSFunction accessor, we can keep the
  // accessor that's installed by default on the
  // JSBoundFunction/JSWrappedFunction. It lazily computes the value from the
  // underlying internal length.
  Handle<AccessorInfo> function_length_accessor =
      isolate->factory()->function_length_accessor();
  LookupIterator length_lookup(isolate, target,
                               isolate->factory()->length_string(), target,
                               LookupIterator::OWN);
  if (!IsJSFunction(*target) ||
      length_lookup.state() != LookupIterator::ACCESSOR ||
      !length_lookup.GetAccessors().is_identical_to(function_length_accessor)) {
    Handle<Object> length(Smi::zero(), isolate);
    Maybe<PropertyAttributes> attributes =
        JSReceiver::GetPropertyAttributes(&length_lookup);
    if (attributes.IsNothing()) return Nothing<bool>();
    if (attributes.FromJust() != ABSENT) {
      Handle<Object> target_length;
      ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_length,
                                       Object::GetProperty(&length_lookup),
                                       Nothing<bool>());
      if (IsNumber(*target_length)) {
        length = isolate->factory()->NewNumber(std::max(
            0.0, DoubleToInteger(Object::Number(*target_length)) - arg_count));
      }
    }
    LookupIterator it(isolate, function, isolate->factory()->length_string(),
                      function);
    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
    RETURN_ON_EXCEPTION_VALUE(isolate,
                              JSObject::DefineOwnPropertyIgnoreAttributes(
                                  &it, length, it.property_attributes()),
                              Nothing<bool>());
  }

  // Setup the "name" property based on the "name" of the {target}.
  // If the target's name is the default JSFunction accessor, we can keep the
  // accessor that's installed by default on the
  // JSBoundFunction/JSWrappedFunction. It lazily computes the value from the
  // underlying internal name.
  Handle<AccessorInfo> function_name_accessor =
      isolate->factory()->function_name_accessor();
  LookupIterator name_lookup(isolate, target, isolate->factory()->name_string(),
                             target);
  if (!IsJSFunction(*target) ||
      name_lookup.state() != LookupIterator::ACCESSOR ||
      !name_lookup.GetAccessors().is_identical_to(function_name_accessor) ||
      (name_lookup.IsFound() && !name_lookup.HolderIsReceiver())) {
    Handle<Object> target_name;
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_name,
                                     Object::GetProperty(&name_lookup),
                                     Nothing<bool>());
    Handle<String> name;
    if (IsString(*target_name)) {
      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
          isolate, name,
          Name::ToFunctionName(isolate, Handle<String>::cast(target_name)),
          Nothing<bool>());
      if (!prefix.is_null()) {
        ASSIGN_RETURN_ON_EXCEPTION_VALUE(
            isolate, name, isolate->factory()->NewConsString(prefix, name),
            Nothing<bool>());
      }
    } else if (prefix.is_null()) {
      name = isolate->factory()->empty_string();
    } else {
      name = prefix;
    }
    LookupIterator it(isolate, function, isolate->factory()->name_string());
    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
    RETURN_ON_EXCEPTION_VALUE(isolate,
                              JSObject::DefineOwnPropertyIgnoreAttributes(
                                  &it, name, it.property_attributes()),
                              Nothing<bool>());
  }

  return Just(true);
}

// static
MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
                                             Handle<JSBoundFunction> function) {
  Handle<String> prefix = isolate->factory()->bound__string();
  Handle<String> target_name = prefix;
  Factory* factory = isolate->factory();
  // Concatenate the "bound " up to the last non-bound target.
  while (IsJSBoundFunction(function->bound_target_function())) {
    ASSIGN_RETURN_ON_EXCEPTION(isolate, target_name,
                               factory->NewConsString(prefix, target_name),
                               String);
    function = handle(JSBoundFunction::cast(function->bound_target_function()),
                      isolate);
  }
  if (IsJSWrappedFunction(function->bound_target_function())) {
    Handle<JSWrappedFunction> target(
        JSWrappedFunction::cast(function->bound_target_function()), isolate);
    Handle<String> name;
    ASSIGN_RETURN_ON_EXCEPTION(
        isolate, name, JSWrappedFunction::GetName(isolate, target), String);
    return factory->NewConsString(target_name, name);
  }
  if (IsJSFunction(function->bound_target_function())) {
    Handle<JSFunction> target(
        JSFunction::cast(function->bound_target_function()), isolate);
    Handle<String> name = JSFunction::GetName(isolate, target);
    return factory->NewConsString(target_name, name);
  }
  // This will omit the proper target name for bound JSProxies.
  return target_name;
}

// static
Maybe<int> JSBoundFunction::GetLength(Isolate* isolate,
                                      Handle<JSBoundFunction> function) {
  int nof_bound_arguments = function->bound_arguments()->length();
  while (IsJSBoundFunction(function->bound_target_function())) {
    function = handle(JSBoundFunction::cast(function->bound_target_function()),
                      isolate);
    // Make sure we never overflow {nof_bound_arguments}, the number of
    // arguments of a function is strictly limited by the max length of an
    // JSAarray, Smi::kMaxValue is thus a reasonably good overestimate.
    int length = function->bound_arguments()->length();
    if (V8_LIKELY(Smi::kMaxValue - nof_bound_arguments > length)) {
      nof_bound_arguments += length;
    } else {
      nof_bound_arguments = Smi::kMaxValue;
    }
  }
  if (IsJSWrappedFunction(function->bound_target_function())) {
    Handle<JSWrappedFunction> target(
        JSWrappedFunction::cast(function->bound_target_function()), isolate);
    int target_length = 0;
    MAYBE_ASSIGN_RETURN_ON_EXCEPTION_VALUE(
        isolate, target_length, JSWrappedFunction::GetLength(isolate, target),
        Nothing<int>());
    int length = std::max(0, target_length - nof_bound_arguments);
    return Just(length);
  }
  // All non JSFunction targets get a direct property and don't use this
  // accessor.
  Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
                            isolate);
  int target_length = target->length();

  int length = std::max(0, target_length - nof_bound_arguments);
  return Just(length);
}

// static
Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
  Isolate* const isolate = function->GetIsolate();
  return isolate->factory()->function_native_code_string();
}

// static
MaybeHandle<String> JSWrappedFunction::GetName(
    Isolate* isolate, Handle<JSWrappedFunction> function) {
  STACK_CHECK(isolate, MaybeHandle<String>());
  Factory* factory = isolate->factory();
  Handle<String> target_name = factory->empty_string();
  Handle<JSReceiver> target =
      handle(function->wrapped_target_function(), isolate);
  if (IsJSBoundFunction(*target)) {
    return JSBoundFunction::GetName(
        isolate,
        handle(JSBoundFunction::cast(function->wrapped_target_function()),
               isolate));
  } else if (IsJSFunction(*target)) {
    return JSFunction::GetName(
        isolate,
        handle(JSFunction::cast(function->wrapped_target_function()), isolate));
  }
  // This will omit the proper target name for bound JSProxies.
  return target_name;
}

// static
Maybe<int> JSWrappedFunction::GetLength(Isolate* isolate,
                                        Handle<JSWrappedFunction> function) {
  STACK_CHECK(isolate, Nothing<int>());
  Handle<JSReceiver> target =
      handle(function->wrapped_target_function(), isolate);
  if (IsJSBoundFunction(*target)) {
    return JSBoundFunction::GetLength(
        isolate,
        handle(JSBoundFunction::cast(function->wrapped_target_function()),
               isolate));
  }
  // All non JSFunction targets get a direct property and don't use this
  // accessor.
  return Just(Handle<JSFunction>::cast(target)->length());
}

// static
Handle<String> JSWrappedFunction::ToString(Handle<JSWrappedFunction> function) {
  Isolate* const isolate = function->GetIsolate();
  return isolate->factory()->function_native_code_string();
}

// static
MaybeHandle<Object> JSWrappedFunction::Create(
    Isolate* isolate, Handle<NativeContext> creation_context,
    Handle<JSReceiver> value) {
  // The value must be a callable according to the specification.
  DCHECK(IsCallable(*value));
  // The intermediate wrapped functions are not user-visible. And calling a
  // wrapped function won't cause a side effect in the creation realm.
  // Unwrap here to avoid nested unwrapping at the call site.
  if (IsJSWrappedFunction(*value)) {
    Handle<JSWrappedFunction> target_wrapped =
        Handle<JSWrappedFunction>::cast(value);
    value =
        Handle<JSReceiver>(target_wrapped->wrapped_target_function(), isolate);
  }

  // 1. Let internalSlotsList be the internal slots listed in Table 2, plus
  // [[Prototype]] and [[Extensible]].
  // 2. Let wrapped be ! MakeBasicObject(internalSlotsList).
  // 3. Set wrapped.[[Prototype]] to
  // callerRealm.[[Intrinsics]].[[%Function.prototype%]].
  // 4. Set wrapped.[[Call]] as described in 2.1.
  // 5. Set wrapped.[[WrappedTargetFunction]] to Target.
  // 6. Set wrapped.[[Realm]] to callerRealm.
  Handle<JSWrappedFunction> wrapped =
      isolate->factory()->NewJSWrappedFunction(creation_context, value);

  // 7. Let result be CopyNameAndLength(wrapped, Target, "wrapped").
  Maybe<bool> is_abrupt =
      JSFunctionOrBoundFunctionOrWrappedFunction::CopyNameAndLength(
          isolate, wrapped, value, Handle<String>(), 0);

  // 8. If result is an Abrupt Completion, throw a TypeError exception.
  if (is_abrupt.IsNothing()) {
    DCHECK(isolate->has_pending_exception());
    Handle<Object> pending_exception =
        Handle<Object>(isolate->pending_exception(), isolate);
    isolate->clear_pending_exception();

    // The TypeError thrown is created with creation Realm's TypeError
    // constructor instead of the executing Realm's.
    Handle<JSFunction> type_error_function =
        Handle<JSFunction>(creation_context->type_error_function(), isolate);
    Handle<String> string =
        Object::NoSideEffectsToString(isolate, pending_exception);
    THROW_NEW_ERROR_RETURN_VALUE(
        isolate,
        NewError(type_error_function, MessageTemplate::kCannotWrap, string),
        {});
  }
  DCHECK(is_abrupt.FromJust());

  // 9. Return wrapped.
  return wrapped;
}

// static
Handle<String> JSFunction::GetName(Isolate* isolate,
                                   Handle<JSFunction> function) {
  if (function->shared()->name_should_print_as_anonymous()) {
    return isolate->factory()->anonymous_string();
  }
  return handle(function->shared()->Name(), isolate);
}

// static
void JSFunction::EnsureClosureFeedbackCellArray(
    Handle<JSFunction> function, bool reset_budget_for_feedback_allocation) {
  Isolate* const isolate = function->GetIsolate();
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->shared()->HasFeedbackMetadata());
#if V8_ENABLE_WEBASSEMBLY
  if (function->shared()->HasAsmWasmData()) return;
#endif  // V8_ENABLE_WEBASSEMBLY

  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
  DCHECK(function->shared()->HasBytecodeArray());

  const bool has_closure_feedback_cell_array =
      (function->has_closure_feedback_cell_array() ||
       function->has_feedback_vector());
  // Initialize the interrupt budget to the feedback vector allocation budget
  // when initializing the feedback cell for the first time or after a bytecode
  // flush. We retain the closure feedback cell array on bytecode flush, so
  // reset_budget_for_feedback_allocation is used to reset the budget in these
  // cases.
  if (reset_budget_for_feedback_allocation ||
      !has_closure_feedback_cell_array) {
    function->SetInterruptBudget(isolate);
  }

  if (has_closure_feedback_cell_array) {
    return;
  }

  Handle<HeapObject> feedback_cell_array =
      ClosureFeedbackCellArray::New(isolate, shared);
  // Many closure cell is used as a way to specify that there is no
  // feedback cell for this function and a new feedback cell has to be
  // allocated for this function. For ex: for eval functions, we have to create
  // a feedback cell and cache it along with the code. It is safe to use
  // many_closure_cell to indicate this because in regular cases, it should
  // already have a feedback_vector / feedback cell array allocated.
  if (function->raw_feedback_cell() == isolate->heap()->many_closures_cell()) {
    Handle<FeedbackCell> feedback_cell =
        isolate->factory()->NewOneClosureCell(feedback_cell_array);
    function->set_raw_feedback_cell(*feedback_cell, kReleaseStore);
    function->SetInterruptBudget(isolate);
  } else {
    function->raw_feedback_cell()->set_value(*feedback_cell_array,
                                             kReleaseStore);
  }
}

// static
void JSFunction::EnsureFeedbackVector(Isolate* isolate,
                                      Handle<JSFunction> function,
                                      IsCompiledScope* compiled_scope) {
  DCHECK(compiled_scope->is_compiled());
  DCHECK(function->shared()->HasFeedbackMetadata());
  if (function->has_feedback_vector()) return;
#if V8_ENABLE_WEBASSEMBLY
  if (function->shared()->HasAsmWasmData()) return;
#endif  // V8_ENABLE_WEBASSEMBLY

  CreateAndAttachFeedbackVector(isolate, function, compiled_scope);
}

// static
void JSFunction::CreateAndAttachFeedbackVector(
    Isolate* isolate, Handle<JSFunction> function,
    IsCompiledScope* compiled_scope) {
  DCHECK(compiled_scope->is_compiled());
  DCHECK(function->shared()->HasFeedbackMetadata());
  DCHECK(!function->has_feedback_vector());
#if V8_ENABLE_WEBASSEMBLY
  DCHECK(!function->shared()->HasAsmWasmData());
#endif  // V8_ENABLE_WEBASSEMBLY

  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
  DCHECK(function->shared()->HasBytecodeArray());

  EnsureClosureFeedbackCellArray(function, false);
  Handle<ClosureFeedbackCellArray> closure_feedback_cell_array =
      handle(function->closure_feedback_cell_array(), isolate);
  Handle<FeedbackVector> feedback_vector = FeedbackVector::New(
      isolate, shared, closure_feedback_cell_array,
      handle(function->raw_feedback_cell(isolate), isolate), compiled_scope);
  USE(feedback_vector);
  // EnsureClosureFeedbackCellArray should handle the special case where we need
  // to allocate a new feedback cell. Please look at comment in that function
  // for more details.
  DCHECK(function->raw_feedback_cell() !=
         isolate->heap()->many_closures_cell());
  DCHECK_EQ(function->raw_feedback_cell()->value(), *feedback_vector);
  function->SetInterruptBudget(isolate);

  DCHECK_EQ(v8_flags.log_function_events,
            feedback_vector->log_next_execution());

  // Additionally, detect activations of this function on the stack, and update
  // the feedback vector.
  JavaScriptStackFrameIterator it(isolate);
  while (!it.done()) {
    if (it.frame()->is_interpreted() && it.frame()->function() == *function) {
      static_cast<UnoptimizedFrame*>(it.frame())
          ->SetFeedbackVector(*feedback_vector);
    }
    it.Advance();
  }
}

// static
void JSFunction::InitializeFeedbackCell(
    Handle<JSFunction> function, IsCompiledScope* is_compiled_scope,
    bool reset_budget_for_feedback_allocation) {
  Isolate* const isolate = function->GetIsolate();
#if V8_ENABLE_WEBASSEMBLY
  // The following checks ensure that the feedback vectors are compatible with
  // the feedback metadata. For Asm / Wasm functions we never allocate / use
  // feedback vectors, so a mismatch between the metadata and feedback vector is
  // harmless. The checks could fail for functions that has has_asm_wasm_broken
  // set at runtime (for ex: failed instantiation).
  if (function->shared()->HasAsmWasmData()) return;
#endif  // V8_ENABLE_WEBASSEMBLY

  if (function->has_feedback_vector()) {
    CHECK_EQ(function->feedback_vector()->length(),
             function->feedback_vector()->metadata()->slot_count());
    return;
  }

  if (function->has_closure_feedback_cell_array()) {
    CHECK_EQ(
        function->closure_feedback_cell_array()->length(),
        function->shared()->feedback_metadata()->create_closure_slot_count());
  }

  const bool needs_feedback_vector =
      !v8_flags.lazy_feedback_allocation || v8_flags.always_turbofan ||
      // We also need a feedback vector for certain log events, collecting type
      // profile and more precise code coverage.
      v8_flags.log_function_events ||
      !isolate->is_best_effort_code_coverage() ||
      function->shared()->sparkplug_compiled();

  if (needs_feedback_vector) {
    CreateAndAttachFeedbackVector(isolate, function, is_compiled_scope);
  } else {
    EnsureClosureFeedbackCellArray(function,
                                   reset_budget_for_feedback_allocation);
  }
  // TODO(jgruber): Unduplicate these conditions from tiering-manager.cc.
  if (function->shared()->sparkplug_compiled() &&
      CanCompileWithBaseline(isolate, function->shared()) &&
      function->ActiveTierIsIgnition()) {
    if (v8_flags.baseline_batch_compilation) {
      isolate->baseline_batch_compiler()->EnqueueFunction(function);
    } else {
      IsCompiledScope is_compiled_scope(
          function->shared()->is_compiled_scope(isolate));
      Compiler::CompileBaseline(isolate, function, Compiler::CLEAR_EXCEPTION,
                                &is_compiled_scope);
    }
  }
}

namespace {

void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
                          Handle<JSReceiver> value) {
  // Now some logic for the maps of the objects that are created by using this
  // function as a constructor.
  if (function->has_initial_map()) {
    // If the function has allocated the initial map replace it with a
    // copy containing the new prototype.  Also complete any in-object
    // slack tracking that is in progress at this point because it is
    // still tracking the old copy.
    function->CompleteInobjectSlackTrackingIfActive();

    Handle<Map> initial_map(function->initial_map(), isolate);

    if (!isolate->bootstrapper()->IsActive() &&
        initial_map->instance_type() == JS_OBJECT_TYPE) {
      // Put the value in the initial map field until an initial map is needed.
      // At that point, a new initial map is created and the prototype is put
      // into the initial map where it belongs.
      function->set_prototype_or_initial_map(*value, kReleaseStore);
      if (IsJSObjectThatCanBeTrackedAsPrototype(*value)) {
        // Optimize as prototype to detach it from its transition tree.
        JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
      }
    } else {
      Handle<Map> new_map =
          Map::Copy(isolate, initial_map, "SetInstancePrototype");
      JSFunction::SetInitialMap(isolate, function, new_map, value);
      DCHECK_IMPLIES(!isolate->bootstrapper()->IsActive(),
                     *function != function->native_context()->array_function());
    }

    // Deoptimize all code that embeds the previous initial map.
    DependentCode::DeoptimizeDependencyGroups(
        isolate, *initial_map, DependentCode::kInitialMapChangedGroup);
  } else {
    // Put the value in the initial map field until an initial map is
    // needed.  At that point, a new initial map is created and the
    // prototype is put into the initial map where it belongs.
    function->set_prototype_or_initial_map(*value, kReleaseStore);
    if (IsJSObjectThatCanBeTrackedAsPrototype(*value)) {
      // Optimize as prototype to detach it from its transition tree.
      JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
    }
  }
}

}  // anonymous namespace

void JSFunction::SetPrototype(Handle<JSFunction> function,
                              Handle<Object> value) {
  DCHECK(IsConstructor(*function) ||
         IsGeneratorFunction(function->shared()->kind()));
  Isolate* isolate = function->GetIsolate();
  Handle<JSReceiver> construct_prototype;

  // If the value is not a JSReceiver, store the value in the map's
  // constructor field so it can be accessed.  Also, set the prototype
  // used for constructing objects to the original object prototype.
  // See ECMA-262 13.2.2.
  if (!IsJSReceiver(*value)) {
    // Copy the map so this does not affect unrelated functions.
    // Remove map transitions because they point to maps with a
    // different prototype.
    Handle<Map> new_map =
        Map::Copy(isolate, handle(function->map(), isolate), "SetPrototype");

    // Create a new {constructor, non-instance_prototype} tuple and store it
    // in Map::constructor field.
    Handle<Object> constructor(new_map->GetConstructor(), isolate);
    Handle<Tuple2> non_instance_prototype_constructor_tuple =
        isolate->factory()->NewTuple2(constructor, value, AllocationType::kOld);

    new_map->set_has_non_instance_prototype(true);
    new_map->SetConstructor(*non_instance_prototype_constructor_tuple);

    JSObject::MigrateToMap(isolate, function, new_map);

    FunctionKind kind = function->shared()->kind();
    Handle<Context> native_context(function->native_context(), isolate);

    construct_prototype = Handle<JSReceiver>(
        IsGeneratorFunction(kind)
            ? IsAsyncFunction(kind)
                  ? native_context->initial_async_generator_prototype()
                  : native_context->initial_generator_prototype()
            : native_context->initial_object_prototype(),
        isolate);
  } else {
    construct_prototype = Handle<JSReceiver>::cast(value);
    function->map()->set_has_non_instance_prototype(false);
  }

  SetInstancePrototype(isolate, function, construct_prototype);
}

void JSFunction::SetInitialMap(Isolate* isolate, Handle<JSFunction> function,
                               Handle<Map> map, Handle<HeapObject> prototype) {
  SetInitialMap(isolate, function, map, prototype, function);
}

void JSFunction::SetInitialMap(Isolate* isolate, Handle<JSFunction> function,
                               Handle<Map> map, Handle<HeapObject> prototype,
                               Handle<JSFunction> constructor) {
  if (map->prototype() != *prototype) {
    Map::SetPrototype(isolate, map, prototype);
  }
  map->SetConstructor(*constructor);
  function->set_prototype_or_initial_map(*map, kReleaseStore);
  if (v8_flags.log_maps) {
    LOG(isolate, MapEvent("InitialMap", Handle<Map>(), map, "",
                          SharedFunctionInfo::DebugName(
                              isolate, handle(function->shared(), isolate))));
  }
}

void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
  DCHECK(function->has_prototype_slot());
  DCHECK(IsConstructor(*function) ||
         IsResumableFunction(function->shared()->kind()));
  if (function->has_initial_map()) return;
  Isolate* isolate = function->GetIsolate();

  int expected_nof_properties =
      CalculateExpectedNofProperties(isolate, function);

  // {CalculateExpectedNofProperties} can have had the side effect of creating
  // the initial map (e.g. it could have triggered an optimized compilation
  // whose dependency installation reentered {EnsureHasInitialMap}).
  if (function->has_initial_map()) return;

  // Create a new map with the size and number of in-object properties suggested
  // by the function.
  InstanceType instance_type;
  if (IsResumableFunction(function->shared()->kind())) {
    instance_type = IsAsyncGeneratorFunction(function->shared()->kind())
                        ? JS_ASYNC_GENERATOR_OBJECT_TYPE
                        : JS_GENERATOR_OBJECT_TYPE;
  } else {
    instance_type = JS_OBJECT_TYPE;
  }

  int instance_size;
  int inobject_properties;
  CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties,
                              &instance_size, &inobject_properties);

  Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size,
                                               TERMINAL_FAST_ELEMENTS_KIND,
                                               inobject_properties);

  // Fetch or allocate prototype.
  Handle<HeapObject> prototype;
  if (function->has_instance_prototype()) {
    prototype = handle(function->instance_prototype(), isolate);
    map->set_prototype(*prototype);
  } else {
    prototype = isolate->factory()->NewFunctionPrototype(function);
    Map::SetPrototype(isolate, map, prototype);
  }
  DCHECK(map->has_fast_object_elements());

  // Finally link initial map and constructor function.
  DCHECK(IsJSReceiver(*prototype));
  JSFunction::SetInitialMap(isolate, function, map, prototype);
  map->StartInobjectSlackTracking();
}

namespace {

#ifdef DEBUG
bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
  switch (instance_type) {
    case JS_API_OBJECT_TYPE:
    case JS_ARRAY_BUFFER_TYPE:
    case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
    case JS_ARRAY_TYPE:
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    case JS_DATA_VIEW_TYPE:
    case JS_RAB_GSAB_DATA_VIEW_TYPE:
    case JS_DATE_TYPE:
    case JS_GENERATOR_OBJECT_TYPE:
    case JS_FUNCTION_TYPE:
    case JS_CLASS_CONSTRUCTOR_TYPE:
    case JS_PROMISE_CONSTRUCTOR_TYPE:
    case JS_REG_EXP_CONSTRUCTOR_TYPE:
    case JS_ARRAY_CONSTRUCTOR_TYPE:
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
  case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
      TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
    case JS_ITERATOR_PROTOTYPE_TYPE:
    case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
    case JS_OBJECT_PROTOTYPE_TYPE:
    case JS_PROMISE_PROTOTYPE_TYPE:
    case JS_REG_EXP_PROTOTYPE_TYPE:
    case JS_SET_ITERATOR_PROTOTYPE_TYPE:
    case JS_SET_PROTOTYPE_TYPE:
    case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
    case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
#ifdef V8_INTL_SUPPORT
    case JS_COLLATOR_TYPE:
    case JS_DATE_TIME_FORMAT_TYPE:
    case JS_DISPLAY_NAMES_TYPE:
    case JS_DURATION_FORMAT_TYPE:
    case JS_LIST_FORMAT_TYPE:
    case JS_LOCALE_TYPE:
    case JS_NUMBER_FORMAT_TYPE:
    case JS_PLURAL_RULES_TYPE:
    case JS_RELATIVE_TIME_FORMAT_TYPE:
    case JS_SEGMENT_ITERATOR_TYPE:
    case JS_SEGMENTER_TYPE:
    case JS_SEGMENTS_TYPE:
    case JS_V8_BREAK_ITERATOR_TYPE:
#endif
    case JS_ASYNC_FUNCTION_OBJECT_TYPE:
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
    case JS_MAP_TYPE:
    case JS_MESSAGE_OBJECT_TYPE:
    case JS_OBJECT_TYPE:
    case JS_ERROR_TYPE:
    case JS_FINALIZATION_REGISTRY_TYPE:
    case JS_ARGUMENTS_OBJECT_TYPE:
    case JS_PROMISE_TYPE:
    case JS_REG_EXP_TYPE:
    case JS_SET_TYPE:
    case JS_SHADOW_REALM_TYPE:
    case JS_SPECIAL_API_OBJECT_TYPE:
    case JS_TYPED_ARRAY_TYPE:
    case JS_PRIMITIVE_WRAPPER_TYPE:
    case JS_TEMPORAL_CALENDAR_TYPE:
    case JS_TEMPORAL_DURATION_TYPE:
    case JS_TEMPORAL_INSTANT_TYPE:
    case JS_TEMPORAL_PLAIN_DATE_TYPE:
    case JS_TEMPORAL_PLAIN_DATE_TIME_TYPE:
    case JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE:
    case JS_TEMPORAL_PLAIN_TIME_TYPE:
    case JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE:
    case JS_TEMPORAL_TIME_ZONE_TYPE:
    case JS_TEMPORAL_ZONED_DATE_TIME_TYPE:
    case JS_WEAK_MAP_TYPE:
    case JS_WEAK_REF_TYPE:
    case JS_WEAK_SET_TYPE:
#if V8_ENABLE_WEBASSEMBLY
    case WASM_GLOBAL_OBJECT_TYPE:
    case WASM_INSTANCE_OBJECT_TYPE:
    case WASM_MEMORY_OBJECT_TYPE:
    case WASM_MODULE_OBJECT_TYPE:
    case WASM_TABLE_OBJECT_TYPE:
    case WASM_VALUE_OBJECT_TYPE:
#endif  // V8_ENABLE_WEBASSEMBLY
      return true;

    case BIGINT_TYPE:
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
    case BYTECODE_ARRAY_TYPE:
    case BYTE_ARRAY_TYPE:
    case CELL_TYPE:
    case INSTRUCTION_STREAM_TYPE:
    case FILLER_TYPE:
    case FIXED_ARRAY_TYPE:
    case SCRIPT_CONTEXT_TABLE_TYPE:
    case FIXED_DOUBLE_ARRAY_TYPE:
    case FEEDBACK_METADATA_TYPE:
    case FOREIGN_TYPE:
    case FREE_SPACE_TYPE:
    case HASH_TABLE_TYPE:
    case ORDERED_HASH_MAP_TYPE:
    case ORDERED_HASH_SET_TYPE:
    case ORDERED_NAME_DICTIONARY_TYPE:
    case NAME_DICTIONARY_TYPE:
    case GLOBAL_DICTIONARY_TYPE:
    case NUMBER_DICTIONARY_TYPE:
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
    case HEAP_NUMBER_TYPE:
    case JS_BOUND_FUNCTION_TYPE:
    case JS_GLOBAL_OBJECT_TYPE:
    case JS_GLOBAL_PROXY_TYPE:
    case JS_PROXY_TYPE:
    case JS_WRAPPED_FUNCTION_TYPE:
    case MAP_TYPE:
    case ODDBALL_TYPE:
    case PROPERTY_CELL_TYPE:
    case SHARED_FUNCTION_INFO_TYPE:
    case SYMBOL_TYPE:
    case ALLOCATION_SITE_TYPE:

#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
  case FIXED_##TYPE##_ARRAY_TYPE:
#undef TYPED_ARRAY_CASE

#define MAKE_STRUCT_CASE(TYPE, Name, name) case TYPE:
      STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE
      // We must not end up here for these instance types at all.
      UNREACHABLE();
    // Fall through.
    default:
      return false;
  }
}
#endif  // DEBUG

bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
                              Handle<JSFunction> constructor,
                              Handle<Map> constructor_initial_map) {
  // Use the default intrinsic prototype instead.
  if (!new_target->has_prototype_slot()) return false;
  // Check that |function|'s initial map still in sync with the |constructor|,
  // otherwise we must create a new initial map for |function|.
  if (new_target->has_initial_map() &&
      new_target->initial_map()->GetConstructor() == *constructor) {
    DCHECK(IsJSReceiver(new_target->instance_prototype()));
    return true;
  }
  InstanceType instance_type = constructor_initial_map->instance_type();
  DCHECK(CanSubclassHaveInobjectProperties(instance_type));
  // Create a new map with the size and number of in-object properties
  // suggested by |function|.

  // Link initial map and constructor function if the new.target is actually a
  // subclass constructor.
  if (!IsDerivedConstructor(new_target->shared()->kind())) return false;

  int instance_size;
  int in_object_properties;
  int embedder_fields =
      JSObject::GetEmbedderFieldCount(*constructor_initial_map);
  // Constructor expects certain number of in-object properties to be in the
  // object. However, CalculateExpectedNofProperties() may return smaller value
  // if 1) the constructor is not in the prototype chain of new_target, or
  // 2) the prototype chain is modified during iteration, or 3) compilation
  // failure occur during prototype chain iteration.
  // So we take the maximum of two values.
  int expected_nof_properties = std::max(
      static_cast<int>(constructor->shared()->expected_nof_properties()),
      JSFunction::CalculateExpectedNofProperties(isolate, new_target));
  JSFunction::CalculateInstanceSizeHelper(
      instance_type, constructor_initial_map->has_prototype_slot(),
      embedder_fields, expected_nof_properties, &instance_size,
      &in_object_properties);

  int pre_allocated = constructor_initial_map->GetInObjectProperties() -
                      constructor_initial_map->UnusedPropertyFields();
  CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size);
  int unused_property_fields = in_object_properties - pre_allocated;
  Handle<Map> map =
      Map::CopyInitialMap(isolate, constructor_initial_map, instance_size,
                          in_object_properties, unused_property_fields);
  map->set_new_target_is_base(false);
  Handle<HeapObject> prototype(new_target->instance_prototype(), isolate);
  JSFunction::SetInitialMap(isolate, new_target, map, prototype, constructor);
  DCHECK(IsJSReceiver(new_target->instance_prototype()));
  map->set_construction_counter(Map::kNoSlackTracking);
  map->StartInobjectSlackTracking();
  return true;
}

}  // namespace

// static
MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
                                           Handle<JSFunction> constructor,
                                           Handle<JSReceiver> new_target) {
  EnsureHasInitialMap(constructor);

  Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
  if (*new_target == *constructor) return constructor_initial_map;

  Handle<Map> result_map;
  // Fast case, new.target is a subclass of constructor. The map is cacheable
  // (and may already have been cached). new.target.prototype is guaranteed to
  // be a JSReceiver.
  if (IsJSFunction(*new_target)) {
    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
    if (FastInitializeDerivedMap(isolate, function, constructor,
                                 constructor_initial_map)) {
      return handle(function->initial_map(), isolate);
    }
  }

  // Slow path, new.target is either a proxy or can't cache the map.
  // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
  // fall back to the intrinsicDefaultProto.
  Handle<Object> prototype;
  if (IsJSFunction(*new_target)) {
    Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
    if (function->has_prototype_slot()) {
      // Make sure the new.target.prototype is cached.
      EnsureHasInitialMap(function);
      prototype = handle(function->prototype(), isolate);
    } else {
      // No prototype property, use the intrinsict default proto further down.
      prototype = isolate->factory()->undefined_value();
    }
  } else {
    Handle<String> prototype_string = isolate->factory()->prototype_string();
    ASSIGN_RETURN_ON_EXCEPTION(
        isolate, prototype,
        JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);
    // The above prototype lookup might change the constructor and its
    // prototype, hence we have to reload the initial map.
    EnsureHasInitialMap(constructor);
    constructor_initial_map = handle(constructor->initial_map(), isolate);
  }

  // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
  // correct realm. Rather than directly fetching the .prototype, we fetch the
  // constructor that points to the .prototype. This relies on
  // constructor.prototype being FROZEN for those constructors.
  if (!IsJSReceiver(*prototype)) {
    Handle<Context> context;
    ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
                               JSReceiver::GetFunctionRealm(new_target), Map);
    DCHECK(IsNativeContext(*context));
    Handle<Object> maybe_index = JSReceiver::GetDataProperty(
        isolate, constructor,
        isolate->factory()->native_context_index_symbol());
    int index = IsSmi(*maybe_index) ? Smi::ToInt(*maybe_index)
                                    : Context::OBJECT_FUNCTION_INDEX;
    Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)),
                                         isolate);
    prototype = handle(realm_constructor->prototype(), isolate);
  }

  Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map);
  map->set_new_target_is_base(false);
  CHECK(IsJSReceiver(*prototype));
  if (map->prototype() != *prototype)
    Map::SetPrototype(isolate, map, Handle<HeapObject>::cast(prototype));
  map->SetConstructor(*constructor);
  return map;
}

namespace {

// Assert that the computations in TypedArrayElementsKindToConstructorIndex and
// TypedArrayElementsKindToRabGsabCtorIndex are sound.
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                         \
  static_assert(Context::TYPE##_ARRAY_FUN_INDEX ==                        \
                Context::FIRST_FIXED_TYPED_ARRAY_FUN_INDEX +              \
                    ElementsKind::TYPE##_ELEMENTS -                       \
                    ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND); \
  static_assert(Context::RAB_GSAB_##TYPE##_ARRAY_MAP_INDEX ==             \
                Context::FIRST_RAB_GSAB_TYPED_ARRAY_MAP_INDEX +           \
                    ElementsKind::TYPE##_ELEMENTS -                       \
                    ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);

TYPED_ARRAYS(TYPED_ARRAY_CASE)
#undef TYPED_ARRAY_CASE

int TypedArrayElementsKindToConstructorIndex(ElementsKind elements_kind) {
  return Context::FIRST_FIXED_TYPED_ARRAY_FUN_INDEX + elements_kind -
         ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
}

int TypedArrayElementsKindToRabGsabCtorIndex(ElementsKind elements_kind) {
  return Context::FIRST_RAB_GSAB_TYPED_ARRAY_MAP_INDEX + elements_kind -
         ElementsKind::FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND;
}

}  // namespace

MaybeHandle<Map> JSFunction::GetDerivedRabGsabTypedArrayMap(
    Isolate* isolate, Handle<JSFunction> constructor,
    Handle<JSReceiver> new_target) {
  MaybeHandle<Map> maybe_map = GetDerivedMap(isolate, constructor, new_target);
  Handle<Map> map;
  if (!maybe_map.ToHandle(&map)) {
    return MaybeHandle<Map>();
  }
  {
    DisallowHeapAllocation no_alloc;
    Tagged<NativeContext> context = isolate->context()->native_context();
    int ctor_index =
        TypedArrayElementsKindToConstructorIndex(map->elements_kind());
    if (*new_target == context->get(ctor_index)) {
      ctor_index =
          TypedArrayElementsKindToRabGsabCtorIndex(map->elements_kind());
      return handle(Map::cast(context->get(ctor_index)), isolate);
    }
  }

  // This only happens when subclassing TypedArrays. Create a new map with the
  // corresponding RAB / GSAB ElementsKind. Note: the map is not cached and
  // reused -> every array gets a unique map, making ICs slow.
  Handle<Map> rab_gsab_map = Map::Copy(isolate, map, "RAB / GSAB");
  rab_gsab_map->set_elements_kind(
      GetCorrespondingRabGsabElementsKind(map->elements_kind()));
  return rab_gsab_map;
}

MaybeHandle<Map> JSFunction::GetDerivedRabGsabDataViewMap(
    Isolate* isolate, Handle<JSReceiver> new_target) {
  Handle<Context> context =
      handle(isolate->context()->native_context(), isolate);
  Handle<JSFunction> constructor = handle(context->data_view_fun(), isolate);
  MaybeHandle<Map> maybe_map = GetDerivedMap(isolate, constructor, new_target);
  Handle<Map> map;
  if (!maybe_map.ToHandle(&map)) {
    return MaybeHandle<Map>();
  }
  if (*map == constructor->initial_map()) {
    return handle(Map::cast(context->js_rab_gsab_data_view_map()), isolate);
  }

  // This only happens when subclassing DataViews. Create a new map with the
  // JS_RAB_GSAB_DATA_VIEW instance type. Note: the map is not cached and
  // reused -> every data view gets a unique map, making ICs slow.
  Handle<Map> rab_gsab_map = Map::Copy(isolate, map, "RAB / GSAB");
  rab_gsab_map->set_instance_type(JS_RAB_GSAB_DATA_VIEW_TYPE);
  return rab_gsab_map;
}

int JSFunction::ComputeInstanceSizeWithMinSlack(Isolate* isolate) {
  CHECK(has_initial_map());
  if (initial_map()->IsInobjectSlackTrackingInProgress()) {
    int slack = initial_map()->ComputeMinObjectSlack(isolate);
    return initial_map()->InstanceSizeFromSlack(slack);
  }
  return initial_map()->instance_size();
}

std::unique_ptr<char[]> JSFunction::DebugNameCStr() {
  return shared()->DebugNameCStr();
}

void JSFunction::PrintName(FILE* out) {
  PrintF(out, "%s", DebugNameCStr().get());
}

namespace {

bool UseFastFunctionNameLookup(Isolate* isolate, Tagged<Map> map) {
  DCHECK(IsJSFunctionMap(map));
  if (map->NumberOfOwnDescriptors() <
      JSFunction::kMinDescriptorsForFastBindAndWrap) {
    return false;
  }
  DCHECK(!map->is_dictionary_map());
  Tagged<HeapObject> value;
  ReadOnlyRoots roots(isolate);
  auto descriptors = map->instance_descriptors(isolate);
  InternalIndex kNameIndex{JSFunction::kNameDescriptorIndex};
  if (descriptors->GetKey(kNameIndex) != roots.name_string() ||
      !descriptors->GetValue(kNameIndex)
           .GetHeapObjectIfStrong(isolate, &value)) {
    return false;
  }
  return IsAccessorInfo(value);
}

}  // namespace

Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
  // Below we use the same fast-path that we already established for
  // Function.prototype.bind(), where we avoid a slow "name" property
  // lookup if the DescriptorArray for the |function| still has the
  // "name" property at the original spot and that property is still
  // implemented via an AccessorInfo (which effectively means that
  // it must be the FunctionNameGetter).
  Isolate* isolate = function->GetIsolate();
  if (!UseFastFunctionNameLookup(isolate, function->map())) {
    // Normally there should be an else case for the fast-path check
    // above, which should invoke JSFunction::GetName(), since that's
    // what the FunctionNameGetter does, however GetDataProperty() has
    // never invoked accessors and thus always returned undefined for
    // JSFunction where the "name" property is untouched, so we retain
    // that exact behavior and go with SharedFunctionInfo::DebugName()
    // in case of the fast-path.
    Handle<Object> name =
        GetDataProperty(isolate, function, isolate->factory()->name_string());
    if (IsString(*name)) return Handle<String>::cast(name);
  }
  return SharedFunctionInfo::DebugName(isolate,
                                       handle(function->shared(), isolate));
}

bool JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
                         Handle<String> prefix) {
  Isolate* isolate = function->GetIsolate();
  Handle<String> function_name;
  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name,
                                   Name::ToFunctionName(isolate, name), false);
  if (prefix->length() > 0) {
    IncrementalStringBuilder builder(isolate);
    builder.AppendString(prefix);
    builder.AppendCharacter(' ');
    builder.AppendString(function_name);
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name, builder.Finish(),
                                     false);
  }
  RETURN_ON_EXCEPTION_VALUE(
      isolate,
      JSObject::DefinePropertyOrElementIgnoreAttributes(
          function, isolate->factory()->name_string(), function_name,
          static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY)),
      false);
  return true;
}

namespace {

Handle<String> NativeCodeFunctionSourceString(
    Isolate* isolate, Handle<SharedFunctionInfo> shared_info) {
  IncrementalStringBuilder builder(isolate);
  builder.AppendCStringLiteral("function ");
  builder.AppendString(handle(shared_info->Name(), isolate));
  builder.AppendCStringLiteral("() { [native code] }");
  return builder.Finish().ToHandleChecked();
}

}  // namespace

// static
Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
  Isolate* const isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);

  // Check if {function} should hide its source code.
  if (!shared_info->IsUserJavaScript()) {
    return NativeCodeFunctionSourceString(isolate, shared_info);
  }

  if (IsClassConstructor(shared_info->kind())) {
    // Check if we should print {function} as a class.
    Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
        isolate, function, isolate->factory()->class_positions_symbol());
    if (IsClassPositions(*maybe_class_positions)) {
      Tagged<ClassPositions> class_positions =
          ClassPositions::cast(*maybe_class_positions);
      int start_position = class_positions->start();
      int end_position = class_positions->end();
      Handle<String> script_source(
          String::cast(Script::cast(shared_info->script())->source()), isolate);
      return isolate->factory()->NewSubString(script_source, start_position,
                                              end_position);
    }
  }

  // Check if we have source code for the {function}.
  if (!shared_info->HasSourceCode()) {
    return NativeCodeFunctionSourceString(isolate, shared_info);
  }

  // If this function was compiled from asm.js, use the recorded offset
  // information.
#if V8_ENABLE_WEBASSEMBLY
  if (shared_info->HasWasmExportedFunctionData()) {
    Handle<WasmExportedFunctionData> function_data(
        shared_info->wasm_exported_function_data(), isolate);
    const wasm::WasmModule* module = function_data->instance()->module();
    if (is_asmjs_module(module)) {
      std::pair<int, int> offsets =
          module->asm_js_offset_information->GetFunctionOffsets(
              declared_function_index(module, function_data->function_index()));
      Handle<String> source(
          String::cast(Script::cast(shared_info->script())->source()), isolate);
      return isolate->factory()->NewSubString(source, offsets.first,
                                              offsets.second);
    }
  }
#endif  // V8_ENABLE_WEBASSEMBLY

  if (shared_info->function_token_position() == kNoSourcePosition) {
    // If the function token position isn't valid, return [native code] to
    // ensure calling eval on the returned source code throws rather than
    // giving inconsistent call behaviour.
    isolate->CountUsage(
        v8::Isolate::UseCounterFeature::kFunctionTokenOffsetTooLongForToString);
    return NativeCodeFunctionSourceString(isolate, shared_info);
  }
  return Handle<String>::cast(
      SharedFunctionInfo::GetSourceCodeHarmony(isolate, shared_info));
}

// static
int JSFunction::CalculateExpectedNofProperties(Isolate* isolate,
                                               Handle<JSFunction> function) {
  int expected_nof_properties = 0;
  for (PrototypeIterator iter(isolate, function, kStartAtReceiver);
       !iter.IsAtEnd(); iter.Advance()) {
    Handle<JSReceiver> current =
        PrototypeIterator::GetCurrent<JSReceiver>(iter);
    if (!IsJSFunction(*current)) break;
    Handle<JSFunction> func = Handle<JSFunction>::cast(current);
    // The super constructor should be compiled for the number of expected
    // properties to be available.
    Handle<SharedFunctionInfo> shared(func->shared(), isolate);
    IsCompiledScope is_compiled_scope(shared->is_compiled_scope(isolate));
    if (is_compiled_scope.is_compiled() ||
        Compiler::Compile(isolate, func, Compiler::CLEAR_EXCEPTION,
                          &is_compiled_scope)) {
      DCHECK(shared->is_compiled());
      int count = shared->expected_nof_properties();
      // Check that the estimate is sensible.
      if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) {
        expected_nof_properties += count;
      } else {
        return JSObject::kMaxInObjectProperties;
      }
    } else {
      // In case there was a compilation error proceed iterating in case there
      // will be a builtin function in the prototype chain that requires
      // certain number of in-object properties.
      continue;
    }
  }
  // Inobject slack tracking will reclaim redundant inobject space
  // later, so we can afford to adjust the estimate generously,
  // meaning we over-allocate by at least 8 slots in the beginning.
  if (expected_nof_properties > 0) {
    expected_nof_properties += 8;
    if (expected_nof_properties > JSObject::kMaxInObjectProperties) {
      expected_nof_properties = JSObject::kMaxInObjectProperties;
    }
  }
  return expected_nof_properties;
}

// static
void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
                                             bool has_prototype_slot,
                                             int requested_embedder_fields,
                                             int requested_in_object_properties,
                                             int* instance_size,
                                             int* in_object_properties) {
  DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
            JSObject::kMaxEmbedderFields);
  int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
  requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;

  int max_nof_fields =
      (JSObject::kMaxInstanceSize - header_size) >> kTaggedSizeLog2;
  CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
  CHECK_LE(static_cast<unsigned>(requested_embedder_fields),
           static_cast<unsigned>(max_nof_fields));
  *in_object_properties = std::min(requested_in_object_properties,
                                   max_nof_fields - requested_embedder_fields);
  *instance_size =
      header_size +
      ((requested_embedder_fields + *in_object_properties) << kTaggedSizeLog2);
  CHECK_EQ(*in_object_properties,
           ((*instance_size - header_size) >> kTaggedSizeLog2) -
               requested_embedder_fields);
  CHECK_LE(static_cast<unsigned>(*instance_size),
           static_cast<unsigned>(JSObject::kMaxInstanceSize));
}

void JSFunction::ClearAllTypeFeedbackInfoForTesting() {
  ResetIfCodeFlushed();
  if (has_feedback_vector()) {
    Tagged<FeedbackVector> vector = feedback_vector();
    Isolate* isolate = GetIsolate();
    if (vector->ClearAllSlotsForTesting(isolate)) {
      IC::OnFeedbackChanged(isolate, vector, FeedbackSlot::Invalid(),
                            "ClearAllTypeFeedbackInfoForTesting");
    }
  }
}

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

Zerion Mini Shell 1.0