Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

Issue 9460015: Do not count invocations but usage of a function, i.e., increment a function's counter at IC calls … (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/code_generator_x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
11 #include "vm/ast_printer.h" 11 #include "vm/ast_printer.h"
12 #include "vm/class_finalizer.h" 12 #include "vm/class_finalizer.h"
13 #include "vm/dart_entry.h" 13 #include "vm/dart_entry.h"
14 #include "vm/debugger.h" 14 #include "vm/debugger.h"
15 #include "vm/longjump.h" 15 #include "vm/longjump.h"
16 #include "vm/object.h" 16 #include "vm/object.h"
17 #include "vm/object_store.h" 17 #include "vm/object_store.h"
18 #include "vm/parser.h" 18 #include "vm/parser.h"
19 #include "vm/resolver.h" 19 #include "vm/resolver.h"
20 #include "vm/stub_code.h" 20 #include "vm/stub_code.h"
21 21
22 namespace dart { 22 namespace dart {
23 23
24 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 24 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
25 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); 25 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function."); 26 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
27 DEFINE_FLAG(bool, print_ic_in_optimized, false, 27 DEFINE_FLAG(bool, print_ic_in_optimized, false,
28 "Debugging helper to identify potential performance pitfalls."); 28 "Debugging helper to identify potential performance pitfalls.");
29 DEFINE_FLAG(int, optimization_invocation_threshold, 1000, 29 DECLARE_FLAG(int, optimization_counter_threshold);
30 "Number of invocations before a function is optimized, -1 means never.");
31 DECLARE_FLAG(bool, enable_type_checks); 30 DECLARE_FLAG(bool, enable_type_checks);
32 DECLARE_FLAG(bool, report_invocation_count);
33 DECLARE_FLAG(bool, trace_compiler); 31 DECLARE_FLAG(bool, trace_compiler);
34 32
35 #define __ assembler_-> 33 #define __ assembler_->
36 34
37 35
38 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen) 36 CodeGeneratorState::CodeGeneratorState(CodeGenerator* codegen)
39 : StackResource(Isolate::Current()), 37 : StackResource(Isolate::Current()),
40 codegen_(codegen), 38 codegen_(codegen),
41 parent_(codegen->state()) { 39 parent_(codegen->state()) {
42 if (parent_ != NULL) { 40 if (parent_ != NULL) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 196
199 // Pre entry code is called before the frame has been constructed: 197 // Pre entry code is called before the frame has been constructed:
200 // - check for stack overflow. 198 // - check for stack overflow.
201 // - optionally count function invocations. 199 // - optionally count function invocations.
202 // - optionally trigger optimizing compiler if invocation threshold has been 200 // - optionally trigger optimizing compiler if invocation threshold has been
203 // reached. 201 // reached.
204 // Note that first 5 bytes may be patched with a jump. 202 // Note that first 5 bytes may be patched with a jump.
205 // TODO(srdjan): Add check that no object is inlined in the first 203 // TODO(srdjan): Add check that no object is inlined in the first
206 // 5 bytes (length of a jump instruction). 204 // 5 bytes (length of a jump instruction).
207 void CodeGenerator::GeneratePreEntryCode() { 205 void CodeGenerator::GeneratePreEntryCode() {
208 // Do not optimize if: 206 // TODO(srdjan): Still needed?
209 // - we count invocations. 207 __ nop(5);
210 // - optimization disabled via negative 'optimization_invocation_threshold;
211 // - function is marked as non-optimizable.
212 // - type checks are enabled.
213 const bool may_optimize =
214 !FLAG_report_invocation_count &&
215 (FLAG_optimization_invocation_threshold >= 0) &&
216 !Isolate::Current()->debugger()->IsActive() &&
217 parsed_function_.function().is_optimizable();
218 // Count invocation and check.
219 if (FLAG_report_invocation_count || may_optimize) {
220 // TODO(turnidge): It would be nice to remove this nop. Right now
221 // we need it to make sure the function is still patchable.
222 __ nop(5);
223 const Function& function =
224 Function::ZoneHandle(parsed_function_.function().raw());
225 __ LoadObject(EAX, function);
226 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
227 __ incl(EBX);
228 if (may_optimize) {
229 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
230 __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel());
231 }
232 // EBX is an integer value (not an object).
233 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
234 }
235 } 208 }
236 209
237 210
238 // Verify assumptions (in debug mode only). 211 // Verify assumptions (in debug mode only).
239 // - No two deopt descriptors have the same node id (deoptimization). 212 // - No two deopt descriptors have the same node id (deoptimization).
240 // - No two ic-call descriptors have the same node id (type feedback). 213 // - No two ic-call descriptors have the same node id (type feedback).
241 // - No two descriptors of same kind have the same PC. 214 // - No two descriptors of same kind have the same PC.
242 // A function without unique ids is marked as non-optimizable (e.g., because of 215 // A function without unique ids is marked as non-optimizable (e.g., because of
243 // finally blocks). 216 // finally blocks).
244 static void VerifyPcDescriptors(const PcDescriptors& descriptors, 217 static void VerifyPcDescriptors(const PcDescriptors& descriptors,
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 #ifdef DEBUG 678 #ifdef DEBUG
706 // Check that the entry stack size matches the exit stack size. 679 // Check that the entry stack size matches the exit stack size.
707 __ movl(EDX, EBP); 680 __ movl(EDX, EBP);
708 __ subl(EDX, ESP); 681 __ subl(EDX, ESP);
709 ASSERT(locals_space_size() >= 0); 682 ASSERT(locals_space_size() >= 0);
710 __ cmpl(EDX, Immediate(locals_space_size())); 683 __ cmpl(EDX, Immediate(locals_space_size()));
711 Label wrong_stack; 684 Label wrong_stack;
712 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); 685 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
713 #endif // DEBUG. 686 #endif // DEBUG.
714 687
688 if (!IsOptimizing()) {
689 // Count only in unoptimized code.
690 // TODO(srdjan): Replace the counting code with a type feedback
691 // collection and counting stub.
692 const Function& function =
693 Function::ZoneHandle(parsed_function_.function().raw());
694 __ LoadObject(EBX, function);
695 __ incl(FieldAddress(EBX, Function::usage_counter_offset()));
696 if (CodeGenerator::CanOptimize()) {
697 // Do not optimize if usage count must be reported.
698 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()),
699 Immediate(FLAG_optimization_counter_threshold));
700 Label not_yet_hot;
701 __ j(LESS_EQUAL, &not_yet_hot);
702 __ pushl(EAX); // Preserve result.
703 __ pushl(EBX); // Argument for runtime: function to optimize.
704 __ CallRuntimeFromDart(kOptimizeInvokedFunctionRuntimeEntry);
705 __ popl(EBX); // Remove argument.
706 __ popl(EAX); // Restore result.
707 __ Bind(&not_yet_hot);
708 }
709 }
715 if (FLAG_trace_functions) { 710 if (FLAG_trace_functions) {
711 const Function& function =
712 Function::ZoneHandle(parsed_function_.function().raw());
713 __ LoadObject(EBX, function);
716 __ pushl(EAX); // Preserve result. 714 __ pushl(EAX); // Preserve result.
717 const Function& function =
718 Function::ZoneHandle(parsed_function_.function().raw());
719 __ LoadObject(EBX, function);
720 __ pushl(EBX); 715 __ pushl(EBX);
721 GenerateCallRuntime(AstNode::kNoId, 716 GenerateCallRuntime(AstNode::kNoId,
722 0, 717 0,
723 kTraceFunctionExitRuntimeEntry); 718 kTraceFunctionExitRuntimeEntry);
724 __ popl(EAX); // Remove argument. 719 __ popl(EAX); // Remove argument.
725 __ popl(EAX); // Restore result. 720 __ popl(EAX); // Restore result.
726 } 721 }
727 __ LeaveFrame(); 722 __ LeaveFrame();
728 __ ret(); 723 __ ret();
729 // Add a NOP to make return code pattern 5 bytes long for patching 724 // Add a NOP to make return code pattern 5 bytes long for patching
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 1832
1838 // Call operator. 1833 // Call operator.
1839 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name()); 1834 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name());
1840 // Result is in EAX. 1835 // Result is in EAX.
1841 if (IsResultNeeded(node)) { 1836 if (IsResultNeeded(node)) {
1842 __ pushl(EAX); 1837 __ pushl(EAX);
1843 } 1838 }
1844 } 1839 }
1845 1840
1846 1841
1847 void CodeGenerator::CountBackwardLoop() {
1848 Label done;
1849 const Function& function =
1850 Function::ZoneHandle(parsed_function_.function().raw());
1851 __ LoadObject(EAX, function);
1852 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
1853 __ incl(EBX);
1854 if (!FLAG_report_invocation_count) {
1855 // Prevent overflow.
1856 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
1857 __ j(GREATER, &done);
1858 }
1859 // EBX is an integer value (not an object).
1860 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
1861 __ Bind(&done);
1862 }
1863
1864
1865 void CodeGenerator::VisitWhileNode(WhileNode* node) { 1842 void CodeGenerator::VisitWhileNode(WhileNode* node) {
1866 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1843 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1867 SourceLabel* label = node->label(); 1844 SourceLabel* label = node->label();
1868 __ Bind(label->continue_label()); 1845 __ Bind(label->continue_label());
1869 node->condition()->Visit(this); 1846 node->condition()->Visit(this);
1870 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1847 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1871 __ popl(EAX); 1848 __ popl(EAX);
1872 __ LoadObject(EDX, bool_true); 1849 __ LoadObject(EDX, bool_true);
1873 __ cmpl(EAX, EDX); 1850 __ cmpl(EAX, EDX);
1874 __ j(NOT_EQUAL, label->break_label()); 1851 __ j(NOT_EQUAL, label->break_label());
1875 node->body()->Visit(this); 1852 node->body()->Visit(this);
1876 CountBackwardLoop();
1877 __ jmp(label->continue_label()); 1853 __ jmp(label->continue_label());
1878 __ Bind(label->break_label()); 1854 __ Bind(label->break_label());
1879 } 1855 }
1880 1856
1881 1857
1882 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { 1858 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) {
1883 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1859 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1884 SourceLabel* label = node->label(); 1860 SourceLabel* label = node->label();
1885 Label loop; 1861 Label loop;
1886 __ Bind(&loop); 1862 __ Bind(&loop);
1887 node->body()->Visit(this); 1863 node->body()->Visit(this);
1888 CountBackwardLoop();
1889 __ Bind(label->continue_label()); 1864 __ Bind(label->continue_label());
1890 node->condition()->Visit(this); 1865 node->condition()->Visit(this);
1891 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1866 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1892 __ popl(EAX); 1867 __ popl(EAX);
1893 __ LoadObject(EDX, bool_true); 1868 __ LoadObject(EDX, bool_true);
1894 __ cmpl(EAX, EDX); 1869 __ cmpl(EAX, EDX);
1895 __ j(EQUAL, &loop); 1870 __ j(EQUAL, &loop);
1896 __ Bind(label->break_label()); 1871 __ Bind(label->break_label());
1897 } 1872 }
1898 1873
1899 1874
1900 void CodeGenerator::VisitForNode(ForNode* node) { 1875 void CodeGenerator::VisitForNode(ForNode* node) {
1901 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1876 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1902 node->initializer()->Visit(this); 1877 node->initializer()->Visit(this);
1903 SourceLabel* label = node->label(); 1878 SourceLabel* label = node->label();
1904 Label loop; 1879 Label loop;
1905 __ Bind(&loop); 1880 __ Bind(&loop);
1906 if (node->condition() != NULL) { 1881 if (node->condition() != NULL) {
1907 node->condition()->Visit(this); 1882 node->condition()->Visit(this);
1908 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1883 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1909 __ popl(EAX); 1884 __ popl(EAX);
1910 __ LoadObject(EDX, bool_true); 1885 __ LoadObject(EDX, bool_true);
1911 __ cmpl(EAX, EDX); 1886 __ cmpl(EAX, EDX);
1912 __ j(NOT_EQUAL, label->break_label()); 1887 __ j(NOT_EQUAL, label->break_label());
1913 } 1888 }
1914 node->body()->Visit(this); 1889 node->body()->Visit(this);
1915 CountBackwardLoop();
1916 __ Bind(label->continue_label()); 1890 __ Bind(label->continue_label());
1917 node->increment()->Visit(this); 1891 node->increment()->Visit(this);
1918 __ jmp(&loop); 1892 __ jmp(&loop);
1919 __ Bind(label->break_label()); 1893 __ Bind(label->break_label());
1920 } 1894 }
1921 1895
1922 1896
1923 void CodeGenerator::VisitJumpNode(JumpNode* node) { 1897 void CodeGenerator::VisitJumpNode(JumpNode* node) {
1924 SourceLabel* label = node->label(); 1898 SourceLabel* label = node->label();
1925 1899
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after
2745 const Error& error = Error::Handle( 2719 const Error& error = Error::Handle(
2746 Parser::FormatError(script, token_index, "Error", format, args)); 2720 Parser::FormatError(script, token_index, "Error", format, args));
2747 va_end(args); 2721 va_end(args);
2748 Isolate::Current()->long_jump_base()->Jump(1, error); 2722 Isolate::Current()->long_jump_base()->Jump(1, error);
2749 UNREACHABLE(); 2723 UNREACHABLE();
2750 } 2724 }
2751 2725
2752 } // namespace dart 2726 } // namespace dart
2753 2727
2754 #endif // defined TARGET_ARCH_IA32 2728 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/code_generator_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698