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