Commit 5e244175 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[cleanup] Generate FeedbackVector with Torque

Change FeedbackVector into a Torque-generated class, simplifying its
C++ implementation. As a drive-by, also get rid of the lower-cased,
integer-indexed slot accessors, and replace the calls that needed this
integer index with FeedbackSlot (potentially with a new WithOffset
adjustment for extra data slots).

Change-Id: Ie4f7e99b462ef95419edab46b4ac7ceecae9a05f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2398638
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69749}
parent 98c3f98f
......@@ -2305,8 +2305,8 @@ template <typename TIndex>
TNode<MaybeObject> CodeStubAssembler::LoadFeedbackVectorSlot(
TNode<FeedbackVector> feedback_vector, TNode<TIndex> slot,
int additional_offset) {
int32_t header_size =
FeedbackVector::kFeedbackSlotsOffset + additional_offset - kHeapObjectTag;
int32_t header_size = FeedbackVector::kRawFeedbackSlotsOffset +
additional_offset - kHeapObjectTag;
TNode<IntPtrT> offset =
ElementOffsetFromIndex(slot, HOLEY_ELEMENTS, header_size);
CSA_SLOW_ASSERT(
......@@ -2783,8 +2783,8 @@ void CodeStubAssembler::StoreFeedbackVectorSlot(
DCHECK(barrier_mode == SKIP_WRITE_BARRIER ||
barrier_mode == UNSAFE_SKIP_WRITE_BARRIER ||
barrier_mode == UPDATE_WRITE_BARRIER);
int header_size =
FeedbackVector::kFeedbackSlotsOffset + additional_offset - kHeapObjectTag;
int header_size = FeedbackVector::kRawFeedbackSlotsOffset +
additional_offset - kHeapObjectTag;
TNode<IntPtrT> offset =
ElementOffsetFromIndex(Signed(slot), HOLEY_ELEMENTS, header_size);
// Check that slot <= feedback_vector.length.
......
......@@ -297,8 +297,6 @@ void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
CHECK(handler_table().IsByteArray());
}
USE_TORQUE_VERIFIER(FeedbackVector)
USE_TORQUE_VERIFIER(JSReceiver)
bool JSObject::ElementsAreSafeToExamine(const Isolate* isolate) const {
......
......@@ -950,8 +950,9 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
int entry_size = iter.entry_size();
if (entry_size > 0) os << " {";
for (int i = 0; i < entry_size; i++) {
int index = GetIndex(slot) + i;
os << "\n [" << index << "]: " << Brief(get(index));
FeedbackSlot slot_with_offset = slot.WithOffset(i);
os << "\n [" << slot_with_offset.ToInt()
<< "]: " << Brief(Get(slot_with_offset));
}
if (entry_size > 0) os << "\n }";
}
......
......@@ -723,7 +723,7 @@ void ObjectStatsCollectorImpl::RecordVirtualFeedbackVectorDetails(
// Log the monomorphic/polymorphic helper objects that this slot owns.
for (int i = 0; i < it.entry_size(); i++) {
MaybeObject raw_object = vector.get(slot.ToInt() + i);
MaybeObject raw_object = vector.Get(slot.WithOffset(i));
HeapObject object;
if (raw_object->GetHeapObject(&object)) {
if (object.IsCell() || object.IsWeakFixedArray()) {
......
......@@ -30,7 +30,6 @@ namespace internal {
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackMetadata) \
V(FeedbackVector) \
V(FixedDoubleArray) \
V(JSArrayBuffer) \
V(JSDataView) \
......
......@@ -72,7 +72,8 @@ TNode<MaybeObject> AccessorAssembler::TryMonomorphicCase(
// TODO(ishell): add helper class that hides offset computations for a series
// of loads.
int32_t header_size = FeedbackVector::kFeedbackSlotsOffset - kHeapObjectTag;
int32_t header_size =
FeedbackVector::kRawFeedbackSlotsOffset - kHeapObjectTag;
// Adding |header_size| with a separate IntPtrAdd rather than passing it
// into ElementOffsetFromIndex() allows it to be folded into a single
// [base, index, offset] indirect memory access on x64.
......
......@@ -13,7 +13,7 @@
#include "src/interpreter/bytecode-register-optimizer.h"
#include "src/interpreter/bytecode-source-info.h"
#include "src/interpreter/interpreter-intrinsics.h"
#include "src/objects/objects-inl.h"
#include "src/objects/feedback-vector-inl.h"
#include "src/objects/smi.h"
namespace v8 {
......
......@@ -21,14 +21,13 @@
namespace v8 {
namespace internal {
OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(FeedbackVector)
OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(ClosureFeedbackCellArray, FixedArray)
NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
NEVER_READ_ONLY_SPACE_IMPL(ClosureFeedbackCellArray)
CAST_ACCESSOR(FeedbackVector)
CAST_ACCESSOR(FeedbackMetadata)
CAST_ACCESSOR(ClosureFeedbackCellArray)
......@@ -99,22 +98,7 @@ Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
return handle(FeedbackCell::cast(get(index)), GetIsolate());
}
ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
kSharedFunctionInfoOffset)
WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi,
kOptimizedCodeWeakOrSmiOffset)
ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
kClosureFeedbackCellArrayOffset)
INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
void FeedbackVector::clear_padding() {
if (FIELD_SIZE(kPaddingOffset) == 0) return;
DCHECK_EQ(4, FIELD_SIZE(kPaddingOffset));
memset(reinterpret_cast<void*>(address() + kPaddingOffset), 0,
FIELD_SIZE(kPaddingOffset));
}
void FeedbackVector::clear_padding() { set_padding(0); }
bool FeedbackVector::is_empty() const { return length() == 0; }
......@@ -156,24 +140,12 @@ FeedbackSlot FeedbackVector::ToSlot(intptr_t index) {
}
MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
const Isolate* isolate = GetIsolateForPtrCompr(*this);
return Get(isolate, slot);
return raw_feedback_slots(GetIndex(slot));
}
MaybeObject FeedbackVector::Get(const Isolate* isolate,
FeedbackSlot slot) const {
return get(isolate, GetIndex(slot));
}
MaybeObject FeedbackVector::get(int index) const {
const Isolate* isolate = GetIsolateForPtrCompr(*this);
return get(isolate, index);
}
MaybeObject FeedbackVector::get(const Isolate* isolate, int index) const {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
int offset = OffsetOfElementAt(index);
return RELAXED_READ_WEAK_FIELD(*this, offset);
return raw_feedback_slots(isolate, GetIndex(slot));
}
Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
......@@ -185,28 +157,16 @@ Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
WriteBarrierMode mode) {
set(GetIndex(slot), value, mode);
}
void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
DCHECK_GE(index, 0);
DCHECK_LT(index, this->length());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
set_raw_feedback_slots(GetIndex(slot), value, mode);
}
void FeedbackVector::Set(FeedbackSlot slot, Object value,
WriteBarrierMode mode) {
set(GetIndex(slot), MaybeObject::FromObject(value), mode);
}
void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
set(index, MaybeObject::FromObject(value), mode);
set_raw_feedback_slots(GetIndex(slot), MaybeObject::FromObject(value), mode);
}
inline MaybeObjectSlot FeedbackVector::slots_start() {
return RawMaybeWeakField(kFeedbackSlotsOffset);
return RawMaybeWeakField(OffsetOfElementAt(0));
}
// Helper function to transform the feedback to BinaryOperationHint.
......@@ -334,8 +294,7 @@ MaybeObject FeedbackNexus::GetFeedbackExtra() const {
FeedbackSlotKind kind = vector().GetKind(slot());
DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
#endif
int extra_index = vector().GetIndex(slot()) + 1;
return vector().get(extra_index);
return vector().Get(slot().WithOffset(1));
}
void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
......@@ -354,8 +313,8 @@ void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
#endif
int index = vector().GetIndex(slot()) + 1;
vector().set(index, MaybeObject::FromObject(feedback_extra), mode);
vector().Set(slot().WithOffset(1), MaybeObject::FromObject(feedback_extra),
mode);
}
void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
......@@ -363,8 +322,7 @@ void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
#ifdef DEBUG
FeedbackVector::AssertNoLegacyTypes(feedback_extra);
#endif
int index = vector().GetIndex(slot()) + 1;
vector().set(index, feedback_extra, mode);
vector().Set(slot().WithOffset(1), feedback_extra, mode);
}
Isolate* FeedbackNexus::GetIsolate() const { return vector().GetIsolate(); }
......
......@@ -266,7 +266,6 @@ Handle<FeedbackVector> FeedbackVector::New(
for (int i = 0; i < slot_count;) {
FeedbackSlot slot(i);
FeedbackSlotKind kind = feedback_metadata->GetKind(slot);
int index = FeedbackVector::GetIndex(slot);
int entry_size = FeedbackMetadata::GetSlotSize(kind);
Object extra_value = *uninitialized_sentinel;
......@@ -275,19 +274,19 @@ Handle<FeedbackVector> FeedbackVector::New(
case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict:
vector->set(index, HeapObjectReference::ClearedValue(isolate),
vector->Set(slot, HeapObjectReference::ClearedValue(isolate),
SKIP_WRITE_BARRIER);
break;
case FeedbackSlotKind::kForIn:
case FeedbackSlotKind::kCompareOp:
case FeedbackSlotKind::kBinaryOp:
vector->set(index, Smi::zero(), SKIP_WRITE_BARRIER);
vector->Set(slot, Smi::zero(), SKIP_WRITE_BARRIER);
break;
case FeedbackSlotKind::kLiteral:
vector->set(index, Smi::zero(), SKIP_WRITE_BARRIER);
vector->Set(slot, Smi::zero(), SKIP_WRITE_BARRIER);
break;
case FeedbackSlotKind::kCall:
vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
vector->Set(slot, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
extra_value = Smi::zero();
break;
case FeedbackSlotKind::kCloneObject:
......@@ -303,7 +302,7 @@ Handle<FeedbackVector> FeedbackVector::New(
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kTypeProfile:
case FeedbackSlotKind::kInstanceOf:
vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
vector->Set(slot, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
break;
case FeedbackSlotKind::kInvalid:
......@@ -312,7 +311,7 @@ Handle<FeedbackVector> FeedbackVector::New(
break;
}
for (int j = 1; j < entry_size; j++) {
vector->set(index + j, extra_value, SKIP_WRITE_BARRIER);
vector->Set(slot.WithOffset(j), extra_value, SKIP_WRITE_BARRIER);
}
i += entry_size;
}
......
......@@ -17,6 +17,7 @@
#include "src/objects/name.h"
#include "src/objects/type-hints.h"
#include "src/zone/zone-containers.h"
#include "torque-generated/class-definitions-tq.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -180,39 +181,15 @@ class ClosureFeedbackCellArray : public FixedArray {
// - optimized code cell (weak cell or Smi marker)
// followed by an array of feedback slots, of length determined by the feedback
// metadata.
class FeedbackVector : public HeapObject {
class FeedbackVector
: public TorqueGeneratedFeedbackVector<FeedbackVector, HeapObject> {
public:
NEVER_READ_ONLY_SPACE
DECL_CAST(FeedbackVector)
inline bool is_empty() const;
inline FeedbackMetadata metadata() const;
// [shared_function_info]: The shared function info for the function with this
// feedback vector.
DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
// [optimized_code_weak_or_smi]: weak reference to optimized code or a Smi
// marker defining optimization behaviour.
DECL_ACCESSORS(optimized_code_weak_or_smi, MaybeObject)
// [feedback_cell_array]: The FixedArray to hold the feedback cells for any
// closures created by this function.
DECL_ACCESSORS(closure_feedback_cell_array, ClosureFeedbackCellArray)
// [length]: The length of the feedback vector (not including the header, i.e.
// the number of feedback slots).
DECL_INT32_ACCESSORS(length)
// [invocation_count]: The number of times this function has been invoked.
DECL_INT32_ACCESSORS(invocation_count)
// [profiler_ticks]: The number of times this function has been seen by the
// runtime profiler.
DECL_INT32_ACCESSORS(profiler_ticks)
// Increment profiler ticks, saturating at the maximal value.
void SaturatingIncrementProfilerTicks();
......@@ -242,16 +219,10 @@ class FeedbackVector : public HeapObject {
static inline FeedbackSlot ToSlot(intptr_t index);
inline MaybeObject Get(FeedbackSlot slot) const;
inline MaybeObject Get(const Isolate* isolate, FeedbackSlot slot) const;
inline MaybeObject get(int index) const;
inline MaybeObject get(const Isolate* isolate, int index) const;
inline void Set(FeedbackSlot slot, MaybeObject value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void set(int index, MaybeObject value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void Set(FeedbackSlot slot, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void set(int index, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
// Returns the feedback cell at |index| that is used to create the
// closure.
......@@ -303,7 +274,6 @@ class FeedbackVector : public HeapObject {
V8_EXPORT_PRIVATE static void AssertNoLegacyTypes(MaybeObject object);
DECL_PRINTER(FeedbackVector)
DECL_VERIFIER(FeedbackVector)
void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot); // NOLINT
......@@ -323,28 +293,23 @@ class FeedbackVector : public HeapObject {
// garbage collection (e.g., for patching the cache).
static inline Symbol RawUninitializedSentinel(Isolate* isolate);
// Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_FEEDBACK_VECTOR_FIELDS)
static_assert(kSize % kObjectAlignment == 0,
static_assert(kHeaderSize % kObjectAlignment == 0,
"Header must be padded for alignment");
static const int kFeedbackSlotsOffset = kHeaderSize;
class BodyDescriptor;
static constexpr int OffsetOfElementAt(int index) {
return kFeedbackSlotsOffset + index * kTaggedSize;
return kRawFeedbackSlotsOffset + index * kTaggedSize;
}
// Garbage collection support.
static constexpr int SizeFor(int length) { return OffsetOfElementAt(length); }
TQ_OBJECT_CONSTRUCTORS(FeedbackVector)
private:
static void AddToVectorsForProfilingTools(Isolate* isolate,
Handle<FeedbackVector> vector);
OBJECT_CONSTRUCTORS(FeedbackVector, HeapObject);
// Don't expose the raw feedback slot getter/setter.
using TorqueGeneratedFeedbackVector::raw_feedback_slots;
};
class V8_EXPORT_PRIVATE FeedbackVectorSpec {
......
......@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@generateBodyDescriptor
@generateCppClass
extern class FeedbackVector extends HeapObject {
shared_function_info: SharedFunctionInfo;
optimized_code_weak_or_smi: Weak<Code>|Smi;
closure_feedback_cell_array: FixedArray;
const length: int32;
invocation_count: int32;
profiler_ticks: int32;
......@@ -13,8 +12,10 @@ extern class FeedbackVector extends HeapObject {
// tagged pointers, we should make it conditional; however, platform-specific
// interacts badly with GCMole, so we need to address that first.
padding: uint32;
// TODO(tebbi): The variable-length feedback_slots field should be declared
// here once it is possible to declare tagged slots after untagged slots.
shared_function_info: SharedFunctionInfo;
optimized_code_weak_or_smi: Weak<Code>|Smi;
closure_feedback_cell_array: ClosureFeedbackCellArray;
raw_feedback_slots[length]: MaybeObject;
}
extern class FeedbackMetadata extends HeapObject;
......@@ -188,9 +188,6 @@ VisitorId Map::GetVisitorId(Map map) {
case FEEDBACK_METADATA_TYPE:
return kVisitFeedbackMetadata;
case FEEDBACK_VECTOR_TYPE:
return kVisitFeedbackVector;
case ODDBALL_TYPE:
return kVisitOddball;
......
......@@ -42,7 +42,6 @@ enum InstanceType : uint16_t;
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackVector) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
......
......@@ -10,7 +10,6 @@
#include "src/codegen/reloc-info.h"
#include "src/objects/cell.h"
#include "src/objects/data-handler.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/foreign-inl.h"
#include "src/objects/hash-table.h"
#include "src/objects/js-collection.h"
......@@ -504,29 +503,6 @@ class FeedbackMetadata::BodyDescriptor final : public BodyDescriptorBase {
}
};
class FeedbackVector::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return offset == kSharedFunctionInfoOffset ||
offset == kOptimizedCodeWeakOrSmiOffset ||
offset == kClosureFeedbackCellArrayOffset ||
offset >= kFeedbackSlotsOffset;
}
template <typename ObjectVisitor>
static inline void IterateBody(Map map, HeapObject obj, int object_size,
ObjectVisitor* v) {
IteratePointer(obj, kSharedFunctionInfoOffset, v);
IterateMaybeWeakPointer(obj, kOptimizedCodeWeakOrSmiOffset, v);
IteratePointer(obj, kClosureFeedbackCellArrayOffset, v);
IterateMaybeWeakPointers(obj, kFeedbackSlotsOffset, object_size, v);
}
static inline int SizeOf(Map map, HeapObject obj) {
return FeedbackVector::SizeFor(FeedbackVector::cast(obj).length());
}
};
class PreparseData::BodyDescriptor final : public BodyDescriptorBase {
public:
static bool IsValidSlot(Map map, HeapObject obj, int offset) {
......@@ -978,8 +954,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
p4);
case FEEDBACK_CELL_TYPE:
return Op::template apply<FeedbackCell::BodyDescriptor>(p1, p2, p3, p4);
case FEEDBACK_VECTOR_TYPE:
return Op::template apply<FeedbackVector::BodyDescriptor>(p1, p2, p3, p4);
case COVERAGE_INFO_TYPE:
return Op::template apply<CoverageInfo::BodyDescriptor>(p1, p2, p3, p4);
case WASM_ARRAY_TYPE:
......
......@@ -505,6 +505,10 @@ class FeedbackSlot {
V8_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
FeedbackSlot);
FeedbackSlot WithOffset(int offset) const {
return FeedbackSlot(id_ + offset);
}
private:
static const int kInvalidSlot = -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment