chromium/v8/src/ic/ic.cc

// Copyright 2012 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/ic/ic.h"

#include <optional>
#include <tuple>

#include "src/api/api-arguments-inl.h"
#include "src/ast/ast.h"
#include "src/base/logging.h"
#include "src/builtins/accessors.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/execution/arguments-inl.h"
#include "src/execution/execution.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
#include "src/execution/isolate.h"
#include "src/execution/protectors-inl.h"
#include "src/execution/tiering-manager.h"
#include "src/handles/handles-inl.h"
#include "src/handles/maybe-handles.h"
#include "src/ic/call-optimization.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/ic/handler-configuration.h"
#include "src/ic/ic-inl.h"
#include "src/ic/ic-stats.h"
#include "src/ic/stub-cache.h"
#include "src/numbers/conversions.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/field-type.h"
#include "src/objects/instance-type.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/megadom-handler.h"
#include "src/objects/property-descriptor.h"
#include "src/objects/prototype.h"
#include "src/runtime/runtime.h"
#include "src/tracing/trace-event.h"
#include "src/tracing/tracing-category-observer.h"
#include "src/utils/ostreams.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/struct-types.h"
#endif  // V8_ENABLE_WEBASSEMBLY

namespace v8 {
namespace internal {

// Aliases to avoid having to repeat the class.
// With C++20 we can use "using" to introduce scoped enums.
constexpr InlineCacheState NO_FEEDBACK =;
constexpr InlineCacheState UNINITIALIZED =;
constexpr InlineCacheState MONOMORPHIC =;
constexpr InlineCacheState RECOMPUTE_HANDLER =;
constexpr InlineCacheState POLYMORPHIC =;
constexpr InlineCacheState MEGAMORPHIC =;
constexpr InlineCacheState MEGADOM =;
constexpr InlineCacheState GENERIC =;

char IC::TransitionMarkFromState(IC::State state) {}

namespace {

const char* GetModifier(KeyedAccessLoadMode mode) {}

const char* GetModifier(KeyedAccessStoreMode mode) {}

}  // namespace

void IC::TraceIC(const char* type, DirectHandle<Object> name) {}

void IC::TraceIC(const char* type, DirectHandle<Object> name, State old_state,
                 State new_state) {}

IC::IC(Isolate* isolate, Handle<FeedbackVector> vector, FeedbackSlot slot,
       FeedbackSlotKind kind)
    :{}

static void LookupForRead(LookupIterator* it, bool is_has_property) {}

bool IC::ShouldRecomputeHandler(DirectHandle<String> name) {}

bool IC::RecomputeHandlerForName(DirectHandle<Object> name) {}

void IC::UpdateState(DirectHandle<Object> lookup_start_object,
                     Handle<Object> name) {}

MaybeHandle<Object> IC::TypeError(MessageTemplate index, Handle<Object> object,
                                  Handle<Object> key) {}

MaybeHandle<Object> IC::ReferenceError(Handle<Name> name) {}

void IC::OnFeedbackChanged(const char* reason) {}

// static
void IC::OnFeedbackChanged(Isolate* isolate, Tagged<FeedbackVector> vector,
                           FeedbackSlot slot, const char* reason) {}

namespace {

bool MigrateDeprecated(Isolate* isolate, Handle<Object> object) {}

}  // namespace

bool IC::ConfigureVectorState(IC::State new_state, DirectHandle<Object> key) {}

void IC::ConfigureVectorState(Handle<Name> name, DirectHandle<Map> map,
                              Handle<Object> handler) {}

void IC::ConfigureVectorState(Handle<Name> name, DirectHandle<Map> map,
                              const MaybeObjectHandle& handler) {}

void IC::ConfigureVectorState(Handle<Name> name, MapHandlesSpan maps,
                              MaybeObjectHandles* handlers) {}

void IC::ConfigureVectorState(
    Handle<Name> name, std::vector<MapAndHandler> const& maps_and_handlers) {}

MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name,
                                 bool update_feedback,
                                 Handle<Object> receiver) {}

MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name,
                                       bool update_feedback) {}

namespace {

bool AddOneReceiverMapIfMissing(MapHandles* receiver_maps,
                                Handle<Map> new_receiver_map) {}

bool AddOneReceiverMapIfMissing(
    std::vector<MapAndHandler>* receiver_maps_and_handlers,
    Handle<Map> new_receiver_map) {}

Handle<NativeContext> GetAccessorContext(
    const CallOptimization& call_optimization, Tagged<Map> holder_map,
    Isolate* isolate) {}

}  // namespace

bool IC::UpdateMegaDOMIC(const MaybeObjectHandle& handler,
                         DirectHandle<Name> name) {}

bool IC::UpdatePolymorphicIC(Handle<Name> name,
                             const MaybeObjectHandle& handler) {}

void IC::UpdateMonomorphicIC(const MaybeObjectHandle& handler,
                             Handle<Name> name) {}

void IC::CopyICToMegamorphicCache(DirectHandle<Name> name) {}

bool IC::IsTransitionOfMonomorphicTarget(Tagged<Map> source_map,
                                         Tagged<Map> target_map) {}

void IC::SetCache(Handle<Name> name, Handle<Object> handler) {}

void IC::SetCache(Handle<Name> name, const MaybeObjectHandle& handler) {}

void LoadIC::UpdateCaches(LookupIterator* lookup) {}

StubCache* IC::stub_cache() {}

void IC::UpdateMegamorphicCache(DirectHandle<Map> map, DirectHandle<Name> name,
                                const MaybeObjectHandle& handler) {}

MaybeObjectHandle LoadIC::ComputeHandler(LookupIterator* lookup) {}

KeyedAccessLoadMode KeyedLoadIC::GetKeyedAccessLoadModeFor(
    DirectHandle<Map> receiver_map) const {}

// Returns whether the load mode transition is allowed.
bool AllowedHandlerChange(KeyedAccessLoadMode old_mode,
                          KeyedAccessLoadMode new_mode) {}

void KeyedLoadIC::UpdateLoadElement(Handle<HeapObject> receiver,
                                    const KeyedAccessLoadMode new_load_mode) {}

namespace {

bool AllowConvertHoleElementToUndefined(Isolate* isolate,
                                        DirectHandle<Map> receiver_map) {}

bool IsOutOfBoundsAccess(DirectHandle<Object> receiver, size_t index) {}

bool AllowReadingHoleElement(ElementsKind elements_kind) {}

KeyedAccessLoadMode GetNewKeyedLoadMode(Isolate* isolate,
                                        Handle<HeapObject> receiver,
                                        size_t index, bool is_found) {}

KeyedAccessLoadMode GetUpdatedLoadModeForMap(Isolate* isolate,
                                             DirectHandle<Map> map,
                                             KeyedAccessLoadMode load_mode) {}

}  // namespace

Handle<Object> KeyedLoadIC::LoadElementHandler(
    DirectHandle<Map> receiver_map, KeyedAccessLoadMode new_load_mode) {}

void KeyedLoadIC::LoadElementPolymorphicHandlers(
    MapHandles* receiver_maps, MaybeObjectHandles* handlers,
    KeyedAccessLoadMode new_load_mode) {}

namespace {

enum KeyType {};

// The cases where kIntPtr is returned must match what
// CodeStubAssembler::TryToIntptr can handle!
KeyType TryConvertKey(Handle<Object> key, Isolate* isolate, intptr_t* index_out,
                      Handle<Name>* name_out) {}

bool IntPtrKeyToSize(intptr_t index, DirectHandle<HeapObject> receiver,
                     size_t* out) {}

bool CanCache(DirectHandle<Object> receiver, InlineCacheState state) {}

}  // namespace

MaybeHandle<Object> KeyedLoadIC::RuntimeLoad(Handle<Object> object,
                                             Handle<Object> key,
                                             bool* is_found) {}

MaybeHandle<Object> KeyedLoadIC::LoadName(Handle<Object> object,
                                          DirectHandle<Object> key,
                                          Handle<Name> name) {}

MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
                                      Handle<Object> key) {}

bool StoreIC::LookupForWrite(LookupIterator* it, DirectHandle<Object> value,
                             StoreOrigin store_origin) {}

MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
                                         Handle<Object> value) {}

namespace {
Maybe<bool> DefineOwnDataProperty(LookupIterator* it,
                                  LookupIterator::State original_state,
                                  Handle<JSAny> value,
                                  Maybe<ShouldThrow> should_throw,
                                  StoreOrigin store_origin) {}
}  // namespace

MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
                                   Handle<Object> value,
                                   StoreOrigin store_origin) {}

void StoreIC::UpdateCaches(LookupIterator* lookup, DirectHandle<Object> value,
                           StoreOrigin store_origin) {}

MaybeObjectHandle StoreIC::ComputeHandler(LookupIterator* lookup) {}

void KeyedStoreIC::UpdateStoreElement(Handle<Map> receiver_map,
                                      KeyedAccessStoreMode store_mode,
                                      Handle<Map> new_receiver_map) {}

Handle<Object> KeyedStoreIC::StoreElementHandler(
    DirectHandle<Map> receiver_map, KeyedAccessStoreMode store_mode,
    MaybeHandle<UnionOf<Smi, Cell>> prev_validity_cell) {}

void KeyedStoreIC::StoreElementPolymorphicHandlers(
    std::vector<MapAndHandler>* receiver_maps_and_handlers,
    KeyedAccessStoreMode store_mode) {}

namespace {

bool MayHaveTypedArrayInPrototypeChain(DirectHandle<JSObject> object) {}

KeyedAccessStoreMode GetStoreMode(DirectHandle<JSObject> receiver,
                                  size_t index) {}

}  // namespace

MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
                                        Handle<Object> key,
                                        Handle<Object> value) {}

namespace {
Maybe<bool> StoreOwnElement(Isolate* isolate, Handle<JSArray> array,
                            Handle<Object> index, Handle<Object> value) {}
}  // namespace

MaybeHandle<Object> StoreInArrayLiteralIC::Store(Handle<JSArray> array,
                                                 Handle<Object> index,
                                                 Handle<Object> value) {}

// ----------------------------------------------------------------------------
// Static IC stub generators.
//
//
RUNTIME_FUNCTION(Runtime_LoadIC_Miss) {}

RUNTIME_FUNCTION(Runtime_LoadNoFeedbackIC_Miss) {}

RUNTIME_FUNCTION(Runtime_LoadWithReceiverNoFeedbackIC_Miss) {}

RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) {}

RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) {}

RUNTIME_FUNCTION(Runtime_LoadWithReceiverIC_Miss) {}

RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) {}

RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {}

RUNTIME_FUNCTION(Runtime_DefineNamedOwnIC_Miss) {}

RUNTIME_FUNCTION(Runtime_DefineNamedOwnIC_Slow) {}

RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Miss) {}

RUNTIME_FUNCTION(Runtime_StoreGlobalICNoFeedback_Miss) {}

// TODO(mythria): Remove Feedback vector and slot. Since they are not used apart
// from the DCHECK.
RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {}

RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {}

RUNTIME_FUNCTION(Runtime_DefineKeyedOwnIC_Miss) {}

RUNTIME_FUNCTION(Runtime_StoreInArrayLiteralIC_Miss) {}

RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) {}

RUNTIME_FUNCTION(Runtime_DefineKeyedOwnIC_Slow) {}

RUNTIME_FUNCTION(Runtime_StoreInArrayLiteralIC_Slow) {}

RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) {}

namespace {

enum class FastCloneObjectMode {};

FastCloneObjectMode GetCloneModeForMapPreCheck(DirectHandle<Map> map,
                                               bool null_proto_literal,
                                               Isolate* isolate) {}

FastCloneObjectMode GetCloneModeForMap(DirectHandle<Map> map,
                                       bool null_proto_literal,
                                       Isolate* isolate) {}

bool CanCacheCloneTargetMapTransition(
    DirectHandle<Map> source_map, std::optional<DirectHandle<Map>> target_map,
    bool null_proto_literal, Isolate* isolate) {}

// Check if an object with `source_map` can be cloned by `FastCloneJSObject`
// when the result shall have `target_map`. Optionally `override_map` is the map
// of an already existing object that will be written into. If no `override_map`
// is given, we assume that a fresh target object can be allocated with
// already the correct `target_map`.
bool CanFastCloneObjectToObjectLiteral(DirectHandle<Map> source_map,
                                       DirectHandle<Map> target_map,
                                       DirectHandle<Map> override_map,
                                       bool null_proto_literal,
                                       Isolate* isolate) {}

}  // namespace

static MaybeHandle<JSObject> CloneObjectSlowPath(Isolate* isolate,
                                                 Handle<Object> source,
                                                 int flags) {}

RUNTIME_FUNCTION(Runtime_CloneObjectIC_Slow) {}

namespace {

template <SideStepTransition::Kind kind>
Tagged<Object> GetCloneTargetMap(Isolate* isolate, DirectHandle<Map> source_map,
                                 DirectHandle<Map> override_map) {}

template <SideStepTransition::Kind kind>
void SetCloneTargetMap(Isolate* isolate, Handle<Map> source_map,
                       DirectHandle<Map> new_target_map,
                       DirectHandle<Map> override_map) {}

template <SideStepTransition::Kind kind>
void SetCloneTargetMapUnsupported(Isolate* isolate, Handle<Map> source_map,
                                  DirectHandle<Map> override_map) {}

}  // namespace

RUNTIME_FUNCTION(Runtime_CloneObjectIC_Miss) {}

RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {}

namespace {

bool MaybeCanCloneObjectForObjectAssign(Handle<JSReceiver> source,
                                        DirectHandle<Map> source_map,
                                        Handle<JSReceiver> target,
                                        Isolate* isolate) {}

}  // namespace

// Returns one of:
// * A map to be used with FastCloneJSObject
// * Undefined if fast cloning is not possible
// * True if assignment must be skipped (i.e., the runtime already did it)
RUNTIME_FUNCTION(Runtime_ObjectAssignTryFastcase) {}

/**
 * Loads a property with an interceptor performing post interceptor
 * lookup if interceptor failed.
 */
RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptor) {}

RUNTIME_FUNCTION(Runtime_StorePropertyWithInterceptor) {}

RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {}

RUNTIME_FUNCTION(Runtime_KeyedHasIC_Miss) {}

RUNTIME_FUNCTION(Runtime_HasElementWithInterceptor) {}

}  // namespace internal
}  // namespace v8