OLD | NEW |
---|---|
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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
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(int, optimization_invocation_threshold, 1000, | |
28 "number of invocations before a function is optimized, -1 means never."); | |
29 DECLARE_FLAG(bool, enable_type_checks); | 27 DECLARE_FLAG(bool, enable_type_checks); |
30 DECLARE_FLAG(bool, report_invocation_count); | |
31 DECLARE_FLAG(bool, trace_compiler); | 28 DECLARE_FLAG(bool, trace_compiler); |
32 | 29 |
33 #define __ assembler_-> | 30 #define __ assembler_-> |
34 | 31 |
35 | 32 |
36 // TODO(regis): CodeGeneratorState, CodeGenerator::DescriptorList, and | 33 // TODO(regis): CodeGeneratorState, CodeGenerator::DescriptorList, and |
37 // CodeGenerator::HandlerList can probably be moved to code_generator.cc, since | 34 // CodeGenerator::HandlerList can probably be moved to code_generator.cc, since |
38 // they seem to be architecture independent. | 35 // they seem to be architecture independent. |
39 | 36 |
40 | 37 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
261 0, | 258 0, |
262 -1); | 259 -1); |
263 __ jmp(&StubCode::FixCallersTargetLabel()); | 260 __ jmp(&StubCode::FixCallersTargetLabel()); |
264 } | 261 } |
265 | 262 |
266 | 263 |
267 void CodeGenerator::GenerateDeferredCode() { | 264 void CodeGenerator::GenerateDeferredCode() { |
268 } | 265 } |
269 | 266 |
270 | 267 |
271 // Pre entry code is called before the frame has been constructed: | 268 // Pre entry code is called before the frame has been constructed. |
272 // - check for stack overflow. | |
273 // - optionally count function invocations. | |
274 // - optionally trigger optimizing compiler if invocation threshold has been | |
275 // reached. | |
276 // Note that first 13 bytes may be patched with a jump. | 269 // Note that first 13 bytes may be patched with a jump. |
277 // TODO(srdjan): Add check that no object is inlined in the first | 270 // TODO(srdjan): Add check that no object is inlined in the first |
278 // 13 bytes (length of a jump instruction). | 271 // 13 bytes (length of a jump instruction). |
279 void CodeGenerator::GeneratePreEntryCode() { | 272 void CodeGenerator::GeneratePreEntryCode() { |
280 // Do not optimize if: | 273 // Do not optimize if: |
281 // - we count invocations. | 274 // - we count invocations. |
282 // - optimization disabled via negative 'optimization_invocation_threshold; | 275 // - optimization disabled. |
283 // - function is marked as non-optimizable. | 276 // - function is marked as non-optimizable. |
284 // - type checks are enabled. | 277 // - type checks are enabled. |
regis
2012/02/24 23:56:25
In the 32-bit version you added a TODO here:
// TO
srdjan
2012/02/25 00:22:10
Done.
| |
285 const bool may_optimize = | 278 __ nop(8); |
286 false && // TODO(srdjan): Remove once the optimizer is enabled on x64. | 279 __ nop(5); |
287 !FLAG_report_invocation_count && | |
288 (FLAG_optimization_invocation_threshold >= 0) && | |
289 !Isolate::Current()->debugger()->IsActive() && | |
290 parsed_function_.function().is_optimizable(); | |
291 // Count invocation and check. | |
292 if (FLAG_report_invocation_count || may_optimize) { | |
293 // TODO(turnidge): It would be nice to remove this nop. Right now | |
294 // we need it to make sure the function is still patchable. | |
295 __ nop(8); | |
296 __ nop(5); | |
297 const Function& function = | |
298 Function::ZoneHandle(parsed_function_.function().raw()); | |
299 __ LoadObject(RAX, function); | |
300 __ movq(R8, FieldAddress(RAX, Function::invocation_counter_offset())); | |
301 __ incq(R8); | |
302 if (may_optimize) { | |
303 __ cmpq(R8, Immediate(FLAG_optimization_invocation_threshold)); | |
304 __ j(GREATER, &StubCode::OptimizeInvokedFunctionLabel()); | |
305 } | |
306 // R8 contains an integer value, not an object. | |
307 __ movq(FieldAddress(RAX, Function::invocation_counter_offset()), R8); | |
308 } | |
309 } | 280 } |
310 | 281 |
311 | 282 |
312 // Verify assumptions (in debug mode only). | 283 // Verify assumptions (in debug mode only). |
313 // - No two deopt descriptors have the same node id (deoptimization). | 284 // - No two deopt descriptors have the same node id (deoptimization). |
314 // - No two ic-call descriptors have the same node id (type feedback). | 285 // - No two ic-call descriptors have the same node id (type feedback). |
315 // - No two descriptors of same kind have the same PC. | 286 // - No two descriptors of same kind have the same PC. |
316 // A function without unique ids is marked as non-optimizable (e.g., because of | 287 // A function without unique ids is marked as non-optimizable (e.g., because of |
317 // finally blocks). | 288 // finally blocks). |
318 static void VerifyPcDescriptors(const PcDescriptors& descriptors, | 289 static void VerifyPcDescriptors(const PcDescriptors& descriptors, |
(...skipping 1586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1905 | 1876 |
1906 // Call operator. | 1877 // Call operator. |
1907 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name()); | 1878 GenerateBinaryOperatorCall(node->id(), node->token_index(), node->Name()); |
1908 // Result is in RAX. | 1879 // Result is in RAX. |
1909 if (IsResultNeeded(node)) { | 1880 if (IsResultNeeded(node)) { |
1910 __ pushq(RAX); | 1881 __ pushq(RAX); |
1911 } | 1882 } |
1912 } | 1883 } |
1913 | 1884 |
1914 | 1885 |
1915 void CodeGenerator::CountBackwardLoop() { | |
1916 Label done; | |
1917 const Function& function = | |
1918 Function::ZoneHandle(parsed_function_.function().raw()); | |
1919 __ LoadObject(RAX, function); | |
1920 __ movq(RBX, FieldAddress(RAX, Function::invocation_counter_offset())); | |
1921 __ incq(RBX); | |
1922 if (!FLAG_report_invocation_count) { | |
1923 // Prevent overflow. | |
1924 __ cmpq(RBX, Immediate(FLAG_optimization_invocation_threshold)); | |
1925 __ j(GREATER, &done); | |
1926 } | |
1927 // RBX contains an integer value, not an object. | |
1928 __ movq(FieldAddress(RAX, Function::invocation_counter_offset()), RBX); | |
1929 __ Bind(&done); | |
1930 } | |
1931 | |
1932 | |
1933 void CodeGenerator::VisitWhileNode(WhileNode* node) { | 1886 void CodeGenerator::VisitWhileNode(WhileNode* node) { |
1934 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1887 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1935 SourceLabel* label = node->label(); | 1888 SourceLabel* label = node->label(); |
1936 __ Bind(label->continue_label()); | 1889 __ Bind(label->continue_label()); |
1937 node->condition()->Visit(this); | 1890 node->condition()->Visit(this); |
1938 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); | 1891 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1939 __ popq(RAX); | 1892 __ popq(RAX); |
1940 __ LoadObject(RDX, bool_true); | 1893 __ LoadObject(RDX, bool_true); |
1941 __ cmpq(RAX, RDX); | 1894 __ cmpq(RAX, RDX); |
1942 __ j(NOT_EQUAL, label->break_label()); | 1895 __ j(NOT_EQUAL, label->break_label()); |
1943 node->body()->Visit(this); | 1896 node->body()->Visit(this); |
1944 CountBackwardLoop(); | |
1945 __ jmp(label->continue_label()); | 1897 __ jmp(label->continue_label()); |
1946 __ Bind(label->break_label()); | 1898 __ Bind(label->break_label()); |
1947 } | 1899 } |
1948 | 1900 |
1949 | 1901 |
1950 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { | 1902 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { |
1951 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1903 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1952 SourceLabel* label = node->label(); | 1904 SourceLabel* label = node->label(); |
1953 Label loop; | 1905 Label loop; |
1954 __ Bind(&loop); | 1906 __ Bind(&loop); |
1955 node->body()->Visit(this); | 1907 node->body()->Visit(this); |
1956 CountBackwardLoop(); | |
1957 __ Bind(label->continue_label()); | 1908 __ Bind(label->continue_label()); |
1958 node->condition()->Visit(this); | 1909 node->condition()->Visit(this); |
1959 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); | 1910 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1960 __ popq(RAX); | 1911 __ popq(RAX); |
1961 __ LoadObject(RDX, bool_true); | 1912 __ LoadObject(RDX, bool_true); |
1962 __ cmpq(RAX, RDX); | 1913 __ cmpq(RAX, RDX); |
1963 __ j(EQUAL, &loop); | 1914 __ j(EQUAL, &loop); |
1964 __ Bind(label->break_label()); | 1915 __ Bind(label->break_label()); |
1965 } | 1916 } |
1966 | 1917 |
1967 | 1918 |
1968 void CodeGenerator::VisitForNode(ForNode* node) { | 1919 void CodeGenerator::VisitForNode(ForNode* node) { |
1969 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1920 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1970 node->initializer()->Visit(this); | 1921 node->initializer()->Visit(this); |
1971 SourceLabel* label = node->label(); | 1922 SourceLabel* label = node->label(); |
1972 Label loop; | 1923 Label loop; |
1973 __ Bind(&loop); | 1924 __ Bind(&loop); |
1974 if (node->condition() != NULL) { | 1925 if (node->condition() != NULL) { |
1975 node->condition()->Visit(this); | 1926 node->condition()->Visit(this); |
1976 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); | 1927 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1977 __ popq(RAX); | 1928 __ popq(RAX); |
1978 __ LoadObject(RDX, bool_true); | 1929 __ LoadObject(RDX, bool_true); |
1979 __ cmpq(RAX, RDX); | 1930 __ cmpq(RAX, RDX); |
1980 __ j(NOT_EQUAL, label->break_label()); | 1931 __ j(NOT_EQUAL, label->break_label()); |
1981 } | 1932 } |
1982 node->body()->Visit(this); | 1933 node->body()->Visit(this); |
1983 CountBackwardLoop(); | |
1984 __ Bind(label->continue_label()); | 1934 __ Bind(label->continue_label()); |
1985 node->increment()->Visit(this); | 1935 node->increment()->Visit(this); |
1986 __ jmp(&loop); | 1936 __ jmp(&loop); |
1987 __ Bind(label->break_label()); | 1937 __ Bind(label->break_label()); |
1988 } | 1938 } |
1989 | 1939 |
1990 | 1940 |
1991 void CodeGenerator::VisitJumpNode(JumpNode* node) { | 1941 void CodeGenerator::VisitJumpNode(JumpNode* node) { |
1992 SourceLabel* label = node->label(); | 1942 SourceLabel* label = node->label(); |
1993 | 1943 |
(...skipping 819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2813 const Error& error = Error::Handle( | 2763 const Error& error = Error::Handle( |
2814 Parser::FormatError(script, token_index, "Error", format, args)); | 2764 Parser::FormatError(script, token_index, "Error", format, args)); |
2815 va_end(args); | 2765 va_end(args); |
2816 Isolate::Current()->long_jump_base()->Jump(1, error); | 2766 Isolate::Current()->long_jump_base()->Jump(1, error); |
2817 UNREACHABLE(); | 2767 UNREACHABLE(); |
2818 } | 2768 } |
2819 | 2769 |
2820 } // namespace dart | 2770 } // namespace dart |
2821 | 2771 |
2822 #endif // defined TARGET_ARCH_X64 | 2772 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |