Commit ab4a540c authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

Revert "[nci] Share smi feedback and enable related optimizations"

This reverts commit 3599cce1.

Originally landed in
https://chromium-review.googlesource.com/c/v8/v8/+/2531775

Work on NCI is suspended, remove unused complexity. We may want to share
native-context-independent feedback in the future, but probably through other
means.

Bug: v8:8888
Change-Id: I23dfb67f6f01b4891af87bc42a9e62f99d0bf044
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2567701Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMythri Alle <mythria@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71553}
parent e2aa734a
...@@ -3094,9 +3094,6 @@ v8_source_set("v8_base_without_compiler") { ...@@ -3094,9 +3094,6 @@ v8_source_set("v8_base_without_compiler") {
"src/objects/scope-info.h", "src/objects/scope-info.h",
"src/objects/script-inl.h", "src/objects/script-inl.h",
"src/objects/script.h", "src/objects/script.h",
"src/objects/serialized-feedback-inl.h",
"src/objects/serialized-feedback.cc",
"src/objects/serialized-feedback.h",
"src/objects/shared-function-info-inl.h", "src/objects/shared-function-info-inl.h",
"src/objects/shared-function-info.cc", "src/objects/shared-function-info.cc",
"src/objects/shared-function-info.h", "src/objects/shared-function-info.h",
......
...@@ -17,18 +17,11 @@ ...@@ -17,18 +17,11 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace {
// The number of generations for each sub cache. // The number of generations for each sub cache.
constexpr int kRegExpGenerations = 2; static const int kRegExpGenerations = 2;
// Initial size of each compilation cache table allocated. // Initial size of each compilation cache table allocated.
constexpr int kInitialCacheSize = 64; static const int kInitialCacheSize = 64;
// The index of the youngest generation table.
constexpr int kYoungestTableIndex = 0;
} // namespace
CompilationCache::CompilationCache(Isolate* isolate) CompilationCache::CompilationCache(Isolate* isolate)
: isolate_(isolate), : isolate_(isolate),
...@@ -48,22 +41,17 @@ CompilationCache::CompilationCache(Isolate* isolate) ...@@ -48,22 +41,17 @@ CompilationCache::CompilationCache(Isolate* isolate)
Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) { Handle<CompilationCacheTable> CompilationSubCache::GetTable(int generation) {
DCHECK_LT(generation, generations()); DCHECK_LT(generation, generations());
Handle<CompilationCacheTable> result; Handle<CompilationCacheTable> result;
if (has_table(generation)) { if (tables_[generation].IsUndefined(isolate())) {
result = CompilationCacheTable::New(isolate(), kInitialCacheSize);
tables_[generation] = *result;
} else {
CompilationCacheTable table = CompilationCacheTable table =
CompilationCacheTable::cast(tables_[generation]); CompilationCacheTable::cast(tables_[generation]);
result = Handle<CompilationCacheTable>(table, isolate()); result = Handle<CompilationCacheTable>(table, isolate());
} else {
result = CompilationCacheTable::New(isolate(), kInitialCacheSize);
tables_[generation] = *result;
} }
return result; return result;
} }
bool CompilationSubCache::has_table(int generation) const {
DCHECK_LT(generation, generations());
return !tables_[generation].IsUndefined(isolate());
}
// static // static
void CompilationSubCache::AgeByGeneration(CompilationSubCache* c) { void CompilationSubCache::AgeByGeneration(CompilationSubCache* c) {
DCHECK_GT(c->generations(), 1); DCHECK_GT(c->generations(), 1);
...@@ -74,15 +62,14 @@ void CompilationSubCache::AgeByGeneration(CompilationSubCache* c) { ...@@ -74,15 +62,14 @@ void CompilationSubCache::AgeByGeneration(CompilationSubCache* c) {
} }
// Set the first generation as unborn. // Set the first generation as unborn.
c->tables_[kYoungestTableIndex] = c->tables_[0] = ReadOnlyRoots(c->isolate()).undefined_value();
ReadOnlyRoots(c->isolate()).undefined_value();
} }
// static // static
void CompilationSubCache::AgeCustom(CompilationSubCache* c) { void CompilationSubCache::AgeCustom(CompilationSubCache* c) {
DCHECK_EQ(c->generations(), 1); DCHECK_EQ(c->generations(), 1);
if (!c->has_table(kYoungestTableIndex)) return; if (c->tables_[0].IsUndefined(c->isolate())) return;
CompilationCacheTable::cast(c->tables_[kYoungestTableIndex]).Age(); CompilationCacheTable::cast(c->tables_[0]).Age();
} }
void CompilationCacheScript::Age() { void CompilationCacheScript::Age() {
...@@ -283,77 +270,43 @@ void CompilationCacheRegExp::Put(Handle<String> source, JSRegExp::Flags flags, ...@@ -283,77 +270,43 @@ void CompilationCacheRegExp::Put(Handle<String> source, JSRegExp::Flags flags,
CompilationCacheTable::PutRegExp(isolate(), table, source, flags, data)); CompilationCacheTable::PutRegExp(isolate(), table, source, flags, data));
} }
bool CompilationCacheCode::Lookup( MaybeHandle<Code> CompilationCacheCode::Lookup(Handle<SharedFunctionInfo> key) {
Handle<SharedFunctionInfo> key, MaybeHandle<Code>* code_out, // Make sure not to leak the table into the surrounding handle
MaybeHandle<SerializedFeedback>* feedback_out) { // scope. Otherwise, we risk keeping old tables around even after
Code raw_code; // having cleared the cache.
SerializedFeedback raw_feedback; HandleScope scope(isolate());
MaybeHandle<Code> maybe_value;
int generation = 0; int generation = 0;
{ for (; generation < generations(); generation++) {
// Make sure not to leak the table into the surrounding handle Handle<CompilationCacheTable> table = GetTable(generation);
// scope. Otherwise, we risk keeping old tables around even after maybe_value = table->LookupCode(key);
// having cleared the cache. if (!maybe_value.is_null()) break;
HandleScope scope(isolate());
MaybeHandle<Code> maybe_code;
MaybeHandle<SerializedFeedback> maybe_feedback;
bool found = false;
for (; generation < generations(); generation++) {
Handle<CompilationCacheTable> table = GetTable(generation);
found = table->LookupCode(key, &maybe_code, &maybe_feedback);
if (found) break;
}
if (!found) {
isolate()->counters()->compilation_cache_misses()->Increment();
return false;
}
raw_code = *maybe_code.ToHandleChecked();
raw_feedback = *maybe_feedback.ToHandleChecked();
} }
// The Code object shouldn't be marked for deoptimization, otherwise it'd if (maybe_value.is_null()) {
// immediately be thrown out on the next call. isolate()->counters()->compilation_cache_misses()->Increment();
DCHECK(!raw_code.marked_for_deoptimization()); return MaybeHandle<Code>();
*code_out = handle(raw_code, isolate());
*feedback_out = handle(raw_feedback, isolate());
if (generation != kYoungestTableIndex) {
// Copy to youngest generation.
Put(key, code_out->ToHandleChecked(), feedback_out->ToHandleChecked());
} }
Handle<Code> value = maybe_value.ToHandleChecked();
if (generation != 0) Put(key, value); // Add to the first generation.
isolate()->counters()->compilation_cache_hits()->Increment(); isolate()->counters()->compilation_cache_hits()->Increment();
return true; return scope.CloseAndEscape(value);
} }
void CompilationCacheCode::Put(Handle<SharedFunctionInfo> key, void CompilationCacheCode::Put(Handle<SharedFunctionInfo> key,
Handle<Code> value_code, Handle<Code> value) {
Handle<SerializedFeedback> value_feedback) {
HandleScope scope(isolate()); HandleScope scope(isolate());
Handle<CompilationCacheTable> table = GetFirstTable(); Handle<CompilationCacheTable> table = GetFirstTable();
SetFirstTable(CompilationCacheTable::PutCode(isolate(), table, key, SetFirstTable(CompilationCacheTable::PutCode(isolate(), table, key, value));
value_code, value_feedback));
} }
// static
void CompilationCacheCode::TraceAgeing() { void CompilationCacheCode::TraceAgeing() {
DCHECK(FLAG_trace_turbo_nci); DCHECK(FLAG_trace_turbo_nci);
StdoutStream os; StdoutStream os;
os << "NCI cache ageing: Removing oldest generation" << std::endl; os << "NCI cache ageing: Removing oldest generation" << std::endl;
} }
// static
void CompilationCacheCode::TraceRemovalForDeoptimization(SharedFunctionInfo key,
Code value) {
DCHECK(FLAG_trace_turbo_nci);
StdoutStream os;
os << "NCI cache removal for deoptimization: " << Brief(key) << ", "
<< Brief(value) << std::endl;
}
// static
void CompilationCacheCode::TraceInsertion(Handle<SharedFunctionInfo> key, void CompilationCacheCode::TraceInsertion(Handle<SharedFunctionInfo> key,
Handle<Code> value) { Handle<Code> value) {
DCHECK(FLAG_trace_turbo_nci); DCHECK(FLAG_trace_turbo_nci);
...@@ -362,7 +315,6 @@ void CompilationCacheCode::TraceInsertion(Handle<SharedFunctionInfo> key, ...@@ -362,7 +315,6 @@ void CompilationCacheCode::TraceInsertion(Handle<SharedFunctionInfo> key,
<< std::endl; << std::endl;
} }
// static
void CompilationCacheCode::TraceHit(Handle<SharedFunctionInfo> key, void CompilationCacheCode::TraceHit(Handle<SharedFunctionInfo> key,
Handle<Code> value) { Handle<Code> value) {
DCHECK(FLAG_trace_turbo_nci); DCHECK(FLAG_trace_turbo_nci);
...@@ -423,10 +375,8 @@ MaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source, ...@@ -423,10 +375,8 @@ MaybeHandle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
return reg_exp_.Lookup(source, flags); return reg_exp_.Lookup(source, flags);
} }
bool CompilationCache::LookupCode( MaybeHandle<Code> CompilationCache::LookupCode(Handle<SharedFunctionInfo> sfi) {
Handle<SharedFunctionInfo> sfi, MaybeHandle<Code>* code_out, return code_.Lookup(sfi);
MaybeHandle<SerializedFeedback>* feedback_out) {
return code_.Lookup(sfi, code_out, feedback_out);
} }
void CompilationCache::PutScript(Handle<String> source, void CompilationCache::PutScript(Handle<String> source,
...@@ -469,18 +419,8 @@ void CompilationCache::PutRegExp(Handle<String> source, JSRegExp::Flags flags, ...@@ -469,18 +419,8 @@ void CompilationCache::PutRegExp(Handle<String> source, JSRegExp::Flags flags,
} }
void CompilationCache::PutCode(Handle<SharedFunctionInfo> shared, void CompilationCache::PutCode(Handle<SharedFunctionInfo> shared,
Handle<Code> code, Handle<Code> code) {
Handle<SerializedFeedback> feedback) { code_.Put(shared, code);
code_.Put(shared, code, feedback);
}
void CompilationCache::ClearDeoptimizedCode() { code_.ClearDeoptimizedCode(); }
void CompilationCacheCode::ClearDeoptimizedCode() {
for (int i = 0; i < generations(); i++) {
if (!has_table(i)) continue;
GetTable(i)->ClearDeoptimizedCode();
}
} }
void CompilationCache::Clear() { void CompilationCache::Clear() {
......
...@@ -34,7 +34,6 @@ class CompilationSubCache { ...@@ -34,7 +34,6 @@ class CompilationSubCache {
// Get the compilation cache tables for a specific generation. // Get the compilation cache tables for a specific generation.
Handle<CompilationCacheTable> GetTable(int generation); Handle<CompilationCacheTable> GetTable(int generation);
bool has_table(int generation) const;
// Accessors for first generation. // Accessors for first generation.
Handle<CompilationCacheTable> GetFirstTable() { Handle<CompilationCacheTable> GetFirstTable() {
...@@ -160,11 +159,8 @@ class CompilationCacheCode : public CompilationSubCache { ...@@ -160,11 +159,8 @@ class CompilationCacheCode : public CompilationSubCache {
explicit CompilationCacheCode(Isolate* isolate) explicit CompilationCacheCode(Isolate* isolate)
: CompilationSubCache(isolate, kGenerations) {} : CompilationSubCache(isolate, kGenerations) {}
bool Lookup(Handle<SharedFunctionInfo> key, MaybeHandle<Code>* code_out, MaybeHandle<Code> Lookup(Handle<SharedFunctionInfo> key);
MaybeHandle<SerializedFeedback>* feedback_out); void Put(Handle<SharedFunctionInfo> key, Handle<Code> value);
void Put(Handle<SharedFunctionInfo> key, Handle<Code> value_code,
Handle<SerializedFeedback> value_feedback);
void ClearDeoptimizedCode();
void Age() override; void Age() override;
...@@ -174,7 +170,6 @@ class CompilationCacheCode : public CompilationSubCache { ...@@ -174,7 +170,6 @@ class CompilationCacheCode : public CompilationSubCache {
static constexpr int kGenerations = 2; static constexpr int kGenerations = 2;
static void TraceAgeing(); static void TraceAgeing();
static void TraceRemovalForDeoptimization(SharedFunctionInfo key, Code value);
static void TraceInsertion(Handle<SharedFunctionInfo> key, static void TraceInsertion(Handle<SharedFunctionInfo> key,
Handle<Code> value); Handle<Code> value);
static void TraceHit(Handle<SharedFunctionInfo> key, Handle<Code> value); static void TraceHit(Handle<SharedFunctionInfo> key, Handle<Code> value);
...@@ -210,8 +205,7 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -210,8 +205,7 @@ class V8_EXPORT_PRIVATE CompilationCache {
MaybeHandle<FixedArray> LookupRegExp(Handle<String> source, MaybeHandle<FixedArray> LookupRegExp(Handle<String> source,
JSRegExp::Flags flags); JSRegExp::Flags flags);
bool LookupCode(Handle<SharedFunctionInfo> sfi, MaybeHandle<Code>* code_out, MaybeHandle<Code> LookupCode(Handle<SharedFunctionInfo> sfi);
MaybeHandle<SerializedFeedback>* feedback_out);
// Associate the (source, kind) pair to the shared function // Associate the (source, kind) pair to the shared function
// info. This may overwrite an existing mapping. // info. This may overwrite an existing mapping.
...@@ -231,9 +225,7 @@ class V8_EXPORT_PRIVATE CompilationCache { ...@@ -231,9 +225,7 @@ class V8_EXPORT_PRIVATE CompilationCache {
void PutRegExp(Handle<String> source, JSRegExp::Flags flags, void PutRegExp(Handle<String> source, JSRegExp::Flags flags,
Handle<FixedArray> data); Handle<FixedArray> data);
void PutCode(Handle<SharedFunctionInfo> shared, Handle<Code> code, void PutCode(Handle<SharedFunctionInfo> shared, Handle<Code> code);
Handle<SerializedFeedback> feedback);
void ClearDeoptimizedCode();
// Clear the cache - also used to initialize the cache at startup. // Clear the cache - also used to initialize the cache at startup.
void Clear(); void Clear();
......
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
#include "src/objects/js-function-inl.h" #include "src/objects/js-function-inl.h"
#include "src/objects/map.h" #include "src/objects/map.h"
#include "src/objects/object-list-macros.h" #include "src/objects/object-list-macros.h"
#include "src/objects/serialized-feedback.h"
#include "src/objects/shared-function-info.h" #include "src/objects/shared-function-info.h"
#include "src/objects/string.h" #include "src/objects/string.h"
#include "src/parsing/parse-info.h" #include "src/parsing/parse-info.h"
...@@ -919,19 +918,10 @@ void InsertCodeIntoCompilationCache(Isolate* isolate, ...@@ -919,19 +918,10 @@ void InsertCodeIntoCompilationCache(Isolate* isolate,
Handle<Code> code = info->code(); Handle<Code> code = info->code();
DCHECK(!info->function_context_specializing()); DCHECK(!info->function_context_specializing());
Handle<SerializedFeedback> serialized_feedback =
SerializedFeedback::Serialize(
isolate, handle(info->closure()->feedback_vector(), isolate));
Handle<SharedFunctionInfo> sfi = info->shared_info(); Handle<SharedFunctionInfo> sfi = info->shared_info();
CompilationCache* cache = isolate->compilation_cache(); CompilationCache* cache = isolate->compilation_cache();
cache->PutCode(sfi, code, serialized_feedback); cache->PutCode(sfi, code);
DCHECK(!cache->LookupCode(sfi).is_null());
#ifdef DEBUG
MaybeHandle<Code> maybe_code;
MaybeHandle<SerializedFeedback> maybe_feedback;
DCHECK(cache->LookupCode(sfi, &maybe_code, &maybe_feedback));
#endif // DEBUG
sfi->set_may_have_cached_code(true); sfi->set_may_have_cached_code(true);
......
...@@ -4128,6 +4128,7 @@ JSTypeHintLowering::LoweringResult ...@@ -4128,6 +4128,7 @@ JSTypeHintLowering::LoweringResult
BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op, BytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op,
Node* operand, Node* operand,
FeedbackSlot slot) { FeedbackSlot slot) {
if (!CanApplyTypeHintLowering(op)) return NoChange();
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
JSTypeHintLowering::LoweringResult result = JSTypeHintLowering::LoweringResult result =
...@@ -4141,6 +4142,7 @@ JSTypeHintLowering::LoweringResult ...@@ -4141,6 +4142,7 @@ JSTypeHintLowering::LoweringResult
BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left,
Node* right, Node* right,
FeedbackSlot slot) { FeedbackSlot slot) {
if (!CanApplyTypeHintLowering(op)) return NoChange();
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
JSTypeHintLowering::LoweringResult result = JSTypeHintLowering::LoweringResult result =
...@@ -4155,6 +4157,7 @@ BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver, ...@@ -4155,6 +4157,7 @@ BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver,
Node* cache_array, Node* cache_array,
Node* cache_type, Node* index, Node* cache_type, Node* index,
FeedbackSlot slot) { FeedbackSlot slot) {
if (!CanApplyTypeHintLowering(IrOpcode::kJSForInNext)) return NoChange();
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
JSTypeHintLowering::LoweringResult result = JSTypeHintLowering::LoweringResult result =
...@@ -4167,6 +4170,7 @@ BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver, ...@@ -4167,6 +4170,7 @@ BytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver,
JSTypeHintLowering::LoweringResult JSTypeHintLowering::LoweringResult
BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator, BytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator,
FeedbackSlot slot) { FeedbackSlot slot) {
if (!CanApplyTypeHintLowering(IrOpcode::kJSForInPrepare)) return NoChange();
Node* effect = environment()->GetEffectDependency(); Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency(); Node* control = environment()->GetControlDependency();
JSTypeHintLowering::LoweringResult result = JSTypeHintLowering::LoweringResult result =
......
...@@ -4723,8 +4723,8 @@ bool HasMigrationTargets(const MapHandles& maps) { ...@@ -4723,8 +4723,8 @@ bool HasMigrationTargets(const MapHandles& maps) {
} // namespace } // namespace
bool JSHeapBroker::CanUseFeedback(const FeedbackNexus& nexus) const { bool JSHeapBroker::CanUseFeedback(const FeedbackNexus& nexus) const {
// TODO(jgruber,v8:8888): Currently, nci code does not use all feedback // TODO(jgruber,v8:8888): Currently, nci code does not use any
// kinds. This restriction will be relaxed in the future. // feedback. This restriction will be relaxed in the future.
return !is_native_context_independent() && !nexus.IsUninitialized(); return !is_native_context_independent() && !nexus.IsUninitialized();
} }
...@@ -4837,7 +4837,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForGlobalAccess( ...@@ -4837,7 +4837,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForGlobalAccess(
ProcessedFeedback const& JSHeapBroker::ReadFeedbackForBinaryOperation( ProcessedFeedback const& JSHeapBroker::ReadFeedbackForBinaryOperation(
FeedbackSource const& source) const { FeedbackSource const& source) const {
FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config());
if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); if (!CanUseFeedback(nexus)) return NewInsufficientFeedback(nexus.kind());
BinaryOperationHint hint = nexus.GetBinaryOperationFeedback(); BinaryOperationHint hint = nexus.GetBinaryOperationFeedback();
DCHECK_NE(hint, BinaryOperationHint::kNone); // Not uninitialized. DCHECK_NE(hint, BinaryOperationHint::kNone); // Not uninitialized.
return *zone()->New<BinaryOperationFeedback>(hint, nexus.kind()); return *zone()->New<BinaryOperationFeedback>(hint, nexus.kind());
...@@ -4846,7 +4846,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForBinaryOperation( ...@@ -4846,7 +4846,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForBinaryOperation(
ProcessedFeedback const& JSHeapBroker::ReadFeedbackForCompareOperation( ProcessedFeedback const& JSHeapBroker::ReadFeedbackForCompareOperation(
FeedbackSource const& source) const { FeedbackSource const& source) const {
FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config());
if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); if (!CanUseFeedback(nexus)) return NewInsufficientFeedback(nexus.kind());
CompareOperationHint hint = nexus.GetCompareOperationFeedback(); CompareOperationHint hint = nexus.GetCompareOperationFeedback();
DCHECK_NE(hint, CompareOperationHint::kNone); // Not uninitialized. DCHECK_NE(hint, CompareOperationHint::kNone); // Not uninitialized.
return *zone()->New<CompareOperationFeedback>(hint, nexus.kind()); return *zone()->New<CompareOperationFeedback>(hint, nexus.kind());
...@@ -4855,7 +4855,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForCompareOperation( ...@@ -4855,7 +4855,7 @@ ProcessedFeedback const& JSHeapBroker::ReadFeedbackForCompareOperation(
ProcessedFeedback const& JSHeapBroker::ReadFeedbackForForIn( ProcessedFeedback const& JSHeapBroker::ReadFeedbackForForIn(
FeedbackSource const& source) const { FeedbackSource const& source) const {
FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config()); FeedbackNexus nexus(source.vector, source.slot, feedback_nexus_config());
if (nexus.IsUninitialized()) return NewInsufficientFeedback(nexus.kind()); if (!CanUseFeedback(nexus)) return NewInsufficientFeedback(nexus.kind());
ForInHint hint = nexus.GetForInFeedback(); ForInHint hint = nexus.GetForInFeedback();
DCHECK_NE(hint, ForInHint::kNone); // Not uninitialized. DCHECK_NE(hint, ForInHint::kNone); // Not uninitialized.
return *zone()->New<ForInFeedback>(hint, nexus.kind()); return *zone()->New<ForInFeedback>(hint, nexus.kind());
......
...@@ -2371,7 +2371,7 @@ Reduction JSTypedLowering::Reduce(Node* node) { ...@@ -2371,7 +2371,7 @@ Reduction JSTypedLowering::Reduce(Node* node) {
const IrOpcode::Value opcode = node->opcode(); const IrOpcode::Value opcode = node->opcode();
if (broker()->generate_full_feedback_collection() && if (broker()->generate_full_feedback_collection() &&
IrOpcode::OpcodeMustCollectFeedbackForNCI(opcode)) { IrOpcode::IsFeedbackCollectingOpcode(opcode)) {
// In NCI code, it is not valid to reduce feedback-collecting JS opcodes // In NCI code, it is not valid to reduce feedback-collecting JS opcodes
// into non-feedback-collecting lower-level opcodes; missed feedback would // into non-feedback-collecting lower-level opcodes; missed feedback would
// result in soft deopts. // result in soft deopts.
......
...@@ -1092,48 +1092,12 @@ class V8_EXPORT_PRIVATE IrOpcode { ...@@ -1092,48 +1092,12 @@ class V8_EXPORT_PRIVATE IrOpcode {
return kJSCreateFunctionContext <= value && value <= kJSCreateBlockContext; return kJSCreateFunctionContext <= value && value <= kJSCreateBlockContext;
} }
// These opcodes *must* collect full feedback in NCI code in order to avoid
// deopts after tier-up to Turbofan.
// TODO(jgruber,v8:8888): The goal is for this to be the empty set at some
// point in the future.
static bool OpcodeMustCollectFeedbackForNCI(Value value) {
switch (value) {
case kJSCall:
case kJSCallWithArrayLike:
case kJSCallWithSpread:
case kJSCloneObject:
case kJSConstruct:
case kJSConstructWithArrayLike:
case kJSConstructWithSpread:
case kJSCreateEmptyLiteralArray:
case kJSCreateLiteralArray:
case kJSCreateLiteralObject:
case kJSCreateLiteralRegExp:
case kJSGetIterator:
case kJSGetTemplateObject:
case kJSHasProperty:
case kJSInstanceOf:
case kJSLoadGlobal:
case kJSLoadNamed:
case kJSLoadNamedFromSuper:
case kJSLoadProperty:
case kJSStoreDataPropertyInLiteral:
case kJSStoreGlobal:
case kJSStoreInArrayLiteral:
case kJSStoreNamed:
case kJSStoreNamedOwn:
case kJSStoreProperty:
return true;
default:
return false;
}
UNREACHABLE();
}
// These opcode take the feedback vector as an input, and implement // These opcode take the feedback vector as an input, and implement
// feedback-collecting logic in generic lowering. // feedback-collecting logic in generic lowering.
static bool IsFeedbackCollectingOpcode(Value value) { static bool IsFeedbackCollectingOpcode(Value value) {
#define CASE(Name, ...) case k##Name: #define CASE(Name, ...) \
case k##Name: \
return true;
switch (value) { switch (value) {
JS_ARITH_BINOP_LIST(CASE) JS_ARITH_BINOP_LIST(CASE)
JS_ARITH_UNOP_LIST(CASE) JS_ARITH_UNOP_LIST(CASE)
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "src/builtins/accessors.h" #include "src/builtins/accessors.h"
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/codegen/callable.h" #include "src/codegen/callable.h"
#include "src/codegen/compilation-cache.h"
#include "src/codegen/macro-assembler.h" #include "src/codegen/macro-assembler.h"
#include "src/codegen/register-configuration.h" #include "src/codegen/register-configuration.h"
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
...@@ -393,7 +392,6 @@ void Deoptimizer::DeoptimizeAll(Isolate* isolate) { ...@@ -393,7 +392,6 @@ void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
MarkAllCodeForContext(native_context); MarkAllCodeForContext(native_context);
OSROptimizedCodeCache::Clear(native_context); OSROptimizedCodeCache::Clear(native_context);
DeoptimizeMarkedCodeForContext(native_context); DeoptimizeMarkedCodeForContext(native_context);
isolate->compilation_cache()->ClearDeoptimizedCode();
context = native_context.next_context_link(); context = native_context.next_context_link();
} }
} }
...@@ -454,16 +452,6 @@ void Deoptimizer::DeoptimizeFunction(JSFunction function, Code code) { ...@@ -454,16 +452,6 @@ void Deoptimizer::DeoptimizeFunction(JSFunction function, Code code) {
// this call from here. // this call from here.
OSROptimizedCodeCache::Compact( OSROptimizedCodeCache::Compact(
Handle<NativeContext>(function.context().native_context(), isolate)); Handle<NativeContext>(function.context().native_context(), isolate));
// Remove deoptimized Code from the NCI cache - such objects currently
// cannot be reused.
// TODO(jgruber): Instead of removal (and possibly later re-insertion), we
// should learn from deopts. Potentially this already happens now;
// re-insertion will also insert updated (generalized) feedback. We should
// still take a closer look at this in the future though.
if (code.kind() == CodeKind::NATIVE_CONTEXT_INDEPENDENT) {
isolate->compilation_cache()->ClearDeoptimizedCode();
}
} }
} }
......
...@@ -3498,27 +3498,18 @@ Handle<JSFunction> Factory::JSFunctionBuilder::Build() { ...@@ -3498,27 +3498,18 @@ Handle<JSFunction> Factory::JSFunctionBuilder::Build() {
PrepareMap(); PrepareMap();
PrepareFeedbackCell(); PrepareFeedbackCell();
// Determine the associated Code object. If we hit the NCI cache, take that; // Determine the associated Code object.
// otherwise, ask the SharedFunctionInfo for the appropriate Code object. Handle<Code> code;
MaybeHandle<Code> maybe_code; const bool have_cached_code =
MaybeHandle<SerializedFeedback> maybe_feedback; sfi_->TryGetCachedCode(isolate_).ToHandle(&code);
const bool have_nci_cache = sfi_->TryGetCachedCodeAndSerializedFeedback( if (!have_cached_code) code = handle(sfi_->GetCode(), isolate_);
isolate_, &maybe_code, &maybe_feedback);
Handle<Code> code = have_nci_cache ? maybe_code.ToHandleChecked()
: handle(sfi_->GetCode(), isolate_);
Handle<JSFunction> result = BuildRaw(code); Handle<JSFunction> result = BuildRaw(code);
if (have_nci_cache) { if (have_cached_code) {
IsCompiledScope is_compiled_scope(sfi_->is_compiled_scope(isolate_));
JSFunction::EnsureFeedbackVector(result, &is_compiled_scope);
if (FLAG_trace_turbo_nci) CompilationCacheCode::TraceHit(sfi_, code); if (FLAG_trace_turbo_nci) CompilationCacheCode::TraceHit(sfi_, code);
if (!result->has_feedback_vector()) {
IsCompiledScope is_compiled_scope(sfi_->is_compiled_scope(isolate_));
JSFunction::EnsureFeedbackVector(result, &is_compiled_scope);
// TODO(jgruber,v8:8888): Consider combining shared feedback with
// existing feedback here.
maybe_feedback.ToHandleChecked()->DeserializeInto(
result->feedback_vector());
}
} }
Compiler::PostInstantiation(result); Compiler::PostInstantiation(result);
......
...@@ -458,6 +458,7 @@ int Code::stack_slots() const { ...@@ -458,6 +458,7 @@ int Code::stack_slots() const {
} }
bool Code::marked_for_deoptimization() const { bool Code::marked_for_deoptimization() const {
DCHECK(CodeKindCanDeoptimize(kind()));
int32_t flags = code_data_container(kAcquireLoad).kind_specific_flags(); int32_t flags = code_data_container(kAcquireLoad).kind_specific_flags();
return MarkedForDeoptimizationField::decode(flags); return MarkedForDeoptimizationField::decode(flags);
} }
......
...@@ -4,10 +4,8 @@ ...@@ -4,10 +4,8 @@
#include "src/objects/compilation-cache-table.h" #include "src/objects/compilation-cache-table.h"
#include "src/codegen/compilation-cache.h"
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/objects/compilation-cache-table-inl.h" #include "src/objects/compilation-cache-table-inl.h"
#include "src/objects/serialized-feedback-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -285,32 +283,14 @@ Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src, ...@@ -285,32 +283,14 @@ Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
return Handle<Object>(get(EntryToIndex(entry) + 1), isolate); return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
} }
namespace { MaybeHandle<Code> CompilationCacheTable::LookupCode(
Handle<SharedFunctionInfo> key) {
constexpr int CodeCacheSFIIndex(InternalIndex entry) {
return CompilationCacheTable::EntryToIndex(entry) + 0;
}
constexpr int CodeCacheCodeIndex(InternalIndex entry) {
return CompilationCacheTable::EntryToIndex(entry) + 1;
}
constexpr int CodeCacheFeedbackIndex(InternalIndex entry) {
return CompilationCacheTable::EntryToIndex(entry) + 2;
}
} // namespace
bool CompilationCacheTable::LookupCode(
Handle<SharedFunctionInfo> key, MaybeHandle<Code>* code_out,
MaybeHandle<SerializedFeedback>* feedback_out) {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
CodeKey k(key); CodeKey k(key);
InternalIndex entry = FindEntry(isolate, &k); InternalIndex entry = FindEntry(isolate, &k);
if (entry.is_not_found()) return false; if (entry.is_not_found()) return {};
*code_out = handle(Code::cast(get(CodeCacheCodeIndex(entry))), isolate); return Handle<Code>(Code::cast(get(EntryToIndex(entry) + 1)), isolate);
*feedback_out = handle(
SerializedFeedback::cast(get(CodeCacheFeedbackIndex(entry))), isolate);
return true;
} }
Handle<CompilationCacheTable> CompilationCacheTable::PutScript( Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
...@@ -390,18 +370,15 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp( ...@@ -390,18 +370,15 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
Handle<CompilationCacheTable> CompilationCacheTable::PutCode( Handle<CompilationCacheTable> CompilationCacheTable::PutCode(
Isolate* isolate, Handle<CompilationCacheTable> cache, Isolate* isolate, Handle<CompilationCacheTable> cache,
Handle<SharedFunctionInfo> key, Handle<Code> value_code, Handle<SharedFunctionInfo> key, Handle<Code> value) {
Handle<SerializedFeedback> value_feedback) {
STATIC_ASSERT(CompilationCacheShape::kEntrySize >= 3);
CodeKey k(key); CodeKey k(key);
{ {
InternalIndex entry = cache->FindEntry(isolate, &k); InternalIndex entry = cache->FindEntry(isolate, &k);
if (entry.is_found()) { if (entry.is_found()) {
// Update. // Update.
cache->set(CodeCacheSFIIndex(entry), *key); cache->set(EntryToIndex(entry), *key);
cache->set(CodeCacheCodeIndex(entry), *value_code); cache->set(EntryToIndex(entry) + 1, *value);
cache->set(CodeCacheFeedbackIndex(entry), *value_feedback);
return cache; return cache;
} }
} }
...@@ -409,9 +386,8 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutCode( ...@@ -409,9 +386,8 @@ Handle<CompilationCacheTable> CompilationCacheTable::PutCode(
// Insert. // Insert.
cache = EnsureCapacity(isolate, cache); cache = EnsureCapacity(isolate, cache);
InternalIndex entry = cache->FindInsertionEntry(isolate, k.Hash()); InternalIndex entry = cache->FindInsertionEntry(isolate, k.Hash());
cache->set(CodeCacheSFIIndex(entry), *key); cache->set(EntryToIndex(entry), *key);
cache->set(CodeCacheCodeIndex(entry), *value_code); cache->set(EntryToIndex(entry) + 1, *value);
cache->set(CodeCacheFeedbackIndex(entry), *value_feedback);
cache->ElementAdded(); cache->ElementAdded();
return cache; return cache;
} }
...@@ -449,35 +425,6 @@ void CompilationCacheTable::Age() { ...@@ -449,35 +425,6 @@ void CompilationCacheTable::Age() {
} }
} }
void CompilationCacheTable::ClearDeoptimizedCode() {
DisallowGarbageCollection no_gc;
Object the_hole_value = GetReadOnlyRoots().the_hole_value();
Object undefined_value = GetReadOnlyRoots().undefined_value();
for (InternalIndex entry : IterateEntries()) {
Object maybe_code = get(CodeCacheCodeIndex(entry));
if (maybe_code == the_hole_value) continue;
// TODO(jgruber): There should only be one not-present value. Undefined is
// used as the initial filler on allocation. The hole is inserted by
// deletions.
if (maybe_code == undefined_value) continue;
SharedFunctionInfo sfi =
SharedFunctionInfo::cast(get(CodeCacheSFIIndex(entry)));
Code code = Code::cast(maybe_code);
if (code.marked_for_deoptimization()) {
// TODO(jgruber): Due to design of the compilation cache, there's a
// strange layering violation here in which we call the higher-level
// tracing function from the lower-level implementation. At some point,
// the entire compilation cache design should be reconsidered.
if (FLAG_trace_turbo_nci) {
CompilationCacheCode::TraceRemovalForDeoptimization(sfi, code);
}
sfi.set_may_have_cached_code(false);
RemoveEntry(EntryToIndex(entry));
}
}
}
void CompilationCacheTable::Remove(Object value) { void CompilationCacheTable::Remove(Object value) {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
for (InternalIndex entry : IterateEntries()) { for (InternalIndex entry : IterateEntries()) {
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "src/objects/feedback-cell.h" #include "src/objects/feedback-cell.h"
#include "src/objects/hash-table.h" #include "src/objects/hash-table.h"
#include "src/objects/js-regexp.h" #include "src/objects/js-regexp.h"
#include "src/objects/serialized-feedback.h"
#include "src/objects/shared-function-info.h" #include "src/objects/shared-function-info.h"
#include "src/roots/roots.h" #include "src/roots/roots.h"
...@@ -123,14 +122,10 @@ class CompilationCacheTable ...@@ -123,14 +122,10 @@ class CompilationCacheTable
// The Code cache shares native-context-independent (NCI) code between // The Code cache shares native-context-independent (NCI) code between
// contexts. // contexts.
bool LookupCode(Handle<SharedFunctionInfo> key, MaybeHandle<Code>* code_out, MaybeHandle<Code> LookupCode(Handle<SharedFunctionInfo> key);
MaybeHandle<SerializedFeedback>* feedback_out);
static Handle<CompilationCacheTable> PutCode( static Handle<CompilationCacheTable> PutCode(
Isolate* isolate, Handle<CompilationCacheTable> cache, Isolate* isolate, Handle<CompilationCacheTable> cache,
Handle<SharedFunctionInfo> key, Handle<Code> value_code, Handle<SharedFunctionInfo> key, Handle<Code> value);
Handle<SerializedFeedback> value_feedback);
// Removes Code objects that are marked_for_deoptimization from the cache.
void ClearDeoptimizedCode();
void Remove(Object value); void Remove(Object value);
void Age(); void Age();
......
// Copyright 2020 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.
#ifndef V8_OBJECTS_SERIALIZED_FEEDBACK_INL_H_
#define V8_OBJECTS_SERIALIZED_FEEDBACK_INL_H_
#include "src/objects/fixed-array-inl.h"
#include "src/objects/serialized-feedback.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
SerializedFeedback::SerializedFeedback(Address ptr) : ByteArray(ptr) {}
CAST_ACCESSOR(SerializedFeedback)
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_SERIALIZED_FEEDBACK_INL_H_
// Copyright 2020 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.
#include "src/objects/serialized-feedback.h"
#include "src/common/assert-scope.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/serialized-feedback-inl.h"
namespace v8 {
namespace internal {
namespace {
// Currently, only smi-based feedback is serialized.
bool IsSerialized(FeedbackSlotKind kind) {
switch (kind) {
case FeedbackSlotKind::kBinaryOp:
case FeedbackSlotKind::kCompareOp:
case FeedbackSlotKind::kForIn:
return true;
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kCall:
case FeedbackSlotKind::kLoadProperty:
case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
case FeedbackSlotKind::kLoadGlobalInsideTypeof:
case FeedbackSlotKind::kLoadKeyed:
case FeedbackSlotKind::kHasKeyed:
case FeedbackSlotKind::kStoreGlobalStrict:
case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreInArrayLiteral:
case FeedbackSlotKind::kStoreDataPropertyInLiteral:
case FeedbackSlotKind::kTypeProfile:
case FeedbackSlotKind::kLiteral:
case FeedbackSlotKind::kInstanceOf:
case FeedbackSlotKind::kCloneObject:
return false;
case FeedbackSlotKind::kInvalid:
case FeedbackSlotKind::kKindsNumber:
UNREACHABLE();
}
UNREACHABLE();
}
constexpr int SlotCountToByteLength(int slot_count) {
return slot_count * kUInt32Size;
}
constexpr int ByteLengthToSlotCount(int byte_length) {
CONSTEXPR_DCHECK((byte_length % kUInt32Size) == 0);
return byte_length / kUInt32Size;
}
} // namespace
// static
Handle<SerializedFeedback> SerializedFeedback::Serialize(
Isolate* isolate, Handle<FeedbackVector> vector) {
Handle<FeedbackMetadata> metadata(vector->metadata(), isolate);
const int slot_count = metadata->slot_count();
const int byte_length = SlotCountToByteLength(slot_count);
// Allocating in old space since these objects are inserted into long-lived
// caches.
auto sf = Handle<SerializedFeedback>::cast(
isolate->factory()->NewByteArray(byte_length, AllocationType::kOld));
// Initialize all relevant slots.
for (int i = 0; i < slot_count;) {
const FeedbackSlot slot{i};
const FeedbackSlotKind slot_kind = metadata->GetKind(slot);
const int slot_size = FeedbackMetadata::GetSlotSize(slot_kind);
if (IsSerialized(slot_kind)) {
// All handled slot kinds currently use smi-based feedback; these are
// simply serialized as the value.
DCHECK_EQ(slot_size, 1);
const uint32_t value = vector->Get(slot)->ToSmi().value();
sf->set_uint32(i, value);
} else {
// Unhandled slot kinds are zeroed.
sf->set_uint32(i, 0);
}
i += slot_size;
}
return sf;
}
void SerializedFeedback::DeserializeInto(FeedbackVector vector) const {
DisallowGarbageCollection no_gc;
FeedbackMetadata metadata = vector.metadata();
const int slot_count = metadata.slot_count();
CHECK_EQ(slot_count, ByteLengthToSlotCount(length()));
for (int i = 0; i < slot_count;) {
const FeedbackSlot slot{i};
const FeedbackSlotKind slot_kind = metadata.GetKind(slot);
const int slot_size = FeedbackMetadata::GetSlotSize(slot_kind);
const uint32_t serialized_value = get_uint32(i);
if (IsSerialized(slot_kind)) {
DCHECK_EQ(slot_size, 1);
DCHECK_EQ(vector.Get(slot)->ToSmi().value(), 0); // Uninitialized.
vector.SynchronizedSet(slot, Smi::FromInt(serialized_value),
SKIP_WRITE_BARRIER);
DCHECK_EQ(vector.Get(slot)->ToSmi().value(), serialized_value);
} else {
DCHECK_EQ(serialized_value, 0);
}
i += slot_size;
}
}
} // namespace internal
} // namespace v8
// Copyright 2020 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.
#ifndef V8_OBJECTS_SERIALIZED_FEEDBACK_H_
#define V8_OBJECTS_SERIALIZED_FEEDBACK_H_
#include "src/objects/fixed-array.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class FeedbackVector;
// A serialized representation of FeedbackVector, used to share collected
// feedback between native contexts.
//
// Note: The encoding is not final and thus not documented here yet. Currently,
// only smi-based feedback is shared/serialized.
class SerializedFeedback : public ByteArray {
public:
// Serialize current feedback vector values into a SerializedFeedback object.
static Handle<SerializedFeedback> Serialize(Isolate* isolate,
Handle<FeedbackVector> vector);
// Deserialize into the given vector.
void DeserializeInto(FeedbackVector vector) const;
DECL_CAST(SerializedFeedback)
OBJECT_CONSTRUCTORS(SerializedFeedback, ByteArray);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_SERIALIZED_FEEDBACK_H_
...@@ -440,21 +440,10 @@ std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) { ...@@ -440,21 +440,10 @@ std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
} }
} }
bool SharedFunctionInfo::TryGetCachedCodeAndSerializedFeedback(
Isolate* isolate, MaybeHandle<Code>* code_out,
MaybeHandle<SerializedFeedback>* feedback_out) {
if (!may_have_cached_code()) return {};
Handle<SharedFunctionInfo> sfi(*this, isolate);
return isolate->compilation_cache()->LookupCode(sfi, code_out, feedback_out);
}
MaybeHandle<Code> SharedFunctionInfo::TryGetCachedCode(Isolate* isolate) { MaybeHandle<Code> SharedFunctionInfo::TryGetCachedCode(Isolate* isolate) {
if (!may_have_cached_code()) return {}; if (!may_have_cached_code()) return {};
Handle<SharedFunctionInfo> sfi(*this, isolate); Handle<SharedFunctionInfo> zis(*this, isolate);
MaybeHandle<Code> maybe_code; return isolate->compilation_cache()->LookupCode(zis);
MaybeHandle<SerializedFeedback> maybe_feedback;
isolate->compilation_cache()->LookupCode(sfi, &maybe_code, &maybe_feedback);
return maybe_code;
} }
void SharedFunctionInfo::DisableOptimization(BailoutReason reason) { void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
......
...@@ -34,7 +34,6 @@ class BytecodeArray; ...@@ -34,7 +34,6 @@ class BytecodeArray;
class CoverageInfo; class CoverageInfo;
class DebugInfo; class DebugInfo;
class IsCompiledScope; class IsCompiledScope;
class SerializedFeedback;
class WasmCapiFunctionData; class WasmCapiFunctionData;
class WasmExportedFunctionData; class WasmExportedFunctionData;
class WasmJSFunctionData; class WasmJSFunctionData;
...@@ -397,12 +396,8 @@ class SharedFunctionInfo ...@@ -397,12 +396,8 @@ class SharedFunctionInfo
// hence the 'may'. // hence the 'may'.
DECL_BOOLEAN_ACCESSORS(may_have_cached_code) DECL_BOOLEAN_ACCESSORS(may_have_cached_code)
// Fetches cached NCI artifacts, if they exist. Some callsites only care // Returns the cached Code object for this SFI if it exists, an empty handle
// about the cached Code object; to distinguish them clearly, there's a // otherwise.
// dedicated helper that only returns the Code object.
bool TryGetCachedCodeAndSerializedFeedback(
Isolate* isolate, MaybeHandle<Code>* code_out,
MaybeHandle<SerializedFeedback>* feedback_out);
MaybeHandle<Code> TryGetCachedCode(Isolate* isolate); MaybeHandle<Code> TryGetCachedCode(Isolate* isolate);
// Is this function a top-level function (scripts, evals). // Is this function a top-level function (scripts, evals).
......
...@@ -79,21 +79,11 @@ void TryInstallNCICode(Isolate* isolate, Handle<JSFunction> function, ...@@ -79,21 +79,11 @@ void TryInstallNCICode(Isolate* isolate, Handle<JSFunction> function,
DCHECK(sfi->may_have_cached_code()); DCHECK(sfi->may_have_cached_code());
DCHECK_EQ(function->shared(), *sfi); DCHECK_EQ(function->shared(), *sfi);
MaybeHandle<Code> maybe_code; Handle<Code> code;
MaybeHandle<SerializedFeedback> maybe_feedback; if (sfi->TryGetCachedCode(isolate).ToHandle(&code)) {
if (sfi->TryGetCachedCodeAndSerializedFeedback(isolate, &maybe_code,
&maybe_feedback)) {
Handle<Code> code = maybe_code.ToHandleChecked();
if (FLAG_trace_turbo_nci) CompilationCacheCode::TraceHit(sfi, code);
function->set_code(*code); function->set_code(*code);
JSFunction::EnsureFeedbackVector(function, is_compiled_scope);
if (!function->has_feedback_vector()) { if (FLAG_trace_turbo_nci) CompilationCacheCode::TraceHit(sfi, code);
JSFunction::EnsureFeedbackVector(function, is_compiled_scope);
// TODO(jgruber,v8:8888): Consider combining shared feedback with
// existing feedback here.
maybe_feedback.ToHandleChecked()->DeserializeInto(
function->feedback_vector());
}
} }
} }
......
...@@ -1447,19 +1447,6 @@ ...@@ -1447,19 +1447,6 @@
'compiler/serializer-transition-propagation': [SKIP], 'compiler/serializer-transition-propagation': [SKIP],
# crbug.com/v8/11110 # crbug.com/v8/11110
'es6/super-ic-opt*': [SKIP], 'es6/super-ic-opt*': [SKIP],
# Rely on optimizations not yet enabled for NCI. For example, preserving
# kIdentifyZero for kNumberFloor (and thus avoiding later deopts) only works
# if the JSCallReducer reduces the Math.floor builtin call to the
# kNumberFloor operator.
'compiler/number-floor': [SKIP],
'compiler/number-ceil': [SKIP],
'compiler/number-min': [SKIP],
'compiler/number-modulus': [SKIP],
'compiler/number-toboolean': [SKIP],
'compiler/number-abs': [SKIP],
'compiler/number-round': [SKIP],
'compiler/number-max': [SKIP],
'compiler/number-trunc': [SKIP],
}], # variant == nci or variant == nci_as_midtier }], # variant == nci or variant == nci_as_midtier
['((arch == mipsel or arch == mips64el or arch == mips or arch == mips64) and not simd_mips) or (arch in [ppc64, s390x])', { ['((arch == mipsel or arch == mips64el or arch == mips or arch == mips64) and not simd_mips) or (arch in [ppc64, s390x])', {
......
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