Commit 7e48108f authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Sort functions in polymorphic calls based on overall profiling ticks and inlined AST size.

R=svenpanne@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20897 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0735f045
...@@ -1851,6 +1851,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) { ...@@ -1851,6 +1851,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
share->set_debug_info(*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_inferred_name(*empty_string(), SKIP_WRITE_BARRIER);
share->set_initial_map(*undefined_value(), SKIP_WRITE_BARRIER); share->set_initial_map(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_profiler_ticks(0);
share->set_ast_node_count(0); share->set_ast_node_count(0);
share->set_counters(0); share->set_counters(0);
......
...@@ -6962,13 +6962,36 @@ HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction( ...@@ -6962,13 +6962,36 @@ HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
} }
class FunctionSorter {
public:
FunctionSorter(int index = 0, int ticks = 0, int size = 0)
: index_(index), ticks_(ticks), size_(size) { }
int index() const { return index_; }
int ticks() const { return ticks_; }
int size() const { return size_; }
private:
int index_;
int ticks_;
int size_;
};
inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
int diff = lhs.ticks() - rhs.ticks();
if (diff != 0) return diff > 0;
return lhs.size() < rhs.size();
}
void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
Call* expr, Call* expr,
HValue* receiver, HValue* receiver,
SmallMapList* types, SmallMapList* types,
Handle<String> name) { Handle<String> name) {
int argument_count = expr->arguments()->length() + 1; // Includes receiver. int argument_count = expr->arguments()->length() + 1; // Includes receiver.
int order[kMaxCallPolymorphism]; FunctionSorter order[kMaxCallPolymorphism];
bool handle_smi = false; bool handle_smi = false;
bool handled_string = false; bool handled_string = false;
...@@ -6990,17 +7013,20 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( ...@@ -6990,17 +7013,20 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
handle_smi = true; handle_smi = true;
} }
expr->set_target(target); expr->set_target(target);
order[ordered_functions++] = i; order[ordered_functions++] = FunctionSorter(
i, target->shared()->profiler_ticks(), InliningAstSize(target));
} }
} }
std::sort(order, order + ordered_functions);
HBasicBlock* number_block = NULL; HBasicBlock* number_block = NULL;
HBasicBlock* join = NULL; HBasicBlock* join = NULL;
handled_string = false; handled_string = false;
int count = 0; int count = 0;
for (int fn = 0; fn < ordered_functions; ++fn) { for (int fn = 0; fn < ordered_functions; ++fn) {
int i = order[fn]; int i = order[fn].index();
PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
if (info.type()->Is(Type::String())) { if (info.type()->Is(Type::String())) {
if (handled_string) continue; if (handled_string) continue;
......
...@@ -5199,7 +5199,6 @@ ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset) ...@@ -5199,7 +5199,6 @@ ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset) ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset) ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset) ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset) SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
...@@ -5254,6 +5253,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints, ...@@ -5254,6 +5253,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason, SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset) kOptCountAndBailoutReasonOffset)
SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset) SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
#else #else
...@@ -5304,9 +5305,15 @@ PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, ...@@ -5304,9 +5305,15 @@ PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
opt_count_and_bailout_reason, opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset) kOptCountAndBailoutReasonOffset)
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset) PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)
PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
ast_node_count,
kAstNodeCountOffset)
PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
profiler_ticks,
kProfilerTicksOffset)
#endif #endif
...@@ -5350,12 +5357,6 @@ void SharedFunctionInfo::set_optimization_disabled(bool disable) { ...@@ -5350,12 +5357,6 @@ void SharedFunctionInfo::set_optimization_disabled(bool disable) {
} }
int SharedFunctionInfo::profiler_ticks() {
if (code()->kind() != Code::FUNCTION) return 0;
return code()->profiler_ticks();
}
StrictMode SharedFunctionInfo::strict_mode() { StrictMode SharedFunctionInfo::strict_mode() {
return BooleanBit::get(compiler_hints(), kStrictModeFunction) return BooleanBit::get(compiler_hints(), kStrictModeFunction)
? STRICT : SLOPPY; ? STRICT : SLOPPY;
......
...@@ -7240,6 +7240,7 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7240,6 +7240,7 @@ class SharedFunctionInfo: public HeapObject {
inline void set_ast_node_count(int count); inline void set_ast_node_count(int count);
inline int profiler_ticks(); inline int profiler_ticks();
inline void set_profiler_ticks(int ticks);
// Inline cache age is used to infer whether the function survived a context // Inline cache age is used to infer whether the function survived a context
// disposal or not. In the former case we reset the opt_count. // disposal or not. In the former case we reset the opt_count.
...@@ -7413,14 +7414,10 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7413,14 +7414,10 @@ class SharedFunctionInfo: public HeapObject {
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize; static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kInitialMapOffset = static const int kInitialMapOffset =
kInferredNameOffset + kPointerSize; kInferredNameOffset + 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 =
kInitialMapOffset + kPointerSize;
#if V8_HOST_ARCH_32_BIT #if V8_HOST_ARCH_32_BIT
// Smi fields. // Smi fields.
static const int kLengthOffset = static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize; kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize; static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset = static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize; kFormalParameterCountOffset + kPointerSize;
...@@ -7438,9 +7435,13 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7438,9 +7435,13 @@ class SharedFunctionInfo: public HeapObject {
kCompilerHintsOffset + kPointerSize; kCompilerHintsOffset + kPointerSize;
static const int kCountersOffset = static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kPointerSize; kOptCountAndBailoutReasonOffset + kPointerSize;
static const int kAstNodeCountOffset =
kCountersOffset + kPointerSize;
static const int kProfilerTicksOffset =
kAstNodeCountOffset + kPointerSize;
// Total size. // Total size.
static const int kSize = kCountersOffset + kPointerSize; static const int kSize = kProfilerTicksOffset + kPointerSize;
#else #else
// The only reason to use smi fields instead of int fields // The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during // is to allow iteration without maps decoding during
...@@ -7452,7 +7453,7 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7452,7 +7453,7 @@ class SharedFunctionInfo: public HeapObject {
// word is not set and thus this word cannot be treated as pointer // word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal. // to HeapObject during old space traversal.
static const int kLengthOffset = static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize; kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset = static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize; kLengthOffset + kIntSize;
...@@ -7473,12 +7474,16 @@ class SharedFunctionInfo: public HeapObject { ...@@ -7473,12 +7474,16 @@ class SharedFunctionInfo: public HeapObject {
static const int kOptCountAndBailoutReasonOffset = static const int kOptCountAndBailoutReasonOffset =
kCompilerHintsOffset + kIntSize; kCompilerHintsOffset + kIntSize;
static const int kCountersOffset = static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kIntSize; kOptCountAndBailoutReasonOffset + kIntSize;
static const int kAstNodeCountOffset =
kCountersOffset + kIntSize;
static const int kProfilerTicksOffset =
kAstNodeCountOffset + kIntSize;
// Total size. // Total size.
static const int kSize = kCountersOffset + kIntSize; static const int kSize = kProfilerTicksOffset + kIntSize;
#endif #endif
......
...@@ -185,6 +185,16 @@ void RuntimeProfiler::OptimizeNow() { ...@@ -185,6 +185,16 @@ void RuntimeProfiler::OptimizeNow() {
SharedFunctionInfo* shared = function->shared(); SharedFunctionInfo* shared = function->shared();
Code* shared_code = shared->code(); Code* shared_code = shared->code();
List<JSFunction*> functions(4);
frame->GetFunctions(&functions);
for (int i = functions.length(); --i >= 0; ) {
SharedFunctionInfo* shared_function_info = functions[i]->shared();
int ticks = shared_function_info->profiler_ticks();
if (ticks < Smi::kMaxValue) {
shared_function_info->set_profiler_ticks(ticks + 1);
}
}
if (shared_code->kind() != Code::FUNCTION) continue; if (shared_code->kind() != Code::FUNCTION) continue;
if (function->IsInOptimizationQueue()) continue; if (function->IsInOptimizationQueue()) continue;
......
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