// Copyright 2016 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_IC_HANDLER_CONFIGURATION_H_ #define V8_IC_HANDLER_CONFIGURATION_H_ #include "src/common/globals.h" #include "src/handles/maybe-handles.h" #include "src/objects/data-handler.h" #include "src/objects/elements-kind.h" #include "src/objects/field-index.h" #include "src/objects/objects.h" #include "src/utils/utils.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" namespace v8 { namespace internal { class JSProxy; // A set of bit fields representing Smi handlers for loads and a HeapObject // that represents load handlers that can't be encoded in a Smi. // TODO(ishell): move to load-handler.h class LoadHandler final : public DataHandler { public: DECL_CAST(LoadHandler) DECL_PRINTER(LoadHandler) DECL_VERIFIER(LoadHandler) enum Kind { kElement, kIndexedString, kNormal, kGlobal, kField, kConstantFromPrototype, kAccessor, kNativeDataProperty, kApiGetter, kApiGetterHolderIsPrototype, kInterceptor, kSlow, kProxy, kNonExistent, kModuleExport }; using KindBits = BitField; // Defines whether access rights check should be done on receiver object. // Applicable to named property kinds only when loading value from prototype // chain. Ignored when loading from holder. using DoAccessCheckOnReceiverBits = KindBits::Next; // Defines whether a lookup should be done on receiver object before // proceeding to the prototype chain. Applicable to named property kinds only // when loading value from prototype chain. Ignored when loading from holder. using LookupOnReceiverBits = DoAccessCheckOnReceiverBits::Next; // // Encoding when KindBits contains kForConstants. // // Index of a value entry in the descriptor array. using DescriptorBits = LookupOnReceiverBits::Next; // Make sure we don't overflow the smi. STATIC_ASSERT(DescriptorBits::kLastUsedBit < kSmiValueSize); // // Encoding when KindBits contains kField. // using IsInobjectBits = LookupOnReceiverBits::Next; using IsDoubleBits = IsInobjectBits::Next; // +1 here is to cover all possible JSObject header sizes. using FieldIndexBits = IsDoubleBits::Next; // Make sure we don't overflow the smi. STATIC_ASSERT(FieldIndexBits::kLastUsedBit < kSmiValueSize); // // Encoding when KindBits contains kElement or kIndexedString. // using AllowOutOfBoundsBits = LookupOnReceiverBits::Next; // // Encoding when KindBits contains kElement. // using IsJsArrayBits = AllowOutOfBoundsBits::Next; using ConvertHoleBits = IsJsArrayBits::Next; using ElementsKindBits = ConvertHoleBits::Next; // Make sure we don't overflow the smi. STATIC_ASSERT(ElementsKindBits::kLastUsedBit < kSmiValueSize); // // Encoding when KindBits contains kModuleExport. // using ExportsIndexBits = LookupOnReceiverBits::Next< unsigned, kSmiValueSize - LookupOnReceiverBits::kLastUsedBit - 1>; // Decodes kind from Smi-handler. static inline Kind GetHandlerKind(Smi smi_handler); // Creates a Smi-handler for loading a property from a slow object. static inline Handle LoadNormal(Isolate* isolate); // Creates a Smi-handler for loading a property from a global object. static inline Handle LoadGlobal(Isolate* isolate); // Creates a Smi-handler for loading a property from an object with an // interceptor. static inline Handle LoadInterceptor(Isolate* isolate); // Creates a Smi-handler for loading a property from a object. static inline Handle LoadSlow(Isolate* isolate); // Creates a Smi-handler for loading a field from fast object. static inline Handle LoadField(Isolate* isolate, FieldIndex field_index); // Creates a Smi-handler for loading a cached constant from fast // prototype object. static inline Handle LoadConstantFromPrototype(Isolate* isolate); // Creates a Smi-handler for calling a getter on a fast object. static inline Handle LoadAccessor(Isolate* isolate, int descriptor); // Creates a Smi-handler for calling a getter on a proxy. static inline Handle LoadProxy(Isolate* isolate); // Creates a Smi-handler for loading a native data property from fast object. static inline Handle LoadNativeDataProperty(Isolate* isolate, int descriptor); // Creates a Smi-handler for calling a native getter on a fast object. static inline Handle LoadApiGetter(Isolate* isolate, bool holder_is_receiver); // Creates a Smi-handler for loading a Module export. // |index| is the index to the "value" slot in the Module's "exports" // dictionary. static inline Handle LoadModuleExport(Isolate* isolate, int index); // Creates a data handler that represents a load of a non-existent property. // {holder} is the object from which the property is loaded. If no holder is // needed (e.g., for "nonexistent"), null_value() may be passed in. static Handle LoadFullChain(Isolate* isolate, Handle receiver_map, const MaybeObjectHandle& holder, Handle smi_handler); // Creates a data handler that represents a prototype chain check followed // by given Smi-handler that encoded a load from the holder. // Can be used only if GetPrototypeCheckCount() returns non negative value. static Handle LoadFromPrototype( Isolate* isolate, Handle receiver_map, Handle holder, Handle smi_handler, MaybeObjectHandle maybe_data1 = MaybeObjectHandle(), MaybeObjectHandle maybe_data2 = MaybeObjectHandle()); // Creates a Smi-handler for loading a non-existent property. Works only as // a part of prototype chain check. static inline Handle LoadNonExistent(Isolate* isolate); // Creates a Smi-handler for loading an element. static inline Handle LoadElement(Isolate* isolate, ElementsKind elements_kind, bool convert_hole_to_undefined, bool is_js_array, KeyedAccessLoadMode load_mode); // Creates a Smi-handler for loading from a String. static inline Handle LoadIndexedString(Isolate* isolate, KeyedAccessLoadMode load_mode); // Decodes the KeyedAccessLoadMode from a {handler}. static KeyedAccessLoadMode GetKeyedAccessLoadMode(MaybeObject handler); OBJECT_CONSTRUCTORS(LoadHandler, DataHandler); }; // A set of bit fields representing Smi handlers for stores and a HeapObject // that represents store handlers that can't be encoded in a Smi. // TODO(ishell): move to store-handler.h class StoreHandler final : public DataHandler { public: DECL_CAST(StoreHandler) DECL_PRINTER(StoreHandler) DECL_VERIFIER(StoreHandler) enum Kind { kElement, kField, kConstField, kAccessor, kNativeDataProperty, kApiSetter, kApiSetterHolderIsPrototype, kGlobalProxy, kNormal, kInterceptor, kSlow, kProxy, kKindsNumber // Keep last }; using KindBits = BitField; // Applicable to kGlobalProxy, kProxy kinds. // Defines whether access rights check should be done on receiver object. using DoAccessCheckOnReceiverBits = KindBits::Next; // Defines whether a lookup should be done on receiver object before // proceeding to the prototype chain. Applicable to named property kinds only // when storing through prototype chain. Ignored when storing to holder. using LookupOnReceiverBits = DoAccessCheckOnReceiverBits::Next; // Applicable to kField, kTransitionToField and kTransitionToConstant // kinds. // Index of a value entry in the descriptor array. using DescriptorBits = LookupOnReceiverBits::Next; // // Encoding when KindBits contains kTransitionToConstant. // // Make sure we don't overflow the smi. STATIC_ASSERT(DescriptorBits::kLastUsedBit < kSmiValueSize); // // Encoding when KindBits contains kField or kTransitionToField. // using IsInobjectBits = DescriptorBits::Next; using RepresentationBits = IsInobjectBits::Next; // +1 here is to cover all possible JSObject header sizes. using FieldIndexBits = RepresentationBits::Next; // Make sure we don't overflow the smi. STATIC_ASSERT(FieldIndexBits::kLastUsedBit < kSmiValueSize); // Creates a Smi-handler for storing a field to fast object. static inline Handle StoreField(Isolate* isolate, int descriptor, FieldIndex field_index, PropertyConstness constness, Representation representation); static MaybeObjectHandle StoreTransition(Isolate* isolate, Handle transition_map); // Creates a Smi-handler for storing a native data property on a fast object. static inline Handle StoreNativeDataProperty(Isolate* isolate, int descriptor); // Creates a Smi-handler for calling a setter on a fast object. static inline Handle StoreAccessor(Isolate* isolate, int descriptor); // Creates a Smi-handler for calling a native setter on a fast object. static inline Handle StoreApiSetter(Isolate* isolate, bool holder_is_receiver); static Handle StoreThroughPrototype( Isolate* isolate, Handle receiver_map, Handle holder, Handle smi_handler, MaybeObjectHandle maybe_data1 = MaybeObjectHandle(), MaybeObjectHandle maybe_data2 = MaybeObjectHandle()); static Handle StoreElementTransition(Isolate* isolate, Handle receiver_map, Handle transition, KeyedAccessStoreMode store_mode); static Handle StoreProxy(Isolate* isolate, Handle receiver_map, Handle proxy, Handle receiver); // Creates a handler for storing a property to the property cell of a global // object. static MaybeObjectHandle StoreGlobal(Handle cell); // Creates a Smi-handler for storing a property to a global proxy object. static inline Handle StoreGlobalProxy(Isolate* isolate); // Creates a Smi-handler for storing a property to a slow object. static inline Handle StoreNormal(Isolate* isolate); // Creates a Smi-handler for storing a property to an interceptor. static inline Handle StoreInterceptor(Isolate* isolate); // Creates a Smi-handler for storing a property. static inline Handle StoreSlow(Isolate* isolate); // Creates a Smi-handler for storing a property on a proxy. static inline Handle StoreProxy(Isolate* isolate); private: static inline Handle StoreField(Isolate* isolate, Kind kind, int descriptor, FieldIndex field_index, Representation representation); OBJECT_CONSTRUCTORS(StoreHandler, DataHandler); }; } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_IC_HANDLER_CONFIGURATION_H_