feedback-vector-inl.h 12.5 KB
Newer Older
1 2 3 4
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_OBJECTS_FEEDBACK_VECTOR_INL_H_
#define V8_OBJECTS_FEEDBACK_VECTOR_INL_H_
7

8
#include "src/common/globals.h"
9
#include "src/heap/factory-inl.h"
10 11
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/code-inl.h"
12 13
#include "src/objects/feedback-cell-inl.h"
#include "src/objects/feedback-vector.h"
14
#include "src/objects/maybe-object-inl.h"
15
#include "src/objects/shared-function-info.h"
16
#include "src/objects/smi.h"
17

18 19 20
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

21 22 23
namespace v8 {
namespace internal {

24 25
OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
26
OBJECT_CONSTRUCTORS_IMPL(ClosureFeedbackCellArray, FixedArray)
27 28

NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
29
NEVER_READ_ONLY_SPACE_IMPL(ClosureFeedbackCellArray)
30

31 32
CAST_ACCESSOR(FeedbackVector)
CAST_ACCESSOR(FeedbackMetadata)
33
CAST_ACCESSOR(ClosureFeedbackCellArray)
34

35 36
INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)

37 38 39
INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
                kFeedbackCellCountOffset)

40
int32_t FeedbackMetadata::synchronized_slot_count() const {
41
  return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
42
      FIELD_ADDR(*this, kSlotCountOffset)));
43 44 45 46 47
}

int32_t FeedbackMetadata::get(int index) const {
  DCHECK(index >= 0 && index < length());
  int offset = kHeaderSize + index * kInt32Size;
48
  return ReadField<int32_t>(offset);
49
}
50

51 52 53
void FeedbackMetadata::set(int index, int32_t value) {
  DCHECK(index >= 0 && index < length());
  int offset = kHeaderSize + index * kInt32Size;
54
  WriteField<int32_t>(offset, value);
55 56 57 58 59 60
}

bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }

int FeedbackMetadata::length() const {
  return FeedbackMetadata::length(slot_count());
61 62
}

63
int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
64
  switch (kind) {
65
    case FeedbackSlotKind::kForIn:
66
    case FeedbackSlotKind::kInstanceOf:
67 68 69
    case FeedbackSlotKind::kCompareOp:
    case FeedbackSlotKind::kBinaryOp:
    case FeedbackSlotKind::kLiteral:
70
    case FeedbackSlotKind::kTypeProfile:
71 72
      return 1;

73
    case FeedbackSlotKind::kCall:
74
    case FeedbackSlotKind::kCloneObject:
75 76 77 78
    case FeedbackSlotKind::kLoadProperty:
    case FeedbackSlotKind::kLoadGlobalInsideTypeof:
    case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
    case FeedbackSlotKind::kLoadKeyed:
79
    case FeedbackSlotKind::kHasKeyed:
80 81 82
    case FeedbackSlotKind::kStoreNamedSloppy:
    case FeedbackSlotKind::kStoreNamedStrict:
    case FeedbackSlotKind::kStoreOwnNamed:
83 84
    case FeedbackSlotKind::kStoreGlobalSloppy:
    case FeedbackSlotKind::kStoreGlobalStrict:
85 86
    case FeedbackSlotKind::kStoreKeyedSloppy:
    case FeedbackSlotKind::kStoreKeyedStrict:
87
    case FeedbackSlotKind::kStoreInArrayLiteral:
88
    case FeedbackSlotKind::kStoreDataPropertyInLiteral:
89 90
      return 2;

91 92
    case FeedbackSlotKind::kInvalid:
    case FeedbackSlotKind::kKindsNumber:
93
      UNREACHABLE();
94
  }
95
  return 1;
96 97
}

98
Handle<FeedbackCell> ClosureFeedbackCellArray::GetFeedbackCell(int index) {
99
  return handle(FeedbackCell::cast(get(index)), GetIsolate());
100 101
}

102 103
ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
          kSharedFunctionInfoOffset)
Irina Yatsenko's avatar
Irina Yatsenko committed
104 105
WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi,
               kOptimizedCodeWeakOrSmiOffset)
106
ACCESSORS(FeedbackVector, closure_feedback_cell_array, ClosureFeedbackCellArray,
107
          kClosureFeedbackCellArrayOffset)
108 109
INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
110 111 112 113 114 115 116 117
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));
}
118

119
bool FeedbackVector::is_empty() const { return length() == 0; }
120

121
FeedbackMetadata FeedbackVector::metadata() const {
122
  return shared_function_info().feedback_metadata();
123 124
}

125
void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
126

127
Code FeedbackVector::optimized_code() const {
128
  MaybeObject slot = optimized_code_weak_or_smi();
129
  DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
130
  HeapObject heap_object;
131
  return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
132 133
}

134
OptimizationMarker FeedbackVector::optimization_marker() const {
135
  MaybeObject slot = optimized_code_weak_or_smi();
136
  Smi value;
137
  if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
138
  return static_cast<OptimizationMarker>(value.value());
139 140
}

141
bool FeedbackVector::has_optimized_code() const {
142
  return !optimized_code().is_null();
143 144 145
}

bool FeedbackVector::has_optimization_marker() const {
146 147
  return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
         optimization_marker() != OptimizationMarker::kNone;
148 149
}

mvstanton's avatar
mvstanton committed
150
// Conversion from an integer index to either a slot or an ic slot.
151
// static
152 153 154 155
FeedbackSlot FeedbackVector::ToSlot(intptr_t index) {
  DCHECK_LE(static_cast<uintptr_t>(index),
            static_cast<uintptr_t>(std::numeric_limits<int>::max()));
  return FeedbackSlot(static_cast<int>(index));
156 157
}

158
MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
159
  const Isolate* isolate = GetIsolateForPtrCompr(*this);
160 161 162
  return Get(isolate, slot);
}

163 164
MaybeObject FeedbackVector::Get(const Isolate* isolate,
                                FeedbackSlot slot) const {
165
  return get(isolate, GetIndex(slot));
166 167
}

168
MaybeObject FeedbackVector::get(int index) const {
169
  const Isolate* isolate = GetIsolateForPtrCompr(*this);
170 171 172
  return get(isolate, index);
}

173
MaybeObject FeedbackVector::get(const Isolate* isolate, int index) const {
174 175
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  int offset = OffsetOfElementAt(index);
176
  return RELAXED_READ_WEAK_FIELD(*this, offset);
177 178
}

179 180
Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
  DCHECK_GE(index, 0);
181 182
  ClosureFeedbackCellArray cell_array =
      ClosureFeedbackCellArray::cast(closure_feedback_cell_array());
183
  return cell_array.GetFeedbackCell(index);
184 185
}

186
void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
187
                         WriteBarrierMode mode) {
188 189 190
  set(GetIndex(slot), value, mode);
}

191
void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
192 193
  DCHECK_GE(index, 0);
  DCHECK_LT(index, this->length());
194
  int offset = OffsetOfElementAt(index);
195 196
  RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
  CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
197 198
}

199
void FeedbackVector::Set(FeedbackSlot slot, Object value,
200 201 202 203
                         WriteBarrierMode mode) {
  set(GetIndex(slot), MaybeObject::FromObject(value), mode);
}

204
void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
205
  set(index, MaybeObject::FromObject(value), mode);
206 207
}

208
inline MaybeObjectSlot FeedbackVector::slots_start() {
209
  return RawMaybeWeakField(kFeedbackSlotsOffset);
210 211
}

212 213 214
// Helper function to transform the feedback to BinaryOperationHint.
BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
  switch (type_feedback) {
215 216
    case BinaryOperationFeedback::kNone:
      return BinaryOperationHint::kNone;
217 218
    case BinaryOperationFeedback::kSignedSmall:
      return BinaryOperationHint::kSignedSmall;
219 220
    case BinaryOperationFeedback::kSignedSmallInputs:
      return BinaryOperationHint::kSignedSmallInputs;
221 222
    case BinaryOperationFeedback::kNumber:
      return BinaryOperationHint::kNumber;
223
    case BinaryOperationFeedback::kNumberOrOddball:
224
      return BinaryOperationHint::kNumberOrOddball;
225 226
    case BinaryOperationFeedback::kString:
      return BinaryOperationHint::kString;
227
    case BinaryOperationFeedback::kBigInt:
228
      return BinaryOperationHint::kBigInt;
229 230 231 232 233 234 235
    default:
      return BinaryOperationHint::kAny;
  }
  UNREACHABLE();
}

// Helper function to transform the feedback to CompareOperationHint.
236 237 238 239 240
template <CompareOperationFeedback::Type Feedback>
bool Is(int type_feedback) {
  return !(type_feedback & ~Feedback);
}

241
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
242 243
  if (Is<CompareOperationFeedback::kNone>(type_feedback)) {
    return CompareOperationHint::kNone;
244
  }
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276

  if (Is<CompareOperationFeedback::kSignedSmall>(type_feedback)) {
    return CompareOperationHint::kSignedSmall;
  } else if (Is<CompareOperationFeedback::kNumber>(type_feedback)) {
    return CompareOperationHint::kNumber;
  } else if (Is<CompareOperationFeedback::kNumberOrBoolean>(type_feedback)) {
    return CompareOperationHint::kNumberOrBoolean;
  }

  if (Is<CompareOperationFeedback::kInternalizedString>(type_feedback)) {
    return CompareOperationHint::kInternalizedString;
  } else if (Is<CompareOperationFeedback::kString>(type_feedback)) {
    return CompareOperationHint::kString;
  }

  if (Is<CompareOperationFeedback::kReceiver>(type_feedback)) {
    return CompareOperationHint::kReceiver;
  } else if (Is<CompareOperationFeedback::kReceiverOrNullOrUndefined>(
                 type_feedback)) {
    return CompareOperationHint::kReceiverOrNullOrUndefined;
  }

  if (Is<CompareOperationFeedback::kBigInt>(type_feedback)) {
    return CompareOperationHint::kBigInt;
  }

  if (Is<CompareOperationFeedback::kSymbol>(type_feedback)) {
    return CompareOperationHint::kSymbol;
  }

  DCHECK(Is<CompareOperationFeedback::kAny>(type_feedback));
  return CompareOperationHint::kAny;
277
}
278

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
// Helper function to transform the feedback to ForInHint.
ForInHint ForInHintFromFeedback(int type_feedback) {
  switch (type_feedback) {
    case ForInFeedback::kNone:
      return ForInHint::kNone;
    case ForInFeedback::kEnumCacheKeys:
      return ForInHint::kEnumCacheKeys;
    case ForInFeedback::kEnumCacheKeysAndIndices:
      return ForInHint::kEnumCacheKeysAndIndices;
    default:
      return ForInHint::kAny;
  }
  UNREACHABLE();
}

294
Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
295 296 297
  return isolate->factory()->uninitialized_symbol();
}

298 299 300 301
Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
  return isolate->factory()->generic_symbol();
}

302
Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
303 304 305
  return isolate->factory()->megamorphic_symbol();
}

306
Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
307
  return ReadOnlyRoots(isolate).uninitialized_symbol();
308
}
309

310
bool FeedbackMetadataIterator::HasNext() const {
311
  return next_slot_.ToInt() < metadata().slot_count();
312 313
}

314
FeedbackSlot FeedbackMetadataIterator::Next() {
315
  DCHECK(HasNext());
316
  cur_slot_ = next_slot_;
317
  slot_kind_ = metadata().GetKind(cur_slot_);
318
  next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
319
  return cur_slot_;
320 321
}

322 323
int FeedbackMetadataIterator::entry_size() const {
  return FeedbackMetadata::GetSlotSize(kind());
324
}
325

326
MaybeObject FeedbackNexus::GetFeedback() const {
327
  MaybeObject feedback = vector().Get(slot());
328 329 330
  FeedbackVector::AssertNoLegacyTypes(feedback);
  return feedback;
}
331

332
MaybeObject FeedbackNexus::GetFeedbackExtra() const {
333
#ifdef DEBUG
334
  FeedbackSlotKind kind = vector().GetKind(slot());
335
  DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
336
#endif
337 338
  int extra_index = vector().GetIndex(slot()) + 1;
  return vector().get(extra_index);
339 340
}

341
void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
342 343 344
  SetFeedback(MaybeObject::FromObject(feedback));
}

345
void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
346
  FeedbackVector::AssertNoLegacyTypes(feedback);
347
  vector().Set(slot(), feedback, mode);
348 349
}

350
void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
351
                                     WriteBarrierMode mode) {
352
#ifdef DEBUG
353
  FeedbackSlotKind kind = vector().GetKind(slot());
354
  DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
355
  FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
356
#endif
357 358
  int index = vector().GetIndex(slot()) + 1;
  vector().set(index, MaybeObject::FromObject(feedback_extra), mode);
359 360
}

361
void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
362 363
                                     WriteBarrierMode mode) {
#ifdef DEBUG
364
  FeedbackVector::AssertNoLegacyTypes(feedback_extra);
365
#endif
366 367
  int index = vector().GetIndex(slot()) + 1;
  vector().set(index, feedback_extra, mode);
368 369
}

370
Isolate* FeedbackNexus::GetIsolate() const { return vector().GetIsolate(); }
371 372
}  // namespace internal
}  // namespace v8
373

374 375
#include "src/objects/object-macros-undef.h"

376
#endif  // V8_OBJECTS_FEEDBACK_VECTOR_INL_H_