Moved type feedback vector to SharedFunctionInfo.

Type Vector followup: the type vector currently lives off the code object. This CL moves it to the SharedFunctionInfo, facilitating re-use and continued use in crankshafted code if desired.

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/178463007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19712 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mvstanton@chromium.org 2014-03-07 10:12:17 +00:00
parent 31f67939cb
commit 1812f63fd2
26 changed files with 130 additions and 140 deletions

View File

@ -129,8 +129,6 @@ void FullCodeGenerator::Generate() {
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
InitializeFeedbackVector();
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@ -1162,12 +1160,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// We got a fixed array in register x0. Iterate through that.
__ Bind(&fixed_array);
Handle<Object> feedback = Handle<Object>(
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
isolate());
StoreFeedbackVectorSlot(slot, feedback);
__ LoadObject(x1, FeedbackVector());
__ Mov(x10, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
__ Mov(x10, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
__ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot)));
__ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check.
@ -2415,9 +2409,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Record source position for debugger.
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ LoadObject(x2, FeedbackVector());
__ Mov(x3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
@ -2614,9 +2605,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ Peek(x1, arg_count * kXRegSizeInBytes);
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
__ LoadObject(x2, FeedbackVector());
__ Mov(x3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));

View File

@ -131,8 +131,6 @@ void FullCodeGenerator::Generate() {
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
InitializeFeedbackVector();
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@ -1167,12 +1165,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label non_proxy;
__ bind(&fixed_array);
Handle<Object> feedback = Handle<Object>(
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
isolate());
StoreFeedbackVectorSlot(slot, feedback);
__ Move(r1, FeedbackVector());
__ mov(r2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
__ mov(r2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
__ str(r2, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(slot)));
__ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
@ -2714,9 +2708,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Record source position for debugger.
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ Move(r2, FeedbackVector());
__ mov(r3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
@ -2903,9 +2894,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ ldr(r1, MemOperand(sp, arg_count * kPointerSize));
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
__ Move(r2, FeedbackVector());
__ mov(r3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));

View File

@ -141,6 +141,15 @@ void CompilationInfo::Initialize(Isolate* isolate,
SetLanguageMode(shared_info_->language_mode());
}
set_bailout_reason(kUnknown);
if (!shared_info().is_null()) {
FixedArray* info_feedback_vector = shared_info()->feedback_vector();
if (info_feedback_vector->length() > 0) {
// We should initialize the CompilationInfo feedback vector from the
// passed in shared info, rather than creating a new one.
feedback_vector_ = Handle<FixedArray>(info_feedback_vector, isolate);
}
}
}
@ -250,6 +259,20 @@ void CompilationInfo::PrepareForCompilation(Scope* scope) {
ASSERT(scope_ == NULL);
scope_ = scope;
function()->ProcessFeedbackSlots(isolate_);
int length = function()->slot_count();
if (feedback_vector_.is_null()) {
// Allocate the feedback vector too.
feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
// Ensure we can skip the write barrier
ASSERT_EQ(isolate()->heap()->uninitialized_symbol(),
*TypeFeedbackInfo::UninitializedSentinel(isolate()));
for (int i = 0; i < length; i++) {
feedback_vector_->set(i,
*TypeFeedbackInfo::UninitializedSentinel(isolate()),
SKIP_WRITE_BARRIER);
}
}
ASSERT(feedback_vector_->length() == length);
}
@ -571,6 +594,8 @@ static void UpdateSharedFunctionInfo(CompilationInfo* info) {
shared->ReplaceCode(*code);
if (shared->optimization_disabled()) code->set_optimizable(false);
shared->set_feedback_vector(*info->feedback_vector());
// Set the expected number of properties for instances.
FunctionLiteral* lit = info->function();
int expected = lit->expected_property_count();
@ -826,7 +851,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
lit->materialized_literal_count(),
lit->is_generator(),
info->code(),
ScopeInfo::Create(info->scope(), info->zone()));
ScopeInfo::Create(info->scope(), info->zone()),
info->feedback_vector());
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
SetFunctionInfo(result, lit, true, script);
@ -1033,7 +1059,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
literal->materialized_literal_count(),
literal->is_generator(),
info.code(),
scope_info);
scope_info,
info.feedback_vector());
SetFunctionInfo(result, literal, false, script);
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
result->set_allows_lazy_compilation(allow_lazy);

View File

@ -181,6 +181,9 @@ class CompilationInfo {
ASSERT(global_scope_ == NULL);
global_scope_ = global_scope;
}
Handle<FixedArray> feedback_vector() const {
return feedback_vector_;
}
void SetCode(Handle<Code> code) { code_ = code; }
void SetExtension(v8::Extension* extension) {
ASSERT(!is_lazy());
@ -409,6 +412,9 @@ class CompilationInfo {
// global script. Will be a null handle otherwise.
Handle<Context> context_;
// Used by codegen, ultimately kept rooted by the SharedFunctionInfo.
Handle<FixedArray> feedback_vector_;
// Compilation mode flag and whether deoptimization is allowed.
Mode mode_;
BailoutId osr_ast_id_;

View File

@ -1541,10 +1541,12 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
int number_of_literals,
bool is_generator,
Handle<Code> code,
Handle<ScopeInfo> scope_info) {
Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector) {
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
shared->set_code(*code);
shared->set_scope_info(*scope_info);
shared->set_feedback_vector(*feedback_vector);
int literals_array_size = number_of_literals;
// If the function contains object, regexp or array literals,
// allocate extra space for a literals array prefix containing the

View File

@ -516,7 +516,8 @@ class Factory {
int number_of_literals,
bool is_generator,
Handle<Code> code,
Handle<ScopeInfo> scope_info);
Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
Handle<JSMessageObject> NewJSMessageObject(

View File

@ -386,18 +386,6 @@ unsigned FullCodeGenerator::EmitBackEdgeTable() {
}
void FullCodeGenerator::InitializeFeedbackVector() {
int length = info_->function()->slot_count();
feedback_vector_ = isolate()->factory()->NewFixedArray(length, TENURED);
Handle<Object> sentinel = TypeFeedbackInfo::UninitializedSentinel(isolate());
// Ensure that it's safe to set without using a write barrier.
ASSERT_EQ(isolate()->heap()->uninitialized_symbol(), *sentinel);
for (int i = 0; i < length; i++) {
feedback_vector_->set(i, *sentinel, SKIP_WRITE_BARRIER);
}
}
void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
// Fill in the deoptimization information.
ASSERT(info_->HasDeoptimizationSupport() || bailout_entries_.is_empty());
@ -416,7 +404,6 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) {
void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
Handle<TypeFeedbackInfo> info = isolate()->factory()->NewTypeFeedbackInfo();
info->set_ic_total_count(ic_total_count_);
info->set_feedback_vector(*FeedbackVector());
ASSERT(!isolate()->heap()->InNewSpace(*info));
code->set_type_feedback_info(*info);
}
@ -1590,7 +1577,8 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
bool is_generator = false;
Handle<SharedFunctionInfo> shared =
isolate()->factory()->NewSharedFunctionInfo(name, literals, is_generator,
code, Handle<ScopeInfo>(fun->shared()->scope_info()));
code, Handle<ScopeInfo>(fun->shared()->scope_info()),
Handle<FixedArray>(fun->shared()->feedback_vector()));
shared->set_construct_stub(*construct_stub);
// Copy the function data to the shared function info.

View File

@ -437,12 +437,8 @@ class FullCodeGenerator: public AstVisitor {
// Feedback slot support. The feedback vector will be cleared during gc and
// collected by the type-feedback oracle.
Handle<FixedArray> FeedbackVector() {
return feedback_vector_;
return info_->feedback_vector();
}
void StoreFeedbackVectorSlot(int slot, Handle<Object> object) {
feedback_vector_->set(slot, *object);
}
void InitializeFeedbackVector();
// Record a call's return site offset, used to rebuild the frame if the
// called function was inlined at the site.
@ -848,7 +844,6 @@ class FullCodeGenerator: public AstVisitor {
ZoneList<BackEdgeEntry> back_edges_;
int ic_total_count_;
Handle<FixedArray> handler_table_;
Handle<FixedArray> feedback_vector_;
Handle<Cell> profiling_counter_;
bool generate_debug_code_;

View File

@ -1327,6 +1327,9 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
SetInternalReference(obj, entry,
"optimized_code_map", shared->optimized_code_map(),
SharedFunctionInfo::kOptimizedCodeMapOffset);
SetInternalReference(obj, entry,
"feedback_vector", shared->feedback_vector(),
SharedFunctionInfo::kFeedbackVectorOffset);
SetWeakReference(obj, entry,
"initial_map", shared->initial_map(),
SharedFunctionInfo::kInitialMapOffset);

View File

@ -2684,7 +2684,6 @@ MaybeObject* Heap::AllocateTypeFeedbackInfo() {
if (!maybe_info->To(&info)) return maybe_info;
}
info->initialize_storage();
info->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
return info;
}
@ -3806,6 +3805,7 @@ MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) {
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);
share->set_feedback_vector(empty_fixed_array(), SKIP_WRITE_BARRIER);
share->set_initial_map(undefined_value(), SKIP_WRITE_BARRIER);
share->set_ast_node_count(0);
share->set_counters(0);

View File

@ -7210,6 +7210,7 @@ bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
target_shared->set_scope_info(*target_scope_info);
}
target_shared->EnableDeoptimizationSupport(*target_info.code());
target_shared->set_feedback_vector(*target_info.feedback_vector());
Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
&target_info,
target_shared);

View File

@ -119,8 +119,6 @@ void FullCodeGenerator::Generate() {
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
InitializeFeedbackVector();
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@ -1104,15 +1102,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label non_proxy;
__ bind(&fixed_array);
Handle<Object> feedback = Handle<Object>(
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
isolate());
StoreFeedbackVectorSlot(slot, feedback);
// No need for a write barrier, we are storing a Smi in the feedback vector.
__ LoadHeapObject(ebx, FeedbackVector());
__ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
Immediate(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
__ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
@ -2666,9 +2659,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Record source position for debugger.
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ LoadHeapObject(ebx, FeedbackVector());
__ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
@ -2846,9 +2836,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ mov(edi, Operand(esp, arg_count * kPointerSize));
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
__ LoadHeapObject(ebx, FeedbackVector());
__ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));

View File

@ -139,8 +139,6 @@ void FullCodeGenerator::Generate() {
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
InitializeFeedbackVector();
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@ -1176,12 +1174,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label non_proxy;
__ bind(&fixed_array);
Handle<Object> feedback = Handle<Object>(
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
isolate());
StoreFeedbackVectorSlot(slot, feedback);
__ li(a1, FeedbackVector());
__ li(a2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
__ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
__ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
__ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
@ -2737,9 +2731,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Record source position for debugger.
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ li(a2, FeedbackVector());
__ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
@ -2924,9 +2915,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ lw(a1, MemOperand(sp, arg_count * kPointerSize));
// Record call targets in unoptimized code.
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
__ li(a2, FeedbackVector());
__ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));

View File

@ -368,7 +368,6 @@ void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
VerifyObjectField(kStorage1Offset);
VerifyObjectField(kStorage2Offset);
VerifyHeapPointer(feedback_vector());
}
@ -545,6 +544,7 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
VerifyObjectField(kNameOffset);
VerifyObjectField(kCodeOffset);
VerifyObjectField(kOptimizedCodeMapOffset);
VerifyObjectField(kFeedbackVectorOffset);
VerifyObjectField(kScopeInfoOffset);
VerifyObjectField(kInstanceClassNameOffset);
VerifyObjectField(kFunctionDataOffset);

View File

@ -1474,7 +1474,7 @@ AllocationSiteMode AllocationSite::GetMode(
AllocationSiteMode AllocationSite::GetMode(ElementsKind from,
ElementsKind to) {
if (IsFastSmiElementsKind(from) &&
IsMoreGeneralElementsKindTransition(from, to)) {
IsMoreGeneralElementsKindTransition(from, to)) {
return TRACK_ALLOCATION_SITE;
}
@ -4945,6 +4945,8 @@ ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
ACCESSORS(SharedFunctionInfo, optimized_code_map, Object,
kOptimizedCodeMapOffset)
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
ACCESSORS(SharedFunctionInfo, feedback_vector, FixedArray,
kFeedbackVectorOffset)
ACCESSORS(SharedFunctionInfo, initial_map, Object, kInitialMapOffset)
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
kInstanceClassNameOffset)
@ -6624,10 +6626,6 @@ bool TypeFeedbackInfo::matches_inlined_type_change_checksum(int checksum) {
}
ACCESSORS(TypeFeedbackInfo, feedback_vector, FixedArray,
kFeedbackVectorOffset)
SMI_ACCESSORS(AliasedArgumentsEntry, aliased_context_slot, kAliasedContextSlot)

View File

@ -566,8 +566,6 @@ void TypeFeedbackInfo::TypeFeedbackInfoPrint(FILE* out) {
HeapObject::PrintHeader(out, "TypeFeedbackInfo");
PrintF(out, " - ic_total_count: %d, ic_with_type_info_count: %d\n",
ic_total_count(), ic_with_type_info_count());
PrintF(out, " - feedback_vector: ");
feedback_vector()->FixedArrayPrint(out);
}
@ -878,6 +876,8 @@ void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
PrintF(out, "\n - length = %d", length());
PrintF(out, "\n - optimized_code_map = ");
optimized_code_map()->ShortPrint(out);
PrintF(out, "\n - feedback_vector = ");
feedback_vector()->FixedArrayPrint(out);
PrintF(out, "\n");
}

View File

@ -426,9 +426,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCode(
Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
Code* code = Code::cast(object);
if (FLAG_cleanup_code_caches_at_gc) {
code->ClearTypeFeedbackInfo(heap);
}
if (FLAG_age_code && !Serializer::enabled()) {
code->MakeOlder(heap->mark_compact_collector()->marking_parity());
}
@ -444,6 +441,9 @@ void StaticMarkingVisitor<StaticVisitor>::VisitSharedFunctionInfo(
if (shared->ic_age() != heap->global_ic_age()) {
shared->ResetForNewContext(heap->global_ic_age());
}
if (FLAG_cleanup_code_caches_at_gc) {
shared->ClearTypeFeedbackInfo(heap);
}
if (FLAG_cache_optimized_code &&
FLAG_flush_optimized_code_cache &&
!shared->optimized_code_map()->IsSmi()) {

View File

@ -10642,19 +10642,16 @@ void Code::ClearInlineCaches(Code::Kind* kind) {
}
void Code::ClearTypeFeedbackInfo(Heap* heap) {
if (kind() != FUNCTION) return;
Object* raw_info = type_feedback_info();
if (raw_info->IsTypeFeedbackInfo()) {
FixedArray* feedback_vector =
TypeFeedbackInfo::cast(raw_info)->feedback_vector();
for (int i = 0; i < feedback_vector->length(); i++) {
Object* obj = feedback_vector->get(i);
if (!obj->IsAllocationSite()) {
// TODO(mvstanton): Can't I avoid a write barrier for this sentinel?
feedback_vector->set(i,
TypeFeedbackInfo::RawUninitializedSentinel(heap));
}
void SharedFunctionInfo::ClearTypeFeedbackInfo(Heap* heap) {
FixedArray* vector = feedback_vector();
for (int i = 0; i < vector->length(); i++) {
Object* obj = vector->get(i);
if (!obj->IsAllocationSite()) {
// The assert verifies we can skip the write barrier.
ASSERT(heap->uninitialized_symbol() ==
TypeFeedbackInfo::RawUninitializedSentinel(heap));
vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap),
SKIP_WRITE_BARRIER);
}
}
}

View File

@ -5469,8 +5469,6 @@ class Code: public HeapObject {
void ClearInlineCaches();
void ClearInlineCaches(Kind kind);
void ClearTypeFeedbackInfo(Heap* heap);
BailoutId TranslatePcOffsetToAstId(uint32_t pc_offset);
uint32_t TranslateAstIdToPcOffset(BailoutId ast_id);
@ -6666,6 +6664,8 @@ class SharedFunctionInfo: public HeapObject {
// Removed a specific optimized code object from the optimized code map.
void EvictFromOptimizedCodeMap(Code* optimized_code, const char* reason);
void ClearTypeFeedbackInfo(Heap* heap);
// Trims the optimized code map after entries have been removed.
void TrimOptimizedCodeMap(int shrink_by);
@ -6781,6 +6781,12 @@ class SharedFunctionInfo: public HeapObject {
inline int construction_count();
inline void set_construction_count(int value);
// [feedback_vector] - accumulates ast node feedback from full-codegen and
// (increasingly) from crankshafted code where sufficient feedback isn't
// available. Currently the field is duplicated in
// TypeFeedbackInfo::feedback_vector, but the allocation is done here.
DECL_ACCESSORS(feedback_vector, FixedArray)
// [initial_map]: initial map of the first function called as a constructor.
// Saved for the duration of the tracking phase.
// This is a weak link (GC resets it to undefined_value if no other live
@ -7072,8 +7078,10 @@ class SharedFunctionInfo: public HeapObject {
static const int kScriptOffset = kFunctionDataOffset + kPointerSize;
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kInitialMapOffset =
static const int kFeedbackVectorOffset =
kInferredNameOffset + kPointerSize;
static const int kInitialMapOffset =
kFeedbackVectorOffset + kPointerSize;
// ast_node_count is a Smi field. It could be grouped with another Smi field
// into a PSEUDO_SMI_ACCESSORS pair (on x64), if one becomes available.
static const int kAstNodeCountOffset =
@ -8168,8 +8176,6 @@ class TypeFeedbackInfo: public Struct {
inline void set_inlined_type_change_checksum(int checksum);
inline bool matches_inlined_type_change_checksum(int checksum);
DECL_ACCESSORS(feedback_vector, FixedArray)
static inline TypeFeedbackInfo* cast(Object* obj);
// Dispatched behavior.
@ -8178,10 +8184,9 @@ class TypeFeedbackInfo: public Struct {
static const int kStorage1Offset = HeapObject::kHeaderSize;
static const int kStorage2Offset = kStorage1Offset + kPointerSize;
static const int kFeedbackVectorOffset =
kStorage2Offset + kPointerSize;
static const int kSize = kFeedbackVectorOffset + kPointerSize;
static const int kSize = kStorage2Offset + kPointerSize;
// TODO(mvstanton): move these sentinel declarations to shared function info.
// The object that indicates an uninitialized cache.
static inline Handle<Object> UninitializedSentinel(Isolate* isolate);
@ -8197,9 +8202,6 @@ class TypeFeedbackInfo: public Struct {
// garbage collection (e.g., for patching the cache).
static inline Object* RawUninitializedSentinel(Heap* heap);
static const int kForInFastCaseMarker = 0;
static const int kForInSlowCaseMarker = 1;
private:
static const int kTypeChangeChecksumBits = 7;

View File

@ -2942,6 +2942,7 @@ RUNTIME_FUNCTION(MaybeObject*, 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->set_feedback_vector(source_shared->feedback_vector());
target_shared->set_scope_info(source_shared->scope_info());
target_shared->set_length(source_shared->length());
target_shared->set_formal_parameter_count(
@ -8488,10 +8489,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
function->shared()->ClearTypeFeedbackInfo(isolate->heap());
Code* unoptimized = function->shared()->code();
if (unoptimized->kind() == Code::FUNCTION) {
unoptimized->ClearInlineCaches();
unoptimized->ClearTypeFeedbackInfo(isolate->heap());
}
return isolate->heap()->undefined_value();
}

View File

@ -43,16 +43,12 @@ namespace internal {
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
Handle<FixedArray> feedback_vector,
Handle<Context> native_context,
Zone* zone)
: native_context_(native_context),
zone_(zone) {
Object* raw_info = code->type_feedback_info();
if (raw_info->IsTypeFeedbackInfo()) {
feedback_vector_ = Handle<FixedArray>(TypeFeedbackInfo::cast(raw_info)->
feedback_vector());
}
zone_(zone),
feedback_vector_(feedback_vector) {
BuildDictionary(code);
ASSERT(dictionary_->IsDictionary());
}
@ -132,9 +128,9 @@ bool TypeFeedbackOracle::CallNewIsMonomorphic(int slot) {
byte TypeFeedbackOracle::ForInType(int feedback_vector_slot) {
Handle<Object> value = GetInfo(feedback_vector_slot);
return value->IsSmi() &&
Smi::cast(*value)->value() == TypeFeedbackInfo::kForInFastCaseMarker
? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
return value.is_identical_to(
TypeFeedbackInfo::UninitializedSentinel(isolate()))
? ForInStatement::FAST_FOR_IN : ForInStatement::SLOW_FOR_IN;
}

View File

@ -44,6 +44,7 @@ class SmallMapList;
class TypeFeedbackOracle: public ZoneObject {
public:
TypeFeedbackOracle(Handle<Code> code,
Handle<FixedArray> feedback_vector,
Handle<Context> native_context,
Zone* zone);

View File

@ -40,6 +40,7 @@ AstTyper::AstTyper(CompilationInfo* info)
: info_(info),
oracle_(
Handle<Code>(info->closure()->shared()->code()),
Handle<FixedArray>(info->closure()->shared()->feedback_vector()),
Handle<Context>(info->closure()->context()->native_context()),
info->zone()),
store_(info->zone()) {

View File

@ -119,8 +119,6 @@ void FullCodeGenerator::Generate() {
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
InitializeFeedbackVector();
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@ -1127,15 +1125,10 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label non_proxy;
__ bind(&fixed_array);
Handle<Object> feedback = Handle<Object>(
Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
isolate());
StoreFeedbackVectorSlot(slot, feedback);
// No need for a write barrier, we are storing a Smi in the feedback vector.
__ Move(rbx, FeedbackVector());
__ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
TypeFeedbackInfo::MegamorphicSentinel(isolate()));
__ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
__ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
@ -2649,9 +2642,6 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
// Record source position for debugger.
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ Move(rbx, FeedbackVector());
__ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
@ -2829,9 +2819,6 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
__ movp(rdi, Operand(rsp, arg_count * kPointerSize));
// Record call targets in unoptimized code, but not in the snapshot.
Handle<Object> uninitialized =
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
__ Move(rbx, FeedbackVector());
__ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));

View File

@ -312,6 +312,40 @@ TEST(GetScriptLineNumber) {
}
TEST(FeedbackVectorPreservedAcrossRecompiles) {
if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
i::FLAG_allow_natives_syntax = true;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
// Make sure function f has a call that uses a type feedback slot.
CompileRun("function fun() {};"
"fun1 = fun;"
"function f(a) { a(); } f(fun1);");
Handle<JSFunction> f =
v8::Utils::OpenHandle(
*v8::Handle<v8::Function>::Cast(
CcTest::global()->Get(v8_str("f"))));
// We shouldn't have deoptimization support. We want to recompile and
// verify that our feedback vector preserves information.
CHECK(!f->shared()->has_deoptimization_support());
Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
// Verify that we gathered feedback.
CHECK_EQ(1, feedback_vector->length());
CHECK(feedback_vector->get(0)->IsJSFunction());
CompileRun("%OptimizeFunctionOnNextCall(f); f(fun1);");
// Verify that the feedback is still "gathered" despite a recompilation
// of the full code.
CHECK(f->shared()->has_deoptimization_support());
CHECK(f->shared()->feedback_vector()->get(0)->IsJSFunction());
}
// Test that optimized code for different closures is actually shared
// immediately by the FastNewClosureStub when run in the same context.
TEST(OptimizedCodeSharing) {

View File

@ -2855,8 +2855,7 @@ TEST(IncrementalMarkingClearsTypeFeedbackInfo) {
*v8::Handle<v8::Function>::Cast(
CcTest::global()->Get(v8_str("f"))));
Handle<FixedArray> feedback_vector(TypeFeedbackInfo::cast(
f->shared()->code()->type_feedback_info())->feedback_vector());
Handle<FixedArray> feedback_vector(f->shared()->feedback_vector());
CHECK_EQ(2, feedback_vector->length());
CHECK(feedback_vector->get(0)->IsJSFunction());