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