| Index: runtime/vm/code_generator_ia32.cc
|
| ===================================================================
|
| --- runtime/vm/code_generator_ia32.cc (revision 4582)
|
| +++ runtime/vm/code_generator_ia32.cc (working copy)
|
| @@ -26,10 +26,8 @@
|
| DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
|
| DEFINE_FLAG(bool, print_ic_in_optimized, false,
|
| "Debugging helper to identify potential performance pitfalls.");
|
| -DEFINE_FLAG(int, optimization_invocation_threshold, 1000,
|
| - "Number of invocations before a function is optimized, -1 means never.");
|
| +DECLARE_FLAG(int, optimization_counter_threshold);
|
| DECLARE_FLAG(bool, enable_type_checks);
|
| -DECLARE_FLAG(bool, report_invocation_count);
|
| DECLARE_FLAG(bool, trace_compiler);
|
|
|
| #define __ assembler_->
|
| @@ -205,33 +203,8 @@
|
| // TODO(srdjan): Add check that no object is inlined in the first
|
| // 5 bytes (length of a jump instruction).
|
| void CodeGenerator::GeneratePreEntryCode() {
|
| - // Do not optimize if:
|
| - // - we count invocations.
|
| - // - optimization disabled via negative 'optimization_invocation_threshold;
|
| - // - function is marked as non-optimizable.
|
| - // - type checks are enabled.
|
| - const bool may_optimize =
|
| - !FLAG_report_invocation_count &&
|
| - (FLAG_optimization_invocation_threshold >= 0) &&
|
| - !Isolate::Current()->debugger()->IsActive() &&
|
| - parsed_function_.function().is_optimizable();
|
| - // Count invocation and check.
|
| - if (FLAG_report_invocation_count || may_optimize) {
|
| - // TODO(turnidge): It would be nice to remove this nop. Right now
|
| - // we need it to make sure the function is still patchable.
|
| - __ nop(5);
|
| - const Function& function =
|
| - Function::ZoneHandle(parsed_function_.function().raw());
|
| - __ LoadObject(EAX, function);
|
| - __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
|
| - __ incl(EBX);
|
| - if (may_optimize) {
|
| - __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
|
| - __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel());
|
| - }
|
| - // EBX is an integer value (not an object).
|
| - __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
|
| - }
|
| + // TODO(srdjan): Still needed?
|
| + __ nop(5);
|
| }
|
|
|
|
|
| @@ -712,11 +685,33 @@
|
| __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
|
| #endif // DEBUG.
|
|
|
| + if (!IsOptimizing()) {
|
| + // Count only in unoptimized code.
|
| + // TODO(srdjan): Replace the counting code with a type feedback
|
| + // collection and counting stub.
|
| + const Function& function =
|
| + Function::ZoneHandle(parsed_function_.function().raw());
|
| + __ LoadObject(EBX, function);
|
| + __ incl(FieldAddress(EBX, Function::usage_counter_offset()));
|
| + if (CodeGenerator::CanOptimize()) {
|
| + // Do not optimize if usage count must be reported.
|
| + __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()),
|
| + Immediate(FLAG_optimization_counter_threshold));
|
| + Label not_yet_hot;
|
| + __ j(LESS_EQUAL, ¬_yet_hot);
|
| + __ pushl(EAX); // Preserve result.
|
| + __ pushl(EBX); // Argument for runtime: function to optimize.
|
| + __ CallRuntimeFromDart(kOptimizeInvokedFunctionRuntimeEntry);
|
| + __ popl(EBX); // Remove argument.
|
| + __ popl(EAX); // Restore result.
|
| + __ Bind(¬_yet_hot);
|
| + }
|
| + }
|
| if (FLAG_trace_functions) {
|
| - __ pushl(EAX); // Preserve result.
|
| const Function& function =
|
| - Function::ZoneHandle(parsed_function_.function().raw());
|
| + Function::ZoneHandle(parsed_function_.function().raw());
|
| __ LoadObject(EBX, function);
|
| + __ pushl(EAX); // Preserve result.
|
| __ pushl(EBX);
|
| GenerateCallRuntime(AstNode::kNoId,
|
| 0,
|
| @@ -1844,24 +1839,6 @@
|
| }
|
|
|
|
|
| -void CodeGenerator::CountBackwardLoop() {
|
| - Label done;
|
| - const Function& function =
|
| - Function::ZoneHandle(parsed_function_.function().raw());
|
| - __ LoadObject(EAX, function);
|
| - __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
|
| - __ incl(EBX);
|
| - if (!FLAG_report_invocation_count) {
|
| - // Prevent overflow.
|
| - __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
|
| - __ j(GREATER, &done);
|
| - }
|
| - // EBX is an integer value (not an object).
|
| - __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
|
| - __ Bind(&done);
|
| -}
|
| -
|
| -
|
| void CodeGenerator::VisitWhileNode(WhileNode* node) {
|
| const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
| SourceLabel* label = node->label();
|
| @@ -1873,7 +1850,6 @@
|
| __ cmpl(EAX, EDX);
|
| __ j(NOT_EQUAL, label->break_label());
|
| node->body()->Visit(this);
|
| - CountBackwardLoop();
|
| __ jmp(label->continue_label());
|
| __ Bind(label->break_label());
|
| }
|
| @@ -1885,7 +1861,6 @@
|
| Label loop;
|
| __ Bind(&loop);
|
| node->body()->Visit(this);
|
| - CountBackwardLoop();
|
| __ Bind(label->continue_label());
|
| node->condition()->Visit(this);
|
| GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
|
| @@ -1912,7 +1887,6 @@
|
| __ j(NOT_EQUAL, label->break_label());
|
| }
|
| node->body()->Visit(this);
|
| - CountBackwardLoop();
|
| __ Bind(label->continue_label());
|
| node->increment()->Visit(this);
|
| __ jmp(&loop);
|
|
|