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

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

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

Powered by Google App Engine
This is Rietveld 408576698