| OLD | NEW |
| 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 "lib/error.h" | 10 #include "lib/error.h" |
| 11 #include "vm/ast_printer.h" | 11 #include "vm/ast_printer.h" |
| 12 #include "vm/dart_entry.h" | 12 #include "vm/dart_entry.h" |
| 13 #include "vm/deopt_instructions.h" | 13 #include "vm/deopt_instructions.h" |
| 14 #include "vm/il_printer.h" | 14 #include "vm/il_printer.h" |
| 15 #include "vm/locations.h" | 15 #include "vm/locations.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 17 #include "vm/parser.h" |
| 18 #include "vm/stack_frame.h" | 18 #include "vm/stack_frame.h" |
| 19 #include "vm/stub_code.h" | 19 #include "vm/stub_code.h" |
| 20 #include "vm/symbols.h" | 20 #include "vm/symbols.h" |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); | 24 DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization."); |
| 25 DECLARE_FLAG(int, optimization_counter_threshold); | 25 DECLARE_FLAG(int, optimization_counter_threshold); |
| 26 DECLARE_FLAG(int, reoptimization_counter_threshold); |
| 26 DECLARE_FLAG(bool, print_ast); | 27 DECLARE_FLAG(bool, print_ast); |
| 27 DECLARE_FLAG(bool, print_scopes); | 28 DECLARE_FLAG(bool, print_scopes); |
| 28 DECLARE_FLAG(bool, enable_type_checks); | 29 DECLARE_FLAG(bool, enable_type_checks); |
| 29 DECLARE_FLAG(bool, eliminate_type_checks); | 30 DECLARE_FLAG(bool, eliminate_type_checks); |
| 30 | 31 |
| 31 | 32 |
| 32 FlowGraphCompiler::~FlowGraphCompiler() { | 33 FlowGraphCompiler::~FlowGraphCompiler() { |
| 33 // BlockInfos are zone-allocated, so their destructors are not called. | 34 // BlockInfos are zone-allocated, so their destructors are not called. |
| 34 // Verify the labels explicitly here. | 35 // Verify the labels explicitly here. |
| 35 for (int i = 0; i < block_info_.length(); ++i) { | 36 for (int i = 0; i < block_info_.length(); ++i) { |
| (...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX); | 1065 __ StoreIntoObject(RAX, FieldAddress(RAX, offset), RBX); |
| 1065 const Immediate& raw_null = | 1066 const Immediate& raw_null = |
| 1066 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1067 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1067 __ movq(RAX, raw_null); | 1068 __ movq(RAX, raw_null); |
| 1068 __ ret(); | 1069 __ ret(); |
| 1069 } | 1070 } |
| 1070 | 1071 |
| 1071 | 1072 |
| 1072 void FlowGraphCompiler::EmitFrameEntry() { | 1073 void FlowGraphCompiler::EmitFrameEntry() { |
| 1073 const Function& function = parsed_function().function(); | 1074 const Function& function = parsed_function().function(); |
| 1074 if (CanOptimizeFunction() && function.is_optimizable()) { | 1075 if (CanOptimizeFunction() && |
| 1075 const bool can_optimize = !is_optimizing() || may_reoptimize(); | 1076 function.is_optimizable() && |
| 1077 (!is_optimizing() || may_reoptimize())) { |
| 1076 const Register function_reg = RDI; | 1078 const Register function_reg = RDI; |
| 1077 if (can_optimize) { | 1079 __ LoadObject(function_reg, function); |
| 1078 __ LoadObject(function_reg, function); | |
| 1079 } | |
| 1080 // Patch point is after the eventually inlined function object. | 1080 // Patch point is after the eventually inlined function object. |
| 1081 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1081 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1082 Isolate::kNoDeoptId, | 1082 Isolate::kNoDeoptId, |
| 1083 0); // No token position. | 1083 0); // No token position. |
| 1084 if (can_optimize) { | 1084 if (is_optimizing()) { |
| 1085 // Reoptimization of optimized function is triggered by counting in | 1085 // Reoptimization of an optimized function is triggered by counting in |
| 1086 // IC stubs, but not at the entry of the function. | 1086 // IC stubs, but not at the entry of the function. |
| 1087 if (!is_optimizing()) { | |
| 1088 __ incq(FieldAddress(function_reg, Function::usage_counter_offset())); | |
| 1089 } | |
| 1090 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), | 1087 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), |
| 1091 Immediate(FLAG_optimization_counter_threshold)); | 1088 Immediate(FLAG_reoptimization_counter_threshold)); |
| 1092 ASSERT(function_reg == RDI); | 1089 } else { |
| 1093 __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel()); | 1090 __ incq(FieldAddress(function_reg, Function::usage_counter_offset())); |
| 1091 __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), |
| 1092 Immediate(FLAG_optimization_counter_threshold)); |
| 1094 } | 1093 } |
| 1095 } else { | 1094 ASSERT(function_reg == RDI); |
| 1095 __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel()); |
| 1096 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1096 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1097 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1097 Isolate::kNoDeoptId, | 1098 Isolate::kNoDeoptId, |
| 1098 0); // No token position. | 1099 0); // No token position. |
| 1099 } | 1100 } |
| 1100 __ Comment("Enter frame"); | 1101 __ Comment("Enter frame"); |
| 1101 __ EnterDartFrame(StackSize() * kWordSize); | 1102 if (flow_graph().IsCompiledForOsr()) { |
| 1103 intptr_t extra_slots = StackSize() |
| 1104 - flow_graph().num_stack_locals() |
| 1105 - flow_graph().num_copied_params(); |
| 1106 ASSERT(extra_slots >= 0); |
| 1107 __ EnterOsrFrame(extra_slots * kWordSize); |
| 1108 } else { |
| 1109 ASSERT(StackSize() >= 0); |
| 1110 __ EnterDartFrame(StackSize() * kWordSize); |
| 1111 } |
| 1102 } | 1112 } |
| 1103 | 1113 |
| 1104 | 1114 |
| 1105 void FlowGraphCompiler::CompileGraph() { | 1115 void FlowGraphCompiler::CompileGraph() { |
| 1106 InitCompiler(); | 1116 InitCompiler(); |
| 1107 if (TryIntrinsify()) { | 1117 if (TryIntrinsify()) { |
| 1108 // Although this intrinsified code will never be patched, it must satisfy | 1118 // Although this intrinsified code will never be patched, it must satisfy |
| 1109 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum | 1119 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum |
| 1110 // code size, and nop(2) increases the minimum code size appropriately. | 1120 // code size, and nop(2) increases the minimum code size appropriately. |
| 1111 __ nop(2); | 1121 __ nop(2); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1124 | 1134 |
| 1125 // We check the number of passed arguments when we have to copy them due to | 1135 // We check the number of passed arguments when we have to copy them due to |
| 1126 // the presence of optional parameters. | 1136 // the presence of optional parameters. |
| 1127 // No such checking code is generated if only fixed parameters are declared, | 1137 // No such checking code is generated if only fixed parameters are declared, |
| 1128 // unless we are in debug mode or unless we are compiling a closure. | 1138 // unless we are in debug mode or unless we are compiling a closure. |
| 1129 LocalVariable* saved_args_desc_var = | 1139 LocalVariable* saved_args_desc_var = |
| 1130 parsed_function().GetSavedArgumentsDescriptorVar(); | 1140 parsed_function().GetSavedArgumentsDescriptorVar(); |
| 1131 if (num_copied_params == 0) { | 1141 if (num_copied_params == 0) { |
| 1132 #ifdef DEBUG | 1142 #ifdef DEBUG |
| 1133 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1143 ASSERT(!parsed_function().function().HasOptionalParameters()); |
| 1134 const bool check_arguments = true; | 1144 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
| 1135 #else | 1145 #else |
| 1136 const bool check_arguments = function.IsClosureFunction(); | 1146 const bool check_arguments = |
| 1147 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); |
| 1137 #endif | 1148 #endif |
| 1138 if (check_arguments) { | 1149 if (check_arguments) { |
| 1139 __ Comment("Check argument count"); | 1150 __ Comment("Check argument count"); |
| 1140 // Check that exactly num_fixed arguments are passed in. | 1151 // Check that exactly num_fixed arguments are passed in. |
| 1141 Label correct_num_arguments, wrong_num_arguments; | 1152 Label correct_num_arguments, wrong_num_arguments; |
| 1142 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); | 1153 __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); |
| 1143 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); | 1154 __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); |
| 1144 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); | 1155 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); |
| 1145 __ cmpq(RAX, | 1156 __ cmpq(RAX, |
| 1146 FieldAddress(R10, | 1157 FieldAddress(R10, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1184 __ LeaveFrame(); | 1195 __ LeaveFrame(); |
| 1185 __ ret(); | 1196 __ ret(); |
| 1186 } else { | 1197 } else { |
| 1187 __ Stop("Wrong number of arguments"); | 1198 __ Stop("Wrong number of arguments"); |
| 1188 } | 1199 } |
| 1189 __ Bind(&correct_num_arguments); | 1200 __ Bind(&correct_num_arguments); |
| 1190 } | 1201 } |
| 1191 // The arguments descriptor is never saved in the absence of optional | 1202 // The arguments descriptor is never saved in the absence of optional |
| 1192 // parameters, since any argument definition test would always yield true. | 1203 // parameters, since any argument definition test would always yield true. |
| 1193 ASSERT(saved_args_desc_var == NULL); | 1204 ASSERT(saved_args_desc_var == NULL); |
| 1194 } else { | 1205 } else if (!flow_graph().IsCompiledForOsr()) { |
| 1195 if (saved_args_desc_var != NULL) { | 1206 if (saved_args_desc_var != NULL) { |
| 1196 __ Comment("Save arguments descriptor"); | 1207 __ Comment("Save arguments descriptor"); |
| 1197 const Register kArgumentsDescriptorReg = R10; | 1208 const Register kArgumentsDescriptorReg = R10; |
| 1198 // The saved_args_desc_var is allocated one slot before the first local. | 1209 // The saved_args_desc_var is allocated one slot before the first local. |
| 1199 const intptr_t slot = parsed_function().first_stack_local_index() + 1; | 1210 const intptr_t slot = parsed_function().first_stack_local_index() + 1; |
| 1200 // If the saved_args_desc_var is captured, it is first moved to the stack | 1211 // If the saved_args_desc_var is captured, it is first moved to the stack |
| 1201 // and later to the context, once the context is allocated. | 1212 // and later to the context, once the context is allocated. |
| 1202 ASSERT(saved_args_desc_var->is_captured() || | 1213 ASSERT(saved_args_desc_var->is_captured() || |
| 1203 (saved_args_desc_var->index() == slot)); | 1214 (saved_args_desc_var->index() == slot)); |
| 1204 __ movq(Address(RBP, slot * kWordSize), kArgumentsDescriptorReg); | 1215 __ movq(Address(RBP, slot * kWordSize), kArgumentsDescriptorReg); |
| (...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 __ movups(reg, Address(RSP, 0)); | 1904 __ movups(reg, Address(RSP, 0)); |
| 1894 __ addq(RSP, Immediate(kFpuRegisterSize)); | 1905 __ addq(RSP, Immediate(kFpuRegisterSize)); |
| 1895 } | 1906 } |
| 1896 | 1907 |
| 1897 | 1908 |
| 1898 #undef __ | 1909 #undef __ |
| 1899 | 1910 |
| 1900 } // namespace dart | 1911 } // namespace dart |
| 1901 | 1912 |
| 1902 #endif // defined TARGET_ARCH_X64 | 1913 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |