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

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

Issue 10500005: More shared code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language_ia32.cc » ('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_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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.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/code_descriptors.h" 12 #include "vm/code_descriptors.h"
13 #include "vm/code_generator.h" 13 #include "vm/code_generator.h"
14 #include "vm/debugger.h"
15 #include "vm/disassembler.h" 14 #include "vm/disassembler.h"
16 #include "vm/il_printer.h" 15 #include "vm/il_printer.h"
17 #include "vm/intrinsifier.h"
18 #include "vm/locations.h" 16 #include "vm/locations.h"
19 #include "vm/longjump.h"
20 #include "vm/object_store.h" 17 #include "vm/object_store.h"
21 #include "vm/parser.h" 18 #include "vm/parser.h"
22 #include "vm/stub_code.h" 19 #include "vm/stub_code.h"
23 20
24 namespace dart { 21 namespace dart {
25 22
26 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables."); 23 DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
27 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function."); 24 DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
28 DECLARE_FLAG(bool, enable_type_checks); 25 DECLARE_FLAG(bool, enable_type_checks);
29 DECLARE_FLAG(bool, intrinsify);
30 DECLARE_FLAG(int, optimization_counter_threshold);
31 DECLARE_FLAG(bool, print_ast); 26 DECLARE_FLAG(bool, print_ast);
32 DECLARE_FLAG(bool, report_usage_count);
33 DECLARE_FLAG(bool, code_comments); 27 DECLARE_FLAG(bool, code_comments);
34 28
35 29
36 void DeoptimizationStub::GenerateCode(FlowGraphCompilerShared* compiler) { 30 void DeoptimizationStub::GenerateCode(FlowGraphCompilerShared* compiler) {
37 Assembler* assem = compiler->assembler(); 31 Assembler* assem = compiler->assembler();
38 #define __ assem-> 32 #define __ assem->
39 __ Comment("Deopt stub for id %d", deopt_id_); 33 __ Comment("Deopt stub for id %d", deopt_id_);
40 __ Bind(entry_label()); 34 __ Bind(entry_label());
41 for (intptr_t i = 0; i < registers_.length(); i++) { 35 for (intptr_t i = 0; i < registers_.length(); i++) {
42 if (registers_[i] != kNoRegister) { 36 if (registers_[i] != kNoRegister) {
(...skipping 13 matching lines...) Expand all
56 FlowGraphCompiler::FlowGraphCompiler( 50 FlowGraphCompiler::FlowGraphCompiler(
57 Assembler* assembler, 51 Assembler* assembler,
58 const ParsedFunction& parsed_function, 52 const ParsedFunction& parsed_function,
59 const GrowableArray<BlockEntryInstr*>& block_order, 53 const GrowableArray<BlockEntryInstr*>& block_order,
60 bool is_optimizing) 54 bool is_optimizing)
61 : FlowGraphCompilerShared(assembler, 55 : FlowGraphCompilerShared(assembler,
62 parsed_function, 56 parsed_function,
63 block_order, 57 block_order,
64 is_optimizing) {} 58 is_optimizing) {}
65 59
66
67 void FlowGraphCompiler::Bailout(const char* reason) {
68 const char* kFormat = "FlowGraphCompiler Bailout: %s %s.";
69 const char* function_name = parsed_function().function().ToCString();
70 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
71 char* chars = reinterpret_cast<char*>(
72 Isolate::Current()->current_zone()->Allocate(len));
73 OS::SNPrint(chars, len, kFormat, function_name, reason);
74 const Error& error = Error::Handle(
75 LanguageError::New(String::Handle(String::New(chars))));
76 Isolate::Current()->long_jump_base()->Jump(1, error);
77 }
78
79
80 #define __ assembler()-> 60 #define __ assembler()->
81 61
82 62
83 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if 63 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
84 // type test is conclusive, otherwise fallthrough if a type test could not 64 // type test is conclusive, otherwise fallthrough if a type test could not
85 // be completed. 65 // be completed.
86 // RAX: instance (must survive), 66 // RAX: instance (must survive),
87 RawSubtypeTestCache* 67 RawSubtypeTestCache*
88 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 68 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
89 intptr_t cid, 69 intptr_t cid,
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 } else { 533 } else {
554 __ LoadObject(dst, value->AsConstant()->value()); 534 __ LoadObject(dst, value->AsConstant()->value());
555 } 535 }
556 } else { 536 } else {
557 ASSERT(value->IsUse()); 537 ASSERT(value->IsUse());
558 __ popq(dst); 538 __ popq(dst);
559 } 539 }
560 } 540 }
561 541
562 542
563 void FlowGraphCompiler::EmitInstanceCall(intptr_t cid, 543 intptr_t FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
564 intptr_t token_index, 544 const ICData& ic_data,
565 intptr_t try_index, 545 const Array& arguments_descriptor,
566 const String& function_name, 546 intptr_t argument_count) {
567 intptr_t argument_count,
568 const Array& argument_names,
569 intptr_t checked_argument_count) {
570 ICData& ic_data =
571 ICData::ZoneHandle(ICData::New(parsed_function().function(),
572 function_name,
573 cid,
574 checked_argument_count));
575 const Array& arguments_descriptor =
576 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names);
577 __ LoadObject(RBX, ic_data); 547 __ LoadObject(RBX, ic_data);
578 __ LoadObject(R10, arguments_descriptor); 548 __ LoadObject(R10, arguments_descriptor);
579 549
580 uword label_address = 0; 550 __ call(target_label);
581 switch (checked_argument_count) { 551 const intptr_t descr_offset = assembler()->CodeSize();
582 case 1:
583 label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
584 break;
585 case 2:
586 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
587 break;
588 default:
589 UNIMPLEMENTED();
590 }
591 ExternalLabel target_label("InlineCache", label_address);
592 __ call(&target_label);
593 AddCurrentDescriptor(PcDescriptors::kIcCall, cid, token_index, try_index);
594 __ Drop(argument_count); 552 __ Drop(argument_count);
553 return descr_offset;
554 }
555
556 intptr_t FlowGraphCompiler::EmitStaticCall(const Function& function,
557 const Array& arguments_descriptor,
558 intptr_t argument_count) {
559 __ LoadObject(RBX, function);
560 __ LoadObject(R10, arguments_descriptor);
561 __ call(&StubCode::CallStaticFunctionLabel());
562 const intptr_t descr_offset = assembler()->CodeSize();
563 __ Drop(argument_count);
564 return descr_offset;
595 } 565 }
596 566
597 567
598 void FlowGraphCompiler::EmitStaticCall(intptr_t token_index,
599 intptr_t try_index,
600 const Function& function,
601 intptr_t argument_count,
602 const Array& argument_names) {
603 const Array& arguments_descriptor =
604 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names);
605 __ LoadObject(RBX, function);
606 __ LoadObject(R10, arguments_descriptor);
607
608 GenerateCall(token_index,
609 try_index,
610 &StubCode::CallStaticFunctionLabel(),
611 PcDescriptors::kFuncCall);
612 __ Drop(argument_count);
613 }
614
615
616 // Optimize instanceof type test by adding inlined tests for: 568 // Optimize instanceof type test by adding inlined tests for:
617 // - NULL -> return false. 569 // - NULL -> return false.
618 // - Smi -> compile time subtype check (only if dst class is not parameterized). 570 // - Smi -> compile time subtype check (only if dst class is not parameterized).
619 // - Class equality (only if class is not parameterized). 571 // - Class equality (only if class is not parameterized).
620 // Inputs: 572 // Inputs:
621 // - RAX: object. 573 // - RAX: object.
622 // - RDX: instantiator type arguments or raw_null. 574 // - RDX: instantiator type arguments or raw_null.
623 // - RCX: instantiator or raw_null. 575 // - RCX: instantiator or raw_null.
624 // Destroys RCX and RDX. 576 // Destroys RCX and RDX.
625 // Returns: 577 // Returns:
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 __ jmp(&null_args_loop_condition, Assembler::kNearJump); 890 __ jmp(&null_args_loop_condition, Assembler::kNearJump);
939 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize); 891 const Address original_argument_addr(RBP, RCX, TIMES_8, 2 * kWordSize);
940 __ Bind(&null_args_loop); 892 __ Bind(&null_args_loop);
941 __ movq(original_argument_addr, raw_null); 893 __ movq(original_argument_addr, raw_null);
942 __ Bind(&null_args_loop_condition); 894 __ Bind(&null_args_loop_condition);
943 __ decq(RCX); 895 __ decq(RCX);
944 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump); 896 __ j(POSITIVE, &null_args_loop, Assembler::kNearJump);
945 } 897 }
946 898
947 899
948 bool FlowGraphCompiler::CanOptimize() { 900 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
949 return
950 !FLAG_report_usage_count &&
951 (FLAG_optimization_counter_threshold >= 0) &&
952 !Isolate::Current()->debugger()->IsActive();
953 }
954
955
956 void FlowGraphCompiler::IntrinsifyGetter() {
957 // TOS: return address. 901 // TOS: return address.
958 // +1 : receiver. 902 // +1 : receiver.
959 // Sequence node has one return node, its input is load field node. 903 // Sequence node has one return node, its input is load field node.
960 const SequenceNode& sequence_node = *parsed_function().node_sequence();
961 ASSERT(sequence_node.length() == 1);
962 ASSERT(sequence_node.NodeAt(0)->IsReturnNode());
963 const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode();
964 ASSERT(return_node.value()->IsLoadInstanceFieldNode());
965 const LoadInstanceFieldNode& load_node =
966 *return_node.value()->AsLoadInstanceFieldNode();
967 __ movq(RAX, Address(RSP, 1 * kWordSize)); 904 __ movq(RAX, Address(RSP, 1 * kWordSize));
968 __ movq(RAX, FieldAddress(RAX, load_node.field().Offset())); 905 __ movq(RAX, FieldAddress(RAX, offset));
969 __ ret(); 906 __ ret();
970 } 907 }
971 908
972 909
973 void FlowGraphCompiler::IntrinsifySetter() { 910 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
974 // TOS: return address. 911 // TOS: return address.
975 // +1 : value 912 // +1 : value
976 // +2 : receiver. 913 // +2 : receiver.
977 // Sequence node has one store node and one return NULL node. 914 // Sequence node has one store node and one return NULL node.
978 const SequenceNode& sequence_node = *parsed_function().node_sequence();
979 ASSERT(sequence_node.length() == 2);
980 ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode());
981 ASSERT(sequence_node.NodeAt(1)->IsReturnNode());
982 const StoreInstanceFieldNode& store_node =
983 *sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
984 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver. 915 __ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver.
985 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. 916 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value.
986 __ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX); 917 __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX);
987 const Immediate raw_null = 918 const Immediate raw_null =
988 Immediate(reinterpret_cast<intptr_t>(Object::null())); 919 Immediate(reinterpret_cast<intptr_t>(Object::null()));
989 __ movq(RAX, raw_null); 920 __ movq(RAX, raw_null);
990 __ ret(); 921 __ ret();
991 } 922 }
992 923
993 924
994 // Returns 'true' if code generation for this function is complete, i.e.,
995 // no fall-through to regular code is needed.
996 bool FlowGraphCompiler::TryIntrinsify() {
997 if (!CanOptimize()) return false;
998 // Intrinsification skips arguments checks, therefore disable if in checked
999 // mode.
1000 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) {
1001 if ((parsed_function().function().kind() == RawFunction::kImplicitGetter)) {
1002 IntrinsifyGetter();
1003 return true;
1004 }
1005 if ((parsed_function().function().kind() == RawFunction::kImplicitSetter)) {
1006 IntrinsifySetter();
1007 return true;
1008 }
1009 }
1010 // Even if an intrinsified version of the function was successfully
1011 // generated, it may fall through to the non-intrinsified method body.
1012 if (!FLAG_trace_functions) {
1013 return Intrinsifier::Intrinsify(parsed_function().function(), assembler());
1014 }
1015 return false;
1016 }
1017
1018
1019 void FlowGraphCompiler::CompileGraph() { 925 void FlowGraphCompiler::CompileGraph() {
1020 InitCompiler(); 926 InitCompiler();
1021 if (TryIntrinsify()) { 927 if (TryIntrinsify()) {
1022 // Make it patchable: code must have a minimum code size, nop(2) increases 928 // Make it patchable: code must have a minimum code size, nop(2) increases
1023 // the minimum code size appropriately. 929 // the minimum code size appropriately.
1024 __ nop(2); 930 __ nop(2);
1025 __ int3(); 931 __ int3();
1026 __ jmp(&StubCode::FixCallersTargetLabel()); 932 __ jmp(&StubCode::FixCallersTargetLabel());
1027 return; 933 return;
1028 } 934 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 1029
1124 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, 1030 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid,
1125 intptr_t token_index, 1031 intptr_t token_index,
1126 intptr_t try_index, 1032 intptr_t try_index,
1127 const RuntimeEntry& entry) { 1033 const RuntimeEntry& entry) {
1128 __ CallRuntime(entry); 1034 __ CallRuntime(entry);
1129 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); 1035 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index);
1130 } 1036 }
1131 1037
1132 1038
1133 void FlowGraphCompiler::FinalizeComments(const Code& code) {
1134 code.set_comments(assembler()->GetCodeComments());
1135 }
1136
1137 #undef __ 1039 #undef __
1138 1040
1139 } // namespace dart 1041 } // namespace dart
1140 1042
1141 #endif // defined TARGET_ARCH_X64 1043 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | runtime/vm/intermediate_language_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698