diff options
Diffstat (limited to 'deps/v8/src/objects/feedback-vector.h')
-rw-r--r-- | deps/v8/src/objects/feedback-vector.h | 217 |
1 files changed, 160 insertions, 57 deletions
diff --git a/deps/v8/src/objects/feedback-vector.h b/deps/v8/src/objects/feedback-vector.h index 677ec22457..6c5b9b97ab 100644 --- a/deps/v8/src/objects/feedback-vector.h +++ b/deps/v8/src/objects/feedback-vector.h @@ -17,7 +17,6 @@ #include "src/objects/name.h" #include "src/objects/type-hints.h" #include "src/zone/zone-containers.h" -#include "torque-generated/class-definitions.h" // Has to be the last include (doesn't have include guards): #include "src/objects/object-macros.h" @@ -27,7 +26,7 @@ namespace internal { class IsCompiledScope; -enum class FeedbackSlotKind { +enum class FeedbackSlotKind : uint8_t { // This kind means that the slot points to the middle of other slot // which occupies more than one feedback vector element. // There must be no such slots in the system. @@ -153,6 +152,8 @@ using MaybeObjectHandles = std::vector<MaybeObjectHandle>; class FeedbackMetadata; +#include "torque-generated/src/objects/feedback-vector-tq.inc" + // ClosureFeedbackCellArray is a FixedArray that contains feedback cells used // when creating closures from a function. This is created once the function is // compiled and is either held by the feedback vector (if allocated) or by the @@ -174,6 +175,8 @@ class ClosureFeedbackCellArray : public FixedArray { OBJECT_CONSTRUCTORS(ClosureFeedbackCellArray, FixedArray); }; +class NexusConfig; + // A FeedbackVector has a fixed header with: // - shared function info (which includes feedback metadata) // - invocation count @@ -185,6 +188,20 @@ class FeedbackVector : public TorqueGeneratedFeedbackVector<FeedbackVector, HeapObject> { public: NEVER_READ_ONLY_SPACE + DEFINE_TORQUE_GENERATED_FEEDBACK_VECTOR_FLAGS() + STATIC_ASSERT(OptimizationMarker::kLastOptimizationMarker < + OptimizationMarkerBits::kMax); + STATIC_ASSERT(OptimizationTier::kLastOptimizationTier < + OptimizationTierBits::kMax); + + static constexpr uint32_t kHasCompileOptimizedOrLogFirstExecutionMarker = + kNoneOrInOptimizationQueueMask << OptimizationMarkerBits::kShift; + static constexpr uint32_t kHasNoTopTierCodeOrCompileOptimizedMarkerMask = + kNoneOrMidTierMask << OptimizationTierBits::kShift | + kHasCompileOptimizedOrLogFirstExecutionMarker; + static constexpr uint32_t kHasOptimizedCodeOrCompileOptimizedMarkerMask = + OptimizationTierBits::kMask | + kHasCompileOptimizedOrLogFirstExecutionMarker; inline bool is_empty() const; @@ -193,21 +210,21 @@ class FeedbackVector // Increment profiler ticks, saturating at the maximal value. void SaturatingIncrementProfilerTicks(); - // Initialize the padding if necessary. - inline void clear_padding(); - inline void clear_invocation_count(); inline Code optimized_code() const; - inline OptimizationMarker optimization_marker() const; inline bool has_optimized_code() const; inline bool has_optimization_marker() const; + inline OptimizationMarker optimization_marker() const; + inline OptimizationTier optimization_tier() const; void ClearOptimizedCode(); void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo shared, const char* reason); static void SetOptimizedCode(Handle<FeedbackVector> vector, Handle<Code> code); void SetOptimizationMarker(OptimizationMarker marker); + void ClearOptimizationTier(); + void InitializeOptimizationState(); // Clears the optimization marker in the feedback vector. void ClearOptimizationMarker(); @@ -217,12 +234,15 @@ class FeedbackVector // Conversion from an integer index to the underlying array to a slot. static inline FeedbackSlot ToSlot(intptr_t index); + + inline MaybeObject SynchronizedGet(FeedbackSlot slot) const; + inline void SynchronizedSet(FeedbackSlot slot, MaybeObject value, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + inline void SynchronizedSet(FeedbackSlot slot, Object value, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + inline MaybeObject Get(FeedbackSlot slot) const; - inline MaybeObject Get(const Isolate* isolate, FeedbackSlot slot) const; - inline void Set(FeedbackSlot slot, MaybeObject value, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); - inline void Set(FeedbackSlot slot, Object value, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + inline MaybeObject Get(IsolateRoot isolate, FeedbackSlot slot) const; // Returns the feedback cell at |index| that is used to create the // closure. @@ -271,8 +291,6 @@ class FeedbackVector return GetLanguageModeFromSlotKind(GetKind(slot)); } - V8_EXPORT_PRIVATE static void AssertNoLegacyTypes(MaybeObject object); - DECL_PRINTER(FeedbackVector) void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot); // NOLINT @@ -283,9 +301,6 @@ class FeedbackVector // The object that indicates an uninitialized cache. static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate); - // The object that indicates a generic state. - static inline Handle<Symbol> GenericSentinel(Isolate* isolate); - // The object that indicates a megamorphic state. static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate); @@ -308,26 +323,38 @@ class FeedbackVector static void AddToVectorsForProfilingTools(Isolate* isolate, Handle<FeedbackVector> vector); + // Private for initializing stores in FeedbackVector::New(). + inline void Set(FeedbackSlot slot, MaybeObject value, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + inline void Set(FeedbackSlot slot, Object value, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + +#ifdef DEBUG + // Returns true if value is a non-HashTable FixedArray. We want to + // make sure not to store such objects in the vector. + inline static bool IsOfLegacyType(MaybeObject value); +#endif // DEBUG + + // NexusConfig controls setting slots in the vector. + friend NexusConfig; + // Don't expose the raw feedback slot getter/setter. using TorqueGeneratedFeedbackVector::raw_feedback_slots; }; class V8_EXPORT_PRIVATE FeedbackVectorSpec { public: - explicit FeedbackVectorSpec(Zone* zone) - : slot_kinds_(zone), num_closure_feedback_cells_(0) { + explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { slot_kinds_.reserve(16); } - int slots() const { return static_cast<int>(slot_kinds_.size()); } - int closure_feedback_cells() const { return num_closure_feedback_cells_; } + int slot_count() const { return static_cast<int>(slot_kinds_.size()); } + int create_closure_slot_count() const { return create_closure_slot_count_; } - int AddFeedbackCellForCreateClosure() { - return num_closure_feedback_cells_++; - } + int AddCreateClosureSlot() { return create_closure_slot_count_++; } FeedbackSlotKind GetKind(FeedbackSlot slot) const { - return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt())); + return slot_kinds_.at(slot.ToInt()); } bool HasTypeProfileSlot() const; @@ -428,12 +455,11 @@ class V8_EXPORT_PRIVATE FeedbackVectorSpec { private: FeedbackSlot AddSlot(FeedbackSlotKind kind); - void append(FeedbackSlotKind kind) { - slot_kinds_.push_back(static_cast<unsigned char>(kind)); - } + void append(FeedbackSlotKind kind) { slot_kinds_.push_back(kind); } - ZoneVector<unsigned char> slot_kinds_; - unsigned int num_closure_feedback_cells_; + STATIC_ASSERT(sizeof(FeedbackSlotKind) == sizeof(uint8_t)); + ZoneVector<FeedbackSlotKind> slot_kinds_; + int create_closure_slot_count_ = 0; friend class SharedFeedbackSlot; }; @@ -472,7 +498,7 @@ class FeedbackMetadata : public HeapObject { // int32. // TODO(mythria): Consider using 16 bits for this and slot_count so that we // can save 4 bytes. - DECL_INT32_ACCESSORS(closure_feedback_cell_count) + DECL_INT32_ACCESSORS(create_closure_slot_count) // Get slot_count using an acquire load. inline int32_t synchronized_slot_count() const; @@ -505,9 +531,13 @@ class FeedbackMetadata : public HeapObject { return OBJECT_POINTER_ALIGN(kHeaderSize + length(slot_count) * kInt32Size); } - static const int kSlotCountOffset = HeapObject::kHeaderSize; - static const int kFeedbackCellCountOffset = kSlotCountOffset + kInt32Size; - static const int kHeaderSize = kFeedbackCellCountOffset + kInt32Size; +#define FIELDS(V) \ + V(kSlotCountOffset, kInt32Size) \ + V(kCreateClosureSlotCountOffset, kInt32Size) \ + V(kHeaderSize, 0) + + DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FIELDS) +#undef FIELDS class BodyDescriptor; @@ -587,20 +617,79 @@ class FeedbackMetadataIterator { FeedbackSlotKind slot_kind_; }; -// A FeedbackNexus is the combination of a FeedbackVector and a slot. -class V8_EXPORT_PRIVATE FeedbackNexus final { +// NexusConfig adapts the FeedbackNexus to be used on the main thread +// or a background thread. It controls the actual read and writes of +// the underlying feedback vector, manages the creation of handles, and +// expresses capabilities available in the very different contexts of +// main and background thread. Here are the differences: +// +// Capability: MainThread BackgroundThread +// Write to vector Allowed Not allowed +// Handle creation Via Isolate Via LocalHeap +// Reads of vector "Live" Cached after initial read +// Thread safety Exclusive write, Shared read only +// shared read +class V8_EXPORT_PRIVATE NexusConfig { public: - FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) - : vector_handle_(vector), slot_(slot) { - kind_ = - (vector.is_null()) ? FeedbackSlotKind::kInvalid : vector->GetKind(slot); + static NexusConfig FromMainThread(Isolate* isolate) { + return NexusConfig(isolate); } - FeedbackNexus(FeedbackVector vector, FeedbackSlot slot) - : vector_(vector), slot_(slot) { - kind_ = - (vector.is_null()) ? FeedbackSlotKind::kInvalid : vector.GetKind(slot); + + static NexusConfig FromBackgroundThread(Isolate* isolate, + LocalHeap* local_heap) { + return NexusConfig(isolate, local_heap); + } + + enum Mode { MainThread, BackgroundThread }; + + Mode mode() const { + return local_heap_ == nullptr ? MainThread : BackgroundThread; } + Isolate* isolate() const { return isolate_; } + + MaybeObjectHandle NewHandle(MaybeObject object) const; + template <typename T> + Handle<T> NewHandle(T object) const; + + bool can_write() const { return mode() == MainThread; } + + inline MaybeObject GetFeedback(FeedbackVector vector, + FeedbackSlot slot) const; + inline void SetFeedback(FeedbackVector vector, FeedbackSlot slot, + MaybeObject object, + WriteBarrierMode mode = UPDATE_WRITE_BARRIER) const; + + std::pair<MaybeObject, MaybeObject> GetFeedbackPair(FeedbackVector vector, + FeedbackSlot slot) const; + void SetFeedbackPair(FeedbackVector vector, FeedbackSlot start_slot, + MaybeObject feedback, WriteBarrierMode mode, + MaybeObject feedback_extra, + WriteBarrierMode mode_extra) const; + + private: + explicit NexusConfig(Isolate* isolate) + : isolate_(isolate), local_heap_(nullptr) {} + NexusConfig(Isolate* isolate, LocalHeap* local_heap) + : isolate_(isolate), local_heap_(local_heap) {} + + Isolate* const isolate_; + LocalHeap* const local_heap_; +}; + +// A FeedbackNexus is the combination of a FeedbackVector and a slot. +class V8_EXPORT_PRIVATE FeedbackNexus final { + public: + // For use on the main thread. A null {vector} is accepted as well. + FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot); + FeedbackNexus(FeedbackVector vector, FeedbackSlot slot); + + // For use on the main or background thread as configured by {config}. + // {vector} must be valid. + FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot, + const NexusConfig& config); + + const NexusConfig* config() const { return &config_; } Handle<FeedbackVector> vector_handle() const { DCHECK(vector_.is_null()); return vector_handle_; @@ -608,6 +697,7 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { FeedbackVector vector() const { return vector_handle_.is_null() ? vector_ : *vector_handle_; } + FeedbackSlot slot() const { return slot_; } FeedbackSlotKind kind() const { return kind_; } @@ -624,13 +714,14 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { // For map-based ICs (load, keyed-load, store, keyed-store). Map GetFirstMap() const; - int ExtractMaps(MapHandles* maps) const; // Used to obtain maps and the associated handlers stored in the feedback - // vector. This should be called when we expect only a handler to be sotred in - // the extra feedback. This is used by ICs when updting the handlers. - int ExtractMapsAndHandlers(std::vector<MapAndHandler>* maps_and_handlers, - bool try_update_deprecated = false) const; + // vector. This should be called when we expect only a handler to be stored in + // the extra feedback. This is used by ICs when updating the handlers. + using TryUpdateHandler = std::function<MaybeHandle<Map>(Handle<Map>)>; + int ExtractMapsAndHandlers( + std::vector<MapAndHandler>* maps_and_handlers, + TryUpdateHandler map_handler = TryUpdateHandler()) const; MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const; // Used to obtain maps and the associated feedback stored in the feedback // vector. The returned feedback need not be always a handler. It could be a @@ -654,6 +745,7 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { inline MaybeObject GetFeedback() const; inline MaybeObject GetFeedbackExtra() const; + inline std::pair<MaybeObject, MaybeObject> GetFeedbackPair() const; inline Isolate* GetIsolate() const; @@ -726,19 +818,25 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { std::vector<int> GetSourcePositions() const; std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const; - inline void SetFeedback(Object feedback, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); - inline void SetFeedback(MaybeObject feedback, + private: + template <typename FeedbackType> + inline void SetFeedback(FeedbackType feedback, WriteBarrierMode mode = UPDATE_WRITE_BARRIER); - inline void SetFeedbackExtra(Object feedback_extra, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); - inline void SetFeedbackExtra(MaybeObject feedback_extra, - WriteBarrierMode mode = UPDATE_WRITE_BARRIER); + template <typename FeedbackType, typename FeedbackExtraType> + inline void SetFeedback(FeedbackType feedback, WriteBarrierMode mode, + FeedbackExtraType feedback_extra, + WriteBarrierMode mode_extra = UPDATE_WRITE_BARRIER); + + inline MaybeObject UninitializedSentinel() const; + inline MaybeObject MegamorphicSentinel() const; // Create an array. The caller must install it in a feedback vector slot. Handle<WeakFixedArray> CreateArrayOfSize(int length); - private: + // Helpers to maintain feedback_cache_. + inline MaybeObject FromHandle(MaybeObjectHandle slot) const; + inline MaybeObjectHandle ToHandle(MaybeObject value) const; + // The reason for having a vector handle and a raw pointer is that we can and // should use handles during IC miss, but not during GC when we clear ICs. If // you have a handle to the vector that is better because more operations can @@ -747,6 +845,11 @@ class V8_EXPORT_PRIVATE FeedbackNexus final { FeedbackVector vector_; FeedbackSlot slot_; FeedbackSlotKind kind_; + // When using the background-thread configuration, a cache is used to + // guarantee a consistent view of the feedback to FeedbackNexus methods. + mutable base::Optional<std::pair<MaybeObjectHandle, MaybeObjectHandle>> + feedback_cache_; + NexusConfig config_; }; class V8_EXPORT_PRIVATE FeedbackIterator final { @@ -788,7 +891,7 @@ class V8_EXPORT_PRIVATE FeedbackIterator final { inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback); inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback); -inline ForInHint ForInHintFromFeedback(int type_feedback); +inline ForInHint ForInHintFromFeedback(ForInFeedback type_feedback); } // namespace internal } // namespace v8 |