V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
feedback-vector-inl.h
1 // Copyright 2012 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_INL_H_
6 #define V8_FEEDBACK_VECTOR_INL_H_
7 
8 #include "src/feedback-vector.h"
9 #include "src/globals.h"
10 #include "src/heap/factory-inl.h"
11 #include "src/heap/heap-inl.h"
12 #include "src/heap/heap-write-barrier.h"
13 #include "src/objects/maybe-object-inl.h"
14 #include "src/objects/shared-function-info.h"
15 #include "src/objects/smi.h"
16 
17 // Has to be the last include (doesn't have include guards):
18 #include "src/objects/object-macros.h"
19 
20 namespace v8 {
21 namespace internal {
22 
23 INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
24 
25 int32_t FeedbackMetadata::synchronized_slot_count() const {
26  return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
27  FIELD_ADDR(this, kSlotCountOffset)));
28 }
29 
30 // static
31 FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
32  DCHECK(obj->IsFeedbackMetadata());
33  return reinterpret_cast<FeedbackMetadata*>(obj);
34 }
35 
36 int32_t FeedbackMetadata::get(int index) const {
37  DCHECK(index >= 0 && index < length());
38  int offset = kHeaderSize + index * kInt32Size;
39  return READ_INT32_FIELD(this, offset);
40 }
41 
42 void FeedbackMetadata::set(int index, int32_t value) {
43  DCHECK(index >= 0 && index < length());
44  int offset = kHeaderSize + index * kInt32Size;
45  WRITE_INT32_FIELD(this, offset, value);
46 }
47 
48 bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
49 
50 int FeedbackMetadata::length() const {
51  return FeedbackMetadata::length(slot_count());
52 }
53 
54 // static
55 FeedbackVector* FeedbackVector::cast(Object* obj) {
56  DCHECK(obj->IsFeedbackVector());
57  return reinterpret_cast<FeedbackVector*>(obj);
58 }
59 
60 int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
61  switch (kind) {
62  case FeedbackSlotKind::kForIn:
63  case FeedbackSlotKind::kInstanceOf:
64  case FeedbackSlotKind::kCompareOp:
65  case FeedbackSlotKind::kBinaryOp:
66  case FeedbackSlotKind::kLiteral:
67  case FeedbackSlotKind::kCreateClosure:
68  case FeedbackSlotKind::kTypeProfile:
69  return 1;
70 
71  case FeedbackSlotKind::kCall:
72  case FeedbackSlotKind::kCloneObject:
73  case FeedbackSlotKind::kLoadProperty:
74  case FeedbackSlotKind::kLoadGlobalInsideTypeof:
75  case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
76  case FeedbackSlotKind::kLoadKeyed:
77  case FeedbackSlotKind::kStoreNamedSloppy:
78  case FeedbackSlotKind::kStoreNamedStrict:
79  case FeedbackSlotKind::kStoreOwnNamed:
80  case FeedbackSlotKind::kStoreGlobalSloppy:
81  case FeedbackSlotKind::kStoreGlobalStrict:
82  case FeedbackSlotKind::kStoreKeyedSloppy:
83  case FeedbackSlotKind::kStoreKeyedStrict:
84  case FeedbackSlotKind::kStoreInArrayLiteral:
85  case FeedbackSlotKind::kStoreDataPropertyInLiteral:
86  return 2;
87 
88  case FeedbackSlotKind::kInvalid:
89  case FeedbackSlotKind::kKindsNumber:
90  UNREACHABLE();
91  break;
92  }
93  return 1;
94 }
95 
96 ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
97  kSharedFunctionInfoOffset)
98 WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
99 INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
100 INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
101 INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
102 INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
103 
104 bool FeedbackVector::is_empty() const { return length() == 0; }
105 
106 FeedbackMetadata* FeedbackVector::metadata() const {
107  return shared_function_info()->feedback_metadata();
108 }
109 
110 void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
111 
112 void FeedbackVector::increment_deopt_count() {
113  int count = deopt_count();
114  if (count < std::numeric_limits<int32_t>::max()) {
115  set_deopt_count(count + 1);
116  }
117 }
118 
119 Code FeedbackVector::optimized_code() const {
120  MaybeObject slot = optimized_code_weak_or_smi();
121  DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
122  HeapObject* heap_object;
123  return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
124 }
125 
126 OptimizationMarker FeedbackVector::optimization_marker() const {
127  MaybeObject slot = optimized_code_weak_or_smi();
128  Smi value;
129  if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
130  return static_cast<OptimizationMarker>(value->value());
131 }
132 
133 bool FeedbackVector::has_optimized_code() const {
134  return !optimized_code().is_null();
135 }
136 
137 bool FeedbackVector::has_optimization_marker() const {
138  return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
139  optimization_marker() != OptimizationMarker::kNone;
140 }
141 
142 // Conversion from an integer index to either a slot or an ic slot.
143 // static
144 FeedbackSlot FeedbackVector::ToSlot(int index) {
145  DCHECK_GE(index, 0);
146  return FeedbackSlot(index);
147 }
148 
149 MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
150  return get(GetIndex(slot));
151 }
152 
153 MaybeObject FeedbackVector::get(int index) const {
154  DCHECK_GE(index, 0);
155  DCHECK_LT(index, this->length());
156  int offset = kFeedbackSlotsOffset + index * kPointerSize;
157  return RELAXED_READ_WEAK_FIELD(this, offset);
158 }
159 
160 void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
161  WriteBarrierMode mode) {
162  set(GetIndex(slot), value, mode);
163 }
164 
165 void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
166  DCHECK_GE(index, 0);
167  DCHECK_LT(index, this->length());
168  int offset = kFeedbackSlotsOffset + index * kPointerSize;
169  RELAXED_WRITE_WEAK_FIELD(this, offset, value);
170  CONDITIONAL_WEAK_WRITE_BARRIER(this, offset, value, mode);
171 }
172 
173 void FeedbackVector::Set(FeedbackSlot slot, Object* value,
174  WriteBarrierMode mode) {
175  set(GetIndex(slot), MaybeObject::FromObject(value), mode);
176 }
177 
178 void FeedbackVector::set(int index, Object* value, WriteBarrierMode mode) {
179  set(index, MaybeObject::FromObject(value), mode);
180 }
181 
182 inline MaybeObjectSlot FeedbackVector::slots_start() {
183  return HeapObject::RawMaybeWeakField(this, kFeedbackSlotsOffset);
184 }
185 
186 // Helper function to transform the feedback to BinaryOperationHint.
187 BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
188  switch (type_feedback) {
189  case BinaryOperationFeedback::kNone:
190  return BinaryOperationHint::kNone;
191  case BinaryOperationFeedback::kSignedSmall:
192  return BinaryOperationHint::kSignedSmall;
193  case BinaryOperationFeedback::kSignedSmallInputs:
194  return BinaryOperationHint::kSignedSmallInputs;
195  case BinaryOperationFeedback::kNumber:
196  return BinaryOperationHint::kNumber;
197  case BinaryOperationFeedback::kNumberOrOddball:
198  return BinaryOperationHint::kNumberOrOddball;
199  case BinaryOperationFeedback::kString:
200  return BinaryOperationHint::kString;
201  case BinaryOperationFeedback::kBigInt:
202  return BinaryOperationHint::kBigInt;
203  default:
204  return BinaryOperationHint::kAny;
205  }
206  UNREACHABLE();
207 }
208 
209 // Helper function to transform the feedback to CompareOperationHint.
210 CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
211  switch (type_feedback) {
212  case CompareOperationFeedback::kNone:
213  return CompareOperationHint::kNone;
214  case CompareOperationFeedback::kSignedSmall:
215  return CompareOperationHint::kSignedSmall;
216  case CompareOperationFeedback::kNumber:
217  return CompareOperationHint::kNumber;
218  case CompareOperationFeedback::kNumberOrOddball:
219  return CompareOperationHint::kNumberOrOddball;
220  case CompareOperationFeedback::kInternalizedString:
221  return CompareOperationHint::kInternalizedString;
222  case CompareOperationFeedback::kString:
223  return CompareOperationHint::kString;
224  case CompareOperationFeedback::kSymbol:
225  return CompareOperationHint::kSymbol;
226  case CompareOperationFeedback::kBigInt:
227  return CompareOperationHint::kBigInt;
228  case CompareOperationFeedback::kReceiver:
229  return CompareOperationHint::kReceiver;
230  case CompareOperationFeedback::kReceiverOrNullOrUndefined:
231  return CompareOperationHint::kReceiverOrNullOrUndefined;
232  default:
233  return CompareOperationHint::kAny;
234  }
235  UNREACHABLE();
236 }
237 
238 // Helper function to transform the feedback to ForInHint.
239 ForInHint ForInHintFromFeedback(int type_feedback) {
240  switch (type_feedback) {
241  case ForInFeedback::kNone:
242  return ForInHint::kNone;
243  case ForInFeedback::kEnumCacheKeys:
244  return ForInHint::kEnumCacheKeys;
245  case ForInFeedback::kEnumCacheKeysAndIndices:
246  return ForInHint::kEnumCacheKeysAndIndices;
247  default:
248  return ForInHint::kAny;
249  }
250  UNREACHABLE();
251 }
252 
253 void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
254  int* vector_ic_count) {
255  MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
256  *FeedbackVector::MegamorphicSentinel(GetIsolate()));
257  int with = 0;
258  int gen = 0;
259  int total = 0;
260  FeedbackMetadataIterator iter(metadata());
261  while (iter.HasNext()) {
262  FeedbackSlot slot = iter.Next();
263  FeedbackSlotKind kind = iter.kind();
264 
265  MaybeObject const obj = Get(slot);
266  AssertNoLegacyTypes(obj);
267  switch (kind) {
268  case FeedbackSlotKind::kCall:
269  case FeedbackSlotKind::kLoadProperty:
270  case FeedbackSlotKind::kLoadGlobalInsideTypeof:
271  case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
272  case FeedbackSlotKind::kLoadKeyed:
273  case FeedbackSlotKind::kStoreNamedSloppy:
274  case FeedbackSlotKind::kStoreNamedStrict:
275  case FeedbackSlotKind::kStoreOwnNamed:
276  case FeedbackSlotKind::kStoreGlobalSloppy:
277  case FeedbackSlotKind::kStoreGlobalStrict:
278  case FeedbackSlotKind::kStoreKeyedSloppy:
279  case FeedbackSlotKind::kStoreKeyedStrict:
280  case FeedbackSlotKind::kStoreInArrayLiteral:
281  case FeedbackSlotKind::kStoreDataPropertyInLiteral:
282  case FeedbackSlotKind::kTypeProfile: {
283  HeapObject* heap_object;
284  if (obj->IsWeakOrCleared() ||
285  (obj->GetHeapObjectIfStrong(&heap_object) &&
286  (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
287  with++;
288  } else if (obj == megamorphic_sentinel) {
289  gen++;
290  with++;
291  }
292  total++;
293  break;
294  }
295  case FeedbackSlotKind::kBinaryOp: {
296  int const feedback = obj.ToSmi().value();
297  BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
298  if (hint == BinaryOperationHint::kAny) {
299  gen++;
300  }
301  if (hint != BinaryOperationHint::kNone) {
302  with++;
303  }
304  total++;
305  break;
306  }
307  case FeedbackSlotKind::kCompareOp: {
308  int const feedback = obj.ToSmi().value();
309  CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
310  if (hint == CompareOperationHint::kAny) {
311  gen++;
312  }
313  if (hint != CompareOperationHint::kNone) {
314  with++;
315  }
316  total++;
317  break;
318  }
319  case FeedbackSlotKind::kForIn: {
320  int const feedback = obj.ToSmi().value();
321  ForInHint hint = ForInHintFromFeedback(feedback);
322  if (hint == ForInHint::kAny) {
323  gen++;
324  }
325  if (hint != ForInHint::kNone) {
326  with++;
327  }
328  total++;
329  break;
330  }
331  case FeedbackSlotKind::kInstanceOf: {
332  if (obj->IsWeakOrCleared()) {
333  with++;
334  } else if (obj == megamorphic_sentinel) {
335  gen++;
336  with++;
337  }
338  total++;
339  break;
340  }
341  case FeedbackSlotKind::kCreateClosure:
342  case FeedbackSlotKind::kLiteral:
343  case FeedbackSlotKind::kCloneObject:
344  break;
345  case FeedbackSlotKind::kInvalid:
346  case FeedbackSlotKind::kKindsNumber:
347  UNREACHABLE();
348  break;
349  }
350  }
351 
352  *with_type_info = with;
353  *generic = gen;
354  *vector_ic_count = total;
355 }
356 
357 Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
358  return isolate->factory()->uninitialized_symbol();
359 }
360 
361 Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
362  return isolate->factory()->generic_symbol();
363 }
364 
365 Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
366  return isolate->factory()->megamorphic_symbol();
367 }
368 
369 Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
370  return isolate->factory()->premonomorphic_symbol();
371 }
372 
373 Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
374  return ReadOnlyRoots(isolate).uninitialized_symbol();
375 }
376 
377 bool FeedbackMetadataIterator::HasNext() const {
378  return next_slot_.ToInt() < metadata()->slot_count();
379 }
380 
381 FeedbackSlot FeedbackMetadataIterator::Next() {
382  DCHECK(HasNext());
383  cur_slot_ = next_slot_;
384  slot_kind_ = metadata()->GetKind(cur_slot_);
385  next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
386  return cur_slot_;
387 }
388 
389 int FeedbackMetadataIterator::entry_size() const {
390  return FeedbackMetadata::GetSlotSize(kind());
391 }
392 
393 MaybeObject FeedbackNexus::GetFeedback() const {
394  MaybeObject feedback = vector()->Get(slot());
395  FeedbackVector::AssertNoLegacyTypes(feedback);
396  return feedback;
397 }
398 
399 MaybeObject FeedbackNexus::GetFeedbackExtra() const {
400 #ifdef DEBUG
401  FeedbackSlotKind kind = vector()->GetKind(slot());
402  DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
403 #endif
404  int extra_index = vector()->GetIndex(slot()) + 1;
405  return vector()->get(extra_index);
406 }
407 
408 void FeedbackNexus::SetFeedback(Object* feedback, WriteBarrierMode mode) {
409  SetFeedback(MaybeObject::FromObject(feedback));
410 }
411 
412 void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
413  FeedbackVector::AssertNoLegacyTypes(feedback);
414  vector()->Set(slot(), feedback, mode);
415 }
416 
417 void FeedbackNexus::SetFeedbackExtra(Object* feedback_extra,
418  WriteBarrierMode mode) {
419 #ifdef DEBUG
420  FeedbackSlotKind kind = vector()->GetKind(slot());
421  DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
422  FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
423 #endif
424  int index = vector()->GetIndex(slot()) + 1;
425  vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
426 }
427 
428 void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
429  WriteBarrierMode mode) {
430 #ifdef DEBUG
431  FeedbackVector::AssertNoLegacyTypes(feedback_extra);
432 #endif
433  int index = vector()->GetIndex(slot()) + 1;
434  vector()->set(index, feedback_extra, mode);
435 }
436 
437 Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
438 } // namespace internal
439 } // namespace v8
440 
441 #include "src/objects/object-macros-undef.h"
442 
443 #endif // V8_FEEDBACK_VECTOR_INL_H_
Definition: libplatform.h:13