Commit a1bba7fe authored by mvstanton's avatar mvstanton Committed by Commit bot

[FeedbackVector] Clarify the way the feedback vector is installed.

Installing a feedback vector in a closure is a multi-step process.
The closure actually points to a Cell that points to a feedback
vector or undefined if we haven't created one yet.
This happens because we often create closures before we've compiled
the code.

JSFunction::EnsureLiterals is the bottleneck in our system that
creates a feedback vector if necessary. The predicates it used to
determine what to do were arcane. This CL allows it to think it
terms of state, and clarifies the reading of that useful
bottleneck.

I also did a few renamings in parts of the code that referred
to a "literals array," which we don't have any more.

BUG=

Review-Url: https://codereview.chromium.org/2681773004
Cr-Commit-Position: refs/heads/master@{#43035}
parent 0c137304
......@@ -402,8 +402,8 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneRegExp(Node* closure,
Variable result(this, MachineRepresentation::kTagged);
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
Node* literals_array = LoadObjectField(cell, Cell::kValueOffset);
Node* boilerplate = LoadFixedArrayElement(literals_array, literal_index, 0,
Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
Node* boilerplate = LoadFixedArrayElement(feedback_vector, literal_index, 0,
CodeStubAssembler::SMI_PARAMETERS);
GotoIf(IsUndefined(boilerplate), &call_runtime);
......@@ -485,12 +485,12 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowArray(
Variable result(this, MachineRepresentation::kTagged);
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
Node* literals_array = LoadObjectField(cell, Cell::kValueOffset);
Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
Node* allocation_site = LoadFixedArrayElement(
literals_array, literal_index, 0, CodeStubAssembler::SMI_PARAMETERS);
feedback_vector, literal_index, 0, CodeStubAssembler::SMI_PARAMETERS);
GotoIf(IsUndefined(allocation_site), call_runtime);
allocation_site = LoadFixedArrayElement(literals_array, literal_index, 0,
allocation_site = LoadFixedArrayElement(feedback_vector, literal_index, 0,
CodeStubAssembler::SMI_PARAMETERS);
Node* boilerplate =
......@@ -643,9 +643,9 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
CodeAssemblerLabel* call_runtime, Node* closure, Node* literals_index,
Node* properties_count) {
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
Node* literals_array = LoadObjectField(cell, Cell::kValueOffset);
Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
Node* allocation_site = LoadFixedArrayElement(
literals_array, literals_index, 0, CodeStubAssembler::SMI_PARAMETERS);
feedback_vector, literals_index, 0, CodeStubAssembler::SMI_PARAMETERS);
GotoIf(IsUndefined(allocation_site), call_runtime);
// Calculate the object and allocation size based on the properties count.
......
......@@ -1455,8 +1455,7 @@ MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
shared_info, context, vector, NOT_TENURED);
} else {
result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared_info, context, isolate->factory()->undefined_cell(),
NOT_TENURED);
shared_info, context, NOT_TENURED);
JSFunction::EnsureLiterals(result);
// Make sure to cache this result.
Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
......
......@@ -291,9 +291,6 @@ DEFINE_IMPLICATION(track_field_types, track_fields)
DEFINE_IMPLICATION(track_field_types, track_heap_object_fields)
DEFINE_BOOL(type_profile, false, "collect type information")
// Flags for strongly rooting literal arrays in the feedback vector.
DEFINE_BOOL(trace_strong_rooted_literals, false, "trace literal rooting")
// Flags for optimization types.
DEFINE_BOOL(optimize_for_size, false,
"Enables optimizations which favor memory size over execution "
......
......@@ -6596,6 +6596,18 @@ bool JSFunction::has_feedback_vector() const {
return !feedback_vector_cell()->value()->IsUndefined(GetIsolate());
}
JSFunction::FeedbackVectorState JSFunction::GetFeedbackVectorState(
Isolate* isolate) const {
Cell* cell = feedback_vector_cell();
if (cell == isolate->heap()->undefined_cell()) {
return TOP_LEVEL_SCRIPT_NEEDS_VECTOR;
} else if (cell->value() == isolate->heap()->undefined_value() ||
!has_feedback_vector()) {
return NEEDS_VECTOR;
}
return HAS_VECTOR;
}
Context* JSFunction::context() {
return Context::cast(READ_FIELD(this, kContextOffset));
}
......
......@@ -12108,39 +12108,27 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
// static
void JSFunction::EnsureLiterals(Handle<JSFunction> function) {
Handle<SharedFunctionInfo> shared(function->shared());
Handle<Context> native_context(function->context()->native_context());
Isolate* isolate = shared->GetIsolate();
Cell* cell = function->feedback_vector_cell();
if (cell == isolate->heap()->undefined_cell()) {
if (FLAG_trace_strong_rooted_literals) {
PrintF("EnsureLiterals: Installing literals cell in %s %p\n",
shared->DebugName()->ToCString().get(),
reinterpret_cast<void*>(*function));
}
// Top level code didn't get it's literals installed.
Handle<FeedbackVector> feedback_vector =
FeedbackVector::New(isolate, shared);
Handle<Cell> new_cell = isolate->factory()->NewCell(feedback_vector);
function->set_feedback_vector_cell(*new_cell);
} else if (!cell->value()->IsFeedbackVector() ||
!function->has_feedback_vector()) {
DCHECK(cell != isolate->heap()->undefined_cell());
if (FLAG_trace_strong_rooted_literals) {
PrintF("EnsureLiterals: Update literals cell in %s %p\n",
shared->DebugName()->ToCString().get(),
reinterpret_cast<void*>(*function));
}
Handle<FeedbackVector> feedback_vector =
FeedbackVector::New(isolate, shared);
// Re-get the feedback_vector() value as GC may have occurred.
function->feedback_vector_cell()->set_value(*feedback_vector);
} else {
if (FLAG_trace_strong_rooted_literals) {
PrintF("EnsureLiterals: did nothing for %s %p\n",
shared->DebugName()->ToCString().get(),
reinterpret_cast<void*>(*function));
FeedbackVectorState state = function->GetFeedbackVectorState(isolate);
switch (state) {
case TOP_LEVEL_SCRIPT_NEEDS_VECTOR: {
// A top level script didn't get it's literals installed.
Handle<FeedbackVector> feedback_vector =
FeedbackVector::New(isolate, shared);
Handle<Cell> new_cell = isolate->factory()->NewCell(feedback_vector);
function->set_feedback_vector_cell(*new_cell);
break;
}
case NEEDS_VECTOR: {
Handle<FeedbackVector> feedback_vector =
FeedbackVector::New(isolate, shared);
function->feedback_vector_cell()->set_value(*feedback_vector);
break;
}
case HAS_VECTOR:
// Nothing to do.
break;
}
}
......
......@@ -8067,6 +8067,14 @@ class JSFunction: public JSObject {
// [feedback_vector_cell]: Fixed array holding the feedback vector.
DECL_ACCESSORS(feedback_vector_cell, Cell)
enum FeedbackVectorState {
TOP_LEVEL_SCRIPT_NEEDS_VECTOR,
NEEDS_VECTOR,
HAS_VECTOR
};
inline FeedbackVectorState GetFeedbackVectorState(Isolate* isolate) const;
// feedback_vector() can be used once the function is compiled.
inline FeedbackVector* feedback_vector() const;
inline bool has_feedback_vector() const;
......
......@@ -28,9 +28,10 @@ RUNTIME_FUNCTION(Runtime_InterpreterNewClosure) {
CONVERT_SMI_ARG_CHECKED(pretenured_flag, 3);
Handle<Context> context(isolate->context(), isolate);
FeedbackSlot slot = FeedbackVector::ToSlot(index);
Handle<Cell> literals(Cell::cast(vector->Get(slot)), isolate);
Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
return *isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared, context, literals, static_cast<PretenureFlag>(pretenured_flag));
shared, context, vector_cell,
static_cast<PretenureFlag>(pretenured_flag));
}
namespace {
......
......@@ -638,10 +638,10 @@ RUNTIME_FUNCTION(Runtime_NewClosure) {
CONVERT_SMI_ARG_CHECKED(index, 2);
Handle<Context> context(isolate->context(), isolate);
FeedbackSlot slot = FeedbackVector::ToSlot(index);
Handle<Cell> literals(Cell::cast(vector->Get(slot)), isolate);
Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared, context, literals, NOT_TENURED);
shared, context, vector_cell, NOT_TENURED);
return *function;
}
......@@ -654,12 +654,12 @@ RUNTIME_FUNCTION(Runtime_NewClosure_Tenured) {
CONVERT_SMI_ARG_CHECKED(index, 2);
Handle<Context> context(isolate->context(), isolate);
FeedbackSlot slot = FeedbackVector::ToSlot(index);
Handle<Cell> literals(Cell::cast(vector->Get(slot)), isolate);
Handle<Cell> vector_cell(Cell::cast(vector->Get(slot)), isolate);
// The caller ensures that we pretenure closures that are assigned
// directly to properties.
Handle<JSFunction> function =
isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
literals, TENURED);
isolate->factory()->NewFunctionFromSharedFunctionInfo(
shared, context, vector_cell, TENURED);
return *function;
}
......
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