Skip to content

Commit 6d0be9b

Browse files
author
Srdjan Mitrovic
committed
Eliminate excessive increment of deoptimization counters (e.g., with deep recursion of deoptimized function). Instead increment deoptimization_count for all (inlined) functions at deoptimization point if deoptimization was triggered from function's optimized code. Cases where that is not the case are OSR codes, lazy-deopts and code disabling due to loading/finalizing classes or guard invalidation.
Rename deoptimization_counter_threshold to max_deoptimization_counter_threshold. BUG= [email protected] Review URL: https://codereview.chromium.org/1557533002 .
1 parent 6602644 commit 6d0be9b

8 files changed

+45
-20
lines changed

runtime/vm/code_generator.cc

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ DEFINE_FLAG(bool, trace_patching, false, "Trace patching of code.");
5757
DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
5858
DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
5959

60-
DECLARE_FLAG(int, deoptimization_counter_threshold);
60+
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
6161
DECLARE_FLAG(bool, enable_inlining_annotations);
6262
DECLARE_FLAG(bool, trace_compiler);
6363
DECLARE_FLAG(bool, trace_optimizing_compiler);
@@ -677,7 +677,7 @@ DEFINE_RUNTIME_ENTRY(PatchStaticCall, 0) {
677677
target_code);
678678
caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code);
679679
if (FLAG_trace_patching) {
680-
OS::PrintErr("PatchStaticCall: patching caller pc %#" Px ""
680+
THR_Print("PatchStaticCall: patching caller pc %#" Px ""
681681
" to '%s' new entry point %#" Px " (%s)\n",
682682
caller_frame->pc(),
683683
target_function.ToFullyQualifiedCString(),
@@ -1255,7 +1255,7 @@ static bool CanOptimizeFunction(const Function& function, Thread* thread) {
12551255
return false;
12561256
}
12571257
if (function.deoptimization_counter() >=
1258-
FLAG_deoptimization_counter_threshold) {
1258+
FLAG_max_deoptimization_counter_threshold) {
12591259
if (FLAG_trace_failed_optimization_attempts ||
12601260
FLAG_stop_on_excessive_deoptimization) {
12611261
OS::PrintErr("Too Many Deoptimizations: %s\n",
@@ -1707,6 +1707,9 @@ static void CopySavedRegisters(uword saved_registers_address,
17071707

17081708
// Copies saved registers and caller's frame into temporary buffers.
17091709
// Returns the stack size of unoptimized frame.
1710+
// The calling code must be optimized, but its function may not have
1711+
// have optimized code if the code is OSR code, or if the code was invalidated
1712+
// through class loading/finalization or field guard.
17101713
DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
17111714
2,
17121715
uword saved_registers_address,
@@ -1728,6 +1731,16 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
17281731
ASSERT(caller_frame != NULL);
17291732
const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
17301733
ASSERT(optimized_code.is_optimized());
1734+
const Function& top_function =
1735+
Function::Handle(thread->zone(), optimized_code.function());
1736+
const bool deoptimizing_code = top_function.HasOptimizedCode();
1737+
if (FLAG_trace_deoptimization) {
1738+
const Function& function = Function::Handle(optimized_code.function());
1739+
THR_Print("== Deoptimizing code for '%s', %s, %s\n",
1740+
function.ToFullyQualifiedCString(),
1741+
deoptimizing_code ? "code & frame" : "frame",
1742+
is_lazy_deopt ? "lazy-deopt" : "");
1743+
}
17311744

17321745
// Copy the saved registers from the stack.
17331746
fpu_register_t* fpu_registers;
@@ -1741,7 +1754,8 @@ DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
17411754
DeoptContext::kDestIsOriginalFrame,
17421755
fpu_registers,
17431756
cpu_registers,
1744-
is_lazy_deopt != 0);
1757+
is_lazy_deopt != 0,
1758+
deoptimizing_code);
17451759
isolate->set_deopt_context(deopt_context);
17461760

17471761
// Stack size (FP - SP) in bytes.

runtime/vm/compiler.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ DEFINE_FLAG(bool, common_subexpression_elimination, true,
4646
"Do common subexpression elimination.");
4747
DEFINE_FLAG(bool, constant_propagation, true,
4848
"Do conditional constant propagation/unreachable code elimination.");
49-
DEFINE_FLAG(int, deoptimization_counter_threshold, 16,
49+
DEFINE_FLAG(int, max_deoptimization_counter_threshold, 16,
5050
"How many times we allow deoptimization before we disallow optimization.");
5151
DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code.");
5252
DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code.");
@@ -639,7 +639,7 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
639639
// Extract type feedback before the graph is built, as the graph
640640
// builder uses it to attach it to nodes.
641641
ASSERT(function.deoptimization_counter() <
642-
FLAG_deoptimization_counter_threshold);
642+
FLAG_max_deoptimization_counter_threshold);
643643

644644
// 'Freeze' ICData in background compilation so that it does not
645645
// change while compiling.

runtime/vm/debugger.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,8 @@ RawArray* Debugger::DeoptimizeToArray(Thread* thread,
14441444
DeoptContext::kDestIsAllocated,
14451445
NULL,
14461446
NULL,
1447-
true);
1447+
true,
1448+
false /* deoptimizing_code */);
14481449
isolate->set_deopt_context(deopt_context);
14491450

14501451
deopt_context->FillDestFrame();

runtime/vm/deferred_objects.cc

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,16 +173,18 @@ void DeferredPcMarker::Materialize(DeoptContext* deopt_context) {
173173
*reinterpret_cast<RawObject**>(dest_addr) = code.raw();
174174

175175
if (FLAG_trace_deoptimization_verbose) {
176-
OS::PrintErr("materializing pc marker at 0x%" Px ": %s, %s\n",
177-
reinterpret_cast<uword>(slot()), code.ToCString(),
178-
function.ToCString());
176+
THR_Print("materializing pc marker at 0x%" Px ": %s, %s\n",
177+
reinterpret_cast<uword>(slot()), code.ToCString(),
178+
function.ToCString());
179179
}
180180

181181
// Increment the deoptimization counter. This effectively increments each
182182
// function occurring in the optimized frame.
183-
function.set_deoptimization_counter(function.deoptimization_counter() + 1);
183+
if (deopt_context->deoptimizing_code()) {
184+
function.set_deoptimization_counter(function.deoptimization_counter() + 1);
185+
}
184186
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
185-
OS::PrintErr("Deoptimizing %s (count %d)\n",
187+
THR_Print("Deoptimizing '%s' (count %d)\n",
186188
function.ToFullyQualifiedCString(),
187189
function.deoptimization_counter());
188190
}

runtime/vm/deopt_instructions.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ DeoptContext::DeoptContext(const StackFrame* frame,
2727
DestFrameOptions dest_options,
2828
fpu_register_t* fpu_registers,
2929
intptr_t* cpu_registers,
30-
bool is_lazy_deopt)
30+
bool is_lazy_deopt,
31+
bool deoptimizing_code)
3132
: code_(code.raw()),
3233
object_pool_(code.GetObjectPool()),
3334
deopt_info_(TypedData::null()),
@@ -47,7 +48,8 @@ DeoptContext::DeoptContext(const StackFrame* frame,
4748
deferred_slots_(NULL),
4849
deferred_objects_count_(0),
4950
deferred_objects_(NULL),
50-
is_lazy_deopt_(is_lazy_deopt) {
51+
is_lazy_deopt_(is_lazy_deopt),
52+
deoptimizing_code_(deoptimizing_code) {
5153
const TypedData& deopt_info = TypedData::Handle(
5254
code.GetDeoptInfoAtPc(frame->pc(), &deopt_reason_, &deopt_flags_));
5355
ASSERT(!deopt_info.IsNull());
@@ -103,7 +105,7 @@ DeoptContext::DeoptContext(const StackFrame* frame,
103105
}
104106

105107
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
106-
OS::PrintErr(
108+
THR_Print(
107109
"Deoptimizing (reason %d '%s') at pc %#" Px " '%s' (count %d)\n",
108110
deopt_reason(),
109111
DeoptReasonToCString(deopt_reason()),

runtime/vm/deopt_instructions.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,22 @@ class StackFrame;
2323
class TimelineEvent;
2424

2525
// Holds all data relevant for execution of deoptimization instructions.
26+
// Structure is allocated in C-heap.
2627
class DeoptContext {
2728
public:
2829
enum DestFrameOptions {
2930
kDestIsOriginalFrame, // Replace the original frame with deopt frame.
3031
kDestIsAllocated // Write deopt frame to a buffer.
3132
};
3233

34+
// If 'deoptimizing_code' is false, only frame is being deoptimized.
3335
DeoptContext(const StackFrame* frame,
3436
const Code& code,
3537
DestFrameOptions dest_options,
3638
fpu_register_t* fpu_registers,
3739
intptr_t* cpu_registers,
38-
bool is_lazy_deopt);
40+
bool is_lazy_deopt,
41+
bool deoptimizing_code);
3942
virtual ~DeoptContext();
4043

4144
// Returns the offset of the dest fp from the dest sp. Used in
@@ -97,6 +100,8 @@ class DeoptContext {
97100

98101
bool is_lazy_deopt() const { return is_lazy_deopt_; }
99102

103+
bool deoptimizing_code() const { return deoptimizing_code_; }
104+
100105
ICData::DeoptReasonId deopt_reason() const { return deopt_reason_; }
101106
bool HasDeoptFlag(ICData::DeoptFlags flag) {
102107
return (deopt_flags_ & flag) != 0;
@@ -232,6 +237,7 @@ class DeoptContext {
232237
DeferredObject** deferred_objects_;
233238

234239
const bool is_lazy_deopt_;
240+
const bool deoptimizing_code_;
235241

236242
DISALLOW_COPY_AND_ASSIGN(DeoptContext);
237243
};

runtime/vm/flow_graph_inliner.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ DEFINE_FLAG(bool, enable_inlining_annotations, false,
5959
"Enable inlining annotations");
6060

6161
DECLARE_FLAG(bool, compiler_stats);
62-
DECLARE_FLAG(int, deoptimization_counter_threshold);
62+
DECLARE_FLAG(int, max_deoptimization_counter_threshold);
6363
DECLARE_FLAG(bool, polymorphic_with_deopt);
6464
DECLARE_FLAG(bool, print_flow_graph);
6565
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -639,7 +639,7 @@ class CallSiteInliner : public ValueObject {
639639

640640
// Abort if this function has deoptimized too much.
641641
if (function.deoptimization_counter() >=
642-
FLAG_deoptimization_counter_threshold) {
642+
FLAG_max_deoptimization_counter_threshold) {
643643
function.set_is_inlinable(false);
644644
TRACE_INLINING(THR_Print(" Bailout: deoptimization threshold\n"));
645645
PRINT_INLINING_TREE("Deoptimization threshold exceeded",

runtime/vm/object.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7725,8 +7725,8 @@ class FieldDependentArray : public WeakCodeReferences {
77257725
virtual void ReportSwitchingCode(const Code& code) {
77267726
if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
77277727
Function& function = Function::Handle(code.function());
7728-
THR_Print("Switching %s to unoptimized code because guard"
7729-
" on field %s was violated.\n",
7728+
THR_Print("Switching '%s' to unoptimized code because guard"
7729+
" on field '%s' was violated.\n",
77307730
function.ToFullyQualifiedCString(),
77317731
field_.ToCString());
77327732
}

0 commit comments

Comments
 (0)