From 7e48108f3b27ef3b74afa61fa9ce8970ade3217a Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Wed, 23 Apr 2014 07:07:54 +0000 Subject: [PATCH] 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 --- src/factory.cc | 1 + src/hydrogen.cc | 32 +++++++++++++++++++++++++++++--- src/objects-inl.h | 17 +++++++++-------- src/objects.h | 23 ++++++++++++++--------- src/runtime-profiler.cc | 10 ++++++++++ 5 files changed, 63 insertions(+), 20 deletions(-) diff --git a/src/factory.cc b/src/factory.cc index 389789f..3aacc59 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -1851,6 +1851,7 @@ Handle Factory::NewSharedFunctionInfo(Handle 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); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 7ac1d5e..843be65 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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 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; diff --git a/src/objects-inl.h b/src/objects-inl.h index 83afd32..68bd159 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -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; diff --git a/src/objects.h b/src/objects.h index a0b4982..a190f8d 100644 --- a/src/objects.h +++ b/src/objects.h @@ -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 diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc index 5784e4d..0c9b9e2 100644 --- a/src/runtime-profiler.cc +++ b/src/runtime-profiler.cc @@ -185,6 +185,16 @@ void RuntimeProfiler::OptimizeNow() { SharedFunctionInfo* shared = function->shared(); Code* shared_code = shared->code(); + List 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; -- 2.7.4