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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed comments Created 5 years, 3 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
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/gc_marker.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 "vm/ast_printer.h" 10 #include "vm/ast_printer.h"
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 // Emit all kMaterializeObject instructions describing objects to be 94 // Emit all kMaterializeObject instructions describing objects to be
95 // materialized on the deoptimization as a prefix to the deoptimization info. 95 // materialized on the deoptimization as a prefix to the deoptimization info.
96 EmitMaterializations(deopt_env_, builder); 96 EmitMaterializations(deopt_env_, builder);
97 97
98 // The real frame starts here. 98 // The real frame starts here.
99 builder->MarkFrameStart(); 99 builder->MarkFrameStart();
100 100
101 Zone* zone = compiler->zone(); 101 Zone* zone = compiler->zone();
102 102
103 // Current PP, FP, and PC.
104 builder->AddPp(current->function(), slot_ix++); 103 builder->AddPp(current->function(), slot_ix++);
105 builder->AddPcMarker(Function::Handle(zone), slot_ix++); 104 builder->AddPcMarker(Function::Handle(zone), slot_ix++);
106 builder->AddCallerFp(slot_ix++); 105 builder->AddCallerFp(slot_ix++);
107 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++); 106 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
108 107
109 // Emit all values that are needed for materialization as a part of the 108 // Emit all values that are needed for materialization as a part of the
110 // expression stack for the bottom-most frame. This guarantees that GC 109 // expression stack for the bottom-most frame. This guarantees that GC
111 // will be able to find them during materialization. 110 // will be able to find them during materialization.
112 slot_ix = builder->EmitMaterializationArguments(slot_ix); 111 slot_ix = builder->EmitMaterializationArguments(slot_ix);
113 112
114 // For the innermost environment, set outgoing arguments and the locals. 113 // For the innermost environment, set outgoing arguments and the locals.
115 for (intptr_t i = current->Length() - 1; 114 for (intptr_t i = current->Length() - 1;
116 i >= current->fixed_parameter_count(); 115 i >= current->fixed_parameter_count();
117 i--) { 116 i--) {
118 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++); 117 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
119 } 118 }
120 119
121 Environment* previous = current; 120 Environment* previous = current;
122 current = current->outer(); 121 current = current->outer();
123 while (current != NULL) { 122 while (current != NULL) {
124 // PP, FP, and PC.
125 builder->AddPp(current->function(), slot_ix++); 123 builder->AddPp(current->function(), slot_ix++);
126 builder->AddPcMarker(previous->function(), slot_ix++); 124 builder->AddPcMarker(previous->function(), slot_ix++);
127 builder->AddCallerFp(slot_ix++); 125 builder->AddCallerFp(slot_ix++);
128 126
129 // For any outer environment the deopt id is that of the call instruction 127 // For any outer environment the deopt id is that of the call instruction
130 // which is recorded in the outer environment. 128 // which is recorded in the outer environment.
131 builder->AddReturnAddress( 129 builder->AddReturnAddress(
132 current->function(), 130 current->function(),
133 Isolate::ToDeoptAfter(current->deopt_id()), 131 Isolate::ToDeoptAfter(current->deopt_id()),
134 slot_ix++); 132 slot_ix++);
(...skipping 15 matching lines...) Expand all
150 slot_ix++); 148 slot_ix++);
151 } 149 }
152 150
153 // Iterate on the outer environment. 151 // Iterate on the outer environment.
154 previous = current; 152 previous = current;
155 current = current->outer(); 153 current = current->outer();
156 } 154 }
157 // The previous pointer is now the outermost environment. 155 // The previous pointer is now the outermost environment.
158 ASSERT(previous != NULL); 156 ASSERT(previous != NULL);
159 157
160 // For the outermost environment, set caller PC, caller PP, and caller FP. 158 // Set slots for the outermost environment.
161 builder->AddCallerPp(slot_ix++); 159 builder->AddCallerPp(slot_ix++);
162 // PC marker.
163 builder->AddPcMarker(previous->function(), slot_ix++); 160 builder->AddPcMarker(previous->function(), slot_ix++);
164 builder->AddCallerFp(slot_ix++); 161 builder->AddCallerFp(slot_ix++);
165 builder->AddCallerPc(slot_ix++); 162 builder->AddCallerPc(slot_ix++);
166 163
167 // For the outermost environment, set the incoming arguments. 164 // For the outermost environment, set the incoming arguments.
168 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) { 165 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
169 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++); 166 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
170 } 167 }
171 168
172 return builder->CreateDeoptInfo(deopt_table); 169 return builder->CreateDeoptInfo(deopt_table);
173 } 170 }
174 171
175 172
176 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 173 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
177 intptr_t stub_ix) { 174 intptr_t stub_ix) {
178 // Calls do not need stubs, they share a deoptimization trampoline. 175 // Calls do not need stubs, they share a deoptimization trampoline.
179 ASSERT(reason() != ICData::kDeoptAtCall); 176 ASSERT(reason() != ICData::kDeoptAtCall);
180 Assembler* assem = compiler->assembler(); 177 Assembler* assem = compiler->assembler();
181 #define __ assem-> 178 #define __ assem->
182 __ Comment("%s", Name()); 179 __ Comment("%s", Name());
183 __ Bind(entry_label()); 180 __ Bind(entry_label());
184 if (FLAG_trap_on_deoptimization) { 181 if (FLAG_trap_on_deoptimization) {
185 __ int3(); 182 __ int3();
186 } 183 }
187 184
188 ASSERT(deopt_env() != NULL); 185 ASSERT(deopt_env() != NULL);
189 186
187 __ pushq(CODE_REG);
190 __ Call(*StubCode::Deoptimize_entry()); 188 __ Call(*StubCode::Deoptimize_entry());
191 set_pc_offset(assem->CodeSize()); 189 set_pc_offset(assem->CodeSize());
192 __ int3(); 190 __ int3();
193 #undef __ 191 #undef __
194 } 192 }
195 193
196 194
197 #define __ assembler()-> 195 #define __ assembler()->
198 196
199 197
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 916 __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
919 __ SmiUntag(RBX); 917 __ SmiUntag(RBX);
920 // Check that RCX equals RBX, i.e. no named arguments passed. 918 // Check that RCX equals RBX, i.e. no named arguments passed.
921 __ cmpq(RCX, RBX); 919 __ cmpq(RCX, RBX);
922 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); 920 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump);
923 } 921 }
924 } 922 }
925 923
926 __ Bind(&wrong_num_arguments); 924 __ Bind(&wrong_num_arguments);
927 if (function.IsClosureFunction()) { 925 if (function.IsClosureFunction()) {
928 ASSERT(assembler()->constant_pool_allowed()); 926 __ LeaveDartFrame(kKeepCalleePP); // The arguments are still on the stack.
929 __ LeaveDartFrame(); // The arguments are still on the stack. 927 __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
930 ASSERT(!assembler()->constant_pool_allowed());
931 __ jmp(*StubCode::CallClosureNoSuchMethod_entry());
932 __ set_constant_pool_allowed(true);
933 // The noSuchMethod call may return to the caller, but not here. 928 // The noSuchMethod call may return to the caller, but not here.
934 } else if (check_correct_named_args) { 929 } else if (check_correct_named_args) {
935 __ Stop("Wrong arguments"); 930 __ Stop("Wrong arguments");
936 } 931 }
937 932
938 __ Bind(&all_arguments_processed); 933 __ Bind(&all_arguments_processed);
939 // Nullify originally passed arguments only after they have been copied and 934 // Nullify originally passed arguments only after they have been copied and
940 // checked, otherwise noSuchMethod would not see their original values. 935 // checked, otherwise noSuchMethod would not see their original values.
941 // This step can be skipped in case we decide that formal parameters are 936 // This step can be skipped in case we decide that formal parameters are
942 // implicitly final, since garbage collecting the unmodified value is not 937 // implicitly final, since garbage collecting the unmodified value is not
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value. 974 __ movq(RBX, Address(RSP, 1 * kWordSize)); // Value.
980 __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX); 975 __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX);
981 __ LoadObject(RAX, Object::null_object()); 976 __ LoadObject(RAX, Object::null_object());
982 __ ret(); 977 __ ret();
983 } 978 }
984 979
985 980
986 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc 981 // NOTE: If the entry code shape changes, ReturnAddressLocator in profiler.cc
987 // needs to be updated to match. 982 // needs to be updated to match.
988 void FlowGraphCompiler::EmitFrameEntry() { 983 void FlowGraphCompiler::EmitFrameEntry() {
989 ASSERT(Assembler::EntryPointToPcMarkerOffset() == 0);
990
991 const Function& function = parsed_function().function(); 984 const Function& function = parsed_function().function();
992 const Register new_pp = R13;
993 const Register new_pc = R12;
994
995 // Load PC marker.
996 const intptr_t kRIPRelativeLeaqSize = 7;
997 const intptr_t entry_to_rip_offset = __ CodeSize() + kRIPRelativeLeaqSize;
998 __ leaq(new_pc, Address::AddressRIPRelative(-entry_to_rip_offset));
999 ASSERT(__ CodeSize() == entry_to_rip_offset);
1000
1001 // Load pool pointer. 985 // Load pool pointer.
1002 const intptr_t object_pool_pc_dist =
1003 Instructions::HeaderSize() - Instructions::object_pool_offset();
1004 __ movq(new_pp, Address(new_pc, -object_pool_pc_dist));
1005 986
1006 if (flow_graph().IsCompiledForOsr()) { 987 if (flow_graph().IsCompiledForOsr()) {
1007 intptr_t extra_slots = StackSize() 988 intptr_t extra_slots = StackSize()
1008 - flow_graph().num_stack_locals() 989 - flow_graph().num_stack_locals()
1009 - flow_graph().num_copied_params(); 990 - flow_graph().num_copied_params();
1010 ASSERT(extra_slots >= 0); 991 ASSERT(extra_slots >= 0);
1011 __ EnterOsrFrame(extra_slots * kWordSize, new_pp, new_pc); 992 __ EnterOsrFrame(extra_slots * kWordSize);
1012 } else { 993 } else {
994 const Register new_pp = R13;
995 __ LoadPoolPointer(new_pp);
996
1013 if (CanOptimizeFunction() && 997 if (CanOptimizeFunction() &&
1014 function.IsOptimizable() && 998 function.IsOptimizable() &&
1015 (!is_optimizing() || may_reoptimize())) { 999 (!is_optimizing() || may_reoptimize())) {
1016 const Register function_reg = RDI; 1000 const Register function_reg = RDI;
1017 // Load function object using the callee's pool pointer. 1001 // Load function object using the callee's pool pointer.
1018 __ LoadFunctionFromCalleePool(function_reg, function, new_pp); 1002 __ LoadFunctionFromCalleePool(function_reg, function, new_pp);
1019 1003
1020 // Patch point is after the eventually inlined function object.
1021 entry_patch_pc_offset_ = assembler()->CodeSize();
1022
1023 // Reoptimization of an optimized function is triggered by counting in 1004 // Reoptimization of an optimized function is triggered by counting in
1024 // IC stubs, but not at the entry of the function. 1005 // IC stubs, but not at the entry of the function.
1025 if (!is_optimizing()) { 1006 if (!is_optimizing()) {
1026 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); 1007 __ incl(FieldAddress(function_reg, Function::usage_counter_offset()));
1027 } 1008 }
1028 __ cmpl( 1009 __ cmpl(
1029 FieldAddress(function_reg, Function::usage_counter_offset()), 1010 FieldAddress(function_reg, Function::usage_counter_offset()),
1030 Immediate(GetOptimizationThreshold())); 1011 Immediate(GetOptimizationThreshold()));
1031 ASSERT(function_reg == RDI); 1012 ASSERT(function_reg == RDI);
1032 __ J(GREATER_EQUAL, 1013 __ J(GREATER_EQUAL,
1033 *StubCode::OptimizeFunction_entry(), 1014 *StubCode::OptimizeFunction_entry(),
1034 new_pp); 1015 new_pp);
1035 } else {
1036 entry_patch_pc_offset_ = assembler()->CodeSize();
1037 } 1016 }
1038 ASSERT(StackSize() >= 0); 1017 ASSERT(StackSize() >= 0);
1039 __ Comment("Enter frame"); 1018 __ Comment("Enter frame");
1040 __ EnterDartFrame(StackSize() * kWordSize, new_pp, new_pc); 1019 __ EnterDartFrame(StackSize() * kWordSize, new_pp);
1041 } 1020 }
1042 } 1021 }
1043 1022
1044 1023
1045 void FlowGraphCompiler::CompileGraph() { 1024 void FlowGraphCompiler::CompileGraph() {
1046 InitCompiler(); 1025 InitCompiler();
1047 1026
1048 TryIntrinsify(); 1027 TryIntrinsify();
1049 1028
1050 EmitFrameEntry(); 1029 EmitFrameEntry();
(...skipping 24 matching lines...) Expand all
1075 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); 1054 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
1076 __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params))); 1055 __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)));
1077 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); 1056 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump);
1078 __ cmpq(RAX, 1057 __ cmpq(RAX,
1079 FieldAddress(R10, 1058 FieldAddress(R10,
1080 ArgumentsDescriptor::positional_count_offset())); 1059 ArgumentsDescriptor::positional_count_offset()));
1081 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump); 1060 __ j(EQUAL, &correct_num_arguments, Assembler::kNearJump);
1082 1061
1083 __ Bind(&wrong_num_arguments); 1062 __ Bind(&wrong_num_arguments);
1084 if (function.IsClosureFunction()) { 1063 if (function.IsClosureFunction()) {
1085 ASSERT(assembler()->constant_pool_allowed()); 1064 __ LeaveDartFrame(kKeepCalleePP); // Leave arguments on the stack.
1086 __ LeaveDartFrame(); // The arguments are still on the stack. 1065 __ Jmp(*StubCode::CallClosureNoSuchMethod_entry());
1087 ASSERT(!assembler()->constant_pool_allowed());
1088 __ jmp(*StubCode::CallClosureNoSuchMethod_entry());
1089 __ set_constant_pool_allowed(true);
1090 // The noSuchMethod call may return to the caller, but not here. 1066 // The noSuchMethod call may return to the caller, but not here.
1091 } else { 1067 } else {
1092 __ Stop("Wrong number of arguments"); 1068 __ Stop("Wrong number of arguments");
1093 } 1069 }
1094 __ Bind(&correct_num_arguments); 1070 __ Bind(&correct_num_arguments);
1095 } 1071 }
1096 } else if (!flow_graph().IsCompiledForOsr()) { 1072 } else if (!flow_graph().IsCompiledForOsr()) {
1097 CopyParameters(); 1073 CopyParameters();
1098 } 1074 }
1099 1075
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 } 1119 }
1144 1120
1145 ASSERT(!block_order().is_empty()); 1121 ASSERT(!block_order().is_empty());
1146 VisitBlocks(); 1122 VisitBlocks();
1147 1123
1148 __ int3(); 1124 __ int3();
1149 ASSERT(assembler()->constant_pool_allowed()); 1125 ASSERT(assembler()->constant_pool_allowed());
1150 GenerateDeferredCode(); 1126 GenerateDeferredCode();
1151 // Emit function patching code. This will be swapped with the first 13 bytes 1127 // Emit function patching code. This will be swapped with the first 13 bytes
1152 // at entry point. 1128 // at entry point.
1153 patch_code_pc_offset_ = assembler()->CodeSize();
1154 // This is patched up to a point in FrameEntry where the PP for the
1155 // current function is in R13 instead of PP.
1156 __ JmpPatchable(*StubCode::FixCallersTarget_entry(), R13);
1157 1129
1158 if (is_optimizing()) { 1130 if (is_optimizing()) {
1159 lazy_deopt_pc_offset_ = assembler()->CodeSize(); 1131 lazy_deopt_pc_offset_ = assembler()->CodeSize();
1160 __ Jmp(*StubCode::DeoptimizeLazy_entry(), PP); 1132 __ Jmp(*StubCode::DeoptimizeLazy_entry(), PP);
1161 } 1133 }
1162 } 1134 }
1163 1135
1164 1136
1165 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, 1137 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
1166 const StubEntry& stub_entry, 1138 const StubEntry& stub_entry,
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
1789 __ movups(reg, Address(RSP, 0)); 1761 __ movups(reg, Address(RSP, 0));
1790 __ AddImmediate(RSP, Immediate(kFpuRegisterSize)); 1762 __ AddImmediate(RSP, Immediate(kFpuRegisterSize));
1791 } 1763 }
1792 1764
1793 1765
1794 #undef __ 1766 #undef __
1795 1767
1796 } // namespace dart 1768 } // namespace dart
1797 1769
1798 #endif // defined TARGET_ARCH_X64 1770 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_mips.cc ('k') | runtime/vm/gc_marker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698