| 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_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/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 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic."); | 25 DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic."); |
| 26 DECLARE_FLAG(int, optimization_counter_threshold); | 26 DECLARE_FLAG(int, optimization_counter_threshold); |
| 27 DECLARE_FLAG(int, reoptimization_counter_threshold); | |
| 28 DECLARE_FLAG(bool, print_ast); | 27 DECLARE_FLAG(bool, print_ast); |
| 29 DECLARE_FLAG(bool, print_scopes); | 28 DECLARE_FLAG(bool, print_scopes); |
| 30 DECLARE_FLAG(bool, enable_type_checks); | 29 DECLARE_FLAG(bool, enable_type_checks); |
| 31 DECLARE_FLAG(bool, eliminate_type_checks); | 30 DECLARE_FLAG(bool, eliminate_type_checks); |
| 32 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); | 31 DECLARE_FLAG(bool, throw_on_javascript_int_overflow); |
| 33 | 32 |
| 34 | 33 |
| 35 FlowGraphCompiler::~FlowGraphCompiler() { | 34 FlowGraphCompiler::~FlowGraphCompiler() { |
| 36 // BlockInfos are zone-allocated, so their destructors are not called. | 35 // BlockInfos are zone-allocated, so their destructors are not called. |
| 37 // Verify the labels explicitly here. | 36 // Verify the labels explicitly here. |
| (...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1071 __ StoreIntoObject(EAX, FieldAddress(EAX, offset), EBX); | 1070 __ StoreIntoObject(EAX, FieldAddress(EAX, offset), EBX); |
| 1072 const Immediate& raw_null = | 1071 const Immediate& raw_null = |
| 1073 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1072 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1074 __ movl(EAX, raw_null); | 1073 __ movl(EAX, raw_null); |
| 1075 __ ret(); | 1074 __ ret(); |
| 1076 } | 1075 } |
| 1077 | 1076 |
| 1078 | 1077 |
| 1079 void FlowGraphCompiler::EmitFrameEntry() { | 1078 void FlowGraphCompiler::EmitFrameEntry() { |
| 1080 const Function& function = parsed_function().function(); | 1079 const Function& function = parsed_function().function(); |
| 1081 if (CanOptimizeFunction() && | 1080 if (CanOptimizeFunction() && function.is_optimizable()) { |
| 1082 function.is_optimizable() && | 1081 const bool can_optimize = !is_optimizing() || may_reoptimize(); |
| 1083 (!is_optimizing() || may_reoptimize())) { | |
| 1084 const Register function_reg = EDI; | 1082 const Register function_reg = EDI; |
| 1085 __ LoadObject(function_reg, function); | 1083 if (can_optimize) { |
| 1084 __ LoadObject(function_reg, function); |
| 1085 } |
| 1086 // Patch point is after the eventually inlined function object. | 1086 // Patch point is after the eventually inlined function object. |
| 1087 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1087 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1088 Isolate::kNoDeoptId, | 1088 Isolate::kNoDeoptId, |
| 1089 0); // No token position. | 1089 0); // No token position. |
| 1090 if (is_optimizing()) { | 1090 if (can_optimize) { |
| 1091 // Reoptimization of an optimized function is triggered by counting in | 1091 // Reoptimization of optimized function is triggered by counting in |
| 1092 // IC stubs, but not at the entry of the function. | 1092 // IC stubs, but not at the entry of the function. |
| 1093 if (!is_optimizing()) { |
| 1094 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); |
| 1095 } |
| 1093 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), | 1096 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), |
| 1094 Immediate(FLAG_reoptimization_counter_threshold)); | 1097 Immediate(FLAG_optimization_counter_threshold)); |
| 1095 } else { | 1098 ASSERT(function_reg == EDI); |
| 1096 __ incl(FieldAddress(function_reg, Function::usage_counter_offset())); | 1099 __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel()); |
| 1097 __ cmpl(FieldAddress(function_reg, Function::usage_counter_offset()), | |
| 1098 Immediate(FLAG_optimization_counter_threshold)); | |
| 1099 } | 1100 } |
| 1100 ASSERT(function_reg == EDI); | 1101 } else { |
| 1101 __ j(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel()); | |
| 1102 } else if (!flow_graph().IsCompiledForOsr()) { | |
| 1103 AddCurrentDescriptor(PcDescriptors::kEntryPatch, | 1102 AddCurrentDescriptor(PcDescriptors::kEntryPatch, |
| 1104 Isolate::kNoDeoptId, | 1103 Isolate::kNoDeoptId, |
| 1105 0); // No token position. | 1104 0); // No token position. |
| 1106 } | 1105 } |
| 1107 __ Comment("Enter frame"); | 1106 __ Comment("Enter frame"); |
| 1108 if (flow_graph().IsCompiledForOsr()) { | 1107 __ EnterDartFrame(StackSize() * kWordSize); |
| 1109 intptr_t extra_slots = StackSize() | |
| 1110 - flow_graph().num_stack_locals() | |
| 1111 - flow_graph().num_copied_params(); | |
| 1112 ASSERT(extra_slots >= 0); | |
| 1113 __ EnterOsrFrame(extra_slots * kWordSize); | |
| 1114 } else { | |
| 1115 ASSERT(StackSize() >= 0); | |
| 1116 __ EnterDartFrame(StackSize() * kWordSize); | |
| 1117 } | |
| 1118 } | 1108 } |
| 1119 | 1109 |
| 1120 | 1110 |
| 1121 void FlowGraphCompiler::CompileGraph() { | 1111 void FlowGraphCompiler::CompileGraph() { |
| 1122 InitCompiler(); | 1112 InitCompiler(); |
| 1123 if (TryIntrinsify()) { | 1113 if (TryIntrinsify()) { |
| 1124 // Although this intrinsified code will never be patched, it must satisfy | 1114 // Although this intrinsified code will never be patched, it must satisfy |
| 1125 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum | 1115 // CodePatcher::CodeIsPatchable, which verifies that this code has a minimum |
| 1126 // code size. | 1116 // code size. |
| 1127 __ int3(); | 1117 __ int3(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1139 | 1129 |
| 1140 // We check the number of passed arguments when we have to copy them due to | 1130 // We check the number of passed arguments when we have to copy them due to |
| 1141 // the presence of optional parameters. | 1131 // the presence of optional parameters. |
| 1142 // No such checking code is generated if only fixed parameters are declared, | 1132 // No such checking code is generated if only fixed parameters are declared, |
| 1143 // unless we are in debug mode or unless we are compiling a closure. | 1133 // unless we are in debug mode or unless we are compiling a closure. |
| 1144 LocalVariable* saved_args_desc_var = | 1134 LocalVariable* saved_args_desc_var = |
| 1145 parsed_function().GetSavedArgumentsDescriptorVar(); | 1135 parsed_function().GetSavedArgumentsDescriptorVar(); |
| 1146 if (num_copied_params == 0) { | 1136 if (num_copied_params == 0) { |
| 1147 #ifdef DEBUG | 1137 #ifdef DEBUG |
| 1148 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1138 ASSERT(!parsed_function().function().HasOptionalParameters()); |
| 1149 const bool check_arguments = !flow_graph().IsCompiledForOsr(); | 1139 const bool check_arguments = true; |
| 1150 #else | 1140 #else |
| 1151 const bool check_arguments = | 1141 const bool check_arguments = function.IsClosureFunction(); |
| 1152 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); | |
| 1153 #endif | 1142 #endif |
| 1154 if (check_arguments) { | 1143 if (check_arguments) { |
| 1155 __ Comment("Check argument count"); | 1144 __ Comment("Check argument count"); |
| 1156 // Check that exactly num_fixed arguments are passed in. | 1145 // Check that exactly num_fixed arguments are passed in. |
| 1157 Label correct_num_arguments, wrong_num_arguments; | 1146 Label correct_num_arguments, wrong_num_arguments; |
| 1158 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); | 1147 __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset())); |
| 1159 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | 1148 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
| 1160 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); | 1149 __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); |
| 1161 __ cmpl(EAX, | 1150 __ cmpl(EAX, |
| 1162 FieldAddress(EDX, | 1151 FieldAddress(EDX, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1200 __ LeaveFrame(); | 1189 __ LeaveFrame(); |
| 1201 __ ret(); | 1190 __ ret(); |
| 1202 } else { | 1191 } else { |
| 1203 __ Stop("Wrong number of arguments"); | 1192 __ Stop("Wrong number of arguments"); |
| 1204 } | 1193 } |
| 1205 __ Bind(&correct_num_arguments); | 1194 __ Bind(&correct_num_arguments); |
| 1206 } | 1195 } |
| 1207 // The arguments descriptor is never saved in the absence of optional | 1196 // The arguments descriptor is never saved in the absence of optional |
| 1208 // parameters, since any argument definition test would always yield true. | 1197 // parameters, since any argument definition test would always yield true. |
| 1209 ASSERT(saved_args_desc_var == NULL); | 1198 ASSERT(saved_args_desc_var == NULL); |
| 1210 } else if (!flow_graph().IsCompiledForOsr()) { | 1199 } else { |
| 1211 if (saved_args_desc_var != NULL) { | 1200 if (saved_args_desc_var != NULL) { |
| 1212 __ Comment("Save arguments descriptor"); | 1201 __ Comment("Save arguments descriptor"); |
| 1213 const Register kArgumentsDescriptorReg = EDX; | 1202 const Register kArgumentsDescriptorReg = EDX; |
| 1214 // The saved_args_desc_var is allocated one slot before the first local. | 1203 // The saved_args_desc_var is allocated one slot before the first local. |
| 1215 const intptr_t slot = parsed_function().first_stack_local_index() + 1; | 1204 const intptr_t slot = parsed_function().first_stack_local_index() + 1; |
| 1216 // If the saved_args_desc_var is captured, it is first moved to the stack | 1205 // If the saved_args_desc_var is captured, it is first moved to the stack |
| 1217 // and later to the context, once the context is allocated. | 1206 // and later to the context, once the context is allocated. |
| 1218 ASSERT(saved_args_desc_var->is_captured() || | 1207 ASSERT(saved_args_desc_var->is_captured() || |
| 1219 (saved_args_desc_var->index() == slot)); | 1208 (saved_args_desc_var->index() == slot)); |
| 1220 __ movl(Address(EBP, slot * kWordSize), kArgumentsDescriptorReg); | 1209 __ movl(Address(EBP, slot * kWordSize), kArgumentsDescriptorReg); |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1925 __ movups(reg, Address(ESP, 0)); | 1914 __ movups(reg, Address(ESP, 0)); |
| 1926 __ addl(ESP, Immediate(kFpuRegisterSize)); | 1915 __ addl(ESP, Immediate(kFpuRegisterSize)); |
| 1927 } | 1916 } |
| 1928 | 1917 |
| 1929 | 1918 |
| 1930 #undef __ | 1919 #undef __ |
| 1931 | 1920 |
| 1932 } // namespace dart | 1921 } // namespace dart |
| 1933 | 1922 |
| 1934 #endif // defined TARGET_ARCH_IA32 | 1923 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |