2014-09-18 09:59:53 +00:00
|
|
|
// Copyright 2014 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.
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
#ifndef V8_FEEDBACK_VECTOR_H_
|
|
|
|
#define V8_FEEDBACK_VECTOR_H_
|
2014-09-18 09:59:53 +00:00
|
|
|
|
2014-11-27 16:36:18 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2015-10-12 15:21:20 +00:00
|
|
|
#include "src/base/logging.h"
|
2014-09-18 09:59:53 +00:00
|
|
|
#include "src/elements-kind.h"
|
|
|
|
#include "src/objects.h"
|
2016-09-20 13:53:32 +00:00
|
|
|
#include "src/type-hints.h"
|
2016-09-20 16:07:25 +00:00
|
|
|
#include "src/zone/zone-containers.h"
|
2014-09-18 09:59:53 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
enum class FeedbackSlotKind {
|
2015-10-01 13:48:05 +00:00
|
|
|
// 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.
|
2017-02-07 17:49:58 +00:00
|
|
|
kInvalid,
|
|
|
|
|
|
|
|
kCall,
|
|
|
|
kLoadProperty,
|
|
|
|
kLoadGlobalNotInsideTypeof,
|
|
|
|
kLoadGlobalInsideTypeof,
|
|
|
|
kLoadKeyed,
|
|
|
|
kStorePropertySloppy,
|
|
|
|
kStorePropertyStrict,
|
|
|
|
kStoreKeyedSloppy,
|
|
|
|
kStoreKeyedStrict,
|
|
|
|
kBinaryOp,
|
|
|
|
kCompareOp,
|
|
|
|
kToBoolean,
|
|
|
|
kStoreDataPropertyInLiteral,
|
|
|
|
kCreateClosure,
|
|
|
|
kLiteral,
|
2015-10-01 13:48:05 +00:00
|
|
|
// This is a general purpose slot that occupies one feedback vector element.
|
2017-02-07 17:49:58 +00:00
|
|
|
kGeneral,
|
2015-10-01 13:48:05 +00:00
|
|
|
|
2017-02-07 17:49:58 +00:00
|
|
|
kKindsNumber // Last value indicating number of kinds.
|
2015-09-28 08:23:35 +00:00
|
|
|
};
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsCallICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kCall;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsLoadICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kLoadProperty;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof ||
|
|
|
|
kind == FeedbackSlotKind::kLoadGlobalInsideTypeof;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kLoadKeyed;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsStoreICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kStorePropertySloppy ||
|
|
|
|
kind == FeedbackSlotKind::kStorePropertyStrict;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
|
2017-02-07 17:49:58 +00:00
|
|
|
return kind == FeedbackSlotKind::kStoreKeyedSloppy ||
|
|
|
|
kind == FeedbackSlotKind::kStoreKeyedStrict;
|
2017-02-06 09:31:52 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
|
2017-02-07 09:03:16 +00:00
|
|
|
DCHECK(IsLoadGlobalICKind(kind));
|
2017-02-07 17:49:58 +00:00
|
|
|
return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof)
|
2017-02-07 09:03:16 +00:00
|
|
|
? INSIDE_TYPEOF
|
|
|
|
: NOT_INSIDE_TYPEOF;
|
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
|
2017-02-06 09:31:52 +00:00
|
|
|
DCHECK(IsStoreICKind(kind) || IsKeyedStoreICKind(kind));
|
2017-02-07 17:49:58 +00:00
|
|
|
return (kind == FeedbackSlotKind::kStorePropertySloppy ||
|
|
|
|
kind == FeedbackSlotKind::kStoreKeyedSloppy)
|
2017-02-06 09:31:52 +00:00
|
|
|
? SLOPPY
|
|
|
|
: STRICT;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind);
|
2015-09-28 08:23:35 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
template <typename Derived>
|
|
|
|
class FeedbackVectorSpecBase {
|
2014-11-27 16:36:18 +00:00
|
|
|
public:
|
2017-02-07 17:49:58 +00:00
|
|
|
FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); }
|
2015-03-17 15:16:21 +00:00
|
|
|
|
2017-02-07 17:49:58 +00:00
|
|
|
FeedbackSlot AddLoadICSlot() {
|
|
|
|
return AddSlot(FeedbackSlotKind::kLoadProperty);
|
|
|
|
}
|
2015-03-17 15:16:21 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) {
|
|
|
|
return AddSlot(typeof_mode == INSIDE_TYPEOF
|
2017-02-07 17:49:58 +00:00
|
|
|
? FeedbackSlotKind::kLoadGlobalInsideTypeof
|
|
|
|
: FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
|
2016-06-14 13:20:42 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddCreateClosureSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kCreateClosure);
|
2017-01-09 15:31:00 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddKeyedLoadICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kLoadKeyed);
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
|
2017-02-06 09:31:52 +00:00
|
|
|
STATIC_ASSERT(LANGUAGE_END == 2);
|
|
|
|
return AddSlot(is_strict(language_mode)
|
2017-02-07 17:49:58 +00:00
|
|
|
? FeedbackSlotKind::kStorePropertyStrict
|
|
|
|
: FeedbackSlotKind::kStorePropertySloppy);
|
2015-10-01 13:48:05 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
|
2017-02-06 09:31:52 +00:00
|
|
|
STATIC_ASSERT(LANGUAGE_END == 2);
|
|
|
|
return AddSlot(is_strict(language_mode)
|
2017-02-07 17:49:58 +00:00
|
|
|
? FeedbackSlotKind::kStoreKeyedStrict
|
|
|
|
: FeedbackSlotKind::kStoreKeyedSloppy);
|
2015-10-01 13:48:05 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddInterpreterBinaryOpICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kBinaryOp);
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddInterpreterCompareICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kCompareOp);
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
2017-02-07 17:49:58 +00:00
|
|
|
FeedbackSlot AddGeneralSlot() { return AddSlot(FeedbackSlotKind::kGeneral); }
|
2016-06-24 14:08:09 +00:00
|
|
|
|
2017-02-07 17:49:58 +00:00
|
|
|
FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); }
|
2017-01-30 12:31:35 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddStoreDataPropertyInLiteralICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
|
2017-01-05 07:30:01 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 14:08:09 +00:00
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
|
|
|
DECLARE_PRINTER(FeedbackVectorSpec)
|
|
|
|
|
|
|
|
private:
|
2017-02-07 15:19:35 +00:00
|
|
|
inline FeedbackSlot AddSlot(FeedbackSlotKind kind);
|
2017-02-06 09:31:52 +00:00
|
|
|
|
2016-06-24 14:08:09 +00:00
|
|
|
Derived* This() { return static_cast<Derived*>(this); }
|
2015-03-17 15:16:21 +00:00
|
|
|
};
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
class StaticFeedbackVectorSpec
|
|
|
|
: public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
|
2015-03-17 15:16:21 +00:00
|
|
|
public:
|
2017-01-26 12:08:35 +00:00
|
|
|
StaticFeedbackVectorSpec() : slot_count_(0) {}
|
2015-03-17 15:16:21 +00:00
|
|
|
|
2016-06-24 14:08:09 +00:00
|
|
|
int slots() const { return slot_count_; }
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const {
|
2017-02-06 09:31:52 +00:00
|
|
|
DCHECK(slot.ToInt() >= 0 && slot.ToInt() < slot_count_);
|
|
|
|
return kinds_[slot.ToInt()];
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
private:
|
|
|
|
friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
|
2015-09-28 11:41:40 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
void append(FeedbackSlotKind kind) {
|
2016-06-24 14:08:09 +00:00
|
|
|
DCHECK(slot_count_ < kMaxLength);
|
|
|
|
kinds_[slot_count_++] = kind;
|
|
|
|
}
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
static const int kMaxLength = 12;
|
2015-09-28 11:41:40 +00:00
|
|
|
|
2016-06-24 14:08:09 +00:00
|
|
|
int slot_count_;
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind kinds_[kMaxLength];
|
2015-10-01 13:48:05 +00:00
|
|
|
};
|
2015-09-28 11:41:40 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
|
|
|
|
public:
|
2017-01-26 12:08:35 +00:00
|
|
|
explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
|
2015-10-01 13:48:05 +00:00
|
|
|
slot_kinds_.reserve(16);
|
2015-09-28 11:41:40 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
int slots() const { return static_cast<int>(slot_kinds_.size()); }
|
2015-09-28 11:41:40 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const {
|
|
|
|
return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
|
2015-09-28 11:41:40 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
private:
|
|
|
|
friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
void append(FeedbackSlotKind kind) {
|
2015-10-01 13:48:05 +00:00
|
|
|
slot_kinds_.push_back(static_cast<unsigned char>(kind));
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
ZoneVector<unsigned char> slot_kinds_;
|
2014-11-27 16:36:18 +00:00
|
|
|
};
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
// The shape of the FeedbackMetadata is an array with:
|
2015-10-01 13:48:05 +00:00
|
|
|
// 0: slot_count
|
2016-06-24 14:08:09 +00:00
|
|
|
// 1: names table
|
2017-01-09 15:31:00 +00:00
|
|
|
// 2: parameters table
|
|
|
|
// 3..N: slot kinds packed into a bit vector
|
2015-10-07 10:33:22 +00:00
|
|
|
//
|
2017-02-07 14:05:02 +00:00
|
|
|
class FeedbackMetadata : public FixedArray {
|
2015-10-07 10:33:22 +00:00
|
|
|
public:
|
|
|
|
// Casting.
|
2017-02-07 14:05:02 +00:00
|
|
|
static inline FeedbackMetadata* cast(Object* obj);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
static const int kSlotsCountIndex = 0;
|
2017-01-26 12:08:35 +00:00
|
|
|
static const int kReservedIndexCount = 1;
|
2016-06-24 14:08:09 +00:00
|
|
|
|
2015-10-07 10:33:22 +00:00
|
|
|
// Returns number of feedback vector elements used by given slot kind.
|
2017-02-07 15:19:35 +00:00
|
|
|
static inline int GetSlotSize(FeedbackSlotKind kind);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;
|
|
|
|
|
2016-05-27 08:09:12 +00:00
|
|
|
inline bool is_empty() const;
|
|
|
|
|
2015-10-07 10:33:22 +00:00
|
|
|
// Returns number of slots in the vector.
|
|
|
|
inline int slot_count() const;
|
|
|
|
|
|
|
|
// Returns slot kind for given slot.
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const;
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
template <typename Spec>
|
2017-02-07 14:05:02 +00:00
|
|
|
static Handle<FeedbackMetadata> New(Isolate* isolate, const Spec* spec);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
DECLARE_PRINTER(FeedbackMetadata)
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
static const char* Kind2String(FeedbackSlotKind kind);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
private:
|
2017-02-07 15:19:35 +00:00
|
|
|
static const int kFeedbackSlotKindBits = 5;
|
2017-02-07 17:49:58 +00:00
|
|
|
STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) <
|
2017-02-07 15:19:35 +00:00
|
|
|
(1 << kFeedbackSlotKindBits));
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
void SetKind(FeedbackSlot slot, FeedbackSlotKind kind);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, kSmiValueSize,
|
|
|
|
uint32_t>
|
2017-02-07 14:05:02 +00:00
|
|
|
VectorICComputer;
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata);
|
2015-10-07 10:33:22 +00:00
|
|
|
};
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
// The shape of the FeedbackVector is an array with:
|
2015-10-07 10:33:22 +00:00
|
|
|
// 0: feedback metadata
|
2016-09-14 10:20:08 +00:00
|
|
|
// 1: invocation count
|
|
|
|
// 2: feedback slot #0
|
2014-10-20 11:42:56 +00:00
|
|
|
// ...
|
2016-09-14 10:20:08 +00:00
|
|
|
// 2 + slot_count - 1: feedback slot #(slot_count-1)
|
2014-10-20 11:42:56 +00:00
|
|
|
//
|
2017-02-07 14:05:02 +00:00
|
|
|
class FeedbackVector : public FixedArray {
|
2014-09-18 09:59:53 +00:00
|
|
|
public:
|
|
|
|
// Casting.
|
2017-02-07 14:05:02 +00:00
|
|
|
static inline FeedbackVector* cast(Object* obj);
|
2014-09-18 09:59:53 +00:00
|
|
|
|
2017-02-08 08:33:33 +00:00
|
|
|
static const int kSharedFunctionInfoIndex = 0;
|
2016-09-14 10:20:08 +00:00
|
|
|
static const int kInvocationCountIndex = 1;
|
|
|
|
static const int kReservedIndexCount = 2;
|
2015-12-09 08:32:56 +00:00
|
|
|
|
2016-09-20 13:53:32 +00:00
|
|
|
inline void ComputeCounts(int* with_type_info, int* generic,
|
2016-09-23 15:30:18 +00:00
|
|
|
int* vector_ic_count, bool code_is_interpreted);
|
2015-04-14 12:31:33 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
inline bool is_empty() const;
|
|
|
|
|
|
|
|
// Returns number of slots in the vector.
|
2015-10-07 10:33:22 +00:00
|
|
|
inline int slot_count() const;
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
inline FeedbackMetadata* metadata() const;
|
2017-02-08 08:33:33 +00:00
|
|
|
inline SharedFunctionInfo* shared_function_info() const;
|
2016-09-14 10:20:08 +00:00
|
|
|
inline int invocation_count() const;
|
2017-02-10 08:21:03 +00:00
|
|
|
inline void clear_invocation_count();
|
2014-10-20 11:42:56 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
// Conversion from a slot to an integer index to the underlying array.
|
2017-02-07 15:19:35 +00:00
|
|
|
static int GetIndex(FeedbackSlot slot) {
|
2016-06-14 14:52:41 +00:00
|
|
|
return kReservedIndexCount + slot.ToInt();
|
|
|
|
}
|
2014-10-20 11:42:56 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
// Conversion from an integer index to the underlying array to a slot.
|
2017-02-07 15:19:35 +00:00
|
|
|
static inline FeedbackSlot ToSlot(int index);
|
|
|
|
inline Object* Get(FeedbackSlot slot) const;
|
|
|
|
inline void Set(FeedbackSlot slot, Object* value,
|
2015-09-01 12:28:09 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2014-10-20 11:42:56 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
// Returns slot kind for given slot.
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const;
|
2014-10-20 11:42:56 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
static Handle<FeedbackVector> New(Isolate* isolate,
|
2017-02-08 08:33:33 +00:00
|
|
|
Handle<SharedFunctionInfo> shared);
|
2014-10-20 11:42:56 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
static Handle<FeedbackVector> Copy(Isolate* isolate,
|
|
|
|
Handle<FeedbackVector> vector);
|
2014-09-18 09:59:53 +00:00
|
|
|
|
2017-02-01 16:22:03 +00:00
|
|
|
#define DEFINE_SLOT_KIND_PREDICATE(Name) \
|
2017-02-07 15:19:35 +00:00
|
|
|
bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
|
2017-02-01 16:22:03 +00:00
|
|
|
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
|
|
|
|
#undef DEFINE_SLOT_KIND_PREDICATE
|
|
|
|
|
2017-02-07 09:03:16 +00:00
|
|
|
// Returns typeof mode encoded into kind of given slot.
|
2017-02-07 15:19:35 +00:00
|
|
|
inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
|
|
|
|
return GetTypeofModeFromSlotKind(GetKind(slot));
|
2017-02-07 09:03:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-06 09:31:52 +00:00
|
|
|
// Returns language mode encoded into kind of given slot.
|
2017-02-07 15:19:35 +00:00
|
|
|
inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
|
|
|
|
return GetLanguageModeFromSlotKind(GetKind(slot));
|
2017-02-06 09:31:52 +00:00
|
|
|
}
|
|
|
|
|
2015-07-15 12:21:57 +00:00
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
DECLARE_PRINTER(FeedbackVector)
|
2015-07-15 12:21:57 +00:00
|
|
|
|
2015-10-01 13:48:05 +00:00
|
|
|
// Clears the vector slots.
|
2015-04-02 09:39:32 +00:00
|
|
|
void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
|
2015-10-01 13:48:05 +00:00
|
|
|
|
2015-04-02 09:39:32 +00:00
|
|
|
void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
|
|
|
|
ClearSlotsImpl(shared, false);
|
|
|
|
}
|
|
|
|
|
2014-09-18 12:31:31 +00:00
|
|
|
// The object that indicates an uninitialized cache.
|
2016-03-01 13:55:48 +00:00
|
|
|
static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
|
2014-09-18 12:31:31 +00:00
|
|
|
|
|
|
|
// The object that indicates a megamorphic state.
|
2016-03-01 13:55:48 +00:00
|
|
|
static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
|
2014-09-18 12:31:31 +00:00
|
|
|
|
|
|
|
// The object that indicates a premonomorphic state.
|
2016-03-01 13:55:48 +00:00
|
|
|
static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
|
2014-09-18 12:31:31 +00:00
|
|
|
|
|
|
|
// A raw version of the uninitialized sentinel that's safe to read during
|
|
|
|
// garbage collection (e.g., for patching the cache).
|
2016-03-01 13:55:48 +00:00
|
|
|
static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
|
2014-09-18 12:31:31 +00:00
|
|
|
|
2014-09-18 09:59:53 +00:00
|
|
|
private:
|
2015-04-02 09:39:32 +00:00
|
|
|
void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
|
2017-02-10 08:21:03 +00:00
|
|
|
static void AddToCodeCoverageList(Isolate* isolate,
|
|
|
|
Handle<FeedbackVector> vector);
|
2015-02-04 09:46:05 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
|
2014-09-18 09:59:53 +00:00
|
|
|
};
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2015-04-02 09:39:32 +00:00
|
|
|
// The following asserts protect an optimization in type feedback vector
|
|
|
|
// code that looks into the contents of a slot assuming to find a String,
|
|
|
|
// a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
|
|
|
|
STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
|
|
|
|
STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
|
|
|
|
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
|
|
|
|
STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
|
|
|
|
// Verify that an empty hash field looks like a tagged object, but can't
|
|
|
|
// possibly be confused with a pointer.
|
|
|
|
STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
|
|
|
|
STATIC_ASSERT(Name::kEmptyHashField == 0x3);
|
|
|
|
// Verify that a set hash field will not look like a tagged object.
|
|
|
|
STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
class FeedbackMetadataIterator {
|
2015-10-01 13:48:05 +00:00
|
|
|
public:
|
2017-02-07 14:05:02 +00:00
|
|
|
explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata)
|
2015-10-01 13:48:05 +00:00
|
|
|
: metadata_handle_(metadata),
|
2017-02-07 15:19:35 +00:00
|
|
|
next_slot_(FeedbackSlot(0)),
|
2017-02-07 17:49:58 +00:00
|
|
|
slot_kind_(FeedbackSlotKind::kInvalid) {}
|
2015-10-01 13:48:05 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
explicit FeedbackMetadataIterator(FeedbackMetadata* metadata)
|
2015-10-01 13:48:05 +00:00
|
|
|
: metadata_(metadata),
|
2017-02-07 15:19:35 +00:00
|
|
|
next_slot_(FeedbackSlot(0)),
|
2017-02-07 17:49:58 +00:00
|
|
|
slot_kind_(FeedbackSlotKind::kInvalid) {}
|
2015-10-01 13:48:05 +00:00
|
|
|
|
2016-06-06 14:17:29 +00:00
|
|
|
inline bool HasNext() const;
|
2015-10-01 13:48:05 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline FeedbackSlot Next();
|
2015-10-01 13:48:05 +00:00
|
|
|
|
|
|
|
// Returns slot kind of the last slot returned by Next().
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlotKind kind() const {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_);
|
|
|
|
DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_);
|
2015-10-01 13:48:05 +00:00
|
|
|
return slot_kind_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns entry size of the last slot returned by Next().
|
2016-06-06 14:17:29 +00:00
|
|
|
inline int entry_size() const;
|
2015-10-01 13:48:05 +00:00
|
|
|
|
|
|
|
private:
|
2017-02-07 14:05:02 +00:00
|
|
|
FeedbackMetadata* metadata() const {
|
2015-10-01 13:48:05 +00:00
|
|
|
return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The reason for having a handle and a raw pointer to the meta data is
|
|
|
|
// to have a single iterator implementation for both "handlified" and raw
|
|
|
|
// pointer use cases.
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackMetadata> metadata_handle_;
|
|
|
|
FeedbackMetadata* metadata_;
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot cur_slot_;
|
|
|
|
FeedbackSlot next_slot_;
|
|
|
|
FeedbackSlotKind slot_kind_;
|
2015-10-01 13:48:05 +00:00
|
|
|
};
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
// A FeedbackNexus is the combination of a FeedbackVector and a slot.
|
2014-10-28 16:05:08 +00:00
|
|
|
// Derived classes customize the update and retrieval of feedback.
|
|
|
|
class FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2014-10-28 16:05:08 +00:00
|
|
|
: vector_handle_(vector), vector_(NULL), slot_(slot) {}
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2014-10-28 16:05:08 +00:00
|
|
|
: vector_(vector), slot_(slot) {}
|
|
|
|
virtual ~FeedbackNexus() {}
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackVector> vector_handle() const {
|
2014-10-28 16:05:08 +00:00
|
|
|
DCHECK(vector_ == NULL);
|
|
|
|
return vector_handle_;
|
|
|
|
}
|
2017-02-07 14:05:02 +00:00
|
|
|
FeedbackVector* vector() const {
|
2014-10-28 16:05:08 +00:00
|
|
|
return vector_handle_.is_null() ? vector_ : *vector_handle_;
|
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot slot() const { return slot_; }
|
|
|
|
FeedbackSlotKind kind() const { return vector()->GetKind(slot()); }
|
2014-10-28 16:05:08 +00:00
|
|
|
|
|
|
|
InlineCacheState ic_state() const { return StateFromFeedback(); }
|
2016-02-20 19:05:47 +00:00
|
|
|
bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
|
2014-10-28 16:05:08 +00:00
|
|
|
Map* FindFirstMap() const {
|
|
|
|
MapHandleList maps;
|
|
|
|
ExtractMaps(&maps);
|
|
|
|
if (maps.length() > 0) return *maps.at(0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-27 16:36:18 +00:00
|
|
|
// TODO(mvstanton): remove FindAllMaps, it didn't survive a code review.
|
|
|
|
void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); }
|
|
|
|
|
2014-10-28 16:05:08 +00:00
|
|
|
virtual InlineCacheState StateFromFeedback() const = 0;
|
2015-03-17 11:28:09 +00:00
|
|
|
virtual int ExtractMaps(MapHandleList* maps) const;
|
2016-07-15 17:41:14 +00:00
|
|
|
virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
|
|
|
|
virtual bool FindHandlers(List<Handle<Object>>* code_list,
|
|
|
|
int length = -1) const;
|
2014-10-28 16:05:08 +00:00
|
|
|
virtual Name* FindFirstName() const { return NULL; }
|
|
|
|
|
2015-06-30 09:51:43 +00:00
|
|
|
virtual void ConfigureUninitialized();
|
|
|
|
virtual void ConfigurePremonomorphic();
|
|
|
|
virtual void ConfigureMegamorphic();
|
|
|
|
|
2015-09-01 12:28:09 +00:00
|
|
|
inline Object* GetFeedback() const;
|
|
|
|
inline Object* GetFeedbackExtra() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2015-09-01 12:28:09 +00:00
|
|
|
inline Isolate* GetIsolate() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2015-11-13 12:19:37 +00:00
|
|
|
protected:
|
2015-09-01 12:28:09 +00:00
|
|
|
inline void SetFeedback(Object* feedback,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
|
|
inline void SetFeedbackExtra(Object* feedback_extra,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2015-03-17 11:28:09 +00:00
|
|
|
|
2014-10-28 16:05:08 +00:00
|
|
|
Handle<FixedArray> EnsureArrayOfSize(int length);
|
2015-03-17 11:28:09 +00:00
|
|
|
Handle<FixedArray> EnsureExtraArrayOfSize(int length);
|
|
|
|
void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
|
2016-07-15 17:41:14 +00:00
|
|
|
List<Handle<Object>>* handlers);
|
2014-10-28 16:05:08 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// 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
|
|
|
|
// be done, like allocation.
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackVector> vector_handle_;
|
|
|
|
FeedbackVector* vector_;
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot slot_;
|
2014-10-28 16:05:08 +00:00
|
|
|
};
|
|
|
|
|
2015-12-04 07:33:44 +00:00
|
|
|
class CallICNexus final : public FeedbackNexus {
|
2014-10-28 16:05:08 +00:00
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2014-10-28 16:05:08 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsCallIC(slot));
|
2014-10-28 16:05:08 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
CallICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2014-10-28 16:05:08 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsCallIC(slot));
|
2014-10-28 16:05:08 +00:00
|
|
|
}
|
|
|
|
|
2014-11-27 16:36:18 +00:00
|
|
|
void Clear(Code* host);
|
|
|
|
|
2016-09-13 11:03:43 +00:00
|
|
|
void ConfigureUninitialized() override;
|
2014-10-28 16:05:08 +00:00
|
|
|
void ConfigureMonomorphicArray();
|
|
|
|
void ConfigureMonomorphic(Handle<JSFunction> function);
|
2015-11-13 12:19:37 +00:00
|
|
|
void ConfigureMegamorphic() final;
|
|
|
|
void ConfigureMegamorphic(int call_count);
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2015-11-13 12:19:37 +00:00
|
|
|
InlineCacheState StateFromFeedback() const final;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2015-11-13 12:19:37 +00:00
|
|
|
int ExtractMaps(MapHandleList* maps) const final {
|
2014-10-28 16:05:08 +00:00
|
|
|
// CallICs don't record map feedback.
|
|
|
|
return 0;
|
|
|
|
}
|
2016-07-15 17:41:14 +00:00
|
|
|
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
|
2014-10-28 16:05:08 +00:00
|
|
|
return MaybeHandle<Code>();
|
|
|
|
}
|
2016-07-15 17:41:14 +00:00
|
|
|
bool FindHandlers(List<Handle<Object>>* code_list,
|
|
|
|
int length = -1) const final {
|
2014-10-28 16:05:08 +00:00
|
|
|
return length == 0;
|
|
|
|
}
|
2015-06-25 08:43:28 +00:00
|
|
|
|
|
|
|
int ExtractCallCount();
|
2016-09-14 10:20:08 +00:00
|
|
|
|
|
|
|
// Compute the call frequency based on the call count and the invocation
|
|
|
|
// count (taken from the type feedback vector).
|
|
|
|
float ComputeCallFrequency();
|
2014-10-28 16:05:08 +00:00
|
|
|
};
|
2014-11-27 16:36:18 +00:00
|
|
|
|
|
|
|
class LoadICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2014-11-27 16:36:18 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsLoadIC(slot));
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
LoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2014-11-27 16:36:18 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsLoadIC(slot));
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
2016-07-15 17:41:14 +00:00
|
|
|
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2016-07-15 17:41:14 +00:00
|
|
|
void ConfigurePolymorphic(MapHandleList* maps,
|
|
|
|
List<Handle<Object>>* handlers);
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2015-04-20 13:08:11 +00:00
|
|
|
InlineCacheState StateFromFeedback() const override;
|
2014-11-27 16:36:18 +00:00
|
|
|
};
|
|
|
|
|
2016-06-14 13:20:42 +00:00
|
|
|
class LoadGlobalICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2016-06-14 13:20:42 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsLoadGlobalIC(slot));
|
2016-06-14 13:20:42 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2016-06-14 13:20:42 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsLoadGlobalIC(slot));
|
2016-06-14 13:20:42 +00:00
|
|
|
}
|
|
|
|
|
2016-06-15 12:34:57 +00:00
|
|
|
int ExtractMaps(MapHandleList* maps) const final {
|
|
|
|
// LoadGlobalICs don't record map feedback.
|
|
|
|
return 0;
|
|
|
|
}
|
2016-07-15 17:41:14 +00:00
|
|
|
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
|
2016-06-15 12:34:57 +00:00
|
|
|
return MaybeHandle<Code>();
|
|
|
|
}
|
2016-07-15 17:41:14 +00:00
|
|
|
bool FindHandlers(List<Handle<Object>>* code_list,
|
|
|
|
int length = -1) const final {
|
2016-06-15 12:34:57 +00:00
|
|
|
return length == 0;
|
|
|
|
}
|
|
|
|
|
2016-06-14 13:20:42 +00:00
|
|
|
void ConfigureMegamorphic() override { UNREACHABLE(); }
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
2016-06-15 12:34:57 +00:00
|
|
|
void ConfigureUninitialized() override;
|
|
|
|
void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
|
2016-11-17 12:18:22 +00:00
|
|
|
void ConfigureHandlerMode(Handle<Object> handler);
|
2016-06-15 12:34:57 +00:00
|
|
|
|
2016-06-14 13:20:42 +00:00
|
|
|
InlineCacheState StateFromFeedback() const override;
|
|
|
|
};
|
2014-11-27 16:36:18 +00:00
|
|
|
|
|
|
|
class KeyedLoadICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2014-11-27 16:36:18 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsKeyedLoadIC(slot));
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2014-11-27 16:36:18 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsKeyedLoadIC(slot));
|
2014-11-27 16:36:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
2015-06-30 09:51:43 +00:00
|
|
|
// name can be a null handle for element loads.
|
|
|
|
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
|
2016-07-26 17:51:25 +00:00
|
|
|
Handle<Object> handler);
|
2015-06-30 09:51:43 +00:00
|
|
|
// name can be null.
|
|
|
|
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
|
2016-07-15 17:41:14 +00:00
|
|
|
List<Handle<Object>>* handlers);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
2016-04-21 13:18:00 +00:00
|
|
|
void ConfigureMegamorphicKeyed(IcCheckType property_type);
|
|
|
|
|
|
|
|
IcCheckType GetKeyType() const;
|
2015-06-30 09:51:43 +00:00
|
|
|
InlineCacheState StateFromFeedback() const override;
|
|
|
|
Name* FindFirstName() const override;
|
|
|
|
};
|
|
|
|
|
|
|
|
class StoreICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2015-06-30 09:51:43 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsStoreIC(slot));
|
2015-06-30 09:51:43 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2015-06-30 09:51:43 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsStoreIC(slot));
|
2015-06-30 09:51:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
2016-10-24 10:00:04 +00:00
|
|
|
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
2016-07-15 17:41:14 +00:00
|
|
|
void ConfigurePolymorphic(MapHandleList* maps,
|
|
|
|
List<Handle<Object>>* handlers);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
|
|
|
InlineCacheState StateFromFeedback() const override;
|
|
|
|
};
|
|
|
|
|
|
|
|
class KeyedStoreICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2015-06-30 09:51:43 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsKeyedStoreIC(slot));
|
2015-06-30 09:51:43 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2015-06-30 09:51:43 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-01 16:22:03 +00:00
|
|
|
DCHECK(vector->IsKeyedStoreIC(slot));
|
2015-06-30 09:51:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
2014-11-27 16:36:18 +00:00
|
|
|
// name can be a null handle for element loads.
|
2015-02-17 15:33:26 +00:00
|
|
|
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
|
2016-10-24 10:00:04 +00:00
|
|
|
Handle<Object> handler);
|
2014-11-27 16:36:18 +00:00
|
|
|
// name can be null.
|
2015-02-17 15:33:26 +00:00
|
|
|
void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
|
2016-07-15 17:41:14 +00:00
|
|
|
List<Handle<Object>>* handlers);
|
2015-08-28 09:01:22 +00:00
|
|
|
void ConfigurePolymorphic(MapHandleList* maps,
|
|
|
|
MapHandleList* transitioned_maps,
|
2016-12-02 10:03:18 +00:00
|
|
|
List<Handle<Object>>* handlers);
|
2016-04-21 13:18:00 +00:00
|
|
|
void ConfigureMegamorphicKeyed(IcCheckType property_type);
|
2015-08-28 09:01:22 +00:00
|
|
|
|
|
|
|
KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
|
|
|
|
IcCheckType GetKeyType() const;
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2015-04-20 13:08:11 +00:00
|
|
|
InlineCacheState StateFromFeedback() const override;
|
|
|
|
Name* FindFirstName() const override;
|
2014-11-27 16:36:18 +00:00
|
|
|
};
|
2016-09-20 13:53:32 +00:00
|
|
|
|
|
|
|
class BinaryOpICNexus final : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2016-09-20 13:53:32 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
BinaryOpICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2016-09-20 13:53:32 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
|
|
|
InlineCacheState StateFromFeedback() const final;
|
|
|
|
BinaryOperationHint GetBinaryOperationFeedback() const;
|
|
|
|
|
|
|
|
int ExtractMaps(MapHandleList* maps) const final {
|
|
|
|
// BinaryOpICs don't record map feedback.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
|
|
|
|
return MaybeHandle<Code>();
|
|
|
|
}
|
|
|
|
bool FindHandlers(List<Handle<Object>>* code_list,
|
|
|
|
int length = -1) const final {
|
|
|
|
return length == 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class CompareICNexus final : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2016-09-20 13:53:32 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
CompareICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2016-09-20 13:53:32 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host);
|
|
|
|
|
|
|
|
InlineCacheState StateFromFeedback() const final;
|
|
|
|
CompareOperationHint GetCompareOperationFeedback() const;
|
|
|
|
|
|
|
|
int ExtractMaps(MapHandleList* maps) const final {
|
|
|
|
// BinaryOpICs don't record map feedback.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
|
|
|
|
return MaybeHandle<Code>();
|
|
|
|
}
|
|
|
|
bool FindHandlers(List<Handle<Object>>* code_list,
|
|
|
|
int length = -1) const final {
|
|
|
|
return length == 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-01-05 07:30:01 +00:00
|
|
|
class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
|
|
|
|
public:
|
2017-02-07 14:05:02 +00:00
|
|
|
StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector,
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot slot)
|
2017-01-05 07:30:01 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
|
2017-01-05 07:30:01 +00:00
|
|
|
vector->GetKind(slot));
|
|
|
|
}
|
2017-02-07 15:19:35 +00:00
|
|
|
StoreDataPropertyInLiteralICNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2017-01-05 07:30:01 +00:00
|
|
|
: FeedbackNexus(vector, slot) {
|
2017-02-07 17:49:58 +00:00
|
|
|
DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral,
|
2017-01-05 07:30:01 +00:00
|
|
|
vector->GetKind(slot));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(Code* host) { ConfigureUninitialized(); }
|
|
|
|
|
|
|
|
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
|
|
|
|
|
|
|
|
InlineCacheState StateFromFeedback() const override;
|
|
|
|
};
|
|
|
|
|
2016-09-20 13:53:32 +00:00
|
|
|
inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
|
|
|
|
inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
|
|
|
|
|
2015-09-30 13:46:56 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
2014-09-18 09:59:53 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
#endif // V8_FEEDBACK_VECTOR_H_
|