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"
|
2017-07-27 12:45:00 +00:00
|
|
|
#include "src/base/macros.h"
|
2014-09-18 09:59:53 +00:00
|
|
|
#include "src/elements-kind.h"
|
2017-12-08 14:07:56 +00:00
|
|
|
#include "src/globals.h"
|
2017-05-17 11:31:18 +00:00
|
|
|
#include "src/objects/map.h"
|
2017-06-12 11:08:30 +00:00
|
|
|
#include "src/objects/name.h"
|
2017-07-27 12:45:00 +00:00
|
|
|
#include "src/objects/object-macros.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,
|
|
|
|
|
2017-09-02 00:52:16 +00:00
|
|
|
// Sloppy kinds come first, for easy language mode testing.
|
|
|
|
kStoreGlobalSloppy,
|
|
|
|
kStoreNamedSloppy,
|
|
|
|
kStoreKeyedSloppy,
|
|
|
|
kLastSloppyKind = kStoreKeyedSloppy,
|
|
|
|
|
|
|
|
// Strict and language mode unaware kinds.
|
2017-02-07 17:49:58 +00:00
|
|
|
kCall,
|
|
|
|
kLoadProperty,
|
|
|
|
kLoadGlobalNotInsideTypeof,
|
|
|
|
kLoadGlobalInsideTypeof,
|
|
|
|
kLoadKeyed,
|
2017-03-23 16:46:53 +00:00
|
|
|
kStoreGlobalStrict,
|
2017-02-17 15:15:07 +00:00
|
|
|
kStoreNamedStrict,
|
|
|
|
kStoreOwnNamed,
|
2017-02-07 17:49:58 +00:00
|
|
|
kStoreKeyedStrict,
|
|
|
|
kBinaryOp,
|
|
|
|
kCompareOp,
|
|
|
|
kStoreDataPropertyInLiteral,
|
2017-03-16 15:01:31 +00:00
|
|
|
kTypeProfile,
|
2017-02-07 17:49:58 +00:00
|
|
|
kCreateClosure,
|
|
|
|
kLiteral,
|
2017-09-01 10:49:06 +00:00
|
|
|
kForIn,
|
2017-10-23 09:18:57 +00:00
|
|
|
kInstanceOf,
|
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-03-23 16:46:53 +00:00
|
|
|
inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
|
|
|
|
kind == FeedbackSlotKind::kStoreGlobalStrict;
|
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
inline bool IsStoreICKind(FeedbackSlotKind kind) {
|
2017-02-17 15:15:07 +00:00
|
|
|
return kind == FeedbackSlotKind::kStoreNamedSloppy ||
|
|
|
|
kind == FeedbackSlotKind::kStoreNamedStrict;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool IsStoreOwnICKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kStoreOwnNamed;
|
2017-02-01 16:22:03 +00:00
|
|
|
}
|
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
inline bool IsStoreDataPropertyInLiteralKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kStoreDataPropertyInLiteral;
|
|
|
|
}
|
|
|
|
|
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-12-18 18:35:25 +00:00
|
|
|
inline bool IsGlobalICKind(FeedbackSlotKind kind) {
|
|
|
|
return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
|
|
|
|
}
|
|
|
|
|
2017-03-22 11:51:07 +00:00
|
|
|
inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kTypeProfile;
|
|
|
|
}
|
|
|
|
|
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-17 15:15:07 +00:00
|
|
|
DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
|
2017-03-23 16:46:53 +00:00
|
|
|
IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
|
2017-09-02 00:52:16 +00:00
|
|
|
STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <=
|
|
|
|
FeedbackSlotKind::kLastSloppyKind);
|
|
|
|
STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <=
|
|
|
|
FeedbackSlotKind::kLastSloppyKind);
|
|
|
|
STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <=
|
|
|
|
FeedbackSlotKind::kLastSloppyKind);
|
2017-10-16 10:55:06 +00:00
|
|
|
return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy
|
|
|
|
: LanguageMode::kStrict;
|
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
|
|
|
|
2017-08-30 07:24:59 +00:00
|
|
|
typedef std::vector<Handle<Object>> ObjectHandles;
|
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
class FeedbackMetadata;
|
|
|
|
|
2017-07-27 12:45:00 +00:00
|
|
|
// A FeedbackVector has a fixed header with:
|
|
|
|
// - shared function info (which includes feedback metadata)
|
|
|
|
// - invocation count
|
|
|
|
// - runtime profiler ticks
|
|
|
|
// - optimized code cell (weak cell or Smi marker)
|
|
|
|
// followed by an array of feedback slots, of length determined by the feedback
|
|
|
|
// metadata.
|
|
|
|
class FeedbackVector : public HeapObject {
|
2017-07-25 11:24:21 +00:00
|
|
|
public:
|
|
|
|
// Casting.
|
|
|
|
static inline FeedbackVector* cast(Object* obj);
|
|
|
|
|
|
|
|
inline void ComputeCounts(int* with_type_info, int* generic,
|
2017-08-31 14:15:21 +00:00
|
|
|
int* vector_ic_count);
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
inline bool is_empty() const;
|
|
|
|
|
|
|
|
inline FeedbackMetadata* metadata() const;
|
2017-07-27 12:45:00 +00:00
|
|
|
|
|
|
|
// [shared_function_info]: The shared function info for the function with this
|
|
|
|
// feedback vector.
|
|
|
|
DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
|
|
|
|
|
|
|
|
// [optimized_code_cell]: WeakCell containing optimized code or a Smi marker
|
2017-08-02 08:23:36 +00:00
|
|
|
// defining optimization behaviour.
|
2017-07-27 12:45:00 +00:00
|
|
|
DECL_ACCESSORS(optimized_code_cell, Object)
|
|
|
|
|
|
|
|
// [length]: The length of the feedback vector (not including the header, i.e.
|
|
|
|
// the number of feedback slots).
|
|
|
|
DECL_INT32_ACCESSORS(length)
|
|
|
|
|
|
|
|
// [invocation_count]: The number of times this function has been invoked.
|
|
|
|
DECL_INT32_ACCESSORS(invocation_count)
|
|
|
|
|
|
|
|
// [invocation_count]: The number of times this function has been seen by the
|
|
|
|
// runtime profiler.
|
|
|
|
DECL_INT32_ACCESSORS(profiler_ticks)
|
|
|
|
|
2017-07-31 15:01:44 +00:00
|
|
|
// [deopt_count]: The number of times this function has deoptimized.
|
|
|
|
DECL_INT32_ACCESSORS(deopt_count)
|
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
inline void clear_invocation_count();
|
2017-07-31 15:01:44 +00:00
|
|
|
inline void increment_deopt_count();
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
inline Code* optimized_code() const;
|
|
|
|
inline OptimizationMarker optimization_marker() const;
|
|
|
|
inline bool has_optimized_code() const;
|
|
|
|
inline bool has_optimization_marker() const;
|
|
|
|
void ClearOptimizedCode();
|
|
|
|
void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo* shared,
|
|
|
|
const char* reason);
|
|
|
|
static void SetOptimizedCode(Handle<FeedbackVector> vector,
|
|
|
|
Handle<Code> code);
|
|
|
|
void SetOptimizationMarker(OptimizationMarker marker);
|
|
|
|
|
2017-11-30 15:23:42 +00:00
|
|
|
// Clears the optimization marker in the feedback vector.
|
|
|
|
void ClearOptimizationMarker();
|
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
// Conversion from a slot to an integer index to the underlying array.
|
2017-07-27 12:45:00 +00:00
|
|
|
static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); }
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
// Conversion from an integer index to the underlying array to a slot.
|
|
|
|
static inline FeedbackSlot ToSlot(int index);
|
|
|
|
inline Object* Get(FeedbackSlot slot) const;
|
2017-07-27 12:45:00 +00:00
|
|
|
inline Object* get(int index) const;
|
2017-07-25 11:24:21 +00:00
|
|
|
inline void Set(FeedbackSlot slot, Object* value,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2017-07-27 12:45:00 +00:00
|
|
|
inline void set(int index, Object* value,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
|
|
|
|
|
|
// Gives access to raw memory which stores the array's data.
|
|
|
|
inline Object** slots_start();
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
// Returns slot kind for given slot.
|
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const;
|
|
|
|
|
|
|
|
FeedbackSlot GetTypeProfileSlot() const;
|
|
|
|
|
2018-02-22 14:41:23 +00:00
|
|
|
V8_EXPORT_PRIVATE static Handle<FeedbackVector> New(
|
|
|
|
Isolate* isolate, Handle<SharedFunctionInfo> shared);
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
static Handle<FeedbackVector> Copy(Isolate* isolate,
|
|
|
|
Handle<FeedbackVector> vector);
|
|
|
|
|
|
|
|
#define DEFINE_SLOT_KIND_PREDICATE(Name) \
|
|
|
|
bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
|
|
|
|
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
|
2017-12-18 18:35:25 +00:00
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC)
|
2017-07-25 11:24:21 +00:00
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
|
|
|
|
DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
|
|
|
|
#undef DEFINE_SLOT_KIND_PREDICATE
|
|
|
|
|
|
|
|
// Returns typeof mode encoded into kind of given slot.
|
|
|
|
inline TypeofMode GetTypeofMode(FeedbackSlot slot) const {
|
|
|
|
return GetTypeofModeFromSlotKind(GetKind(slot));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns language mode encoded into kind of given slot.
|
|
|
|
inline LanguageMode GetLanguageMode(FeedbackSlot slot) const {
|
|
|
|
return GetLanguageModeFromSlotKind(GetKind(slot));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
|
|
|
DECL_PRINTER(FeedbackVector)
|
2017-07-27 12:45:00 +00:00
|
|
|
DECL_VERIFIER(FeedbackVector)
|
2017-07-25 11:24:21 +00:00
|
|
|
|
2017-10-23 11:23:45 +00:00
|
|
|
void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot); // NOLINT
|
|
|
|
|
2017-09-05 07:29:09 +00:00
|
|
|
// Clears the vector slots. Return true if feedback has changed.
|
|
|
|
bool ClearSlots(Isolate* isolate);
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
// The object that indicates an uninitialized cache.
|
|
|
|
static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
|
|
|
|
|
2017-08-28 05:26:15 +00:00
|
|
|
// The object that indicates a generic state.
|
|
|
|
static inline Handle<Symbol> GenericSentinel(Isolate* isolate);
|
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
// The object that indicates a megamorphic state.
|
|
|
|
static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
|
|
|
|
|
|
|
|
// The object that indicates a premonomorphic state.
|
|
|
|
static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
|
|
|
|
|
|
|
|
// A raw version of the uninitialized sentinel that's safe to read during
|
|
|
|
// garbage collection (e.g., for patching the cache).
|
|
|
|
static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
|
|
|
|
|
2017-07-27 12:45:00 +00:00
|
|
|
// Layout description.
|
|
|
|
#define FEEDBACK_VECTOR_FIELDS(V) \
|
|
|
|
/* Header fields. */ \
|
|
|
|
V(kSharedFunctionInfoOffset, kPointerSize) \
|
|
|
|
V(kOptimizedCodeOffset, kPointerSize) \
|
|
|
|
V(kLengthOffset, kInt32Size) \
|
|
|
|
V(kInvocationCountOffset, kInt32Size) \
|
|
|
|
V(kProfilerTicksOffset, kInt32Size) \
|
2017-07-31 15:01:44 +00:00
|
|
|
V(kDeoptCountOffset, kInt32Size) \
|
2017-07-27 12:45:00 +00:00
|
|
|
V(kUnalignedHeaderSize, 0)
|
|
|
|
|
|
|
|
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS)
|
|
|
|
#undef FEEDBACK_VECTOR_FIELDS
|
|
|
|
|
|
|
|
static const int kHeaderSize =
|
|
|
|
RoundUp<kPointerAlignment>(kUnalignedHeaderSize);
|
|
|
|
static const int kFeedbackSlotsOffset = kHeaderSize;
|
|
|
|
|
|
|
|
class BodyDescriptor;
|
|
|
|
// No weak fields.
|
|
|
|
typedef BodyDescriptor BodyDescriptorWeak;
|
|
|
|
|
|
|
|
// Garbage collection support.
|
|
|
|
static constexpr int SizeFor(int length) {
|
|
|
|
return kFeedbackSlotsOffset + length * kPointerSize;
|
|
|
|
}
|
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
private:
|
2017-10-17 13:21:10 +00:00
|
|
|
static void AddToVectorsForProfilingTools(Isolate* isolate,
|
|
|
|
Handle<FeedbackVector> vector);
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector);
|
|
|
|
};
|
|
|
|
|
2018-01-31 14:29:45 +00:00
|
|
|
class V8_EXPORT_PRIVATE FeedbackVectorSpec {
|
2014-11-27 16:36:18 +00:00
|
|
|
public:
|
2018-01-31 14:29:45 +00:00
|
|
|
explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) {
|
|
|
|
slot_kinds_.reserve(16);
|
|
|
|
}
|
|
|
|
|
|
|
|
int slots() const { return static_cast<int>(slot_kinds_.size()); }
|
|
|
|
|
|
|
|
FeedbackSlotKind GetKind(FeedbackSlot slot) const {
|
|
|
|
return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt()));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool HasTypeProfileSlot() const;
|
|
|
|
|
|
|
|
// If used, the TypeProfileSlot is always added as the first slot and its
|
|
|
|
// index is constant. If other slots are added before the TypeProfileSlot,
|
|
|
|
// this number changes.
|
|
|
|
static const int kTypeProfileSlotIndex = 0;
|
|
|
|
|
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-10-16 10:55:06 +00:00
|
|
|
STATIC_ASSERT(LanguageModeSize == 2);
|
2017-02-06 09:31:52 +00:00
|
|
|
return AddSlot(is_strict(language_mode)
|
2017-02-17 15:15:07 +00:00
|
|
|
? FeedbackSlotKind::kStoreNamedStrict
|
|
|
|
: FeedbackSlotKind::kStoreNamedSloppy);
|
|
|
|
}
|
|
|
|
|
|
|
|
FeedbackSlot AddStoreOwnICSlot() {
|
|
|
|
return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
|
2015-10-01 13:48:05 +00:00
|
|
|
}
|
|
|
|
|
2017-03-23 16:46:53 +00:00
|
|
|
FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
|
2017-10-16 10:55:06 +00:00
|
|
|
STATIC_ASSERT(LanguageModeSize == 2);
|
2017-03-23 16:46:53 +00:00
|
|
|
return AddSlot(is_strict(language_mode)
|
|
|
|
? FeedbackSlotKind::kStoreGlobalStrict
|
|
|
|
: FeedbackSlotKind::kStoreGlobalSloppy);
|
|
|
|
}
|
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
|
2017-10-16 10:55:06 +00:00
|
|
|
STATIC_ASSERT(LanguageModeSize == 2);
|
2017-02-06 09:31:52 +00:00
|
|
|
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-10-19 15:12:42 +00:00
|
|
|
FeedbackSlot AddBinaryOpICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kBinaryOp);
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
2017-10-19 15:12:42 +00:00
|
|
|
FeedbackSlot AddCompareICSlot() {
|
2017-02-07 17:49:58 +00:00
|
|
|
return AddSlot(FeedbackSlotKind::kCompareOp);
|
2016-09-20 13:53:32 +00:00
|
|
|
}
|
|
|
|
|
2017-09-01 10:49:06 +00:00
|
|
|
FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); }
|
2016-06-24 14:08:09 +00:00
|
|
|
|
2017-10-23 09:18:57 +00:00
|
|
|
FeedbackSlot AddInstanceOfSlot() {
|
|
|
|
return AddSlot(FeedbackSlotKind::kInstanceOf);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-03-27 12:13:54 +00:00
|
|
|
FeedbackSlot AddTypeProfileSlot();
|
2017-03-16 15:01:31 +00:00
|
|
|
|
2016-06-24 14:08:09 +00:00
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
2017-06-29 13:14:20 +00:00
|
|
|
DECL_PRINTER(FeedbackVectorSpec)
|
2016-06-24 14:08:09 +00:00
|
|
|
|
|
|
|
private:
|
2017-09-13 10:56:20 +00:00
|
|
|
FeedbackSlot AddSlot(FeedbackSlotKind kind);
|
2017-02-06 09:31:52 +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
|
|
|
|
2018-01-31 14:29:45 +00:00
|
|
|
// If {spec} is null, then it is considered empty.
|
2018-02-22 14:41:23 +00:00
|
|
|
V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New(
|
|
|
|
Isolate* isolate, const FeedbackVectorSpec* spec = nullptr);
|
2015-10-07 10:33:22 +00:00
|
|
|
|
|
|
|
#ifdef OBJECT_PRINT
|
|
|
|
// For gdb debugging.
|
|
|
|
void Print();
|
|
|
|
#endif // OBJECT_PRINT
|
|
|
|
|
2017-06-29 13:14:20 +00:00
|
|
|
DECL_PRINTER(FeedbackMetadata)
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2017-02-07 15:19:35 +00:00
|
|
|
static const char* Kind2String(FeedbackSlotKind kind);
|
2017-03-27 12:13:54 +00:00
|
|
|
bool HasTypeProfileSlot() const;
|
2017-03-16 15:01:31 +00:00
|
|
|
|
2015-10-07 10:33:22 +00:00
|
|
|
private:
|
2017-09-02 00:52:16 +00:00
|
|
|
friend class AccessorAssembler;
|
|
|
|
|
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
|
|
|
};
|
|
|
|
|
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);
|
2017-07-10 09:48:02 +00:00
|
|
|
STATIC_ASSERT(WeakCell::kValueOffset ==
|
|
|
|
AllocationSite::kTransitionInfoOrBoilerplateOffset);
|
2015-04-02 09:39:32 +00:00
|
|
|
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.
|
2018-01-31 13:51:30 +00:00
|
|
|
class FeedbackNexus final {
|
2014-10-28 16:05:08 +00:00
|
|
|
public:
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
|
2018-01-31 13:51:30 +00:00
|
|
|
: vector_handle_(vector),
|
|
|
|
vector_(nullptr),
|
|
|
|
slot_(slot),
|
|
|
|
kind_(vector->GetKind(slot)) {}
|
2017-02-07 15:19:35 +00:00
|
|
|
FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot)
|
2018-01-31 13:51:30 +00:00
|
|
|
: vector_(vector), slot_(slot), kind_(vector->GetKind(slot)) {}
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackVector> vector_handle() const {
|
2017-10-18 09:06:55 +00:00
|
|
|
DCHECK_NULL(vector_);
|
2014-10-28 16:05:08 +00:00
|
|
|
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_; }
|
2018-01-31 13:51:30 +00:00
|
|
|
FeedbackSlotKind kind() const { return kind_; }
|
|
|
|
|
|
|
|
inline LanguageMode GetLanguageMode() const {
|
|
|
|
return vector()->GetLanguageMode(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; }
|
2017-08-28 05:26:15 +00:00
|
|
|
bool IsMegamorphic() const { return StateFromFeedback() == MEGAMORPHIC; }
|
|
|
|
bool IsGeneric() const { return StateFromFeedback() == GENERIC; }
|
2018-01-31 13:51:30 +00:00
|
|
|
|
|
|
|
void Print(std::ostream& os); // NOLINT
|
|
|
|
|
|
|
|
// For map-based ICs (load, keyed-load, store, keyed-store).
|
2014-10-28 16:05:08 +00:00
|
|
|
Map* FindFirstMap() const {
|
2017-05-09 22:36:00 +00:00
|
|
|
MapHandles maps;
|
2014-10-28 16:05:08 +00:00
|
|
|
ExtractMaps(&maps);
|
2017-05-09 22:36:00 +00:00
|
|
|
if (maps.size() > 0) return *maps.at(0);
|
2017-10-13 16:33:03 +00:00
|
|
|
return nullptr;
|
2014-10-28 16:05:08 +00:00
|
|
|
}
|
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
InlineCacheState StateFromFeedback() const;
|
|
|
|
int ExtractMaps(MapHandles* maps) const;
|
|
|
|
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
|
|
|
|
bool FindHandlers(ObjectHandles* code_list, int length = -1) const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
bool IsCleared() const {
|
2017-02-15 12:12:46 +00:00
|
|
|
InlineCacheState state = StateFromFeedback();
|
|
|
|
return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
|
|
|
|
}
|
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// Clear() returns true if the state of the underlying vector was changed.
|
|
|
|
bool Clear();
|
|
|
|
void ConfigureUninitialized();
|
2017-03-21 16:13:00 +00:00
|
|
|
void ConfigurePremonomorphic();
|
2017-11-17 18:38:23 +00:00
|
|
|
bool ConfigureMegamorphic(IcCheckType property_type);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
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
|
|
|
|
2017-03-21 16:13:00 +00:00
|
|
|
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
|
|
|
|
Handle<Object> handler);
|
|
|
|
|
2017-05-09 22:36:00 +00:00
|
|
|
void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
|
2017-08-30 07:24:59 +00:00
|
|
|
ObjectHandles* handlers);
|
2017-03-21 16:13:00 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
BinaryOperationHint GetBinaryOperationFeedback() const;
|
|
|
|
CompareOperationHint GetCompareOperationFeedback() const;
|
|
|
|
ForInHint GetForInFeedback() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For KeyedLoad ICs.
|
|
|
|
KeyedAccessLoadMode GetKeyedAccessLoadMode() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For KeyedStore ICs.
|
|
|
|
KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For KeyedLoad and KeyedStore ICs.
|
|
|
|
IcCheckType GetKeyType() const;
|
|
|
|
Name* FindFirstName() const;
|
2015-06-25 08:43:28 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For Call ICs.
|
2017-12-08 12:56:58 +00:00
|
|
|
int GetCallCount();
|
|
|
|
void SetSpeculationMode(SpeculationMode mode);
|
|
|
|
SpeculationMode GetSpeculationMode();
|
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();
|
2017-12-08 12:56:58 +00:00
|
|
|
|
|
|
|
typedef BitField<SpeculationMode, 0, 1> SpeculationModeField;
|
|
|
|
typedef BitField<uint32_t, 1, 31> CallCountField;
|
2014-11-27 16:36:18 +00:00
|
|
|
|
2018-02-22 12:04:01 +00:00
|
|
|
// For CreateClosure ICs.
|
|
|
|
Handle<FeedbackCell> GetFeedbackCell() const;
|
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For InstanceOf ICs.
|
|
|
|
MaybeHandle<JSObject> GetConstructorFeedback() const;
|
2017-12-13 09:30:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For Global Load and Store ICs.
|
2017-12-13 09:30:08 +00:00
|
|
|
void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
|
2017-12-18 18:35:25 +00:00
|
|
|
// Returns false if given combination of indices is not allowed.
|
|
|
|
bool ConfigureLexicalVarMode(int script_context_index,
|
|
|
|
int context_slot_index);
|
2017-12-13 09:30:08 +00:00
|
|
|
void ConfigureHandlerMode(Handle<Object> handler);
|
|
|
|
|
2017-12-18 18:35:25 +00:00
|
|
|
// Bit positions in a smi that encodes lexical environment variable access.
|
|
|
|
#define LEXICAL_MODE_BIT_FIELDS(V, _) \
|
|
|
|
V(ContextIndexBits, unsigned, 12, _) \
|
|
|
|
V(SlotIndexBits, unsigned, 19, _)
|
|
|
|
|
|
|
|
DEFINE_BIT_FIELDS(LEXICAL_MODE_BIT_FIELDS)
|
|
|
|
#undef LEXICAL_MODE_BIT_FIELDS
|
|
|
|
|
|
|
|
// Make sure we don't overflow the smi.
|
|
|
|
STATIC_ASSERT(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
// For TypeProfile feedback vector slots.
|
|
|
|
// ResetTypeProfile will always reset type profile information.
|
|
|
|
void ResetTypeProfile();
|
2017-03-16 15:01:31 +00:00
|
|
|
|
2017-04-03 14:08:32 +00:00
|
|
|
// Add a type to the list of types for source position <position>.
|
2017-03-31 08:40:38 +00:00
|
|
|
void Collect(Handle<String> type, int position);
|
2017-04-03 14:08:32 +00:00
|
|
|
JSObject* GetTypeProfile() const;
|
2017-03-16 15:01:31 +00:00
|
|
|
|
[type-profile] Incorporate into inspector protocol.
JavaScript is a dynamically typed language. But most code is
written with fixed types in mind. When debugging JavaScript,
it is helpful to know the types of variables and parameters
at runtime. It is often hard to infer types for complex code.
Type profiling provides this information at runtime.
Node.js uses the inspector protocol. This CL allows Node.js users
to access and analyse type profile for via Node modules or the
in-procress api. Type Profile helps developers to analyze
their code for correctness and performance.
Design doc: https://docs.google.com/a/google.com/document/d/1O1uepXZXBI6IwiawTrYC3ohhiNgzkyTdjn3R8ysbYgk/edit?usp=sharing
Add `takeTypeProfile` to the inspector protocol. It returns a list
of TypeProfileForScripts, which in turn contains the type profile for
each function. We can use TypeProfile data to annotate JavaScript code.
Sample script with data from TypeProfile:
function f(/*Object, number, undefined*/a,
/*Array, number, null*/b,
/*boolean, Object, symbol*/c) {
return 'bye';
/*string*/};
f({}, [], true);
f(3, 2.3, {a: 42});
f(undefined, null, Symbol('hello'));/*string*/
Bug: v8:5933
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: I626bfb886b752f90b9c86cc6953601558b18b60d
Reviewed-on: https://chromium-review.googlesource.com/508588
Commit-Queue: Franziska Hinkelmann <franzih@chromium.org>
Reviewed-by: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47920}
2017-09-08 08:28:29 +00:00
|
|
|
std::vector<int> GetSourcePositions() const;
|
|
|
|
std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const;
|
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
protected:
|
|
|
|
inline void SetFeedback(Object* feedback,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
|
|
inline void SetFeedbackExtra(Object* feedback_extra,
|
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
|
|
|
|
|
|
Handle<FixedArray> EnsureArrayOfSize(int length);
|
|
|
|
Handle<FixedArray> EnsureExtraArrayOfSize(int length);
|
[type-profile] Incorporate into inspector protocol.
JavaScript is a dynamically typed language. But most code is
written with fixed types in mind. When debugging JavaScript,
it is helpful to know the types of variables and parameters
at runtime. It is often hard to infer types for complex code.
Type profiling provides this information at runtime.
Node.js uses the inspector protocol. This CL allows Node.js users
to access and analyse type profile for via Node modules or the
in-procress api. Type Profile helps developers to analyze
their code for correctness and performance.
Design doc: https://docs.google.com/a/google.com/document/d/1O1uepXZXBI6IwiawTrYC3ohhiNgzkyTdjn3R8ysbYgk/edit?usp=sharing
Add `takeTypeProfile` to the inspector protocol. It returns a list
of TypeProfileForScripts, which in turn contains the type profile for
each function. We can use TypeProfile data to annotate JavaScript code.
Sample script with data from TypeProfile:
function f(/*Object, number, undefined*/a,
/*Array, number, null*/b,
/*boolean, Object, symbol*/c) {
return 'bye';
/*string*/};
f({}, [], true);
f(3, 2.3, {a: 42});
f(undefined, null, Symbol('hello'));/*string*/
Bug: v8:5933
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: I626bfb886b752f90b9c86cc6953601558b18b60d
Reviewed-on: https://chromium-review.googlesource.com/508588
Commit-Queue: Franziska Hinkelmann <franzih@chromium.org>
Reviewed-by: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47920}
2017-09-08 08:28:29 +00:00
|
|
|
|
2018-01-31 13:51:30 +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.
|
|
|
|
Handle<FeedbackVector> vector_handle_;
|
|
|
|
FeedbackVector* vector_;
|
|
|
|
FeedbackSlot slot_;
|
|
|
|
FeedbackSlotKind kind_;
|
2017-03-16 15:01:31 +00:00
|
|
|
};
|
|
|
|
|
2016-09-20 13:53:32 +00:00
|
|
|
inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
|
|
|
|
inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
|
2017-09-01 10:49:06 +00:00
|
|
|
inline ForInHint ForInHintFromFeedback(int type_feedback);
|
2016-09-20 13:53:32 +00:00
|
|
|
|
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_
|