summaryrefslogtreecommitdiff
path: root/deps/v8/src/objects/feedback-vector.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/objects/feedback-vector.h')
-rw-r--r--deps/v8/src/objects/feedback-vector.h217
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