Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_FEEDBACK_VECTOR_H_
6 : #define V8_FEEDBACK_VECTOR_H_
7 :
8 : #include <vector>
9 :
10 : #include "src/base/logging.h"
11 : #include "src/base/macros.h"
12 : #include "src/elements-kind.h"
13 : #include "src/globals.h"
14 : #include "src/objects/map.h"
15 : #include "src/objects/name.h"
16 : #include "src/type-hints.h"
17 : #include "src/zone/zone-containers.h"
18 :
19 : // Has to be the last include (doesn't have include guards):
20 : #include "src/objects/object-macros.h"
21 :
22 : namespace v8 {
23 : namespace internal {
24 :
25 : enum class FeedbackSlotKind {
26 : // This kind means that the slot points to the middle of other slot
27 : // which occupies more than one feedback vector element.
28 : // There must be no such slots in the system.
29 : kInvalid,
30 :
31 : // Sloppy kinds come first, for easy language mode testing.
32 : kStoreGlobalSloppy,
33 : kStoreNamedSloppy,
34 : kStoreKeyedSloppy,
35 : kLastSloppyKind = kStoreKeyedSloppy,
36 :
37 : // Strict and language mode unaware kinds.
38 : kCall,
39 : kLoadProperty,
40 : kLoadGlobalNotInsideTypeof,
41 : kLoadGlobalInsideTypeof,
42 : kLoadKeyed,
43 : kHasKeyed,
44 : kStoreGlobalStrict,
45 : kStoreNamedStrict,
46 : kStoreOwnNamed,
47 : kStoreKeyedStrict,
48 : kStoreInArrayLiteral,
49 : kBinaryOp,
50 : kCompareOp,
51 : kStoreDataPropertyInLiteral,
52 : kTypeProfile,
53 : kLiteral,
54 : kForIn,
55 : kInstanceOf,
56 : kCloneObject,
57 :
58 : kKindsNumber // Last value indicating number of kinds.
59 : };
60 :
61 : inline bool IsCallICKind(FeedbackSlotKind kind) {
62 : return kind == FeedbackSlotKind::kCall;
63 : }
64 :
65 : inline bool IsLoadICKind(FeedbackSlotKind kind) {
66 : return kind == FeedbackSlotKind::kLoadProperty;
67 : }
68 :
69 : inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
70 10576422 : return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
71 : kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
72 : }
73 :
74 : inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
75 : return kind == FeedbackSlotKind::kLoadKeyed;
76 : }
77 :
78 : inline bool IsKeyedHasICKind(FeedbackSlotKind kind) {
79 3671708 : return kind == FeedbackSlotKind::kHasKeyed;
80 : }
81 :
82 : inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
83 7774358 : return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
84 7774358 : kind == FeedbackSlotKind::kStoreGlobalStrict;
85 : }
86 :
87 : inline bool IsStoreICKind(FeedbackSlotKind kind) {
88 : return kind == FeedbackSlotKind::kStoreNamedSloppy ||
89 : kind == FeedbackSlotKind::kStoreNamedStrict;
90 : }
91 :
92 : inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
93 : return kind == FeedbackSlotKind::kStoreOwnNamed;
94 : }
95 :
96 : inline bool IsStoreDataPropertyInLiteralKind(FeedbackSlotKind kind) {
97 : return kind == FeedbackSlotKind::kStoreDataPropertyInLiteral;
98 : }
99 :
100 : inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
101 3446269 : return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
102 3446269 : kind == FeedbackSlotKind::kStoreKeyedStrict;
103 : }
104 :
105 : inline bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind) {
106 : return kind == FeedbackSlotKind::kStoreInArrayLiteral;
107 : }
108 :
109 : inline bool IsGlobalICKind(FeedbackSlotKind kind) {
110 : return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
111 : }
112 :
113 : inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
114 : return kind == FeedbackSlotKind::kTypeProfile;
115 : }
116 :
117 : inline bool IsCloneObjectKind(FeedbackSlotKind kind) {
118 : return kind == FeedbackSlotKind::kCloneObject;
119 : }
120 :
121 : inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
122 : DCHECK(IsLoadGlobalICKind(kind));
123 : return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
124 : ? INSIDE_TYPEOF
125 : : NOT_INSIDE_TYPEOF;
126 : }
127 :
128 : inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
129 : DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
130 : IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
131 : STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
132 : FeedbackSlotKind::kLastSloppyKind);
133 : STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
134 : FeedbackSlotKind::kLastSloppyKind);
135 : STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
136 : FeedbackSlotKind::kLastSloppyKind);
137 : return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy
138 319234 : : LanguageMode::kStrict;
139 : }
140 :
141 : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
142 : FeedbackSlotKind kind);
143 :
144 : typedef std::vector<MaybeObjectHandle> MaybeObjectHandles;
145 :
146 : class FeedbackMetadata;
147 :
148 : // ClosureFeedbackCellArray is a FixedArray that contains feedback cells used
149 : // when creating closures from a function. Along with the feedback
150 : // cells, the first slot (slot 0) is used to hold a budget to measure the
151 : // hotness of the function. This is created once the function is compiled and is
152 : // either held by the feedback vector (if allocated) or by the FeedbackCell of
153 : // the closure.
154 : class ClosureFeedbackCellArray : public FixedArray {
155 : public:
156 : NEVER_READ_ONLY_SPACE
157 :
158 : DECL_CAST(ClosureFeedbackCellArray)
159 :
160 : V8_EXPORT_PRIVATE static Handle<ClosureFeedbackCellArray> New(
161 : Isolate* isolate, Handle<SharedFunctionInfo> shared);
162 : inline Handle<FeedbackCell> GetFeedbackCell(int index);
163 :
164 : DECL_VERIFIER(ClosureFeedbackCellArray)
165 : DECL_PRINTER(ClosureFeedbackCellArray)
166 :
167 : private:
168 : OBJECT_CONSTRUCTORS(ClosureFeedbackCellArray, FixedArray);
169 : };
170 :
171 : // A FeedbackVector has a fixed header with:
172 : // - shared function info (which includes feedback metadata)
173 : // - invocation count
174 : // - runtime profiler ticks
175 : // - optimized code cell (weak cell or Smi marker)
176 : // followed by an array of feedback slots, of length determined by the feedback
177 : // metadata.
178 : class FeedbackVector : public HeapObject {
179 : public:
180 : NEVER_READ_ONLY_SPACE
181 :
182 : DECL_CAST(FeedbackVector)
183 :
184 : inline bool is_empty() const;
185 :
186 : inline FeedbackMetadata metadata() const;
187 :
188 : // [shared_function_info]: The shared function info for the function with this
189 : // feedback vector.
190 : DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
191 :
192 : // [optimized_code_weak_or_smi]: weak reference to optimized code or a Smi
193 : // marker defining optimization behaviour.
194 : DECL_ACCESSORS(optimized_code_weak_or_smi, MaybeObject)
195 :
196 : // [feedback_cell_array]: The FixedArray to hold the feedback cells for any
197 : // closures created by this function.
198 : DECL_ACCESSORS(closure_feedback_cell_array, ClosureFeedbackCellArray)
199 :
200 : // [length]: The length of the feedback vector (not including the header, i.e.
201 : // the number of feedback slots).
202 : DECL_INT32_ACCESSORS(length)
203 :
204 : // [invocation_count]: The number of times this function has been invoked.
205 : DECL_INT32_ACCESSORS(invocation_count)
206 :
207 : // [invocation_count]: The number of times this function has been seen by the
208 : // runtime profiler.
209 : DECL_INT32_ACCESSORS(profiler_ticks)
210 :
211 : // [deopt_count]: The number of times this function has deoptimized.
212 : DECL_INT32_ACCESSORS(deopt_count)
213 :
214 : inline void clear_invocation_count();
215 : inline void increment_deopt_count();
216 :
217 : inline Code optimized_code() const;
218 : inline OptimizationMarker optimization_marker() const;
219 : inline bool has_optimized_code() const;
220 : inline bool has_optimization_marker() const;
221 : void ClearOptimizedCode();
222 : void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo shared,
223 : const char* reason);
224 : static void SetOptimizedCode(Handle<FeedbackVector> vector,
225 : Handle<Code> code);
226 : void SetOptimizationMarker(OptimizationMarker marker);
227 :
228 : // Clears the optimization marker in the feedback vector.
229 : void ClearOptimizationMarker();
230 :
231 : // Conversion from a slot to an integer index to the underlying array.
232 : static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); }
233 :
234 : // Conversion from an integer index to the underlying array to a slot.
235 : static inline FeedbackSlot ToSlot(int index);
236 : inline MaybeObject Get(FeedbackSlot slot) const;
237 : inline MaybeObject get(int index) const;
238 : inline void Set(FeedbackSlot slot, MaybeObject value,
239 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
240 : inline void set(int index, MaybeObject value,
241 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
242 : inline void Set(FeedbackSlot slot, Object value,
243 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
244 : inline void set(int index, Object value,
245 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
246 :
247 : // Returns the feedback cell at |index| that is used to create the
248 : // closure.
249 : inline Handle<FeedbackCell> GetClosureFeedbackCell(int index) const;
250 :
251 : // Gives access to raw memory which stores the array's data.
252 : inline MaybeObjectSlot slots_start();
253 :
254 : // Returns slot kind for given slot.
255 : V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const;
256 :
257 : FeedbackSlot GetTypeProfileSlot() const;
258 :
259 : V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
260 : Isolate* isolate, Handle<SharedFunctionInfo> shared,
261 : Handle<ClosureFeedbackCellArray> closure_feedback_cell_array);
262 :
263 : #define DEFINE_SLOT_KIND_PREDICATE(Name) \
264 : bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
265 :
266 : DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
267 : DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC)
268 : DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
269 : DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
270 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
271 : DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
272 : DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
273 : DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
274 : DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
275 : DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
276 : #undef DEFINE_SLOT_KIND_PREDICATE
277 :
278 : // Returns typeof mode encoded into kind of given slot.
279 : inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
280 : return GetTypeofModeFromSlotKind(GetKind(slot));
281 : }
282 :
283 : // Returns language mode encoded into kind of given slot.
284 : inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
285 319234 : return GetLanguageModeFromSlotKind(GetKind(slot));
286 : }
287 :
288 : V8_EXPORT_PRIVATE static void AssertNoLegacyTypes(MaybeObject object);
289 :
290 : DECL_PRINTER(FeedbackVector)
291 : DECL_VERIFIER(FeedbackVector)
292 :
293 : void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot); // NOLINT
294 :
295 : // Clears the vector slots. Return true if feedback has changed.
296 : bool ClearSlots(Isolate* isolate);
297 :
298 : // The object that indicates an uninitialized cache.
299 : static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
300 :
301 : // The object that indicates a generic state.
302 : static inline Handle<Symbol> GenericSentinel(Isolate* isolate);
303 :
304 : // The object that indicates a megamorphic state.
305 : static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
306 :
307 : // The object that indicates a premonomorphic state.
308 : static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
309 :
310 : // A raw version of the uninitialized sentinel that's safe to read during
311 : // garbage collection (e.g., for patching the cache).
312 : static inline Symbol RawUninitializedSentinel(Isolate* isolate);
313 :
314 : // Layout description.
315 : #define FEEDBACK_VECTOR_FIELDS(V) \
316 : /* Header fields. */ \
317 : V(kSharedFunctionInfoOffset, kTaggedSize) \
318 : V(kOptimizedCodeOffset, kTaggedSize) \
319 : V(kClosureFeedbackCellArrayOffset, kTaggedSize) \
320 : V(kLengthOffset, kInt32Size) \
321 : V(kInvocationCountOffset, kInt32Size) \
322 : V(kProfilerTicksOffset, kInt32Size) \
323 : V(kDeoptCountOffset, kInt32Size) \
324 : V(kUnalignedHeaderSize, 0)
325 :
326 : DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
327 : #undef FEEDBACK_VECTOR_FIELDS
328 :
329 : static const int kHeaderSize =
330 : RoundUp<kObjectAlignment>(int{kUnalignedHeaderSize});
331 : static const int kFeedbackSlotsOffset = kHeaderSize;
332 :
333 : class BodyDescriptor;
334 :
335 : // Garbage collection support.
336 : static constexpr int SizeFor(int length) {
337 14524777 : return kFeedbackSlotsOffset + length * kTaggedSize;
338 : }
339 :
340 : private:
341 : static void AddToVectorsForProfilingTools(Isolate* isolate,
342 : Handle<FeedbackVector> vector);
343 :
344 : OBJECT_CONSTRUCTORS(FeedbackVector, HeapObject);
345 : };
346 :
347 2139087 : class V8_EXPORT_PRIVATE FeedbackVectorSpec {
348 : public:
349 : explicit FeedbackVectorSpec(Zone* zone)
350 2139076 : : slot_kinds_(zone), num_closure_feedback_cells_(0) {
351 2139076 : slot_kinds_.reserve(16);
352 : }
353 :
354 16760128 : int slots() const { return static_cast<int>(slot_kinds_.size()); }
355 2111018 : int closure_feedback_cells() const { return num_closure_feedback_cells_; }
356 :
357 : int AddFeedbackCellForCreateClosure() {
358 2957201 : return num_closure_feedback_cells_++;
359 : }
360 :
361 : FeedbackSlotKind GetKind(FeedbackSlot slot) const {
362 51964370 : return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
363 : }
364 :
365 : bool HasTypeProfileSlot() const;
366 :
367 : // If used, the TypeProfileSlot is always added as the first slot and its
368 : // index is constant. If other slots are added before the TypeProfileSlot,
369 : // this number changes.
370 : static const int kTypeProfileSlotIndex = 0;
371 :
372 4202946 : FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
373 :
374 : FeedbackSlot AddLoadICSlot() {
375 1125385 : return AddSlot(FeedbackSlotKind::kLoadProperty);
376 : }
377 :
378 : FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
379 : return AddSlot(typeof_mode == INSIDE_TYPEOF
380 : ? FeedbackSlotKind::kLoadGlobalInsideTypeof
381 3081051 : : FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
382 : }
383 :
384 : FeedbackSlot AddKeyedLoadICSlot() {
385 142731 : return AddSlot(FeedbackSlotKind::kLoadKeyed);
386 : }
387 :
388 : FeedbackSlot AddKeyedHasICSlot() {
389 3815 : return AddSlot(FeedbackSlotKind::kHasKeyed);
390 : }
391 :
392 : FeedbackSlotKind GetStoreICSlot(LanguageMode language_mode) {
393 : STATIC_ASSERT(LanguageModeSize == 2);
394 : return is_strict(language_mode) ? FeedbackSlotKind::kStoreNamedStrict
395 2292769 : : FeedbackSlotKind::kStoreNamedSloppy;
396 : }
397 :
398 : FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
399 2292775 : return AddSlot(GetStoreICSlot(language_mode));
400 : }
401 :
402 : FeedbackSlot AddStoreOwnICSlot() {
403 244347 : return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
404 : }
405 :
406 : FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
407 : STATIC_ASSERT(LanguageModeSize == 2);
408 : return AddSlot(is_strict(language_mode)
409 : ? FeedbackSlotKind::kStoreGlobalStrict
410 1201575 : : FeedbackSlotKind::kStoreGlobalSloppy);
411 : }
412 :
413 : FeedbackSlotKind GetKeyedStoreICSlotKind(LanguageMode language_mode) {
414 : STATIC_ASSERT(LanguageModeSize == 2);
415 : return is_strict(language_mode) ? FeedbackSlotKind::kStoreKeyedStrict
416 36553 : : FeedbackSlotKind::kStoreKeyedSloppy;
417 : }
418 :
419 : FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
420 36559 : return AddSlot(GetKeyedStoreICSlotKind(language_mode));
421 : }
422 :
423 : FeedbackSlot AddStoreInArrayLiteralICSlot() {
424 584 : return AddSlot(FeedbackSlotKind::kStoreInArrayLiteral);
425 : }
426 :
427 : FeedbackSlot AddBinaryOpICSlot() {
428 1127445 : return AddSlot(FeedbackSlotKind::kBinaryOp);
429 : }
430 :
431 : FeedbackSlot AddCompareICSlot() {
432 730128 : return AddSlot(FeedbackSlotKind::kCompareOp);
433 : }
434 :
435 4833 : FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); }
436 :
437 : FeedbackSlot AddInstanceOfSlot() {
438 15325 : return AddSlot(FeedbackSlotKind::kInstanceOf);
439 : }
440 :
441 305621 : FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
442 :
443 : FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
444 2399 : return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
445 : }
446 :
447 : FeedbackSlot AddTypeProfileSlot();
448 :
449 : FeedbackSlot AddCloneObjectSlot() {
450 284 : return AddSlot(FeedbackSlotKind::kCloneObject);
451 : }
452 :
453 : #ifdef OBJECT_PRINT
454 : // For gdb debugging.
455 : void Print();
456 : #endif // OBJECT_PRINT
457 :
458 : DECL_PRINTER(FeedbackVectorSpec)
459 :
460 : private:
461 : FeedbackSlot AddSlot(FeedbackSlotKind kind);
462 :
463 : void append(FeedbackSlotKind kind) {
464 54224419 : slot_kinds_.push_back(static_cast<unsigned char>(kind));
465 : }
466 :
467 : ZoneVector<unsigned char> slot_kinds_;
468 : unsigned int num_closure_feedback_cells_;
469 :
470 : friend class SharedFeedbackSlot;
471 : };
472 :
473 : // Helper class that creates a feedback slot on-demand.
474 : class SharedFeedbackSlot {
475 : public:
476 : // FeedbackSlot default constructor constructs an invalid slot.
477 : SharedFeedbackSlot(FeedbackVectorSpec* spec, FeedbackSlotKind kind)
478 4234808 : : kind_(kind), spec_(spec) {}
479 :
480 : FeedbackSlot Get() {
481 266066 : if (slot_.IsInvalid()) slot_ = spec_->AddSlot(kind_);
482 1710 : return slot_;
483 : }
484 :
485 : private:
486 : FeedbackSlotKind kind_;
487 : FeedbackSlot slot_;
488 : FeedbackVectorSpec* spec_;
489 : };
490 :
491 : // FeedbackMetadata is an array-like object with a slot count (indicating how
492 : // many slots are stored). We save space by packing several slots into an array
493 : // of int32 data. The length is never stored - it is always calculated from
494 : // slot_count. All instances are created through the static New function, and
495 : // the number of slots is static once an instance is created.
496 : class FeedbackMetadata : public HeapObject {
497 : public:
498 : DECL_CAST(FeedbackMetadata)
499 :
500 : // The number of slots that this metadata contains. Stored as an int32.
501 : DECL_INT32_ACCESSORS(slot_count)
502 :
503 : // The number of feedback cells required for create closures. Stored as an
504 : // int32.
505 : // TODO(mythria): Consider using 16 bits for this and slot_count so that we
506 : // can save 4 bytes.
507 : DECL_INT32_ACCESSORS(closure_feedback_cell_count)
508 :
509 : // Get slot_count using an acquire load.
510 : inline int32_t synchronized_slot_count() const;
511 :
512 : // Returns number of feedback vector elements used by given slot kind.
513 : static inline int GetSlotSize(FeedbackSlotKind kind);
514 :
515 : bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
516 :
517 : inline bool is_empty() const;
518 :
519 : // Returns slot kind for given slot.
520 : V8_EXPORT_PRIVATE FeedbackSlotKind GetKind(FeedbackSlot slot) const;
521 :
522 : // If {spec} is null, then it is considered empty.
523 : V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
524 : Isolate* isolate, const FeedbackVectorSpec* spec = nullptr);
525 :
526 : DECL_PRINTER(FeedbackMetadata)
527 : DECL_VERIFIER(FeedbackMetadata)
528 :
529 : static const char* Kind2String(FeedbackSlotKind kind);
530 : bool HasTypeProfileSlot() const;
531 :
532 : // Garbage collection support.
533 : // This includes any necessary padding at the end of the object for pointer
534 : // size alignment.
535 : static int SizeFor(int slot_count) {
536 6975049 : return OBJECT_POINTER_ALIGN(kHeaderSize + length(slot_count) * kInt32Size);
537 : }
538 :
539 : static const int kSlotCountOffset = HeapObject::kHeaderSize;
540 : static const int kFeedbackCellCountOffset = kSlotCountOffset + kInt32Size;
541 : static const int kHeaderSize = kFeedbackCellCountOffset + kInt32Size;
542 :
543 : class BodyDescriptor;
544 :
545 : private:
546 : friend class AccessorAssembler;
547 :
548 : // Raw accessors to the encoded slot data.
549 : inline int32_t get(int index) const;
550 : inline void set(int index, int32_t value);
551 :
552 : // The number of int32 data fields needed to store {slot_count} slots.
553 : // Does not include any extra padding for pointer size alignment.
554 : static int length(int slot_count) {
555 : return VectorICComputer::word_count(slot_count);
556 : }
557 : inline int length() const;
558 :
559 : static const int kFeedbackSlotKindBits = 5;
560 : STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
561 : (1 << kFeedbackSlotKindBits));
562 :
563 : void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
564 :
565 : typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits,
566 : kInt32Size * kBitsPerByte, uint32_t>
567 : VectorICComputer;
568 :
569 : OBJECT_CONSTRUCTORS(FeedbackMetadata, HeapObject);
570 : };
571 :
572 : // Verify that an empty hash field looks like a tagged object, but can't
573 : // possibly be confused with a pointer.
574 : STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
575 : STATIC_ASSERT(Name::kEmptyHashField == 0x3);
576 : // Verify that a set hash field will not look like a tagged object.
577 : STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
578 :
579 : class FeedbackMetadataIterator {
580 : public:
581 : explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
582 : : metadata_handle_(metadata),
583 : next_slot_(FeedbackSlot(0)),
584 : slot_kind_(FeedbackSlotKind::kInvalid) {}
585 :
586 : explicit FeedbackMetadataIterator(FeedbackMetadata metadata)
587 : : metadata_(metadata),
588 : next_slot_(FeedbackSlot(0)),
589 105370 : slot_kind_(FeedbackSlotKind::kInvalid) {}
590 :
591 : inline bool HasNext() const;
592 :
593 : inline FeedbackSlot Next();
594 :
595 : // Returns slot kind of the last slot returned by Next().
596 : FeedbackSlotKind kind() const {
597 : DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
598 : DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
599 : return slot_kind_;
600 : }
601 :
602 : // Returns entry size of the last slot returned by Next().
603 : inline int entry_size() const;
604 :
605 : private:
606 : FeedbackMetadata metadata() const {
607 430802 : return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
608 : }
609 :
610 : // The reason for having a handle and a raw pointer to the meta data is
611 : // to have a single iterator implementation for both "handlified" and raw
612 : // pointer use cases.
613 : Handle<FeedbackMetadata> metadata_handle_;
614 : FeedbackMetadata metadata_;
615 : FeedbackSlot cur_slot_;
616 : FeedbackSlot next_slot_;
617 : FeedbackSlotKind slot_kind_;
618 : };
619 :
620 : // A FeedbackNexus is the combination of a FeedbackVector and a slot.
621 : class V8_EXPORT_PRIVATE FeedbackNexus final {
622 : public:
623 : FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
624 35157818 : : vector_handle_(vector), slot_(slot) {
625 : kind_ =
626 35042570 : (vector.is_null()) ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
627 : }
628 55810 : FeedbackNexus(FeedbackVector vector, FeedbackSlot slot)
629 56050 : : vector_(vector), slot_(slot) {
630 : kind_ =
631 111860 : (vector.is_null()) ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
632 55810 : }
633 :
634 : Handle<FeedbackVector> vector_handle() const {
635 : DCHECK(vector_.is_null());
636 : return vector_handle_;
637 : }
638 : FeedbackVector vector() const {
639 67226272 : return vector_handle_.is_null() ? vector_ : *vector_handle_;
640 : }
641 : FeedbackSlot slot() const { return slot_; }
642 : FeedbackSlotKind kind() const { return kind_; }
643 :
644 : inline LanguageMode GetLanguageMode() const {
645 : return vector()->GetLanguageMode(slot());
646 : }
647 :
648 : InlineCacheState ic_state() const;
649 1711925 : bool IsUninitialized() const { return ic_state() == UNINITIALIZED; }
650 450 : bool IsMegamorphic() const { return ic_state() == MEGAMORPHIC; }
651 : bool IsGeneric() const { return ic_state() == GENERIC; }
652 :
653 : void Print(std::ostream& os); // NOLINT
654 :
655 : // For map-based ICs (load, keyed-load, store, keyed-store).
656 : Map GetFirstMap() const;
657 :
658 : int ExtractMaps(MapHandles* maps) const;
659 : MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const;
660 : bool FindHandlers(MaybeObjectHandles* code_list, int length = -1) const;
661 :
662 : bool IsCleared() const {
663 47770 : InlineCacheState state = ic_state();
664 47770 : return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
665 : }
666 :
667 : // Clear() returns true if the state of the underlying vector was changed.
668 : bool Clear();
669 : void ConfigureUninitialized();
670 : void ConfigurePremonomorphic(Handle<Map> receiver_map);
671 : // ConfigureMegamorphic() returns true if the state of the underlying vector
672 : // was changed. Extra feedback is cleared if the 0 parameter version is used.
673 : bool ConfigureMegamorphic();
674 : bool ConfigureMegamorphic(IcCheckType property_type);
675 :
676 : inline MaybeObject GetFeedback() const;
677 : inline MaybeObject GetFeedbackExtra() const;
678 :
679 : inline Isolate* GetIsolate() const;
680 :
681 : void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
682 : const MaybeObjectHandle& handler);
683 :
684 : void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
685 : MaybeObjectHandles* handlers);
686 :
687 : BinaryOperationHint GetBinaryOperationFeedback() const;
688 : CompareOperationHint GetCompareOperationFeedback() const;
689 : ForInHint GetForInFeedback() const;
690 :
691 : // For KeyedLoad ICs.
692 : KeyedAccessLoadMode GetKeyedAccessLoadMode() const;
693 :
694 : // For KeyedStore ICs.
695 : KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
696 :
697 : // For KeyedLoad and KeyedStore ICs.
698 : IcCheckType GetKeyType() const;
699 : Name GetName() const;
700 :
701 : // For Call ICs.
702 : int GetCallCount();
703 : void SetSpeculationMode(SpeculationMode mode);
704 : SpeculationMode GetSpeculationMode();
705 :
706 : // Compute the call frequency based on the call count and the invocation
707 : // count (taken from the type feedback vector).
708 : float ComputeCallFrequency();
709 :
710 : typedef BitField<SpeculationMode, 0, 1> SpeculationModeField;
711 : typedef BitField<uint32_t, 1, 31> CallCountField;
712 :
713 : // For InstanceOf ICs.
714 : MaybeHandle<JSObject> GetConstructorFeedback() const;
715 :
716 : // For Global Load and Store ICs.
717 : void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
718 : // Returns false if given combination of indices is not allowed.
719 : bool ConfigureLexicalVarMode(int script_context_index, int context_slot_index,
720 : bool immutable);
721 : void ConfigureHandlerMode(const MaybeObjectHandle& handler);
722 :
723 : // For CloneObject ICs
724 : static constexpr int kCloneObjectPolymorphicEntrySize = 2;
725 : void ConfigureCloneObject(Handle<Map> source_map, Handle<Map> result_map);
726 :
727 : // Bit positions in a smi that encodes lexical environment variable access.
728 : #define LEXICAL_MODE_BIT_FIELDS(V, _) \
729 : V(ContextIndexBits, unsigned, 12, _) \
730 : V(SlotIndexBits, unsigned, 18, _) \
731 : V(ImmutabilityBit, bool, 1, _)
732 :
733 : DEFINE_BIT_FIELDS(LEXICAL_MODE_BIT_FIELDS)
734 : #undef LEXICAL_MODE_BIT_FIELDS
735 :
736 : // Make sure we don't overflow the smi.
737 : STATIC_ASSERT(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize);
738 :
739 : // For TypeProfile feedback vector slots.
740 : // ResetTypeProfile will always reset type profile information.
741 : void ResetTypeProfile();
742 :
743 : // Add a type to the list of types for source position <position>.
744 : void Collect(Handle<String> type, int position);
745 : JSObject GetTypeProfile() const;
746 :
747 : std::vector<int> GetSourcePositions() const;
748 : std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
749 :
750 : inline void SetFeedback(Object feedback,
751 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
752 : inline void SetFeedback(MaybeObject feedback,
753 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
754 : inline void SetFeedbackExtra(Object feedback_extra,
755 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
756 : inline void SetFeedbackExtra(MaybeObject feedback_extra,
757 : WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
758 :
759 : Handle<WeakFixedArray> EnsureArrayOfSize(int length);
760 : Handle<WeakFixedArray> EnsureExtraArrayOfSize(int length);
761 :
762 : private:
763 : // The reason for having a vector handle and a raw pointer is that we can and
764 : // should use handles during IC miss, but not during GC when we clear ICs. If
765 : // you have a handle to the vector that is better because more operations can
766 : // be done, like allocation.
767 : Handle<FeedbackVector> vector_handle_;
768 : FeedbackVector vector_;
769 : FeedbackSlot slot_;
770 : FeedbackSlotKind kind_;
771 : };
772 :
773 : inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
774 : inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
775 : inline ForInHint ForInHintFromFeedback(int type_feedback);
776 :
777 : } // namespace internal
778 : } // namespace v8
779 :
780 : #include "src/objects/object-macros-undef.h"
781 :
782 : #endif // V8_FEEDBACK_VECTOR_H_
|