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) {
share->set_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_inferred_name(*empty_string(), 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_counters(0);
......
......@@ -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(
Call* expr,
HValue* receiver,
SmallMapList* types,
Handle<String> name) {
int argument_count = expr->arguments()->length() + 1; // Includes receiver.
int order[kMaxCallPolymorphism];
FunctionSorter order[kMaxCallPolymorphism];
bool handle_smi = false;
bool handled_string = false;
......@@ -6990,17 +7013,20 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
handle_smi = true;
}
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* join = NULL;
handled_string = false;
int count = 0;
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);
if (info.type()->Is(Type::String())) {
if (handled_string) continue;
......
......@@ -5199,7 +5199,6 @@ ACCESSORS(SharedFunctionInfo, function_data, Object, kFunctionDataOffset)
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(FunctionTemplateInfo, length, kLengthOffset)
......@@ -5254,6 +5253,8 @@ SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset)
SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)
SMI_ACCESSORS(SharedFunctionInfo, ast_node_count, kAstNodeCountOffset)
SMI_ACCESSORS(SharedFunctionInfo, profiler_ticks, kProfilerTicksOffset)
#else
......@@ -5304,9 +5305,15 @@ PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo,
PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
opt_count_and_bailout_reason,
kOptCountAndBailoutReasonOffset)
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
......@@ -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() {
return BooleanBit::get(compiler_hints(), kStrictModeFunction)
? STRICT : SLOPPY;
......
......@@ -7240,6 +7240,7 @@ class SharedFunctionInfo: public HeapObject {
inline void set_ast_node_count(int count);
inline int profiler_ticks();
inline void set_profiler_ticks(int ticks);
// 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.
......@@ -7413,14 +7414,10 @@ class SharedFunctionInfo: public HeapObject {
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kInitialMapOffset =
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
// Smi fields.
static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize;
kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset = kLengthOffset + kPointerSize;
static const int kExpectedNofPropertiesOffset =
kFormalParameterCountOffset + kPointerSize;
......@@ -7438,9 +7435,13 @@ class SharedFunctionInfo: public HeapObject {
kCompilerHintsOffset + kPointerSize;
static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kPointerSize;
static const int kAstNodeCountOffset =
kCountersOffset + kPointerSize;
static const int kProfilerTicksOffset =
kAstNodeCountOffset + kPointerSize;
// Total size.
static const int kSize = kCountersOffset + kPointerSize;
static const int kSize = kProfilerTicksOffset + kPointerSize;
#else
// The only reason to use smi fields instead of int fields
// is to allow iteration without maps decoding during
......@@ -7452,7 +7453,7 @@ class SharedFunctionInfo: public HeapObject {
// word is not set and thus this word cannot be treated as pointer
// to HeapObject during old space traversal.
static const int kLengthOffset =
kAstNodeCountOffset + kPointerSize;
kInitialMapOffset + kPointerSize;
static const int kFormalParameterCountOffset =
kLengthOffset + kIntSize;
......@@ -7473,12 +7474,16 @@ class SharedFunctionInfo: public HeapObject {
static const int kOptCountAndBailoutReasonOffset =
kCompilerHintsOffset + kIntSize;
static const int kCountersOffset =
kOptCountAndBailoutReasonOffset + kIntSize;
static const int kAstNodeCountOffset =
kCountersOffset + kIntSize;
static const int kProfilerTicksOffset =
kAstNodeCountOffset + kIntSize;
// Total size.
static const int kSize = kCountersOffset + kIntSize;
static const int kSize = kProfilerTicksOffset + kIntSize;
#endif
......
......@@ -185,6 +185,16 @@ void RuntimeProfiler::OptimizeNow() {
SharedFunctionInfo* shared = function->shared();
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 (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