OLD | NEW |
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/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 // Use previously compiled code. | 124 // Use previously compiled code. |
125 function.SetCode(Code::Handle(function.unoptimized_code())); | 125 function.SetCode(Code::Handle(function.unoptimized_code())); |
126 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | 126 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); |
127 if (FLAG_trace_compiler) { | 127 if (FLAG_trace_compiler) { |
128 OS::Print("--> restoring entry at 0x%x\n", | 128 OS::Print("--> restoring entry at 0x%x\n", |
129 Code::Handle(function.unoptimized_code()).EntryPoint()); | 129 Code::Handle(function.unoptimized_code()).EntryPoint()); |
130 } | 130 } |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 static void CompileParsedFunctionHelper( | 134 // Return false if bailed out. |
| 135 static bool CompileWithNewCompiler( |
135 const ParsedFunction& parsed_function, bool optimized) { | 136 const ParsedFunction& parsed_function, bool optimized) { |
| 137 bool is_compiled = false; |
136 Isolate* isolate = Isolate::Current(); | 138 Isolate* isolate = Isolate::Current(); |
137 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 139 LongJump* old_base = isolate->long_jump_base(); |
138 const Function& function = parsed_function.function(); | 140 LongJump bailout_jump; |
139 const char* function_fullname = function.ToFullyQualifiedCString(); | 141 isolate->set_long_jump_base(&bailout_jump); |
140 bool is_compiled = false; | 142 if (setjmp(*bailout_jump.Set()) == 0) { |
141 // TODO(srdjan): Remove once the old compiler has been ripped out. | 143 GrowableArray<BlockEntryInstr*> block_order; |
142 #if defined(TARGET_ARCH_X64) | 144 // TimerScope needs an isolate to be properly terminated in case of a |
143 const bool use_new_compiler = true; | 145 // LongJump. |
144 #else | 146 { |
145 const bool use_new_compiler = FLAG_use_new_compiler; | 147 TimerScope timer(FLAG_compiler_stats, |
146 #endif | 148 &CompilerStats::graphbuilder_timer, |
147 if (use_new_compiler) { | 149 isolate); |
148 LongJump* old_base = isolate->long_jump_base(); | 150 CompilerStats::graphbuilder_timer.Start(); |
149 LongJump bailout_jump; | |
150 isolate->set_long_jump_base(&bailout_jump); | |
151 if (setjmp(*bailout_jump.Set()) == 0) { | |
152 FlowGraphBuilder graph_builder(parsed_function); | 151 FlowGraphBuilder graph_builder(parsed_function); |
153 graph_builder.BuildGraph(optimized); | 152 graph_builder.BuildGraph(optimized); |
154 | 153 |
155 // The non-optimizing compiler compiles blocks in reverse postorder, | 154 // The non-optimizing compiler compiles blocks in reverse postorder, |
156 // because it is a 'natural' order for the human reader of the | 155 // because it is a 'natural' order for the human reader of the |
157 // generated code. | 156 // generated code. |
158 intptr_t length = graph_builder.postorder_block_entries().length(); | 157 intptr_t length = graph_builder.postorder_block_entries().length(); |
159 GrowableArray<BlockEntryInstr*> block_order(length); | |
160 for (intptr_t i = length - 1; i >= 0; --i) { | 158 for (intptr_t i = length - 1; i >= 0; --i) { |
161 block_order.Add(graph_builder.postorder_block_entries()[i]); | 159 block_order.Add(graph_builder.postorder_block_entries()[i]); |
162 } | 160 } |
163 | 161 |
164 if (optimized) { | 162 if (optimized) { |
165 // Transition to optimized code only from unoptimized code ... | 163 // Transition to optimized code only from unoptimized code ... |
166 // for now. | 164 // for now. |
167 ASSERT(function.HasCode()); | 165 ASSERT(parsed_function.function().HasCode()); |
168 ASSERT(!function.HasOptimizedCode()); | 166 ASSERT(!parsed_function.function().HasOptimizedCode()); |
169 // Do not use type feedback to optimize a function that was | 167 // Do not use type feedback to optimize a function that was |
170 // deoptimized too often. | 168 // deoptimized too often. |
171 if (parsed_function.function().deoptimization_counter() < | 169 if (parsed_function.function().deoptimization_counter() < |
172 FLAG_deoptimization_counter_threshold) { | 170 FLAG_deoptimization_counter_threshold) { |
173 // Extract type feedback etc. | 171 // Extract type feedback etc. |
174 } | 172 } |
175 } | 173 } |
176 Assembler assembler; | 174 } |
177 FlowGraphCompiler graph_compiler(&assembler, parsed_function, | 175 |
178 block_order, optimized); | 176 Assembler assembler; |
| 177 FlowGraphCompiler graph_compiler(&assembler, parsed_function, |
| 178 block_order, optimized); |
| 179 { |
| 180 TimerScope timer(FLAG_compiler_stats, |
| 181 &CompilerStats::graphcompiler_timer, |
| 182 isolate); |
179 graph_compiler.CompileGraph(); | 183 graph_compiler.CompileGraph(); |
180 | 184 } |
| 185 { |
181 TimerScope timer(FLAG_compiler_stats, | 186 TimerScope timer(FLAG_compiler_stats, |
182 &CompilerStats::codefinalizer_timer); | 187 &CompilerStats::codefinalizer_timer, |
183 const Code& code = | 188 isolate); |
184 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | 189 const Function& function = parsed_function.function(); |
| 190 const Code& code = Code::Handle(Code::FinalizeCode(function, &assembler)); |
185 code.set_is_optimized(optimized); | 191 code.set_is_optimized(optimized); |
186 graph_compiler.FinalizePcDescriptors(code); | 192 graph_compiler.FinalizePcDescriptors(code); |
187 graph_compiler.FinalizeStackmaps(code); | 193 graph_compiler.FinalizeStackmaps(code); |
188 graph_compiler.FinalizeVarDescriptors(code); | 194 graph_compiler.FinalizeVarDescriptors(code); |
189 graph_compiler.FinalizeExceptionHandlers(code); | 195 graph_compiler.FinalizeExceptionHandlers(code); |
190 if (optimized) { | 196 if (optimized) { |
191 function.SetCode(code); | 197 function.SetCode(code); |
192 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | 198 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
193 if (FLAG_trace_compiler) { | 199 if (FLAG_trace_compiler) { |
194 OS::Print("--> patching entry 0x%x\n", | 200 OS::Print("--> patching entry 0x%x\n", |
195 Code::Handle(function.unoptimized_code()).EntryPoint()); | 201 Code::Handle(function.unoptimized_code()).EntryPoint()); |
196 } | 202 } |
197 } else { | 203 } else { |
198 function.set_unoptimized_code(code); | 204 function.set_unoptimized_code(code); |
199 function.SetCode(code); | 205 function.SetCode(code); |
200 ASSERT(CodePatcher::CodeIsPatchable(code)); | 206 ASSERT(CodePatcher::CodeIsPatchable(code)); |
201 } | 207 } |
202 is_compiled = true; | |
203 } else { | |
204 // We bailed out. | |
205 Error& bailout_error = Error::Handle( | |
206 isolate->object_store()->sticky_error()); | |
207 isolate->object_store()->clear_sticky_error(); | |
208 if (FLAG_trace_bailout) { | |
209 OS::Print("%s\n", bailout_error.ToErrorCString()); | |
210 } | |
211 } | 208 } |
212 isolate->set_long_jump_base(old_base); | 209 is_compiled = true; |
| 210 } else { |
| 211 // We bailed out. |
| 212 Error& bailout_error = Error::Handle( |
| 213 isolate->object_store()->sticky_error()); |
| 214 isolate->object_store()->clear_sticky_error(); |
| 215 if (FLAG_trace_bailout) { |
| 216 OS::Print("%s\n", bailout_error.ToErrorCString()); |
| 217 } |
| 218 is_compiled = false; |
213 } | 219 } |
| 220 isolate->set_long_jump_base(old_base); |
| 221 return is_compiled; |
| 222 } |
214 | 223 |
215 if (!is_compiled) { | 224 |
216 Assembler assembler; | 225 static void CompileWithOldCompiler( |
217 if (optimized) { | 226 const ParsedFunction& parsed_function, bool optimized) { |
218 // Transition to optimized code only from unoptimized code ... | 227 const Function& function = parsed_function.function(); |
219 // for now. | 228 Assembler assembler; |
220 ASSERT(function.HasCode()); | 229 if (optimized) { |
221 ASSERT(!function.HasOptimizedCode()); | 230 // Transition to optimized code only from unoptimized code ... |
222 // Do not use type feedback to optimize a function that was | 231 // for now. |
223 // deoptimized too often. | 232 ASSERT(function.HasCode()); |
224 if (parsed_function.function().deoptimization_counter() < | 233 ASSERT(!function.HasOptimizedCode()); |
225 FLAG_deoptimization_counter_threshold) { | 234 // Do not use type feedback to optimize a function that was |
226 ExtractTypeFeedback( | 235 // deoptimized too often. |
227 Code::Handle(parsed_function.function().unoptimized_code()), | 236 if (parsed_function.function().deoptimization_counter() < |
228 parsed_function.node_sequence()); | 237 FLAG_deoptimization_counter_threshold) { |
229 } | 238 TimerScope timer(FLAG_compiler_stats, |
230 OptimizingCodeGenerator code_gen(&assembler, parsed_function); | 239 &CompilerStats::graphbuilder_timer); |
| 240 ExtractTypeFeedback( |
| 241 Code::Handle(parsed_function.function().unoptimized_code()), |
| 242 parsed_function.node_sequence()); |
| 243 } |
| 244 OptimizingCodeGenerator code_gen(&assembler, parsed_function); |
| 245 { |
| 246 TimerScope timer(FLAG_compiler_stats, |
| 247 &CompilerStats::graphcompiler_timer); |
231 code_gen.GenerateCode(); | 248 code_gen.GenerateCode(); |
| 249 } |
| 250 { |
232 TimerScope timer(FLAG_compiler_stats, | 251 TimerScope timer(FLAG_compiler_stats, |
233 &CompilerStats::codefinalizer_timer); | 252 &CompilerStats::codefinalizer_timer); |
234 Code& code = Code::Handle( | 253 Code& code = Code::Handle(Code::FinalizeCode(function, &assembler)); |
235 Code::FinalizeCode(function_fullname, &assembler)); | |
236 code.set_is_optimized(true); | 254 code.set_is_optimized(true); |
237 code_gen.FinalizePcDescriptors(code); | 255 code_gen.FinalizePcDescriptors(code); |
238 code_gen.FinalizeStackmaps(code); | 256 code_gen.FinalizeStackmaps(code); |
239 code_gen.FinalizeExceptionHandlers(code); | 257 code_gen.FinalizeExceptionHandlers(code); |
240 function.SetCode(code); | 258 function.SetCode(code); |
241 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | 259 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
242 if (FLAG_trace_compiler) { | 260 } |
243 OS::Print("--> patching entry 0x%x\n", | 261 if (FLAG_trace_compiler) { |
244 Code::Handle(function.unoptimized_code()).EntryPoint()); | 262 OS::Print("--> patching entry 0x%x\n", |
245 } | 263 Code::Handle(function.unoptimized_code()).EntryPoint()); |
246 } else { | 264 } |
247 // Compile unoptimized code. | 265 } else { |
248 ASSERT(!function.HasCode()); | 266 // Compile unoptimized code. |
249 // Compiling first time. | 267 ASSERT(!function.HasCode()); |
250 CodeGenerator code_gen(&assembler, parsed_function); | 268 // Compiling first time. |
| 269 CodeGenerator code_gen(&assembler, parsed_function); |
| 270 { |
| 271 TimerScope timer(FLAG_compiler_stats, |
| 272 &CompilerStats::graphcompiler_timer); |
251 code_gen.GenerateCode(); | 273 code_gen.GenerateCode(); |
| 274 } |
| 275 { |
252 TimerScope timer(FLAG_compiler_stats, | 276 TimerScope timer(FLAG_compiler_stats, |
253 &CompilerStats::codefinalizer_timer); | 277 &CompilerStats::codefinalizer_timer); |
254 const Code& code = | 278 const Code& code = Code::Handle(Code::FinalizeCode(function, &assembler)); |
255 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | |
256 code.set_is_optimized(false); | 279 code.set_is_optimized(false); |
257 code_gen.FinalizePcDescriptors(code); | 280 code_gen.FinalizePcDescriptors(code); |
258 code_gen.FinalizeStackmaps(code); | 281 code_gen.FinalizeStackmaps(code); |
259 code_gen.FinalizeVarDescriptors(code); | 282 code_gen.FinalizeVarDescriptors(code); |
260 code_gen.FinalizeExceptionHandlers(code); | 283 code_gen.FinalizeExceptionHandlers(code); |
261 function.set_unoptimized_code(code); | 284 function.set_unoptimized_code(code); |
262 function.SetCode(code); | 285 function.SetCode(code); |
263 ASSERT(CodePatcher::CodeIsPatchable(code)); | 286 ASSERT(CodePatcher::CodeIsPatchable(code)); |
264 } | 287 } |
265 } | 288 } |
266 } | 289 } |
267 | 290 |
| 291 static void CompileParsedFunctionHelper( |
| 292 const ParsedFunction& parsed_function, bool optimized) { |
| 293 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
| 294 bool is_compiled = false; |
| 295 // TODO(srdjan): Remove once the old compiler has been ripped out. |
| 296 #if defined(TARGET_ARCH_X64) |
| 297 const bool use_new_compiler = true; |
| 298 #else |
| 299 const bool use_new_compiler = FLAG_use_new_compiler; |
| 300 #endif |
| 301 if (use_new_compiler) { |
| 302 is_compiled = CompileWithNewCompiler(parsed_function, optimized); |
| 303 } |
| 304 |
| 305 if (!is_compiled) { |
| 306 CompileWithOldCompiler(parsed_function, optimized); |
| 307 } |
| 308 } |
| 309 |
268 | 310 |
269 static RawError* CompileFunctionHelper(const Function& function, | 311 static RawError* CompileFunctionHelper(const Function& function, |
270 bool optimized) { | 312 bool optimized) { |
271 Isolate* isolate = Isolate::Current(); | 313 Isolate* isolate = Isolate::Current(); |
272 LongJump* base = isolate->long_jump_base(); | 314 LongJump* base = isolate->long_jump_base(); |
273 LongJump jump; | 315 LongJump jump; |
274 isolate->set_long_jump_base(&jump); | 316 isolate->set_long_jump_base(&jump); |
275 // Skips parsing if we need to only install unoptimized code. | 317 // Skips parsing if we need to only install unoptimized code. |
276 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { | 318 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { |
277 InstallUnoptimizedCode(function); | 319 InstallUnoptimizedCode(function); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 isolate->object_store()->clear_sticky_error(); | 508 isolate->object_store()->clear_sticky_error(); |
467 isolate->set_long_jump_base(base); | 509 isolate->set_long_jump_base(base); |
468 return result.raw(); | 510 return result.raw(); |
469 } | 511 } |
470 UNREACHABLE(); | 512 UNREACHABLE(); |
471 return Object::null(); | 513 return Object::null(); |
472 } | 514 } |
473 | 515 |
474 | 516 |
475 } // namespace dart | 517 } // namespace dart |
OLD | NEW |