Revision: 10753
Author: [email protected]
Date: Mon Feb 20 04:57:23 2012
Log: Count ICs that have type information.
Hidden behind --type-info-threshold=X flag, usage dependent on experimental
profiler.
Review URL: https://chromiumcodereview.appspot.com/9403009
http://code.google.com/p/v8/source/detail?r=10753
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
/branches/bleeding_edge/src/flag-definitions.h
/branches/bleeding_edge/src/full-codegen.cc
/branches/bleeding_edge/src/full-codegen.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/ic-inl.h
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/ic.h
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects-visiting-inl.h
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime-profiler.cc
/branches/bleeding_edge/src/type-info.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Wed Feb 1 04:58:34 2012
+++ /branches/bleeding_edge/include/v8.h Mon Feb 20 04:57:23 2012
@@ -3850,7 +3850,7 @@
static const int kFullStringRepresentationMask = 0x07;
static const int kExternalTwoByteRepresentationTag = 0x02;
- static const int kJSObjectType = 0xa7;
+ static const int kJSObjectType = 0xa8;
static const int kFirstNonstringType = 0x80;
static const int kForeignType = 0x85;
=======================================
--- /branches/bleeding_edge/src/factory.cc Mon Feb 13 06:15:43 2012
+++ /branches/bleeding_edge/src/factory.cc Mon Feb 20 04:57:23 2012
@@ -146,6 +146,13 @@
isolate()->heap()->AllocateAccessorPair(),
AccessorPair);
}
+
+
+Handle<TypeFeedbackInfo> Factory::NewTypeFeedbackInfo() {
+ CALL_HEAP_FUNCTION(isolate(),
+ isolate()->heap()->AllocateTypeFeedbackInfo(),
+ TypeFeedbackInfo);
+}
// Symbols are created in the old generation (data space).
=======================================
--- /branches/bleeding_edge/src/factory.h Thu Jan 26 13:47:57 2012
+++ /branches/bleeding_edge/src/factory.h Mon Feb 20 04:57:23 2012
@@ -76,6 +76,8 @@
// Allocates a pre-tenured empty AccessorPair.
Handle<AccessorPair> NewAccessorPair();
+ Handle<TypeFeedbackInfo> NewTypeFeedbackInfo();
+
Handle<String> LookupSymbol(Vector<const char> str);
Handle<String> LookupSymbol(Handle<String> str);
Handle<String> LookupAsciiSymbol(Vector<const char> str);
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h Thu Feb 16 07:47:36 2012
+++ /branches/bleeding_edge/src/flag-definitions.h Mon Feb 20 04:57:23 2012
@@ -177,12 +177,17 @@
"weight back edges by jump distance for interrupt triggering")
DEFINE_int(interrupt_budget, 10000,
"execution budget before interrupt is triggered")
+DEFINE_int(type_info_threshold, 0,
+ "percentage of ICs that must have type info to allow
optimization")
DEFINE_implication(experimental_profiler, watch_ic_patching)
DEFINE_implication(experimental_profiler, self_optimization)
DEFINE_implication(experimental_profiler, count_based_interrupts)
DEFINE_implication(experimental_profiler, weighted_back_edges)
+DEFINE_bool(trace_opt_verbose, false, "extra verbose compilation tracing")
+DEFINE_implication(trace_opt_verbose, trace_opt)
+
// assembler-ia32.cc / assembler-arm.cc / assembler-x64.cc
DEFINE_bool(debug_code, false,
"generate extra code (assertions) for debugging")
=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Tue Feb 14 06:14:51 2012
+++ /branches/bleeding_edge/src/full-codegen.cc Mon Feb 20 04:57:23 2012
@@ -303,6 +303,7 @@
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
code->set_optimizable(info->IsOptimizable());
cgen.PopulateDeoptimizationData(code);
+ cgen.PopulateTypeFeedbackInfo(code);
cgen.PopulateTypeFeedbackCells(code);
code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
code->set_handler_table(*cgen.handler_table());
@@ -359,6 +360,13 @@
}
code->set_deoptimization_data(*data);
}
+
+
+void FullCodeGenerator::PopulateTypeFeedbackInfo(Handle<Code> code) {
+ Handle<TypeFeedbackInfo> info =
isolate()->factory()->NewTypeFeedbackInfo();
+ info->set_ic_total_count(ic_total_count_);
+ code->set_type_feedback_info(*info);
+}
void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
@@ -371,7 +379,8 @@
cache->SetAstId(i, Smi::FromInt(type_feedback_cells_[i].ast_id));
cache->SetCell(i, *type_feedback_cells_[i].cell);
}
- code->set_type_feedback_cells(*cache);
+
TypeFeedbackInfo::cast(code->type_feedback_info())->set_type_feedback_cells(
+ *cache);
}
=======================================
--- /branches/bleeding_edge/src/full-codegen.h Tue Feb 14 06:14:51 2012
+++ /branches/bleeding_edge/src/full-codegen.h Mon Feb 20 04:57:23 2012
@@ -89,15 +89,10 @@
? info->function()->ast_node_count() : 0),
stack_checks_(2), // There's always at least one.
type_feedback_cells_(info->HasDeoptimizationSupport()
- ? info->function()->ast_node_count() : 0) { }
+ ? info->function()->ast_node_count() : 0),
+ ic_total_count_(0) { }
static bool MakeCode(CompilationInfo* info);
-
- void Generate();
- void PopulateDeoptimizationData(Handle<Code> code);
- void PopulateTypeFeedbackCells(Handle<Code> code);
-
- Handle<FixedArray> handler_table() { return handler_table_; }
// Encode state and pc-offset as a BitField<type, start, size>.
// Only use 30 bits because we encode the result as a smi.
@@ -516,6 +511,10 @@
// accumulator.
void EmitKeyedPropertyAssignment(Assignment* expr);
+ void CallIC(Handle<Code> code,
+ RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
+ unsigned ast_id = kNoASTId);
+
void SetFunctionPosition(FunctionLiteral* fun);
void SetReturnPosition(FunctionLiteral* fun);
void SetStatementPosition(Statement* stmt);
@@ -580,6 +579,13 @@
void VisitArithmeticExpression(BinaryOperation* expr);
void VisitForTypeofValue(Expression* expr);
+
+ void Generate();
+ void PopulateDeoptimizationData(Handle<Code> code);
+ void PopulateTypeFeedbackInfo(Handle<Code> code);
+ void PopulateTypeFeedbackCells(Handle<Code> code);
+
+ Handle<FixedArray> handler_table() { return handler_table_; }
struct BailoutEntry {
unsigned id;
@@ -779,6 +785,7 @@
ZoneList<BailoutEntry> bailout_entries_;
ZoneList<BailoutEntry> stack_checks_;
ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
+ int ic_total_count_;
Handle<FixedArray> handler_table_;
Handle<JSGlobalPropertyCell> profiling_counter_;
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Feb 20 00:42:18 2012
+++ /branches/bleeding_edge/src/heap.cc Mon Feb 20 04:57:23 2012
@@ -1936,6 +1936,19 @@
// accessors->set_setter(the_hole_value(), SKIP_WRITE_BARRIER);
return accessors;
}
+
+
+MaybeObject* Heap::AllocateTypeFeedbackInfo() {
+ TypeFeedbackInfo* info;
+ { MaybeObject* maybe_result = AllocateStruct(TYPE_FEEDBACK_INFO_TYPE);
+ if (!maybe_result->To(&info)) return maybe_result;
+ }
+ info->set_ic_total_count(0);
+ info->set_ic_with_typeinfo_count(0);
+
info->set_type_feedback_cells(TypeFeedbackCells::cast(empty_fixed_array()),
+ SKIP_WRITE_BARRIER);
+ return info;
+}
const Heap::StringTypeTable Heap::string_type_table[] = {
@@ -3361,8 +3374,7 @@
code->set_check_type(RECEIVER_MAP_CHECK);
}
code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
-
code->set_type_feedback_cells(TypeFeedbackCells::cast(empty_fixed_array()),
- SKIP_WRITE_BARRIER);
+ code->set_type_feedback_info(undefined_value(), SKIP_WRITE_BARRIER);
code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_gc_metadata(Smi::FromInt(0));
// Allow self references to created code object by patching the handle to
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Feb 20 00:42:18 2012
+++ /branches/bleeding_edge/src/heap.h Mon Feb 20 04:57:23 2012
@@ -640,6 +640,9 @@
// Allocates a pre-tenured empty AccessorPair.
MUST_USE_RESULT MaybeObject* AllocateAccessorPair();
+ // Allocates an empty TypeFeedbackInfo.
+ MUST_USE_RESULT MaybeObject* AllocateTypeFeedbackInfo();
+
// Clear the Instanceof cache (used when a prototype changes).
inline void ClearInstanceofCache();
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Tue Feb 14
06:14:51 2012
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Feb 20
04:57:23 2012
@@ -876,7 +876,7 @@
// Record position before stub call for type feedback.
SetSourcePosition(clause->position());
Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
- __ call(ic, RelocInfo::CODE_TARGET, clause->CompareId());
+ CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId());
patch_site.EmitPatchInfo();
__ test(eax, eax);
__ j(not_equal, &next_test);
@@ -1189,7 +1189,7 @@
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
- __ call(ic, mode);
+ CallIC(ic, mode);
}
@@ -1270,7 +1270,7 @@
__ mov(eax, GlobalObjectOperand());
__ mov(ecx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
context()->Plug(eax);
break;
}
@@ -1470,7 +1470,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET, key->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, key->id());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
} else {
VisitForEffect(value);
@@ -1734,14 +1734,14 @@
ASSERT(!key->handle()->IsSmi());
__ mov(ecx, Immediate(key->handle()));
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET, prop->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
}
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
- __ call(ic, RelocInfo::CODE_TARGET, prop->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, prop->id());
}
@@ -1762,7 +1762,7 @@
__ bind(&stub_call);
__ mov(eax, ecx);
BinaryOpStub stub(op, mode);
- __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
+ CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@@ -1847,7 +1847,7 @@
__ pop(edx);
BinaryOpStub stub(op, mode);
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi
code.
- __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
+ CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo();
context()->Plug(eax);
}
@@ -1888,7 +1888,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
- __ call(ic);
+ CallIC(ic);
break;
}
case KEYED_PROPERTY: {
@@ -1901,7 +1901,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
- __ call(ic);
+ CallIC(ic);
break;
}
}
@@ -1919,7 +1919,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT);
+ CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
} else if (op == Token::INIT_CONST) {
// Const initializers need a write barrier.
@@ -2028,7 +2028,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
// If the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) {
@@ -2068,7 +2068,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
// If the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) {
@@ -2100,6 +2100,16 @@
context()->Plug(eax);
}
}
+
+
+void FullCodeGenerator::CallIC(Handle<Code> code,
+ RelocInfo::Mode rmode,
+ unsigned ast_id) {
+ ic_total_count_++;
+ __ call(code, rmode, ast_id);
+}
+
+
void FullCodeGenerator::EmitCallWithIC(Call* expr,
@@ -2118,7 +2128,7 @@
SetSourcePosition(expr->position());
Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
- __ call(ic, mode, expr->id());
+ CallIC(ic, mode, expr->id());
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -2150,7 +2160,7 @@
Handle<Code> ic =
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
__ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key.
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
RecordJSReturnSite(expr);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -3737,7 +3747,7 @@
RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
- __ call(ic, mode, expr->id());
+ CallIC(ic, mode, expr->id());
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
} else {
@@ -3895,7 +3905,7 @@
// accumulator register eax.
VisitForAccumulatorValue(expr->expression());
SetSourcePosition(expr->position());
- __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
+ CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
context()->Plug(eax);
}
@@ -4015,7 +4025,7 @@
__ mov(edx, eax);
__ mov(eax, Immediate(Smi::FromInt(1)));
BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
- __ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
+ CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->CountId());
patch_site.EmitPatchInfo();
__ bind(&done);
@@ -4049,7 +4059,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -4066,7 +4076,7 @@
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
// Result is on the stack
@@ -4094,7 +4104,7 @@
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
// Use a regular load, not a contextual load, to avoid a reference
// error.
- __ call(ic);
+ CallIC(ic);
PrepareForBailout(expr, TOS_REG);
context()->Plug(eax);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
@@ -4274,7 +4284,7 @@
// Record position and call the compare IC.
SetSourcePosition(expr->position());
Handle<Code> ic = CompareIC::GetUninitialized(op);
- __ call(ic, RelocInfo::CODE_TARGET, expr->id());
+ CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
=======================================
--- /branches/bleeding_edge/src/ic-inl.h Fri Feb 10 04:36:05 2012
+++ /branches/bleeding_edge/src/ic-inl.h Mon Feb 20 04:57:23 2012
@@ -79,10 +79,10 @@
void IC::SetTargetAtAddress(Address address, Code* target) {
ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
+ Code* old_target = GetTargetAtAddress(address);
#ifdef DEBUG
// STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark
// ICs as strict mode. The strict-ness of the IC must be preserved.
- Code* old_target = GetTargetAtAddress(address);
if (old_target->kind() == Code::STORE_IC ||
old_target->kind() == Code::KEYED_STORE_IC) {
ASSERT(Code::GetStrictMode(old_target->extra_ic_state()) ==
@@ -92,7 +92,7 @@
Assembler::set_target_address_at(address, target->instruction_start());
target->GetHeap()->incremental_marking()->RecordCodeTargetPatch(address,
target);
- PostPatching();
+ PostPatching(address, target, old_target);
}
=======================================
--- /branches/bleeding_edge/src/ic.cc Mon Feb 13 05:39:31 2012
+++ /branches/bleeding_edge/src/ic.cc Mon Feb 20 04:57:23 2012
@@ -296,7 +296,32 @@
}
-void IC::PostPatching() {
+void IC::PostPatching(Address address, Code* target, Code* old_target) {
+ if (FLAG_type_info_threshold > 0) {
+ if (old_target->is_inline_cache_stub() &&
+ target->is_inline_cache_stub()) {
+ State old_state = old_target->ic_state();
+ State new_state = target->ic_state();
+ bool was_uninitialized =
+ old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
+ bool is_uninitialized =
+ new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
+ int delta = 0;
+ if (was_uninitialized && !is_uninitialized) {
+ delta = 1;
+ } else if (!was_uninitialized && is_uninitialized) {
+ delta = -1;
+ }
+ if (delta != 0) {
+ Code* host = target->GetHeap()->isolate()->
+ inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
+ TypeFeedbackInfo* info =
+ TypeFeedbackInfo::cast(host->type_feedback_info());
+ info->set_ic_with_typeinfo_count(
+ info->ic_with_typeinfo_count() + delta);
+ }
+ }
+ }
if (FLAG_watch_ic_patching) {
Isolate::Current()->runtime_profiler()->NotifyICChanged();
// We do not want to optimize until the ICs have settled down,
@@ -313,7 +338,9 @@
if (raw_frame->is_java_script()) {
JSFunction* function =
JSFunction::cast(JavaScriptFrame::cast(raw_frame)->function());
- function->shared()->set_profiler_ticks(0);
+ if (function->IsOptimized()) continue;
+ SharedFunctionInfo* shared = function->shared();
+ shared->set_profiler_ticks(0);
}
it.Advance();
}
=======================================
--- /branches/bleeding_edge/src/ic.h Fri Feb 10 04:36:05 2012
+++ /branches/bleeding_edge/src/ic.h Mon Feb 20 04:57:23 2012
@@ -165,7 +165,7 @@
// Access the target code for the given IC address.
static inline Code* GetTargetAtAddress(Address address);
static inline void SetTargetAtAddress(Address address, Code* target);
- static void PostPatching();
+ static void PostPatching(Address address, Code* target, Code*
old_target);
private:
// Frame pointer for the frame that uses (calls) the IC.
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Thu Feb 9 05:30:01 2012
+++ /branches/bleeding_edge/src/mark-compact.cc Mon Feb 20 04:57:23 2012
@@ -1176,11 +1176,15 @@
Heap* heap = map->GetHeap();
Code* code = reinterpret_cast<Code*>(object);
if (FLAG_cleanup_code_caches_at_gc) {
- TypeFeedbackCells* type_feedback_cells = code->type_feedback_cells();
- for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
- ASSERT(type_feedback_cells->AstId(i)->IsSmi());
- JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
- cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
+ Object* raw_info = code->type_feedback_info();
+ if (raw_info->IsTypeFeedbackInfo()) {
+ TypeFeedbackCells* type_feedback_cells =
+ TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
+ for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
+ ASSERT(type_feedback_cells->AstId(i)->IsSmi());
+ JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i);
+
cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
+ }
}
}
code->CodeIterateBody<StaticMarkingVisitor>(heap);
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Fri Feb 10 04:36:05 2012
+++ /branches/bleeding_edge/src/objects-debug.cc Mon Feb 20 04:57:23 2012
@@ -324,6 +324,13 @@
VerifyHeapPointer(cache());
ASSERT(cache()->IsUndefined() ||
cache()->IsPolymorphicCodeCacheHashTable());
}
+
+
+void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
+ VerifyObjectField(kIcTotalCountOffset);
+ VerifyObjectField(kIcWithTypeinfoCountOffset);
+ VerifyHeapPointer(type_feedback_cells());
+}
void FixedArray::FixedArrayVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Fri Feb 17 08:02:20 2012
+++ /branches/bleeding_edge/src/objects-inl.h Mon Feb 20 04:57:23 2012
@@ -4123,8 +4123,7 @@
ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
-ACCESSORS(Code, type_feedback_cells, TypeFeedbackCells,
- kTypeFeedbackCellsOffset)
+ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
@@ -4798,6 +4797,13 @@
Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
return heap->raw_unchecked_the_hole_value();
}
+
+
+SMI_ACCESSORS(TypeFeedbackInfo, ic_total_count, kIcTotalCountOffset)
+SMI_ACCESSORS(TypeFeedbackInfo, ic_with_typeinfo_count,
+ kIcWithTypeinfoCountOffset)
+ACCESSORS(TypeFeedbackInfo, type_feedback_cells, TypeFeedbackCells,
+ kTypeFeedbackCellsOffset)
Relocatable::Relocatable(Isolate* isolate) {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Thu Feb 2 03:22:26 2012
+++ /branches/bleeding_edge/src/objects-printer.cc Mon Feb 20 04:57:23 2012
@@ -552,6 +552,15 @@
PrintF(out, "\n - cache: ");
cache()->ShortPrint(out);
}
+
+
+void TypeFeedbackInfo::TypeFeedbackInfoPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "TypeFeedbackInfo");
+ PrintF(out, "\n - ic_total_count: %d, ic_with_typeinfo_count: %d",
+ ic_total_count(), ic_with_typeinfo_count());
+ PrintF(out, "\n - type_feedback_cells: ");
+ type_feedback_cells()->FixedArrayPrint(out);
+}
void FixedArray::FixedArrayPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects-visiting-inl.h Fri Jan 27 05:03:19
2012
+++ /branches/bleeding_edge/src/objects-visiting-inl.h Mon Feb 20 04:57:23
2012
@@ -109,7 +109,7 @@
IteratePointer(v, kRelocationInfoOffset);
IteratePointer(v, kHandlerTableOffset);
IteratePointer(v, kDeoptimizationDataOffset);
- IteratePointer(v, kTypeFeedbackCellsOffset);
+ IteratePointer(v, kTypeFeedbackInfoOffset);
RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) {
@@ -141,7 +141,7 @@
reinterpret_cast<Object**>(this->address() +
kDeoptimizationDataOffset));
StaticVisitor::VisitPointer(
heap,
- reinterpret_cast<Object**>(this->address() +
kTypeFeedbackCellsOffset));
+ reinterpret_cast<Object**>(this->address() +
kTypeFeedbackInfoOffset));
RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) {
=======================================
--- /branches/bleeding_edge/src/objects.h Mon Feb 20 04:36:35 2012
+++ /branches/bleeding_edge/src/objects.h Mon Feb 20 04:57:23 2012
@@ -439,7 +439,8 @@
V(TYPE_SWITCH_INFO, TypeSwitchInfo,
type_switch_info) \
V(SCRIPT, Script,
script) \
V(CODE_CACHE, CodeCache,
code_cache) \
- V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache, polymorphic_code_cache)
+ V(POLYMORPHIC_CODE_CACHE, PolymorphicCodeCache,
polymorphic_code_cache) \
+ V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info)
#ifdef ENABLE_DEBUGGER_SUPPORT
#define
STRUCT_LIST_DEBUGGER(V) \
@@ -594,6 +595,7 @@
SCRIPT_TYPE,
CODE_CACHE_TYPE,
POLYMORPHIC_CODE_CACHE_TYPE,
+ TYPE_FEEDBACK_INFO_TYPE,
// The following two instance types are only used when
ENABLE_DEBUGGER_SUPPORT
// is defined. However as include/v8.h contain some of the instance type
// constants always having them avoids them getting different numbers
@@ -4032,6 +4034,7 @@
// Forward declaration.
class SafepointEntry;
+class TypeFeedbackInfo;
// Code describes objects with on-the-fly generated machine code.
class Code: public HeapObject {
@@ -4103,8 +4106,9 @@
// [deoptimization_data]: Array containing data for deopt.
DECL_ACCESSORS(deoptimization_data, FixedArray)
- // [type_feedback_cells]: Array containing cache cells used for type
feedback.
- DECL_ACCESSORS(type_feedback_cells, TypeFeedbackCells)
+ // [type_feedback_info]: Struct containing type feedback information.
+ // Will contain either a TypeFeedbackInfo object, or undefined.
+ DECL_ACCESSORS(type_feedback_info, Object)
// [gc_metadata]: Field used to hold GC related metadata. The contents
of this
// field does not have to be traced during garbage collection since
@@ -4355,9 +4359,9 @@
static const int kHandlerTableOffset = kRelocationInfoOffset +
kPointerSize;
static const int kDeoptimizationDataOffset =
kHandlerTableOffset + kPointerSize;
- static const int kTypeFeedbackCellsOffset =
+ static const int kTypeFeedbackInfoOffset =
kDeoptimizationDataOffset + kPointerSize;
- static const int kGCMetadataOffset = kTypeFeedbackCellsOffset +
kPointerSize;
+ static const int kGCMetadataOffset = kTypeFeedbackInfoOffset +
kPointerSize;
static const int kFlagsOffset = kGCMetadataOffset + kPointerSize;
static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
@@ -6365,6 +6369,40 @@
};
+class TypeFeedbackInfo: public Struct {
+ public:
+ inline int ic_total_count();
+ inline void set_ic_total_count(int count);
+
+ inline int ic_with_typeinfo_count();
+ inline void set_ic_with_typeinfo_count(int count);
+
+ DECL_ACCESSORS(type_feedback_cells, TypeFeedbackCells)
+
+ static inline TypeFeedbackInfo* cast(Object* obj);
+
+#ifdef OBJECT_PRINT
+ inline void TypeFeedbackInfoPrint() {
+ TypeFeedbackInfoPrint(stdout);
+ }
+ void TypeFeedbackInfoPrint(FILE* out);
+#endif
+#ifdef DEBUG
+ void TypeFeedbackInfoVerify();
+#endif
+
+ static const int kIcTotalCountOffset = HeapObject::kHeaderSize;
+ static const int kIcWithTypeinfoCountOffset =
+ kIcTotalCountOffset + kPointerSize;
+ static const int kTypeFeedbackCellsOffset =
+ kIcWithTypeinfoCountOffset + kPointerSize;
+ static const int kSize = kTypeFeedbackCellsOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackInfo);
+};
+
+
enum AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
=======================================
--- /branches/bleeding_edge/src/runtime-profiler.cc Tue Feb 14 08:05:40 2012
+++ /branches/bleeding_edge/src/runtime-profiler.cc Mon Feb 20 04:57:23 2012
@@ -100,6 +100,25 @@
has_been_globally_set_up_ = true;
#endif
}
+
+
+static void GetICCounts(JSFunction* function,
+ int* ic_with_typeinfo_count,
+ int* ic_total_count,
+ int* percentage) {
+ *ic_total_count = 0;
+ *ic_with_typeinfo_count = 0;
+ Object* raw_info =
+ function->shared()->code()->type_feedback_info();
+ if (raw_info->IsTypeFeedbackInfo()) {
+ TypeFeedbackInfo* info = TypeFeedbackInfo::cast(raw_info);
+ *ic_with_typeinfo_count = info->ic_with_typeinfo_count();
+ *ic_total_count = info->ic_total_count();
+ }
+ *percentage = *ic_total_count > 0
+ ? 100 * *ic_with_typeinfo_count / *ic_total_count
+ : 100;
+}
void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
@@ -109,6 +128,11 @@
function->PrintName();
PrintF(" 0x%" V8PRIxPTR,
reinterpret_cast<intptr_t>(function->address()));
PrintF(" for recompilation, reason: %s", reason);
+ if (FLAG_type_info_threshold > 0) {
+ int typeinfo, total, percentage;
+ GetICCounts(function, &typeinfo, &total, &percentage);
+ PrintF(", ICs with typeinfo: %d/%d (%d%%)", typeinfo, total,
percentage);
+ }
PrintF("]\n");
}
@@ -258,9 +282,20 @@
int ticks = function->shared()->profiler_ticks();
if (ticks >= kProfilerTicksBeforeOptimization) {
- // If this particular function hasn't had any ICs patched for
enough
- // ticks, optimize it now.
- Optimize(function, "hot and stable");
+ int typeinfo, total, percentage;
+ GetICCounts(function, &typeinfo, &total, &percentage);
+ if (percentage >= FLAG_type_info_threshold) {
+ // If this particular function hasn't had any ICs patched for
enough
+ // ticks, optimize it now.
+ Optimize(function, "hot and stable");
+ } else {
+ if (FLAG_trace_opt_verbose) {
+ PrintF("[not yet optimizing ");
+ function->PrintName();
+ PrintF(", not enough type info: %d/%d (%d%%)]\n",
+ typeinfo, total, percentage);
+ }
+ }
} else if (!any_ic_changed_ &&
function->shared()->code()->instruction_size() <
kMaxSizeEarlyOpt) {
// If no IC was patched since the last tick and this function is
very
=======================================
--- /branches/bleeding_edge/src/type-info.cc Fri Feb 10 04:36:05 2012
+++ /branches/bleeding_edge/src/type-info.cc Mon Feb 20 04:57:23 2012
@@ -573,7 +573,11 @@
void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
ZoneList<RelocInfo>* infos) {
DisableAssertNoAllocation allocation_allowed;
- int length = infos->length() + code->type_feedback_cells()->CellCount();
+ int cell_count = code->type_feedback_info()->IsTypeFeedbackInfo()
+ ? TypeFeedbackInfo::cast(code->type_feedback_info())->
+ type_feedback_cells()->CellCount()
+ : 0;
+ int length = infos->length() + cell_count;
byte* old_start = code->instruction_start();
dictionary_ = FACTORY->NewUnseededNumberDictionary(length);
byte* new_start = code->instruction_start();
@@ -643,7 +647,10 @@
void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) {
- Handle<TypeFeedbackCells> cache(code->type_feedback_cells());
+ Object* raw_info = code->type_feedback_info();
+ if (!raw_info->IsTypeFeedbackInfo()) return;
+ Handle<TypeFeedbackCells> cache(
+ TypeFeedbackInfo::cast(raw_info)->type_feedback_cells());
for (int i = 0; i < cache->CellCount(); i++) {
unsigned ast_id = cache->AstId(i)->value();
Object* value = cache->Cell(i)->value();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev