Commit d0f234d0 authored by Franziska Hinkelmann's avatar Franziska Hinkelmann Committed by Commit Bot

[type-profile] Constant TypeProfileSlot index.

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.

BUG=v8:5933

Change-Id: I57bc6bea3c48804af28c2d1dafe6a52bdd7d12e3
Reviewed-on: https://chromium-review.googlesource.com/459511Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Franziska Hinkelmann <franzih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44149}
parent cd5c0095
...@@ -697,7 +697,7 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) { ...@@ -697,7 +697,7 @@ bool AstNumberingVisitor::Renumber(FunctionLiteral* node) {
LanguageModeScope language_mode_scope(this, node->language_mode()); LanguageModeScope language_mode_scope(this, node->language_mode());
if (collect_type_profile_) { if (collect_type_profile_) {
node->SetTypeProfileSlot(properties_.get_spec()->AddTypeProfileSlot()); properties_.get_spec()->AddTypeProfileSlot();
} }
VisitDeclarations(scope->declarations()); VisitDeclarations(scope->declarations());
......
...@@ -2618,10 +2618,7 @@ class FunctionLiteral final : public Expression { ...@@ -2618,10 +2618,7 @@ class FunctionLiteral final : public Expression {
literal_feedback_slot_ = spec->AddCreateClosureSlot(); literal_feedback_slot_ = spec->AddCreateClosureSlot();
} }
void SetTypeProfileSlot(FeedbackSlot slot) { type_profile_slot_ = slot; }
FeedbackSlot LiteralFeedbackSlot() const { return literal_feedback_slot_; } FeedbackSlot LiteralFeedbackSlot() const { return literal_feedback_slot_; }
FeedbackSlot TypeProfileSlot() const { return type_profile_slot_; }
static bool NeedsHomeObject(Expression* expr); static bool NeedsHomeObject(Expression* expr);
...@@ -2784,7 +2781,6 @@ class FunctionLiteral final : public Expression { ...@@ -2784,7 +2781,6 @@ class FunctionLiteral final : public Expression {
AstProperties ast_properties_; AstProperties ast_properties_;
int function_literal_id_; int function_literal_id_;
FeedbackSlot literal_feedback_slot_; FeedbackSlot literal_feedback_slot_;
FeedbackSlot type_profile_slot_;
}; };
// Property is used for passing information // Property is used for passing information
......
...@@ -809,13 +809,11 @@ void BytecodeGraphBuilder::VisitCollectTypeProfile() { ...@@ -809,13 +809,11 @@ void BytecodeGraphBuilder::VisitCollectTypeProfile() {
Node* position = Node* position =
jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
Node* value = environment()->LookupAccumulator(); Node* value = environment()->LookupAccumulator();
Node* index = jsgraph()->Constant(bytecode_iterator().GetIndexOperand(1));
Node* vector = jsgraph()->Constant(feedback_vector()); Node* vector = jsgraph()->Constant(feedback_vector());
const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile); const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile);
Node* node = NewNode(op, position, value, vector, index); Node* node = NewNode(op, position, value, vector);
environment()->RecordAfterState(node, Environment::kAttachFrameState); environment()->RecordAfterState(node, Environment::kAttachFrameState);
} }
......
...@@ -23,6 +23,15 @@ FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) { ...@@ -23,6 +23,15 @@ FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) {
return FeedbackSlot(slot); return FeedbackSlot(slot);
} }
template <typename Derived>
FeedbackSlot FeedbackVectorSpecBase<Derived>::AddTypeProfileSlot() {
DCHECK(FLAG_type_profile);
FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
FeedbackVector::GetIndex(slot));
return slot;
}
// static // static
FeedbackMetadata* FeedbackMetadata::cast(Object* obj) { FeedbackMetadata* FeedbackMetadata::cast(Object* obj) {
DCHECK(obj->IsFeedbackMetadata()); DCHECK(obj->IsFeedbackMetadata());
......
...@@ -12,6 +12,15 @@ ...@@ -12,6 +12,15 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
bool FeedbackVectorSpec::HasTypeProfileSlot() const {
FeedbackSlot slot =
FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
if (slots() <= slot.ToInt()) {
return false;
}
return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
}
static bool IsPropertyNameFeedback(Object* feedback) { static bool IsPropertyNameFeedback(Object* feedback) {
if (feedback->IsString()) return true; if (feedback->IsString()) return true;
if (!feedback->IsSymbol()) return false; if (!feedback->IsSymbol()) return false;
...@@ -164,16 +173,10 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) { ...@@ -164,16 +173,10 @@ const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
return "?"; return "?";
} }
bool FeedbackMetadata::HasTypeProfileSlot() { bool FeedbackMetadata::HasTypeProfileSlot() const {
FeedbackMetadataIterator iter(this); FeedbackSlot slot =
while (iter.HasNext()) { FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
iter.Next(); return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
FeedbackSlotKind kind = iter.kind();
if (kind == FeedbackSlotKind::kTypeProfile) {
return true;
}
}
return false;
} }
FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const { FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
...@@ -182,14 +185,11 @@ FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const { ...@@ -182,14 +185,11 @@ FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
} }
FeedbackSlot FeedbackVector::GetTypeProfileSlot() const { FeedbackSlot FeedbackVector::GetTypeProfileSlot() const {
FeedbackMetadataIterator iter(metadata()); DCHECK(metadata()->HasTypeProfileSlot());
while (iter.HasNext()) { FeedbackSlot slot =
FeedbackSlot slot = iter.Next(); FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
if (IsTypeProfile(slot)) { DCHECK_EQ(FeedbackSlotKind::kTypeProfile, GetKind(slot));
return slot; return slot;
}
}
return FeedbackSlot();
} }
// static // static
......
...@@ -170,10 +170,7 @@ class FeedbackVectorSpecBase { ...@@ -170,10 +170,7 @@ class FeedbackVectorSpecBase {
return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral); return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral);
} }
FeedbackSlot AddTypeProfileSlot() { FeedbackSlot AddTypeProfileSlot();
DCHECK(FLAG_type_profile);
return AddSlot(FeedbackSlotKind::kTypeProfile);
}
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
// For gdb debugging. // For gdb debugging.
...@@ -226,6 +223,13 @@ class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> { ...@@ -226,6 +223,13 @@ class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt())); 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 = 2;
private: private:
friend class FeedbackVectorSpecBase<FeedbackVectorSpec>; friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
...@@ -274,8 +278,7 @@ class FeedbackMetadata : public FixedArray { ...@@ -274,8 +278,7 @@ class FeedbackMetadata : public FixedArray {
DECLARE_PRINTER(FeedbackMetadata) DECLARE_PRINTER(FeedbackMetadata)
static const char* Kind2String(FeedbackSlotKind kind); static const char* Kind2String(FeedbackSlotKind kind);
bool HasTypeProfileSlot() const;
bool HasTypeProfileSlot();
private: private:
static const int kFeedbackSlotKindBits = 5; static const int kFeedbackSlotKindBits = 5;
......
...@@ -652,10 +652,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral( ...@@ -652,10 +652,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreDataPropertyInLiteral(
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile( BytecodeArrayBuilder& BytecodeArrayBuilder::CollectTypeProfile(int position) {
int position, int feedback_slot) {
DCHECK(FLAG_type_profile); DCHECK(FLAG_type_profile);
OutputCollectTypeProfile(position, feedback_slot); OutputCollectTypeProfile(position);
return *this; return *this;
} }
......
...@@ -140,8 +140,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -140,8 +140,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Collect type information for developer tools. The value for which we // Collect type information for developer tools. The value for which we
// record the type is stored in the accumulator. // record the type is stored in the accumulator.
// TODO(franzih): Do not pass the name, instead use the source position. BytecodeArrayBuilder& CollectTypeProfile(int position);
BytecodeArrayBuilder& CollectTypeProfile(int position, int feedback_slot);
// Store a property named by a property name. The value to be stored should be // Store a property named by a property name. The value to be stored should be
// in the accumulator. // in the accumulator.
......
...@@ -2023,10 +2023,8 @@ void BytecodeGenerator::BuildReturn() { ...@@ -2023,10 +2023,8 @@ void BytecodeGenerator::BuildReturn() {
builder()->StoreAccumulatorInRegister(result).CallRuntime( builder()->StoreAccumulatorInRegister(result).CallRuntime(
Runtime::kTraceExit, result); Runtime::kTraceExit, result);
} }
if (!info()->literal()->TypeProfileSlot().IsInvalid()) { if (info()->literal()->feedback_vector_spec()->HasTypeProfileSlot()) {
builder()->CollectTypeProfile( builder()->CollectTypeProfile(info()->literal()->position());
info()->literal()->position(),
feedback_index(info()->literal()->TypeProfileSlot()));
} }
builder()->Return(); builder()->Return();
} }
......
...@@ -105,8 +105,7 @@ namespace interpreter { ...@@ -105,8 +105,7 @@ namespace interpreter {
OperandType::kReg, OperandType::kIdx) \ OperandType::kReg, OperandType::kIdx) \
V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \ V(StaDataPropertyInLiteral, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kReg, OperandType::kFlag8, OperandType::kIdx) \ OperandType::kReg, OperandType::kFlag8, OperandType::kIdx) \
V(CollectTypeProfile, AccumulatorUse::kRead, OperandType::kImm, \ V(CollectTypeProfile, AccumulatorUse::kRead, OperandType::kImm) \
OperandType::kIdx) \
\ \
/* Binary Operators */ \ /* Binary Operators */ \
V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \ V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
......
...@@ -820,13 +820,12 @@ void InterpreterGenerator::DoCollectTypeProfile( ...@@ -820,13 +820,12 @@ void InterpreterGenerator::DoCollectTypeProfile(
InterpreterAssembler* assembler) { InterpreterAssembler* assembler) {
Node* position = __ BytecodeOperandImmSmi(0); Node* position = __ BytecodeOperandImmSmi(0);
Node* value = __ GetAccumulator(); Node* value = __ GetAccumulator();
Node* vector_index = __ SmiTag(__ BytecodeOperandIdx(1));
Node* feedback_vector = __ LoadFeedbackVector(); Node* feedback_vector = __ LoadFeedbackVector();
Node* context = __ GetContext(); Node* context = __ GetContext();
__ CallRuntime(Runtime::kCollectTypeProfile, context, position, value, __ CallRuntime(Runtime::kCollectTypeProfile, context, position, value,
feedback_vector, vector_index); feedback_vector);
__ Dispatch(); __ Dispatch();
} }
......
...@@ -700,11 +700,10 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) { ...@@ -700,11 +700,10 @@ RUNTIME_FUNCTION(Runtime_DefineDataPropertyInLiteral) {
RUNTIME_FUNCTION(Runtime_CollectTypeProfile) { RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(4, args.length()); DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(Smi, position, 0); CONVERT_ARG_HANDLE_CHECKED(Smi, position, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2); CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 2);
CONVERT_SMI_ARG_CHECKED(index, 3);
DCHECK(FLAG_type_profile); DCHECK(FLAG_type_profile);
...@@ -714,8 +713,8 @@ RUNTIME_FUNCTION(Runtime_CollectTypeProfile) { ...@@ -714,8 +713,8 @@ RUNTIME_FUNCTION(Runtime_CollectTypeProfile) {
type = JSReceiver::GetConstructorName(object); type = JSReceiver::GetConstructorName(object);
} }
DCHECK(!vector->ToSlot(index).IsInvalid()); DCHECK(vector->metadata()->HasTypeProfileSlot());
CollectTypeProfileNexus nexus(vector, vector->ToSlot(index)); CollectTypeProfileNexus nexus(vector, vector->GetTypeProfileSlot());
nexus.Collect(type, position->value()); nexus.Collect(type, position->value());
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
......
...@@ -225,8 +225,8 @@ RUNTIME_FUNCTION(Runtime_PrintTypeProfile) { ...@@ -225,8 +225,8 @@ RUNTIME_FUNCTION(Runtime_PrintTypeProfile) {
Object* function_name = vector->shared_function_info()->name(); Object* function_name = vector->shared_function_info()->name();
PrintF("Function: %s\n", String::cast(function_name)->ToCString().get()); PrintF("Function: %s\n", String::cast(function_name)->ToCString().get());
FeedbackSlot slot = vector->GetTypeProfileSlot(); if (vector->metadata()->HasTypeProfileSlot()) {
if (!slot.IsInvalid()) { FeedbackSlot slot = vector->GetTypeProfileSlot();
CollectTypeProfileNexus nexus(vector, slot); CollectTypeProfileNexus nexus(vector, slot);
nexus.Print(); nexus.Print();
PrintF("\n"); PrintF("\n");
......
...@@ -396,7 +396,7 @@ namespace internal { ...@@ -396,7 +396,7 @@ namespace internal {
F(IsJSGlobalProxy, 1, 1) \ F(IsJSGlobalProxy, 1, 1) \
F(DefineAccessorPropertyUnchecked, 5, 1) \ F(DefineAccessorPropertyUnchecked, 5, 1) \
F(DefineDataPropertyInLiteral, 6, 1) \ F(DefineDataPropertyInLiteral, 6, 1) \
F(CollectTypeProfile, 4, 1) \ F(CollectTypeProfile, 3, 1) \
F(GetDataProperty, 2, 1) \ F(GetDataProperty, 2, 1) \
F(GetConstructorName, 1, 1) \ F(GetConstructorName, 1, 1) \
F(HasFastPackedElements, 1, 1) \ F(HasFastPackedElements, 1, 1) \
......
...@@ -57,4 +57,7 @@ fall_off(); ...@@ -57,4 +57,7 @@ fall_off();
testReturnOfNonVariable(); testReturnOfNonVariable();
function never_call() {}
%PrintTypeProfile(never_call);
throw "throw otherwise test fails with --stress-opt"; throw "throw otherwise test fails with --stress-opt";
...@@ -21,6 +21,6 @@ Function: try_finally ...@@ -21,6 +21,6 @@ Function: try_finally
Function: fall_off Function: fall_off
1105: undefined 1105: undefined
*%(basename)s:60: throw otherwise test fails with --stress-opt *%(basename)s:63: throw otherwise test fails with --stress-opt
throw "throw otherwise test fails with --stress-opt"; throw "throw otherwise test fails with --stress-opt";
^ ^
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment