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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10753 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2740d306
...@@ -3850,7 +3850,7 @@ class Internals { ...@@ -3850,7 +3850,7 @@ class Internals {
static const int kFullStringRepresentationMask = 0x07; static const int kFullStringRepresentationMask = 0x07;
static const int kExternalTwoByteRepresentationTag = 0x02; static const int kExternalTwoByteRepresentationTag = 0x02;
static const int kJSObjectType = 0xa7; static const int kJSObjectType = 0xa8;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kForeignType = 0x85; static const int kForeignType = 0x85;
......
...@@ -148,6 +148,13 @@ Handle<AccessorPair> Factory::NewAccessorPair() { ...@@ -148,6 +148,13 @@ Handle<AccessorPair> Factory::NewAccessorPair() {
} }
Handle<TypeFeedbackInfo> Factory::NewTypeFeedbackInfo() {
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->AllocateTypeFeedbackInfo(),
TypeFeedbackInfo);
}
// Symbols are created in the old generation (data space). // Symbols are created in the old generation (data space).
Handle<String> Factory::LookupSymbol(Vector<const char> string) { Handle<String> Factory::LookupSymbol(Vector<const char> string) {
CALL_HEAP_FUNCTION(isolate(), CALL_HEAP_FUNCTION(isolate(),
......
...@@ -76,6 +76,8 @@ class Factory { ...@@ -76,6 +76,8 @@ class Factory {
// Allocates a pre-tenured empty AccessorPair. // Allocates a pre-tenured empty AccessorPair.
Handle<AccessorPair> NewAccessorPair(); Handle<AccessorPair> NewAccessorPair();
Handle<TypeFeedbackInfo> NewTypeFeedbackInfo();
Handle<String> LookupSymbol(Vector<const char> str); Handle<String> LookupSymbol(Vector<const char> str);
Handle<String> LookupSymbol(Handle<String> str); Handle<String> LookupSymbol(Handle<String> str);
Handle<String> LookupAsciiSymbol(Vector<const char> str); Handle<String> LookupAsciiSymbol(Vector<const char> str);
......
...@@ -177,12 +177,17 @@ DEFINE_bool(weighted_back_edges, false, ...@@ -177,12 +177,17 @@ DEFINE_bool(weighted_back_edges, false,
"weight back edges by jump distance for interrupt triggering") "weight back edges by jump distance for interrupt triggering")
DEFINE_int(interrupt_budget, 10000, DEFINE_int(interrupt_budget, 10000,
"execution budget before interrupt is triggered") "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, watch_ic_patching)
DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, self_optimization)
DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, count_based_interrupts)
DEFINE_implication(experimental_profiler, weighted_back_edges) 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 // assembler-ia32.cc / assembler-arm.cc / assembler-x64.cc
DEFINE_bool(debug_code, false, DEFINE_bool(debug_code, false,
"generate extra code (assertions) for debugging") "generate extra code (assertions) for debugging")
......
...@@ -303,6 +303,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -303,6 +303,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info); Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
code->set_optimizable(info->IsOptimizable()); code->set_optimizable(info->IsOptimizable());
cgen.PopulateDeoptimizationData(code); cgen.PopulateDeoptimizationData(code);
cgen.PopulateTypeFeedbackInfo(code);
cgen.PopulateTypeFeedbackCells(code); cgen.PopulateTypeFeedbackCells(code);
code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
code->set_handler_table(*cgen.handler_table()); code->set_handler_table(*cgen.handler_table());
...@@ -361,6 +362,13 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { ...@@ -361,6 +362,13 @@ 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_);
code->set_type_feedback_info(*info);
}
void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) { void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
if (type_feedback_cells_.is_empty()) return; if (type_feedback_cells_.is_empty()) return;
int length = type_feedback_cells_.length(); int length = type_feedback_cells_.length();
...@@ -371,7 +379,8 @@ void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) { ...@@ -371,7 +379,8 @@ void FullCodeGenerator::PopulateTypeFeedbackCells(Handle<Code> code) {
cache->SetAstId(i, Smi::FromInt(type_feedback_cells_[i].ast_id)); cache->SetAstId(i, Smi::FromInt(type_feedback_cells_[i].ast_id));
cache->SetCell(i, *type_feedback_cells_[i].cell); 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);
} }
......
...@@ -89,16 +89,11 @@ class FullCodeGenerator: public AstVisitor { ...@@ -89,16 +89,11 @@ class FullCodeGenerator: public AstVisitor {
? info->function()->ast_node_count() : 0), ? info->function()->ast_node_count() : 0),
stack_checks_(2), // There's always at least one. stack_checks_(2), // There's always at least one.
type_feedback_cells_(info->HasDeoptimizationSupport() 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); 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>. // Encode state and pc-offset as a BitField<type, start, size>.
// Only use 30 bits because we encode the result as a smi. // Only use 30 bits because we encode the result as a smi.
class StateField : public BitField<State, 0, 1> { }; class StateField : public BitField<State, 0, 1> { };
...@@ -516,6 +511,10 @@ class FullCodeGenerator: public AstVisitor { ...@@ -516,6 +511,10 @@ class FullCodeGenerator: public AstVisitor {
// accumulator. // accumulator.
void EmitKeyedPropertyAssignment(Assignment* expr); void EmitKeyedPropertyAssignment(Assignment* expr);
void CallIC(Handle<Code> code,
RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
unsigned ast_id = kNoASTId);
void SetFunctionPosition(FunctionLiteral* fun); void SetFunctionPosition(FunctionLiteral* fun);
void SetReturnPosition(FunctionLiteral* fun); void SetReturnPosition(FunctionLiteral* fun);
void SetStatementPosition(Statement* stmt); void SetStatementPosition(Statement* stmt);
...@@ -581,6 +580,13 @@ class FullCodeGenerator: public AstVisitor { ...@@ -581,6 +580,13 @@ class FullCodeGenerator: public AstVisitor {
void VisitForTypeofValue(Expression* 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 { struct BailoutEntry {
unsigned id; unsigned id;
unsigned pc_and_state; unsigned pc_and_state;
...@@ -779,6 +785,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -779,6 +785,7 @@ class FullCodeGenerator: public AstVisitor {
ZoneList<BailoutEntry> bailout_entries_; ZoneList<BailoutEntry> bailout_entries_;
ZoneList<BailoutEntry> stack_checks_; ZoneList<BailoutEntry> stack_checks_;
ZoneList<TypeFeedbackCellEntry> type_feedback_cells_; ZoneList<TypeFeedbackCellEntry> type_feedback_cells_;
int ic_total_count_;
Handle<FixedArray> handler_table_; Handle<FixedArray> handler_table_;
Handle<JSGlobalPropertyCell> profiling_counter_; Handle<JSGlobalPropertyCell> profiling_counter_;
......
...@@ -1938,6 +1938,19 @@ MaybeObject* Heap::AllocateAccessorPair() { ...@@ -1938,6 +1938,19 @@ MaybeObject* Heap::AllocateAccessorPair() {
} }
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[] = { const Heap::StringTypeTable Heap::string_type_table[] = {
#define STRING_TYPE_ELEMENT(type, size, name, camel_name) \ #define STRING_TYPE_ELEMENT(type, size, name, camel_name) \
{type, size, k##camel_name##MapRootIndex}, {type, size, k##camel_name##MapRootIndex},
...@@ -3361,8 +3374,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc, ...@@ -3361,8 +3374,7 @@ MaybeObject* Heap::CreateCode(const CodeDesc& desc,
code->set_check_type(RECEIVER_MAP_CHECK); code->set_check_type(RECEIVER_MAP_CHECK);
} }
code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_deoptimization_data(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_type_feedback_cells(TypeFeedbackCells::cast(empty_fixed_array()), code->set_type_feedback_info(undefined_value(), SKIP_WRITE_BARRIER);
SKIP_WRITE_BARRIER);
code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER); code->set_handler_table(empty_fixed_array(), SKIP_WRITE_BARRIER);
code->set_gc_metadata(Smi::FromInt(0)); code->set_gc_metadata(Smi::FromInt(0));
// Allow self references to created code object by patching the handle to // Allow self references to created code object by patching the handle to
......
...@@ -640,6 +640,9 @@ class Heap { ...@@ -640,6 +640,9 @@ class Heap {
// Allocates a pre-tenured empty AccessorPair. // Allocates a pre-tenured empty AccessorPair.
MUST_USE_RESULT MaybeObject* AllocateAccessorPair(); MUST_USE_RESULT MaybeObject* AllocateAccessorPair();
// Allocates an empty TypeFeedbackInfo.
MUST_USE_RESULT MaybeObject* AllocateTypeFeedbackInfo();
// Clear the Instanceof cache (used when a prototype changes). // Clear the Instanceof cache (used when a prototype changes).
inline void ClearInstanceofCache(); inline void ClearInstanceofCache();
......
...@@ -876,7 +876,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -876,7 +876,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Record position before stub call for type feedback. // Record position before stub call for type feedback.
SetSourcePosition(clause->position()); SetSourcePosition(clause->position());
Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 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(); patch_site.EmitPatchInfo();
__ test(eax, eax); __ test(eax, eax);
__ j(not_equal, &next_test); __ j(not_equal, &next_test);
...@@ -1189,7 +1189,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, ...@@ -1189,7 +1189,7 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF)
? RelocInfo::CODE_TARGET ? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT; : RelocInfo::CODE_TARGET_CONTEXT;
__ call(ic, mode); CallIC(ic, mode);
} }
...@@ -1270,7 +1270,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { ...@@ -1270,7 +1270,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
__ mov(eax, GlobalObjectOperand()); __ mov(eax, GlobalObjectOperand());
__ mov(ecx, var->name()); __ mov(ecx, var->name());
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT); CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
context()->Plug(eax); context()->Plug(eax);
break; break;
} }
...@@ -1470,7 +1470,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -1470,7 +1470,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize() ? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict(); : isolate()->builtins()->StoreIC_Initialize_Strict();
__ call(ic, RelocInfo::CODE_TARGET, key->id()); CallIC(ic, RelocInfo::CODE_TARGET, key->id());
PrepareForBailoutForId(key->id(), NO_REGISTERS); PrepareForBailoutForId(key->id(), NO_REGISTERS);
} else { } else {
VisitForEffect(value); VisitForEffect(value);
...@@ -1734,14 +1734,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { ...@@ -1734,14 +1734,14 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
ASSERT(!key->handle()->IsSmi()); ASSERT(!key->handle()->IsSmi());
__ mov(ecx, Immediate(key->handle())); __ mov(ecx, Immediate(key->handle()));
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 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) { void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 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 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -1762,7 +1762,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call); __ bind(&stub_call);
__ mov(eax, ecx); __ mov(eax, ecx);
BinaryOpStub stub(op, mode); BinaryOpStub stub(op, mode);
__ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear); __ jmp(&done, Label::kNear);
...@@ -1847,7 +1847,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, ...@@ -1847,7 +1847,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
__ pop(edx); __ pop(edx);
BinaryOpStub stub(op, mode); BinaryOpStub stub(op, mode);
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 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(); patch_site.EmitPatchInfo();
context()->Plug(eax); context()->Plug(eax);
} }
...@@ -1888,7 +1888,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { ...@@ -1888,7 +1888,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize() ? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict(); : isolate()->builtins()->StoreIC_Initialize_Strict();
__ call(ic); CallIC(ic);
break; break;
} }
case KEYED_PROPERTY: { case KEYED_PROPERTY: {
...@@ -1901,7 +1901,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { ...@@ -1901,7 +1901,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize() ? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
__ call(ic); CallIC(ic);
break; break;
} }
} }
...@@ -1919,7 +1919,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, ...@@ -1919,7 +1919,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize() ? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict(); : isolate()->builtins()->StoreIC_Initialize_Strict();
__ call(ic, RelocInfo::CODE_TARGET_CONTEXT); CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
} else if (op == Token::INIT_CONST) { } else if (op == Token::INIT_CONST) {
// Const initializers need a write barrier. // Const initializers need a write barrier.
...@@ -2028,7 +2028,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { ...@@ -2028,7 +2028,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize() ? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict(); : 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 the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) { if (expr->ends_initialization_block()) {
...@@ -2068,7 +2068,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { ...@@ -2068,7 +2068,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize() ? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); : 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 the assignment ends an initialization block, revert to fast case.
if (expr->ends_initialization_block()) { if (expr->ends_initialization_block()) {
...@@ -2102,6 +2102,16 @@ void FullCodeGenerator::VisitProperty(Property* expr) { ...@@ -2102,6 +2102,16 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
} }
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, void FullCodeGenerator::EmitCallWithIC(Call* expr,
Handle<Object> name, Handle<Object> name,
RelocInfo::Mode mode) { RelocInfo::Mode mode) {
...@@ -2118,7 +2128,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr, ...@@ -2118,7 +2128,7 @@ void FullCodeGenerator::EmitCallWithIC(Call* expr,
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
__ call(ic, mode, expr->id()); CallIC(ic, mode, expr->id());
RecordJSReturnSite(expr); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
...@@ -2150,7 +2160,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, ...@@ -2150,7 +2160,7 @@ void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
__ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. __ 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); RecordJSReturnSite(expr);
// Restore context register. // Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
...@@ -3737,7 +3747,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { ...@@ -3737,7 +3747,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
RelocInfo::Mode mode = RelocInfo::CODE_TARGET; RelocInfo::Mode mode = RelocInfo::CODE_TARGET;
Handle<Code> ic = Handle<Code> ic =
isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
__ call(ic, mode, expr->id()); CallIC(ic, mode, expr->id());
// Restore context register. // Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
} else { } else {
...@@ -3895,7 +3905,7 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr, ...@@ -3895,7 +3905,7 @@ void FullCodeGenerator::EmitUnaryOperation(UnaryOperation* expr,
// accumulator register eax. // accumulator register eax.
VisitForAccumulatorValue(expr->expression()); VisitForAccumulatorValue(expr->expression());
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
__ call(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id()); CallIC(stub.GetCode(), RelocInfo::CODE_TARGET, expr->id());
context()->Plug(eax); context()->Plug(eax);
} }
...@@ -4015,7 +4025,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4015,7 +4025,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(edx, eax); __ mov(edx, eax);
__ mov(eax, Immediate(Smi::FromInt(1))); __ mov(eax, Immediate(Smi::FromInt(1)));
BinaryOpStub stub(expr->binary_op(), NO_OVERWRITE); 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(); patch_site.EmitPatchInfo();
__ bind(&done); __ bind(&done);
...@@ -4049,7 +4059,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4049,7 +4059,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->StoreIC_Initialize() ? isolate()->builtins()->StoreIC_Initialize()
: isolate()->builtins()->StoreIC_Initialize_Strict(); : isolate()->builtins()->StoreIC_Initialize_Strict();
__ call(ic, RelocInfo::CODE_TARGET, expr->id()); CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) { if (expr->is_postfix()) {
if (!context()->IsEffect()) { if (!context()->IsEffect()) {
...@@ -4066,7 +4076,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -4066,7 +4076,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Handle<Code> ic = is_classic_mode() Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize() ? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
__ call(ic, RelocInfo::CODE_TARGET, expr->id()); CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) { if (expr->is_postfix()) {
// Result is on the stack // Result is on the stack
...@@ -4094,7 +4104,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { ...@@ -4094,7 +4104,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
// Use a regular load, not a contextual load, to avoid a reference // Use a regular load, not a contextual load, to avoid a reference
// error. // error.
__ call(ic); CallIC(ic);
PrepareForBailout(expr, TOS_REG); PrepareForBailout(expr, TOS_REG);
context()->Plug(eax); context()->Plug(eax);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) { } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
...@@ -4274,7 +4284,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -4274,7 +4284,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Record position and call the compare IC. // Record position and call the compare IC.
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
Handle<Code> ic = CompareIC::GetUninitialized(op); Handle<Code> ic = CompareIC::GetUninitialized(op);
__ call(ic, RelocInfo::CODE_TARGET, expr->id()); CallIC(ic, RelocInfo::CODE_TARGET, expr->id());
patch_site.EmitPatchInfo(); patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
......
...@@ -79,10 +79,10 @@ Code* IC::GetTargetAtAddress(Address address) { ...@@ -79,10 +79,10 @@ Code* IC::GetTargetAtAddress(Address address) {
void IC::SetTargetAtAddress(Address address, Code* target) { void IC::SetTargetAtAddress(Address address, Code* target) {
ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub()); ASSERT(target->is_inline_cache_stub() || target->is_compare_ic_stub());
Code* old_target = GetTargetAtAddress(address);
#ifdef DEBUG #ifdef DEBUG
// STORE_IC and KEYED_STORE_IC use Code::extra_ic_state() to mark // 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. // 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 || if (old_target->kind() == Code::STORE_IC ||
old_target->kind() == Code::KEYED_STORE_IC) { old_target->kind() == Code::KEYED_STORE_IC) {
ASSERT(Code::GetStrictMode(old_target->extra_ic_state()) == ASSERT(Code::GetStrictMode(old_target->extra_ic_state()) ==
...@@ -92,7 +92,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) { ...@@ -92,7 +92,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) {
Assembler::set_target_address_at(address, target->instruction_start()); Assembler::set_target_address_at(address, target->instruction_start());
target->GetHeap()->incremental_marking()->RecordCodeTargetPatch(address, target->GetHeap()->incremental_marking()->RecordCodeTargetPatch(address,
target); target);
PostPatching(); PostPatching(address, target, old_target);
} }
......
...@@ -296,7 +296,32 @@ Failure* IC::ReferenceError(const char* type, Handle<String> name) { ...@@ -296,7 +296,32 @@ Failure* IC::ReferenceError(const char* type, Handle<String> name) {
} }
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) { if (FLAG_watch_ic_patching) {
Isolate::Current()->runtime_profiler()->NotifyICChanged(); Isolate::Current()->runtime_profiler()->NotifyICChanged();
// We do not want to optimize until the ICs have settled down, // We do not want to optimize until the ICs have settled down,
...@@ -313,7 +338,9 @@ void IC::PostPatching() { ...@@ -313,7 +338,9 @@ void IC::PostPatching() {
if (raw_frame->is_java_script()) { if (raw_frame->is_java_script()) {
JSFunction* function = JSFunction* function =
JSFunction::cast(JavaScriptFrame::cast(raw_frame)->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(); it.Advance();
} }
......
...@@ -165,7 +165,7 @@ class IC { ...@@ -165,7 +165,7 @@ class IC {
// Access the target code for the given IC address. // Access the target code for the given IC address.
static inline Code* GetTargetAtAddress(Address address); static inline Code* GetTargetAtAddress(Address address);
static inline void SetTargetAtAddress(Address address, Code* target); static inline void SetTargetAtAddress(Address address, Code* target);
static void PostPatching(); static void PostPatching(Address address, Code* target, Code* old_target);
private: private:
// Frame pointer for the frame that uses (calls) the IC. // Frame pointer for the frame that uses (calls) the IC.
......
...@@ -1176,11 +1176,15 @@ class StaticMarkingVisitor : public StaticVisitorBase { ...@@ -1176,11 +1176,15 @@ class StaticMarkingVisitor : public StaticVisitorBase {
Heap* heap = map->GetHeap(); Heap* heap = map->GetHeap();
Code* code = reinterpret_cast<Code*>(object); Code* code = reinterpret_cast<Code*>(object);
if (FLAG_cleanup_code_caches_at_gc) { if (FLAG_cleanup_code_caches_at_gc) {
TypeFeedbackCells* type_feedback_cells = code->type_feedback_cells(); Object* raw_info = code->type_feedback_info();
for (int i = 0; i < type_feedback_cells->CellCount(); i++) { if (raw_info->IsTypeFeedbackInfo()) {
ASSERT(type_feedback_cells->AstId(i)->IsSmi()); TypeFeedbackCells* type_feedback_cells =
JSGlobalPropertyCell* cell = type_feedback_cells->Cell(i); TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap)); 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); code->CodeIterateBody<StaticMarkingVisitor>(heap);
......
...@@ -326,6 +326,13 @@ void PolymorphicCodeCache::PolymorphicCodeCacheVerify() { ...@@ -326,6 +326,13 @@ void PolymorphicCodeCache::PolymorphicCodeCacheVerify() {
} }
void TypeFeedbackInfo::TypeFeedbackInfoVerify() {
VerifyObjectField(kIcTotalCountOffset);
VerifyObjectField(kIcWithTypeinfoCountOffset);
VerifyHeapPointer(type_feedback_cells());
}
void FixedArray::FixedArrayVerify() { void FixedArray::FixedArrayVerify() {
for (int i = 0; i < length(); i++) { for (int i = 0; i < length(); i++) {
Object* e = get(i); Object* e = get(i);
......
...@@ -4123,8 +4123,7 @@ INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset) ...@@ -4123,8 +4123,7 @@ INT_ACCESSORS(Code, instruction_size, kInstructionSizeOffset)
ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset) ACCESSORS(Code, relocation_info, ByteArray, kRelocationInfoOffset)
ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset) ACCESSORS(Code, handler_table, FixedArray, kHandlerTableOffset)
ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset) ACCESSORS(Code, deoptimization_data, FixedArray, kDeoptimizationDataOffset)
ACCESSORS(Code, type_feedback_cells, TypeFeedbackCells, ACCESSORS(Code, type_feedback_info, Object, kTypeFeedbackInfoOffset)
kTypeFeedbackCellsOffset)
ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset) ACCESSORS(Code, gc_metadata, Object, kGCMetadataOffset)
...@@ -4800,6 +4799,13 @@ Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) { ...@@ -4800,6 +4799,13 @@ Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
} }
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) { Relocatable::Relocatable(Isolate* isolate) {
ASSERT(isolate == Isolate::Current()); ASSERT(isolate == Isolate::Current());
isolate_ = isolate; isolate_ = isolate;
......
...@@ -554,6 +554,15 @@ void PolymorphicCodeCache::PolymorphicCodeCachePrint(FILE* out) { ...@@ -554,6 +554,15 @@ void PolymorphicCodeCache::PolymorphicCodeCachePrint(FILE* 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) { void FixedArray::FixedArrayPrint(FILE* out) {
HeapObject::PrintHeader(out, "FixedArray"); HeapObject::PrintHeader(out, "FixedArray");
PrintF(out, " - length: %d", length()); PrintF(out, " - length: %d", length());
......
...@@ -109,7 +109,7 @@ void Code::CodeIterateBody(ObjectVisitor* v) { ...@@ -109,7 +109,7 @@ void Code::CodeIterateBody(ObjectVisitor* v) {
IteratePointer(v, kRelocationInfoOffset); IteratePointer(v, kRelocationInfoOffset);
IteratePointer(v, kHandlerTableOffset); IteratePointer(v, kHandlerTableOffset);
IteratePointer(v, kDeoptimizationDataOffset); IteratePointer(v, kDeoptimizationDataOffset);
IteratePointer(v, kTypeFeedbackCellsOffset); IteratePointer(v, kTypeFeedbackInfoOffset);
RelocIterator it(this, mode_mask); RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) { for (; !it.done(); it.next()) {
...@@ -141,7 +141,7 @@ void Code::CodeIterateBody(Heap* heap) { ...@@ -141,7 +141,7 @@ void Code::CodeIterateBody(Heap* heap) {
reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset)); reinterpret_cast<Object**>(this->address() + kDeoptimizationDataOffset));
StaticVisitor::VisitPointer( StaticVisitor::VisitPointer(
heap, heap,
reinterpret_cast<Object**>(this->address() + kTypeFeedbackCellsOffset)); reinterpret_cast<Object**>(this->address() + kTypeFeedbackInfoOffset));
RelocIterator it(this, mode_mask); RelocIterator it(this, mode_mask);
for (; !it.done(); it.next()) { for (; !it.done(); it.next()) {
......
...@@ -439,7 +439,8 @@ const int kVariableSizeSentinel = 0; ...@@ -439,7 +439,8 @@ const int kVariableSizeSentinel = 0;
V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \ V(TYPE_SWITCH_INFO, TypeSwitchInfo, type_switch_info) \
V(SCRIPT, Script, script) \ V(SCRIPT, Script, script) \
V(CODE_CACHE, CodeCache, code_cache) \ 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 #ifdef ENABLE_DEBUGGER_SUPPORT
#define STRUCT_LIST_DEBUGGER(V) \ #define STRUCT_LIST_DEBUGGER(V) \
...@@ -594,6 +595,7 @@ enum InstanceType { ...@@ -594,6 +595,7 @@ enum InstanceType {
SCRIPT_TYPE, SCRIPT_TYPE,
CODE_CACHE_TYPE, CODE_CACHE_TYPE,
POLYMORPHIC_CODE_CACHE_TYPE, POLYMORPHIC_CODE_CACHE_TYPE,
TYPE_FEEDBACK_INFO_TYPE,
// The following two instance types are only used when ENABLE_DEBUGGER_SUPPORT // 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 // is defined. However as include/v8.h contain some of the instance type
// constants always having them avoids them getting different numbers // constants always having them avoids them getting different numbers
...@@ -4032,6 +4034,7 @@ class TypeFeedbackCells: public FixedArray { ...@@ -4032,6 +4034,7 @@ class TypeFeedbackCells: public FixedArray {
// Forward declaration. // Forward declaration.
class SafepointEntry; class SafepointEntry;
class TypeFeedbackInfo;
// Code describes objects with on-the-fly generated machine code. // Code describes objects with on-the-fly generated machine code.
class Code: public HeapObject { class Code: public HeapObject {
...@@ -4103,8 +4106,9 @@ class Code: public HeapObject { ...@@ -4103,8 +4106,9 @@ class Code: public HeapObject {
// [deoptimization_data]: Array containing data for deopt. // [deoptimization_data]: Array containing data for deopt.
DECL_ACCESSORS(deoptimization_data, FixedArray) DECL_ACCESSORS(deoptimization_data, FixedArray)
// [type_feedback_cells]: Array containing cache cells used for type feedback. // [type_feedback_info]: Struct containing type feedback information.
DECL_ACCESSORS(type_feedback_cells, TypeFeedbackCells) // 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 // [gc_metadata]: Field used to hold GC related metadata. The contents of this
// field does not have to be traced during garbage collection since // field does not have to be traced during garbage collection since
...@@ -4355,9 +4359,9 @@ class Code: public HeapObject { ...@@ -4355,9 +4359,9 @@ class Code: public HeapObject {
static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize; static const int kHandlerTableOffset = kRelocationInfoOffset + kPointerSize;
static const int kDeoptimizationDataOffset = static const int kDeoptimizationDataOffset =
kHandlerTableOffset + kPointerSize; kHandlerTableOffset + kPointerSize;
static const int kTypeFeedbackCellsOffset = static const int kTypeFeedbackInfoOffset =
kDeoptimizationDataOffset + kPointerSize; kDeoptimizationDataOffset + kPointerSize;
static const int kGCMetadataOffset = kTypeFeedbackCellsOffset + kPointerSize; static const int kGCMetadataOffset = kTypeFeedbackInfoOffset + kPointerSize;
static const int kFlagsOffset = kGCMetadataOffset + kPointerSize; static const int kFlagsOffset = kGCMetadataOffset + kPointerSize;
static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize; static const int kKindSpecificFlagsOffset = kFlagsOffset + kIntSize;
...@@ -6365,6 +6369,40 @@ class PolymorphicCodeCacheHashTable ...@@ -6365,6 +6369,40 @@ class PolymorphicCodeCacheHashTable
}; };
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 AllowNullsFlag {ALLOW_NULLS, DISALLOW_NULLS};
enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL}; enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
......
...@@ -102,6 +102,25 @@ void RuntimeProfiler::GlobalSetup() { ...@@ -102,6 +102,25 @@ void RuntimeProfiler::GlobalSetup() {
} }
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) { void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
ASSERT(function->IsOptimizable()); ASSERT(function->IsOptimizable());
if (FLAG_trace_opt) { if (FLAG_trace_opt) {
...@@ -109,6 +128,11 @@ void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) { ...@@ -109,6 +128,11 @@ void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
function->PrintName(); function->PrintName();
PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address())); PrintF(" 0x%" V8PRIxPTR, reinterpret_cast<intptr_t>(function->address()));
PrintF(" for recompilation, reason: %s", reason); 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"); PrintF("]\n");
} }
...@@ -258,9 +282,20 @@ void RuntimeProfiler::OptimizeNow() { ...@@ -258,9 +282,20 @@ void RuntimeProfiler::OptimizeNow() {
int ticks = function->shared()->profiler_ticks(); int ticks = function->shared()->profiler_ticks();
if (ticks >= kProfilerTicksBeforeOptimization) { if (ticks >= kProfilerTicksBeforeOptimization) {
// If this particular function hasn't had any ICs patched for enough int typeinfo, total, percentage;
// ticks, optimize it now. GetICCounts(function, &typeinfo, &total, &percentage);
Optimize(function, "hot and stable"); 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_ && } else if (!any_ic_changed_ &&
function->shared()->code()->instruction_size() < kMaxSizeEarlyOpt) { function->shared()->code()->instruction_size() < kMaxSizeEarlyOpt) {
// If no IC was patched since the last tick and this function is very // If no IC was patched since the last tick and this function is very
......
...@@ -573,7 +573,11 @@ void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code, ...@@ -573,7 +573,11 @@ void TypeFeedbackOracle::GetRelocInfos(Handle<Code> code,
void TypeFeedbackOracle::CreateDictionary(Handle<Code> code, void TypeFeedbackOracle::CreateDictionary(Handle<Code> code,
ZoneList<RelocInfo>* infos) { ZoneList<RelocInfo>* infos) {
DisableAssertNoAllocation allocation_allowed; 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(); byte* old_start = code->instruction_start();
dictionary_ = FACTORY->NewUnseededNumberDictionary(length); dictionary_ = FACTORY->NewUnseededNumberDictionary(length);
byte* new_start = code->instruction_start(); byte* new_start = code->instruction_start();
...@@ -643,7 +647,10 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) { ...@@ -643,7 +647,10 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
void TypeFeedbackOracle::ProcessTypeFeedbackCells(Handle<Code> code) { 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++) { for (int i = 0; i < cache->CellCount(); i++) {
unsigned ast_id = cache->AstId(i)->value(); unsigned ast_id = cache->AstId(i)->value();
Object* value = cache->Cell(i)->value(); Object* value = cache->Cell(i)->value();
......
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