Reviewers: Jakob,
Message:
Hi Jakob,
Could you have a look?
I'd be keen to get this in a chrome build.
Thanks for the help,
--Michael
Description:
Some extra checks to debug a crash failure related to type feedback vector.
It appears that we have some path that recompiles code that looks quite
different from the first compile. The vector structure is different. I've
added
extra CHECKs() to catch the problem a bit sooner, and also made it clear
that
setting code in the SharedFunctionInfo requires setting a vector, too.
BUG=503565
Please review this at https://codereview.chromium.org/1219533003/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+58, -39 lines):
M src/compiler.cc
M src/debug.cc
M src/factory.cc
M src/heap/mark-compact.cc
M src/objects.h
M src/objects.cc
M src/objects-inl.h
M src/runtime/runtime-function.cc
M src/type-feedback-vector.h
M test/cctest/test-heap.cc
Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index
0f3ebe0e6726666acba53cb8745366e992aed288..9598351c62abdbaf2b411f93011e1ef896f554bd
100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -213,6 +213,7 @@ bool CompilationInfo::ShouldSelfOptimize() {
void CompilationInfo::EnsureFeedbackVector() {
if (feedback_vector_.is_null() ||
feedback_vector_->SpecDiffersFrom(function()->feedback_vector_spec())) {
+ CHECK(feedback_vector_.is_null());
feedback_vector_ = isolate()->factory()->NewTypeFeedbackVector(
function()->feedback_vector_spec());
}
@@ -684,8 +685,7 @@ MUST_USE_RESULT static MaybeHandle<Code>
GetUnoptimizedCodeCommon(
shared->set_scope_info(*scope_info);
// Update the code and feedback vector for the shared function info.
- shared->ReplaceCode(*info->code());
- shared->set_feedback_vector(*info->feedback_vector());
+ shared->ReplaceCode(*info->code(), *info->feedback_vector());
return info->code();
}
@@ -957,9 +957,8 @@ bool
Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
}
if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
- shared->EnableDeoptimizationSupport(*unoptimized.code());
- shared->set_feedback_vector(*unoptimized.feedback_vector());
-
+ shared->EnableDeoptimizationSupport(*unoptimized.code(),
+ *unoptimized.feedback_vector());
info->MarkAsCompiled();
// The scope info might not have been set if a lazily compiled
@@ -1461,9 +1460,8 @@ Handle<SharedFunctionInfo>
Compiler::GetSharedFunctionInfo(
} else if (!lazy) {
// We have additional data from compilation now.
DCHECK(!existing->is_compiled());
- existing->ReplaceCode(*info.code());
+ existing->ReplaceCode(*info.code(), *info.feedback_vector());
existing->set_scope_info(*scope_info);
- existing->set_feedback_vector(*info.feedback_vector());
}
return existing;
}
@@ -1501,7 +1499,7 @@ MaybeHandle<Code>
Compiler::GetOptimizedCode(Handle<JSFunction> function,
if (!GetUnoptimizedCodeCommon(&unoptimized).ToHandle(¤t_code)) {
return MaybeHandle<Code>();
}
- shared->ReplaceCode(*current_code);
+ shared->ReplaceCode(*current_code, *unoptimized.feedback_vector());
}
current_code->set_profiler_ticks(0);
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index
e952fe7ebb88a9dc07893f4e973be4fc5fc9ffab..5e043abe8681c4eaf66bc5a2fd269b549a8c1d0d
100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1873,7 +1873,9 @@ void Debug::PrepareForBreakPoints() {
if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
if (shared->is_generator()) continue;
if (HasDebugBreakSlots(shared->code())) continue;
- shared->ReplaceCode(*lazy_compile);
+ shared->ReplaceCode(
+ *lazy_compile,
+
TypeFeedbackVector::cast(isolate_->heap()->empty_fixed_array()));
}
}
@@ -1890,12 +1892,14 @@ void Debug::PrepareForBreakPoints() {
// Mark generator functions that didn't have suspended activations for
lazy
// recompilation. Note that this set does not include any active
functions.
+ Heap* heap = isolate_->heap();
for (int i = 0; i < generator_functions.length(); i++) {
Handle<JSFunction> &function = generator_functions[i];
if (function->code()->kind() != Code::FUNCTION) continue;
if (function->code()->has_debug_break_slots()) continue;
function->ReplaceCode(*lazy_compile);
- function->shared()->ReplaceCode(*lazy_compile);
+ function->shared()->ReplaceCode(
+ *lazy_compile,
TypeFeedbackVector::cast(heap->empty_fixed_array()));
}
// Now recompile all functions with activation frames and and
Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index
2b79a5bf8f25a74a8ac37a35efa75fe7427ea86e..10d57e74948d4820698cd0237123b89a78dc867d
100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -2158,6 +2158,9 @@ Handle<SharedFunctionInfo>
Factory::NewSharedFunctionInfo(
MaybeHandle<Code> maybe_code) {
Handle<Map> map = shared_function_info_map();
Handle<SharedFunctionInfo> share = New<SharedFunctionInfo>(map,
OLD_SPACE);
+ FeedbackVectorSpec empty_spec(0);
+ Handle<TypeFeedbackVector> feedback_vector =
+ NewTypeFeedbackVector(&empty_spec);
// Set pointer fields.
share->set_name(*name);
@@ -2166,6 +2169,7 @@ Handle<SharedFunctionInfo>
Factory::NewSharedFunctionInfo(
code = handle(isolate()->builtins()->builtin(Builtins::kIllegal));
}
share->set_code(*code);
+ share->set_feedback_vector(*feedback_vector, SKIP_WRITE_BARRIER);
share->set_optimized_code_map(Smi::FromInt(0));
share->set_scope_info(ScopeInfo::Empty(isolate()));
Code* construct_stub =
@@ -2176,10 +2180,6 @@ Handle<SharedFunctionInfo>
Factory::NewSharedFunctionInfo(
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_inferred_name(*empty_string(), SKIP_WRITE_BARRIER);
- FeedbackVectorSpec empty_spec(0);
- Handle<TypeFeedbackVector> feedback_vector =
- NewTypeFeedbackVector(&empty_spec);
- share->set_feedback_vector(*feedback_vector, SKIP_WRITE_BARRIER);
#if TRACE_MAPS
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
#endif
Index: src/heap/mark-compact.cc
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
index
8bbfeb173f7ba3ac5e55b63145e62d3085338727..e833eb7e2c0c99081cd205be11e0de2928f94c37
100644
--- a/src/heap/mark-compact.cc
+++ b/src/heap/mark-compact.cc
@@ -851,6 +851,7 @@ void MarkCompactCollector::Finish() {
void CodeFlusher::ProcessJSFunctionCandidates() {
Code* lazy_compile =
isolate_->builtins()->builtin(Builtins::kCompileLazy);
Object* undefined = isolate_->heap()->undefined_value();
+ FixedArray* empty_fixed_array = isolate_->heap()->empty_fixed_array();
JSFunction* candidate = jsfunction_candidates_head_;
JSFunction* next_candidate;
@@ -873,6 +874,7 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
shared->ClearOptimizedCodeMap();
}
shared->set_code(lazy_compile);
+
shared->set_feedback_vector(TypeFeedbackVector::cast(empty_fixed_array));
candidate->set_code(lazy_compile);
} else {
DCHECK(Marking::IsBlack(code_mark));
@@ -900,6 +902,7 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
Code* lazy_compile =
isolate_->builtins()->builtin(Builtins::kCompileLazy);
+ FixedArray* empty_fixed_array = isolate_->heap()->empty_fixed_array();
SharedFunctionInfo* candidate = shared_function_info_candidates_head_;
SharedFunctionInfo* next_candidate;
@@ -920,6 +923,8 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates()
{
candidate->ClearOptimizedCodeMap();
}
candidate->set_code(lazy_compile);
+ candidate->set_feedback_vector(
+ TypeFeedbackVector::cast(empty_fixed_array));
}
Object** code_slot =
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index
0e43e1d3a0fbd434bf311fa3dffc579b3b73a3ee..277a8af4dee35c822ba5920d68cb5ef5cc7afa1c
100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -5443,7 +5443,7 @@ void SharedFunctionInfo::set_code(Code* value,
WriteBarrierMode mode) {
}
-void SharedFunctionInfo::ReplaceCode(Code* value) {
+void SharedFunctionInfo::ReplaceCode(Code* value, TypeFeedbackVector*
vector) {
// If the GC metadata field is already used then the function was
// enqueued as a code flushing candidate and we remove it now.
if (code()->gc_metadata() != NULL) {
@@ -5454,7 +5454,7 @@ void SharedFunctionInfo::ReplaceCode(Code* value) {
DCHECK(code()->gc_metadata() == NULL && value->gc_metadata() == NULL);
set_code(value);
-
+ set_feedback_vector(vector);
if (is_compiled()) set_never_compiled(false);
}
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
b14281a41bbbe9648a6838a292b811264596392b..3094f5d4157109aa88fd7dba061a1d5574f90df2
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -10559,7 +10559,8 @@ static bool IsCodeEquivalent(Code* code, Code*
recompiled) {
}
-void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
+void SharedFunctionInfo::EnableDeoptimizationSupport(
+ Code* recompiled, TypeFeedbackVector* vector) {
DCHECK(!has_deoptimization_support());
DisallowHeapAllocation no_allocation;
Code* code = this->code();
@@ -10572,7 +10573,7 @@ void
SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
// old code, we have to replace it. We should try to avoid this
// altogether because it flushes valuable type feedback by
// effectively resetting all IC state.
- ReplaceCode(recompiled);
+ ReplaceCode(recompiled, vector);
}
DCHECK(has_deoptimization_support());
}
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
dc96725023d6c7f0bf14b0383303d3ef04f2b8ab..5add9261c2c318ed035954ddf45cd4ce0579ddda
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -6580,7 +6580,7 @@ class SharedFunctionInfo: public HeapObject {
// [code]: Function code.
DECL_ACCESSORS(code, Code)
- inline void ReplaceCode(Code* code);
+ inline void ReplaceCode(Code* code, TypeFeedbackVector* vector);
// [optimized_code_map]: Map from native context to optimized code
// and a shared literals array or Smi(0) if none.
@@ -6848,7 +6848,8 @@ class SharedFunctionInfo: public HeapObject {
inline bool has_deoptimization_support();
// Enable deoptimization support through recompiled code.
- void EnableDeoptimizationSupport(Code* recompiled);
+ void EnableDeoptimizationSupport(Code* recompiled,
+ TypeFeedbackVector* vector);
// Disable (further) attempted optimization of all functions sharing this
// shared function info.
Index: src/runtime/runtime-function.cc
diff --git a/src/runtime/runtime-function.cc
b/src/runtime/runtime-function.cc
index
749e16b9ed12dc37b1cf0461606839c06d92c510..026b2939672548ba5944c8430c85703514e910a9
100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -226,10 +226,10 @@ RUNTIME_FUNCTION(Runtime_SetCode) {
// Set the code, scope info, formal parameter count, and the length
// of the target shared function info.
- target_shared->ReplaceCode(source_shared->code());
+ target_shared->ReplaceCode(source_shared->code(),
+ source_shared->feedback_vector());
target_shared->set_scope_info(source_shared->scope_info());
target_shared->set_length(source_shared->length());
- target_shared->set_feedback_vector(source_shared->feedback_vector());
target_shared->set_internal_formal_parameter_count(
source_shared->internal_formal_parameter_count());
target_shared->set_start_position_and_type(
Index: src/type-feedback-vector.h
diff --git a/src/type-feedback-vector.h b/src/type-feedback-vector.h
index
a6f72210fc9f2545d77ea92e885a6f801071fadd..89970c6580dbcfcb3c4509e69e8b34c2f4201231
100644
--- a/src/type-feedback-vector.h
+++ b/src/type-feedback-vector.h
@@ -146,39 +146,47 @@ class TypeFeedbackVector : public FixedArray {
// Conversion from a slot or ic slot to an integer index to the
underlying
// array.
int GetIndex(FeedbackVectorSlot slot) const {
- DCHECK(slot.ToInt() < first_ic_slot_index());
+ CHECK(slot.ToInt() < first_ic_slot_index());
return kReservedIndexCount + ic_metadata_length() + slot.ToInt();
}
int GetIndex(FeedbackVectorICSlot slot) const {
int first_ic_slot = first_ic_slot_index();
- DCHECK(slot.ToInt() < ICSlots());
+ CHECK(slot.ToInt() < ICSlots());
return first_ic_slot + slot.ToInt() * elements_per_ic_slot();
}
// Conversion from an integer index to either a slot or an ic slot. The
caller
// should know what kind she expects.
FeedbackVectorSlot ToSlot(int index) const {
- DCHECK(index >= kReservedIndexCount && index < first_ic_slot_index());
+ CHECK(index >= kReservedIndexCount && index < first_ic_slot_index());
return FeedbackVectorSlot(index - ic_metadata_length() -
kReservedIndexCount);
}
FeedbackVectorICSlot ToICSlot(int index) const {
- DCHECK(index >= first_ic_slot_index() && index < length());
+ CHECK(index >= first_ic_slot_index() && index < length());
int ic_slot = (index - first_ic_slot_index()) / elements_per_ic_slot();
return FeedbackVectorICSlot(ic_slot);
}
- Object* Get(FeedbackVectorSlot slot) const { return get(GetIndex(slot));
}
+ Object* Get(FeedbackVectorSlot slot) const {
+ CHECK(GetIndex(slot) < length());
+ return get(GetIndex(slot));
+ }
void Set(FeedbackVectorSlot slot, Object* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER) {
+ CHECK(GetIndex(slot) < length());
set(GetIndex(slot), value, mode);
}
- Object* Get(FeedbackVectorICSlot slot) const { return
get(GetIndex(slot)); }
+ Object* Get(FeedbackVectorICSlot slot) const {
+ CHECK(GetIndex(slot) < length());
+ return get(GetIndex(slot));
+ }
void Set(FeedbackVectorICSlot slot, Object* value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER) {
+ CHECK(GetIndex(slot) < length());
set(GetIndex(slot), value, mode);
}
@@ -344,11 +352,11 @@ class CallICNexus : public FeedbackNexus {
CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::CALL_IC);
+ CHECK(vector->GetKind(slot) == Code::CALL_IC);
}
CallICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::CALL_IC);
+ CHECK(vector->GetKind(slot) == Code::CALL_IC);
}
void Clear(Code* host);
@@ -377,11 +385,11 @@ class LoadICNexus : public FeedbackNexus {
public:
LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::LOAD_IC);
+ CHECK(vector->GetKind(slot) == Code::LOAD_IC);
}
LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::LOAD_IC);
+ CHECK(vector->GetKind(slot) == Code::LOAD_IC);
}
void Clear(Code* host);
@@ -398,11 +406,11 @@ class KeyedLoadICNexus : public FeedbackNexus {
public:
KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot
slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC);
+ CHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC);
}
KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC);
+ CHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC);
}
void Clear(Code* host);
@@ -423,11 +431,11 @@ class StoreICNexus : public FeedbackNexus {
public:
StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorICSlot
slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::STORE_IC);
+ CHECK(vector->GetKind(slot) == Code::STORE_IC);
}
StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::STORE_IC);
+ CHECK(vector->GetKind(slot) == Code::STORE_IC);
}
void Clear(Code* host);
@@ -445,11 +453,11 @@ class KeyedStoreICNexus : public FeedbackNexus {
KeyedStoreICNexus(Handle<TypeFeedbackVector> vector,
FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
+ CHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
}
KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorICSlot slot)
: FeedbackNexus(vector, slot) {
- DCHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
+ CHECK(vector->GetKind(slot) == Code::KEYED_STORE_IC);
}
void Clear(Code* host);
Index: test/cctest/test-heap.cc
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index
6229670da848efbbf75c6d50e3605d0e052180a7..f0b82a1e4c647cf31d35bfd2d8d845e18826b417
100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -5933,7 +5933,9 @@ static void RemoveCodeAndGC(const
v8::FunctionCallbackInfo<v8::Value>& args) {
Handle<Object> obj = v8::Utils::OpenHandle(*args[0]);
Handle<JSFunction> fun = Handle<JSFunction>::cast(obj);
fun->ReplaceCode(*isolate->builtins()->CompileLazy());
- fun->shared()->ReplaceCode(*isolate->builtins()->CompileLazy());
+ fun->shared()->ReplaceCode(
+ *isolate->builtins()->CompileLazy(),
+ TypeFeedbackVector::cast(isolate->heap()->empty_fixed_array()));
isolate->heap()->CollectAllAvailableGarbage("remove code and gc");
}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.