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

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
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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 265
268 // Pre entry code is called before the frame has been constructed: 266 // Pre entry code is called before the frame has been constructed:
269 // - check for stack overflow. 267 // - check for stack overflow.
270 // - optionally count function invocations. 268 // - optionally count function invocations.
271 // - optionally trigger optimizing compiler if invocation threshold has been 269 // - optionally trigger optimizing compiler if invocation threshold has been
272 // reached. 270 // reached.
273 // Note that first 5 bytes may be patched with a jump. 271 // Note that first 5 bytes may be patched with a jump.
274 // TODO(srdjan): Add check that no object is inlined in the first 272 // TODO(srdjan): Add check that no object is inlined in the first
275 // 5 bytes (length of a jump instruction). 273 // 5 bytes (length of a jump instruction).
276 void CodeGenerator::GeneratePreEntryCode() { 274 void CodeGenerator::GeneratePreEntryCode() {
277 // Do not optimize if: 275 // TODO(srdjan): Still needed?
278 // - we count invocations. 276 __ nop(5);
279 // - optimization disabled via negative 'optimization_invocation_threshold;
280 // - function is marked as non-optimizable.
281 // - type checks are enabled.
282 const bool may_optimize =
283 !FLAG_report_invocation_count &&
284 (FLAG_optimization_invocation_threshold >= 0) &&
285 !Isolate::Current()->debugger()->IsActive() &&
286 parsed_function_.function().is_optimizable();
287 // Count invocation and check.
288 if (FLAG_report_invocation_count || may_optimize) {
289 // TODO(turnidge): It would be nice to remove this nop. Right now
290 // we need it to make sure the function is still patchable.
291 __ nop(5);
292 const Function& function =
293 Function::ZoneHandle(parsed_function_.function().raw());
294 __ LoadObject(EAX, function);
295 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
296 __ incl(EBX);
297 if (may_optimize) {
298 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
299 __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel());
300 }
301 // EBX is an integer value (not an object).
302 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
303 }
304 } 277 }
305 278
306 279
307 // Verify assumptions (in debug mode only). 280 // Verify assumptions (in debug mode only).
308 // - No two deopt descriptors have the same node id (deoptimization). 281 // - No two deopt descriptors have the same node id (deoptimization).
309 // - No two ic-call descriptors have the same node id (type feedback). 282 // - No two ic-call descriptors have the same node id (type feedback).
310 // - No two descriptors of same kind have the same PC. 283 // - No two descriptors of same kind have the same PC.
311 // A function without unique ids is marked as non-optimizable (e.g., because of 284 // A function without unique ids is marked as non-optimizable (e.g., because of
312 // finally blocks). 285 // finally blocks).
313 static void VerifyPcDescriptors(const PcDescriptors& descriptors, 286 static void VerifyPcDescriptors(const PcDescriptors& descriptors,
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 #ifdef DEBUG 747 #ifdef DEBUG
775 // Check that the entry stack size matches the exit stack size. 748 // Check that the entry stack size matches the exit stack size.
776 __ movl(EDX, EBP); 749 __ movl(EDX, EBP);
777 __ subl(EDX, ESP); 750 __ subl(EDX, ESP);
778 ASSERT(locals_space_size() >= 0); 751 ASSERT(locals_space_size() >= 0);
779 __ cmpl(EDX, Immediate(locals_space_size())); 752 __ cmpl(EDX, Immediate(locals_space_size()));
780 Label wrong_stack; 753 Label wrong_stack;
781 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); 754 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump);
782 #endif // DEBUG. 755 #endif // DEBUG.
783 756
757 if (!IsOptimizing()) {
758 // Count only in unoptimized code.
759 // TODO(srdjan): Replace the counting code with a type feedback
760 // collection and counting stub.
761 const Function& function =
762 Function::ZoneHandle(parsed_function_.function().raw());
763 __ LoadObject(EBX, function);
764 __ incl(FieldAddress(EBX, Function::usage_counter_offset()));
765 if (CodeGenerator::CanOptimize()) {
766 // Do not optimize if usage count must be reported.
767 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()),
768 Immediate(FLAG_optimization_counter_threshold));
769 Label not_yet_hot;
770 __ j(LESS_EQUAL, &not_yet_hot);
771 __ pushl(EAX); // Preserve result.
772 __ pushl(EBX); // Argument for runtime: function to optimize.
773 __ CallRuntimeFromDart(kOptimizeInvokedFunctionRuntimeEntry);
774 __ popl(EBX); // Remove argument.
775 __ popl(EAX); // Restore result.
776 __ Bind(&not_yet_hot);
777 }
778 }
784 if (FLAG_trace_functions) { 779 if (FLAG_trace_functions) {
780 const Function& function =
781 Function::ZoneHandle(parsed_function_.function().raw());
782 __ LoadObject(EBX, function);
785 __ pushl(EAX); // Preserve result. 783 __ pushl(EAX); // Preserve result.
786 const Function& function =
787 Function::ZoneHandle(parsed_function_.function().raw());
788 __ LoadObject(EBX, function);
789 __ pushl(EBX); 784 __ pushl(EBX);
790 GenerateCallRuntime(AstNode::kNoId, 785 GenerateCallRuntime(AstNode::kNoId,
791 0, 786 0,
792 kTraceFunctionExitRuntimeEntry); 787 kTraceFunctionExitRuntimeEntry);
793 __ popl(EAX); // Remove argument. 788 __ popl(EAX); // Remove argument.
794 __ popl(EAX); // Restore result. 789 __ popl(EAX); // Restore result.
795 } 790 }
796 __ LeaveFrame(); 791 __ LeaveFrame();
797 __ ret(); 792 __ ret();
798 // Add a NOP to make return code pattern 5 bytes long for patching 793 // 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
1906 1901
1907 // Call operator. 1902 // Call operator.
1908 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name()); 1903 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name());
1909 // Result is in EAX. 1904 // Result is in EAX.
1910 if (IsResultNeeded(node)) { 1905 if (IsResultNeeded(node)) {
1911 __ pushl(EAX); 1906 __ pushl(EAX);
1912 } 1907 }
1913 } 1908 }
1914 1909
1915 1910
1916 void CodeGenerator::CountBackwardLoop() {
1917 Label done;
1918 const Function& function =
1919 Function::ZoneHandle(parsed_function_.function().raw());
1920 __ LoadObject(EAX, function);
1921 __ movl(EBX, FieldAddress(EAX, Function::invocation_counter_offset()));
1922 __ incl(EBX);
1923 if (!FLAG_report_invocation_count) {
1924 // Prevent overflow.
1925 __ cmpl(EBX, Immediate(FLAG_optimization_invocation_threshold));
1926 __ j(GREATER, &done);
1927 }
1928 // EBX is an integer value (not an object).
1929 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX);
1930 __ Bind(&done);
1931 }
1932
1933
1934 void CodeGenerator::VisitWhileNode(WhileNode* node) { 1911 void CodeGenerator::VisitWhileNode(WhileNode* node) {
1935 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1912 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1936 SourceLabel* label = node->label(); 1913 SourceLabel* label = node->label();
1937 __ Bind(label->continue_label()); 1914 __ Bind(label->continue_label());
1938 node->condition()->Visit(this); 1915 node->condition()->Visit(this);
1939 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1916 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1940 __ popl(EAX); 1917 __ popl(EAX);
1941 __ LoadObject(EDX, bool_true); 1918 __ LoadObject(EDX, bool_true);
1942 __ cmpl(EAX, EDX); 1919 __ cmpl(EAX, EDX);
1943 __ j(NOT_EQUAL, label->break_label()); 1920 __ j(NOT_EQUAL, label->break_label());
1944 node->body()->Visit(this); 1921 node->body()->Visit(this);
1945 CountBackwardLoop();
1946 __ jmp(label->continue_label()); 1922 __ jmp(label->continue_label());
1947 __ Bind(label->break_label()); 1923 __ Bind(label->break_label());
1948 } 1924 }
1949 1925
1950 1926
1951 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { 1927 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) {
1952 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1928 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1953 SourceLabel* label = node->label(); 1929 SourceLabel* label = node->label();
1954 Label loop; 1930 Label loop;
1955 __ Bind(&loop); 1931 __ Bind(&loop);
1956 node->body()->Visit(this); 1932 node->body()->Visit(this);
1957 CountBackwardLoop();
1958 __ Bind(label->continue_label()); 1933 __ Bind(label->continue_label());
1959 node->condition()->Visit(this); 1934 node->condition()->Visit(this);
1960 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1935 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1961 __ popl(EAX); 1936 __ popl(EAX);
1962 __ LoadObject(EDX, bool_true); 1937 __ LoadObject(EDX, bool_true);
1963 __ cmpl(EAX, EDX); 1938 __ cmpl(EAX, EDX);
1964 __ j(EQUAL, &loop); 1939 __ j(EQUAL, &loop);
1965 __ Bind(label->break_label()); 1940 __ Bind(label->break_label());
1966 } 1941 }
1967 1942
1968 1943
1969 void CodeGenerator::VisitForNode(ForNode* node) { 1944 void CodeGenerator::VisitForNode(ForNode* node) {
1970 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1945 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1971 node->initializer()->Visit(this); 1946 node->initializer()->Visit(this);
1972 SourceLabel* label = node->label(); 1947 SourceLabel* label = node->label();
1973 Label loop; 1948 Label loop;
1974 __ Bind(&loop); 1949 __ Bind(&loop);
1975 if (node->condition() != NULL) { 1950 if (node->condition() != NULL) {
1976 node->condition()->Visit(this); 1951 node->condition()->Visit(this);
1977 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); 1952 GenerateConditionTypeCheck(node->id(), node->condition()->token_index());
1978 __ popl(EAX); 1953 __ popl(EAX);
1979 __ LoadObject(EDX, bool_true); 1954 __ LoadObject(EDX, bool_true);
1980 __ cmpl(EAX, EDX); 1955 __ cmpl(EAX, EDX);
1981 __ j(NOT_EQUAL, label->break_label()); 1956 __ j(NOT_EQUAL, label->break_label());
1982 } 1957 }
1983 node->body()->Visit(this); 1958 node->body()->Visit(this);
1984 CountBackwardLoop();
1985 __ Bind(label->continue_label()); 1959 __ Bind(label->continue_label());
1986 node->increment()->Visit(this); 1960 node->increment()->Visit(this);
1987 __ jmp(&loop); 1961 __ jmp(&loop);
1988 __ Bind(label->break_label()); 1962 __ Bind(label->break_label());
1989 } 1963 }
1990 1964
1991 1965
1992 void CodeGenerator::VisitJumpNode(JumpNode* node) { 1966 void CodeGenerator::VisitJumpNode(JumpNode* node) {
1993 SourceLabel* label = node->label(); 1967 SourceLabel* label = node->label();
1994 1968
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after
2814 const Error& error = Error::Handle( 2788 const Error& error = Error::Handle(
2815 Parser::FormatError(script, token_index, "Error", format, args)); 2789 Parser::FormatError(script, token_index, "Error", format, args));
2816 va_end(args); 2790 va_end(args);
2817 Isolate::Current()->long_jump_base()->Jump(1, error); 2791 Isolate::Current()->long_jump_base()->Jump(1, error);
2818 UNREACHABLE(); 2792 UNREACHABLE();
2819 } 2793 }
2820 2794
2821 } // namespace dart 2795 } // namespace dart
2822 2796
2823 #endif // defined TARGET_ARCH_IA32 2797 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698