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"
|
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
|
|
|
|
2018-11-30 19:58:04 +00:00
|
|
|
// Has to be the last include (doesn't have include guards):
|
|
|
|
#include "src/objects/object-macros.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,
|
2018-03-02 20:30:34 +00:00
|
|
|
kStoreInArrayLiteral,
|
2017-02-07 17:49:58 +00:00
|
|
|
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,
|
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases
As discussed in
https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#,
this CL introduces a new bytecode (CloneObject), and a new IC type.
In this prototype implementation, the type feedback looks like the
following:
Uninitialized case:
{ uninitialized_sentinel, uninitialized_sentinel }
Monomorphic case:
{ weak 'source' map, strong 'result' map }
Polymorphic case:
{ WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value }
Megamorphic case:
{ megamorphic_sentinel, cleared_Value }
In the fast case, Object cloning is done by allocating an object with
the saved result map, and a shallow clone of the fast properties from
the source object, as well as cloned fast elements from the source object.
If at any point the fast case can't be taken, the IC transitions to the
slow case and remains there.
This prototype CL does not include any TurboFan optimization, and the
CloneObject operation is merely reduced to a stub call.
It may still be possible to get some further improvements by somehow
incorporating compile-time boilerplate elements into the cloned object,
or simplifying how the boilerplate elements are inserted into the
object.
In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/
by about 8x, with substantial improvements over the Babel and ObjectAssign scores.
R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org
BUG=v8:7611
Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e
Reviewed-on: https://chromium-review.googlesource.com/1127472
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
|
|
|
kCloneObject,
|
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
|
|
|
}
|
|
|
|
|
2018-03-02 20:30:34 +00:00
|
|
|
inline bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kStoreInArrayLiteral;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases
As discussed in
https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#,
this CL introduces a new bytecode (CloneObject), and a new IC type.
In this prototype implementation, the type feedback looks like the
following:
Uninitialized case:
{ uninitialized_sentinel, uninitialized_sentinel }
Monomorphic case:
{ weak 'source' map, strong 'result' map }
Polymorphic case:
{ WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value }
Megamorphic case:
{ megamorphic_sentinel, cleared_Value }
In the fast case, Object cloning is done by allocating an object with
the saved result map, and a shallow clone of the fast properties from
the source object, as well as cloned fast elements from the source object.
If at any point the fast case can't be taken, the IC transitions to the
slow case and remains there.
This prototype CL does not include any TurboFan optimization, and the
CloneObject operation is merely reduced to a stub call.
It may still be possible to get some further improvements by somehow
incorporating compile-time boilerplate elements into the cloned object,
or simplifying how the boilerplate elements are inserted into the
object.
In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/
by about 8x, with substantial improvements over the Babel and ObjectAssign scores.
R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org
BUG=v8:7611
Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e
Reviewed-on: https://chromium-review.googlesource.com/1127472
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
|
|
|
inline bool IsCloneObjectKind(FeedbackSlotKind kind) {
|
|
|
|
return kind == FeedbackSlotKind::kCloneObject;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2018-05-14 11:38:37 +00:00
|
|
|
typedef std::vector<MaybeObjectHandle> MaybeObjectHandles;
|
2017-08-30 07:24:59 +00:00
|
|
|
|
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.
|
2018-12-20 15:47:47 +00:00
|
|
|
class FeedbackVector : public HeapObject {
|
2017-07-25 11:24:21 +00:00
|
|
|
public:
|
2018-11-30 19:58:04 +00:00
|
|
|
NEVER_READ_ONLY_SPACE
|
|
|
|
|
2019-01-08 12:58:31 +00:00
|
|
|
DECL_CAST(FeedbackVector)
|
2017-07-25 11:24:21 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2018-11-30 19:58:04 +00:00
|
|
|
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.
|
2019-01-08 12:58:31 +00:00
|
|
|
DECL_ACCESSORS(shared_function_info, SharedFunctionInfo)
|
2017-07-27 12:45:00 +00:00
|
|
|
|
2018-03-05 13:18:51 +00:00
|
|
|
// [optimized_code_weak_or_smi]: weak reference to optimized code or a Smi
|
|
|
|
// marker defining optimization behaviour.
|
2019-01-08 12:58:31 +00:00
|
|
|
DECL_ACCESSORS(optimized_code_weak_or_smi, MaybeObject)
|
2017-07-27 12:45:00 +00:00
|
|
|
|
|
|
|
// [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
|
|
|
|
2018-11-08 21:42:34 +00:00
|
|
|
inline Code optimized_code() const;
|
2017-07-25 11:24:21 +00:00
|
|
|
inline OptimizationMarker optimization_marker() const;
|
|
|
|
inline bool has_optimized_code() const;
|
|
|
|
inline bool has_optimization_marker() const;
|
|
|
|
void ClearOptimizedCode();
|
2018-11-28 19:57:30 +00:00
|
|
|
void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo shared,
|
2017-07-25 11:24:21 +00:00
|
|
|
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);
|
2018-10-26 00:23:24 +00:00
|
|
|
inline MaybeObject Get(FeedbackSlot slot) const;
|
|
|
|
inline MaybeObject get(int index) const;
|
|
|
|
inline void Set(FeedbackSlot slot, MaybeObject value,
|
2018-05-08 07:20:40 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-10-26 00:23:24 +00:00
|
|
|
inline void set(int index, MaybeObject value,
|
2018-05-08 07:20:40 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-12-25 00:19:47 +00:00
|
|
|
inline void Set(FeedbackSlot slot, Object value,
|
2017-07-25 11:24:21 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-12-25 00:19:47 +00:00
|
|
|
inline void set(int index, Object value,
|
2017-07-27 12:45:00 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
|
|
|
|
|
|
|
// Gives access to raw memory which stores the array's data.
|
2018-10-23 23:02:20 +00:00
|
|
|
inline MaybeObjectSlot 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
|
|
|
|
|
|
|
#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));
|
|
|
|
}
|
|
|
|
|
2018-10-26 00:23:24 +00:00
|
|
|
static void AssertNoLegacyTypes(MaybeObject object);
|
2018-05-08 07:20:40 +00:00
|
|
|
|
2017-07-25 11:24:21 +00:00
|
|
|
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).
|
2018-11-27 00:48:42 +00:00
|
|
|
static inline Symbol RawUninitializedSentinel(Isolate* isolate);
|
2017-07-25 11:24:21 +00:00
|
|
|
|
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 =
|
2018-11-19 15:44:21 +00:00
|
|
|
RoundUp<kObjectAlignment>(int{kUnalignedHeaderSize});
|
2017-07-27 12:45:00 +00:00
|
|
|
static const int kFeedbackSlotsOffset = kHeaderSize;
|
|
|
|
|
|
|
|
class BodyDescriptor;
|
|
|
|
|
|
|
|
// 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
|
|
|
|
2018-12-20 15:47:47 +00:00
|
|
|
OBJECT_CONSTRUCTORS(FeedbackVector, HeapObject);
|
2017-07-25 11:24:21 +00:00
|
|
|
};
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-09-05 07:50:48 +00:00
|
|
|
FeedbackSlotKind GetStoreICSlot(LanguageMode language_mode) {
|
Revert "[interpreter] Add bytecode for leading array spreads."
This reverts commit 1c48d52bb1ee9bb28e146c60eda08cd4afaa5745.
Reason for revert: Clusterfuzz found something.
Original change's description:
> [interpreter] Add bytecode for leading array spreads.
>
> This CL improves the performance of creating [...a, b] or [...a].
> If the array literal has a leading spread, this CL emits the bytecode
> [CreateArrayFromIterable] to create the literal. CreateArrayFromIterable
> is implemented by [IterableToListDefault] builtin to create the initial
> array for the leading spread. IterableToListDefault has a fast path to
> clone efficiently if the spread is an actual array.
>
> The bytecode generated is now shorter. Bytecode generation is refactored
> into to BuildCreateArrayLiteral, which allows VisitCallSuper to benefit
> from this optimization also.
> For now, turbofan also lowers the bytecode to the builtin.
>
> The idiomatic use of [...a] to clone the array a now performs better
> than a simple for-loop, but still does not match the performance of slice.
>
> Bug: v8:7980
>
> Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
> Change-Id: Ibde659c82d3c7aa1b1777a3d2f6426ac8cc15e35
> Reviewed-on: https://chromium-review.googlesource.com/1181024
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
> Reviewed-by: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Commit-Queue: Georg Neis <neis@chromium.org>
> Commit-Queue: Hai Dang <dhai@google.com>
> Cr-Commit-Position: refs/heads/master@{#55520}
TBR=rmcilroy@chromium.org,neis@chromium.org,sigurds@chromium.org,gsathya@chromium.org,jgruber@chromium.org,dhai@google.com
Change-Id: I1c86ddcc24274da9f5a8dd3d8bf8d869cbb55cb6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:7980
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/1199303
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55544}
2018-08-31 11:43:24 +00:00
|
|
|
STATIC_ASSERT(LanguageModeSize == 2);
|
2018-09-05 07:50:48 +00:00
|
|
|
return is_strict(language_mode) ? FeedbackSlotKind::kStoreNamedStrict
|
|
|
|
: FeedbackSlotKind::kStoreNamedSloppy;
|
|
|
|
}
|
|
|
|
|
|
|
|
FeedbackSlot AddStoreICSlot(LanguageMode language_mode) {
|
|
|
|
return AddSlot(GetStoreICSlot(language_mode));
|
2017-02-17 15:15:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-08-28 11:22:58 +00:00
|
|
|
FeedbackSlotKind GetKeyedStoreICSlotKind(LanguageMode language_mode) {
|
2017-10-16 10:55:06 +00:00
|
|
|
STATIC_ASSERT(LanguageModeSize == 2);
|
2018-08-28 11:22:58 +00:00
|
|
|
return is_strict(language_mode) ? FeedbackSlotKind::kStoreKeyedStrict
|
|
|
|
: FeedbackSlotKind::kStoreKeyedSloppy;
|
|
|
|
}
|
|
|
|
|
|
|
|
FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
|
|
|
|
return AddSlot(GetKeyedStoreICSlotKind(language_mode));
|
2015-10-01 13:48:05 +00:00
|
|
|
}
|
|
|
|
|
2018-03-02 20:30:34 +00:00
|
|
|
FeedbackSlot AddStoreInArrayLiteralICSlot() {
|
|
|
|
return AddSlot(FeedbackSlotKind::kStoreInArrayLiteral);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases
As discussed in
https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#,
this CL introduces a new bytecode (CloneObject), and a new IC type.
In this prototype implementation, the type feedback looks like the
following:
Uninitialized case:
{ uninitialized_sentinel, uninitialized_sentinel }
Monomorphic case:
{ weak 'source' map, strong 'result' map }
Polymorphic case:
{ WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value }
Megamorphic case:
{ megamorphic_sentinel, cleared_Value }
In the fast case, Object cloning is done by allocating an object with
the saved result map, and a shallow clone of the fast properties from
the source object, as well as cloned fast elements from the source object.
If at any point the fast case can't be taken, the IC transitions to the
slow case and remains there.
This prototype CL does not include any TurboFan optimization, and the
CloneObject operation is merely reduced to a stub call.
It may still be possible to get some further improvements by somehow
incorporating compile-time boilerplate elements into the cloned object,
or simplifying how the boilerplate elements are inserted into the
object.
In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/
by about 8x, with substantial improvements over the Babel and ObjectAssign scores.
R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org
BUG=v8:7611
Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e
Reviewed-on: https://chromium-review.googlesource.com/1127472
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
|
|
|
FeedbackSlot AddCloneObjectSlot() {
|
|
|
|
return AddSlot(FeedbackSlotKind::kCloneObject);
|
|
|
|
}
|
|
|
|
|
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_;
|
2018-08-28 11:22:58 +00:00
|
|
|
|
|
|
|
friend class SharedFeedbackSlot;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Helper class that creates a feedback slot on-demand.
|
|
|
|
class SharedFeedbackSlot {
|
|
|
|
public:
|
|
|
|
// FeedbackSlot default constructor constructs an invalid slot.
|
|
|
|
SharedFeedbackSlot(FeedbackVectorSpec* spec, FeedbackSlotKind kind)
|
|
|
|
: kind_(kind), spec_(spec) {}
|
|
|
|
|
|
|
|
FeedbackSlot Get() {
|
|
|
|
if (slot_.IsInvalid()) slot_ = spec_->AddSlot(kind_);
|
|
|
|
return slot_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
FeedbackSlotKind kind_;
|
|
|
|
FeedbackSlot slot_;
|
|
|
|
FeedbackVectorSpec* spec_;
|
2014-11-27 16:36:18 +00:00
|
|
|
};
|
|
|
|
|
2018-03-09 12:52:04 +00:00
|
|
|
// FeedbackMetadata is an array-like object with a slot count (indicating how
|
|
|
|
// many slots are stored). We save space by packing several slots into an array
|
|
|
|
// of int32 data. The length is never stored - it is always calculated from
|
|
|
|
// slot_count. All instances are created through the static New function, and
|
|
|
|
// the number of slots is static once an instance is created.
|
2018-12-20 15:47:47 +00:00
|
|
|
class FeedbackMetadata : public HeapObject {
|
2015-10-07 10:33:22 +00:00
|
|
|
public:
|
2019-01-08 12:58:31 +00:00
|
|
|
DECL_CAST(FeedbackMetadata)
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2018-03-09 12:52:04 +00:00
|
|
|
// The number of slots that this metadata contains. Stored as an int32.
|
|
|
|
DECL_INT32_ACCESSORS(slot_count)
|
|
|
|
|
|
|
|
// Get slot_count using an acquire load.
|
|
|
|
inline int32_t synchronized_slot_count() const;
|
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 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
|
|
|
|
2017-06-29 13:14:20 +00:00
|
|
|
DECL_PRINTER(FeedbackMetadata)
|
2018-03-09 12:52:04 +00:00
|
|
|
DECL_VERIFIER(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
|
|
|
|
2018-03-09 12:52:04 +00:00
|
|
|
// Garbage collection support.
|
|
|
|
// This includes any necessary padding at the end of the object for pointer
|
|
|
|
// size alignment.
|
|
|
|
static int SizeFor(int slot_count) {
|
|
|
|
return OBJECT_POINTER_ALIGN(kHeaderSize + length(slot_count) * kInt32Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const int kSlotCountOffset = HeapObject::kHeaderSize;
|
|
|
|
static const int kHeaderSize = kSlotCountOffset + kInt32Size;
|
|
|
|
|
|
|
|
class BodyDescriptor;
|
|
|
|
|
2015-10-07 10:33:22 +00:00
|
|
|
private:
|
2017-09-02 00:52:16 +00:00
|
|
|
friend class AccessorAssembler;
|
|
|
|
|
2018-03-09 12:52:04 +00:00
|
|
|
// Raw accessors to the encoded slot data.
|
|
|
|
inline int32_t get(int index) const;
|
|
|
|
inline void set(int index, int32_t value);
|
|
|
|
|
|
|
|
// The number of int32 data fields needed to store {slot_count} slots.
|
|
|
|
// Does not include any extra padding for pointer size alignment.
|
|
|
|
static int length(int slot_count) {
|
|
|
|
return VectorICComputer::word_count(slot_count);
|
|
|
|
}
|
|
|
|
inline int length() const;
|
|
|
|
|
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
|
|
|
|
2018-03-09 12:52:04 +00:00
|
|
|
typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits,
|
|
|
|
kInt32Size * kBitsPerByte, uint32_t>
|
2017-02-07 14:05:02 +00:00
|
|
|
VectorICComputer;
|
2015-10-07 10:33:22 +00:00
|
|
|
|
2018-12-20 15:47:47 +00:00
|
|
|
OBJECT_CONSTRUCTORS(FeedbackMetadata, HeapObject);
|
2015-10-07 10:33:22 +00:00
|
|
|
};
|
|
|
|
|
2015-04-02 09:39:32 +00:00
|
|
|
// 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
|
|
|
|
2018-11-30 19:58:04 +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:
|
2018-11-30 19:58:04 +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_;
|
2018-11-30 19:58:04 +00:00
|
|
|
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-12-11 12:23:21 +00:00
|
|
|
: vector_handle_(vector), slot_(slot) {
|
|
|
|
kind_ =
|
|
|
|
(vector.is_null()) ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
|
|
|
|
}
|
2018-11-30 19:58:04 +00:00
|
|
|
FeedbackNexus(FeedbackVector vector, FeedbackSlot slot)
|
2018-12-11 12:23:21 +00:00
|
|
|
: vector_(vector), slot_(slot) {
|
|
|
|
kind_ =
|
|
|
|
(vector.is_null()) ? FeedbackSlotKind::kInvalid : vector->GetKind(slot);
|
|
|
|
}
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
Handle<FeedbackVector> vector_handle() const {
|
2018-11-30 19:58:04 +00:00
|
|
|
DCHECK(vector_.is_null());
|
2014-10-28 16:05:08 +00:00
|
|
|
return vector_handle_;
|
|
|
|
}
|
2018-11-30 19:58:04 +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).
|
2018-11-13 06:16:42 +00:00
|
|
|
Map FindFirstMap() const;
|
2014-10-28 16:05:08 +00:00
|
|
|
|
2018-01-31 13:51:30 +00:00
|
|
|
InlineCacheState StateFromFeedback() const;
|
|
|
|
int ExtractMaps(MapHandles* maps) const;
|
2018-05-14 11:38:37 +00:00
|
|
|
MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const;
|
|
|
|
bool FindHandlers(MaybeObjectHandles* 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();
|
2018-07-24 11:27:28 +00:00
|
|
|
void ConfigurePremonomorphic(Handle<Map> receiver_map);
|
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases
As discussed in
https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#,
this CL introduces a new bytecode (CloneObject), and a new IC type.
In this prototype implementation, the type feedback looks like the
following:
Uninitialized case:
{ uninitialized_sentinel, uninitialized_sentinel }
Monomorphic case:
{ weak 'source' map, strong 'result' map }
Polymorphic case:
{ WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value }
Megamorphic case:
{ megamorphic_sentinel, cleared_Value }
In the fast case, Object cloning is done by allocating an object with
the saved result map, and a shallow clone of the fast properties from
the source object, as well as cloned fast elements from the source object.
If at any point the fast case can't be taken, the IC transitions to the
slow case and remains there.
This prototype CL does not include any TurboFan optimization, and the
CloneObject operation is merely reduced to a stub call.
It may still be possible to get some further improvements by somehow
incorporating compile-time boilerplate elements into the cloned object,
or simplifying how the boilerplate elements are inserted into the
object.
In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/
by about 8x, with substantial improvements over the Babel and ObjectAssign scores.
R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org
BUG=v8:7611
Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e
Reviewed-on: https://chromium-review.googlesource.com/1127472
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
|
|
|
// ConfigureMegamorphic() returns true if the state of the underlying vector
|
|
|
|
// was changed. Extra feedback is cleared if the 0 parameter version is used.
|
|
|
|
bool ConfigureMegamorphic();
|
2017-11-17 18:38:23 +00:00
|
|
|
bool ConfigureMegamorphic(IcCheckType property_type);
|
2015-06-30 09:51:43 +00:00
|
|
|
|
2018-10-26 00:23:24 +00:00
|
|
|
inline MaybeObject GetFeedback() const;
|
|
|
|
inline MaybeObject 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,
|
2018-05-14 11:38:37 +00:00
|
|
|
const MaybeObjectHandle& handler);
|
2017-03-21 16:13:00 +00:00
|
|
|
|
2017-05-09 22:36:00 +00:00
|
|
|
void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps,
|
2018-05-14 11:38:37 +00:00
|
|
|
MaybeObjectHandles* 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;
|
2018-11-27 00:48:42 +00:00
|
|
|
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.
|
2019-01-17 14:31:01 +00:00
|
|
|
bool ConfigureLexicalVarMode(int script_context_index,
|
|
|
|
int context_slot_index);
|
2018-05-14 11:38:37 +00:00
|
|
|
void ConfigureHandlerMode(const MaybeObjectHandle& handler);
|
2017-12-13 09:30:08 +00:00
|
|
|
|
[runtime] use new CloneObject bytecode for some ObjectLiteralSpread cases
As discussed in
https://docs.google.com/document/d/1sBdGe8RHgeYP850cKSSgGABTyfMdvaEWLy-vertuTCo/edit?ts=5b3ba5cc#,
this CL introduces a new bytecode (CloneObject), and a new IC type.
In this prototype implementation, the type feedback looks like the
following:
Uninitialized case:
{ uninitialized_sentinel, uninitialized_sentinel }
Monomorphic case:
{ weak 'source' map, strong 'result' map }
Polymorphic case:
{ WeakFixedArray with { weak 'source' map, strong 'result' map }, cleared value }
Megamorphic case:
{ megamorphic_sentinel, cleared_Value }
In the fast case, Object cloning is done by allocating an object with
the saved result map, and a shallow clone of the fast properties from
the source object, as well as cloned fast elements from the source object.
If at any point the fast case can't be taken, the IC transitions to the
slow case and remains there.
This prototype CL does not include any TurboFan optimization, and the
CloneObject operation is merely reduced to a stub call.
It may still be possible to get some further improvements by somehow
incorporating compile-time boilerplate elements into the cloned object,
or simplifying how the boilerplate elements are inserted into the
object.
In terms of performance, we improve the ObjectSpread score in JSTests/ObjectLiteralSpread/
by about 8x, with substantial improvements over the Babel and ObjectAssign scores.
R=gsathya@chromium.org, mvstanton@chromium.org, rmcilroy@chromium.org, neis@chromium.org, bmeurer@chromium.org
BUG=v8:7611
Change-Id: I79e1796eb77016fb4feba0e1d3bb9abb348c183e
Reviewed-on: https://chromium-review.googlesource.com/1127472
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54595}
2018-07-20 15:24:04 +00:00
|
|
|
// For CloneObject ICs
|
|
|
|
static constexpr int kCloneObjectPolymorphicEntrySize = 2;
|
|
|
|
void ConfigureCloneObject(Handle<Map> source_map, Handle<Map> result_map);
|
|
|
|
|
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, _) \
|
2019-01-17 14:31:01 +00:00
|
|
|
V(SlotIndexBits, unsigned, 19, _)
|
2017-12-18 18:35:25 +00:00
|
|
|
|
|
|
|
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);
|
2018-12-08 02:59:17 +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-12-25 00:19:47 +00:00
|
|
|
inline void SetFeedback(Object feedback,
|
2018-01-31 13:51:30 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-10-26 00:23:24 +00:00
|
|
|
inline void SetFeedback(MaybeObject feedback,
|
2018-05-23 06:53:49 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-12-25 00:19:47 +00:00
|
|
|
inline void SetFeedbackExtra(Object feedback_extra,
|
2018-01-31 13:51:30 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-10-26 00:23:24 +00:00
|
|
|
inline void SetFeedbackExtra(MaybeObject feedback_extra,
|
2018-05-08 07:20:40 +00:00
|
|
|
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
|
2018-01-31 13:51:30 +00:00
|
|
|
|
2018-05-08 07:20:40 +00:00
|
|
|
Handle<WeakFixedArray> EnsureArrayOfSize(int length);
|
|
|
|
Handle<WeakFixedArray> 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_;
|
2018-11-30 19:58:04 +00:00
|
|
|
FeedbackVector vector_;
|
2018-01-31 13:51:30 +00:00
|
|
|
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
|
|
|
|
2018-11-30 19:58:04 +00:00
|
|
|
#include "src/objects/object-macros-undef.h"
|
|
|
|
|
2017-02-07 14:05:02 +00:00
|
|
|
#endif // V8_FEEDBACK_VECTOR_H_
|