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, |
188 isolate); | |
189 const Function& function = parsed_function.function(); | |
183 const Code& code = | 190 const Code& code = |
184 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | 191 Code::Handle(Code::FinalizeCodeForFunction(function, &assembler)); |
siva
2012/05/08 22:08:45
Why not have FinalizeCode and FinalizeStubCode one
| |
185 code.set_is_optimized(optimized); | 192 code.set_is_optimized(optimized); |
186 graph_compiler.FinalizePcDescriptors(code); | 193 graph_compiler.FinalizePcDescriptors(code); |
187 graph_compiler.FinalizeStackmaps(code); | 194 graph_compiler.FinalizeStackmaps(code); |
188 graph_compiler.FinalizeVarDescriptors(code); | 195 graph_compiler.FinalizeVarDescriptors(code); |
189 graph_compiler.FinalizeExceptionHandlers(code); | 196 graph_compiler.FinalizeExceptionHandlers(code); |
190 if (optimized) { | 197 if (optimized) { |
191 function.SetCode(code); | 198 function.SetCode(code); |
192 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | 199 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
193 if (FLAG_trace_compiler) { | 200 if (FLAG_trace_compiler) { |
194 OS::Print("--> patching entry 0x%x\n", | 201 OS::Print("--> patching entry 0x%x\n", |
195 Code::Handle(function.unoptimized_code()).EntryPoint()); | 202 Code::Handle(function.unoptimized_code()).EntryPoint()); |
196 } | 203 } |
197 } else { | 204 } else { |
198 function.set_unoptimized_code(code); | 205 function.set_unoptimized_code(code); |
199 function.SetCode(code); | 206 function.SetCode(code); |
200 ASSERT(CodePatcher::CodeIsPatchable(code)); | 207 ASSERT(CodePatcher::CodeIsPatchable(code)); |
201 } | 208 } |
202 is_compiled = true; | 209 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 } | 210 } |
212 isolate->set_long_jump_base(old_base); | 211 } else { |
212 // We bailed out. | |
213 Error& bailout_error = Error::Handle( | |
214 isolate->object_store()->sticky_error()); | |
215 isolate->object_store()->clear_sticky_error(); | |
216 if (FLAG_trace_bailout) { | |
217 OS::Print("%s\n", bailout_error.ToErrorCString()); | |
218 } | |
siva
2012/05/08 22:08:45
You may get a compilation error on the build bot b
srdjan
2012/05/08 23:54:32
Done.
| |
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( |
235 Code::FinalizeCode(function_fullname, &assembler)); | 254 Code::FinalizeCodeForFunction(function, &assembler)); |
236 code.set_is_optimized(true); | 255 code.set_is_optimized(true); |
237 code_gen.FinalizePcDescriptors(code); | 256 code_gen.FinalizePcDescriptors(code); |
238 code_gen.FinalizeStackmaps(code); | 257 code_gen.FinalizeStackmaps(code); |
239 code_gen.FinalizeExceptionHandlers(code); | 258 code_gen.FinalizeExceptionHandlers(code); |
240 function.SetCode(code); | 259 function.SetCode(code); |
241 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | 260 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
242 if (FLAG_trace_compiler) { | 261 } |
243 OS::Print("--> patching entry 0x%x\n", | 262 if (FLAG_trace_compiler) { |
244 Code::Handle(function.unoptimized_code()).EntryPoint()); | 263 OS::Print("--> patching entry 0x%x\n", |
245 } | 264 Code::Handle(function.unoptimized_code()).EntryPoint()); |
246 } else { | 265 } |
247 // Compile unoptimized code. | 266 } else { |
248 ASSERT(!function.HasCode()); | 267 // Compile unoptimized code. |
249 // Compiling first time. | 268 ASSERT(!function.HasCode()); |
250 CodeGenerator code_gen(&assembler, parsed_function); | 269 // Compiling first time. |
270 CodeGenerator code_gen(&assembler, parsed_function); | |
271 { | |
272 TimerScope timer(FLAG_compiler_stats, | |
273 &CompilerStats::graphcompiler_timer); | |
251 code_gen.GenerateCode(); | 274 code_gen.GenerateCode(); |
275 } | |
276 { | |
252 TimerScope timer(FLAG_compiler_stats, | 277 TimerScope timer(FLAG_compiler_stats, |
253 &CompilerStats::codefinalizer_timer); | 278 &CompilerStats::codefinalizer_timer); |
254 const Code& code = | 279 const Code& code = |
255 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | 280 Code::Handle(Code::FinalizeCodeForFunction(function, &assembler)); |
256 code.set_is_optimized(false); | 281 code.set_is_optimized(false); |
257 code_gen.FinalizePcDescriptors(code); | 282 code_gen.FinalizePcDescriptors(code); |
258 code_gen.FinalizeStackmaps(code); | 283 code_gen.FinalizeStackmaps(code); |
259 code_gen.FinalizeVarDescriptors(code); | 284 code_gen.FinalizeVarDescriptors(code); |
260 code_gen.FinalizeExceptionHandlers(code); | 285 code_gen.FinalizeExceptionHandlers(code); |
261 function.set_unoptimized_code(code); | 286 function.set_unoptimized_code(code); |
262 function.SetCode(code); | 287 function.SetCode(code); |
263 ASSERT(CodePatcher::CodeIsPatchable(code)); | 288 ASSERT(CodePatcher::CodeIsPatchable(code)); |
264 } | 289 } |
265 } | 290 } |
266 } | 291 } |
267 | 292 |
293 static void CompileParsedFunctionHelper( | |
294 const ParsedFunction& parsed_function, bool optimized) { | |
295 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | |
296 bool is_compiled = false; | |
297 // TODO(srdjan): Remove once the old compiler has been ripped out. | |
298 #if defined(TARGET_ARCH_X64) | |
299 const bool use_new_compiler = true; | |
300 #else | |
301 const bool use_new_compiler = FLAG_use_new_compiler; | |
302 #endif | |
303 if (use_new_compiler) { | |
304 is_compiled = CompileWithNewCompiler(parsed_function, optimized); | |
305 } | |
306 | |
307 if (!is_compiled) { | |
308 CompileWithOldCompiler(parsed_function, optimized); | |
309 } | |
310 } | |
311 | |
268 | 312 |
269 static RawError* CompileFunctionHelper(const Function& function, | 313 static RawError* CompileFunctionHelper(const Function& function, |
270 bool optimized) { | 314 bool optimized) { |
271 Isolate* isolate = Isolate::Current(); | 315 Isolate* isolate = Isolate::Current(); |
272 LongJump* base = isolate->long_jump_base(); | 316 LongJump* base = isolate->long_jump_base(); |
273 LongJump jump; | 317 LongJump jump; |
274 isolate->set_long_jump_base(&jump); | 318 isolate->set_long_jump_base(&jump); |
275 // Skips parsing if we need to only install unoptimized code. | 319 // Skips parsing if we need to only install unoptimized code. |
276 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { | 320 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { |
277 InstallUnoptimizedCode(function); | 321 InstallUnoptimizedCode(function); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 isolate->object_store()->clear_sticky_error(); | 510 isolate->object_store()->clear_sticky_error(); |
467 isolate->set_long_jump_base(base); | 511 isolate->set_long_jump_base(base); |
468 return result.raw(); | 512 return result.raw(); |
469 } | 513 } |
470 UNREACHABLE(); | 514 UNREACHABLE(); |
471 return Object::null(); | 515 return Object::null(); |
472 } | 516 } |
473 | 517 |
474 | 518 |
475 } // namespace dart | 519 } // namespace dart |
OLD | NEW |