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
This commit is contained in:
parent
0735f045de
commit
7e48108f3b
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user