| 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" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/debugger.h" | 12 #include "vm/debugger.h" |
| 13 #include "vm/disassembler.h" | 13 #include "vm/disassembler.h" |
| 14 #include "vm/exceptions.h" | 14 #include "vm/exceptions.h" |
| 15 #include "vm/flags.h" | 15 #include "vm/flags.h" |
| 16 #include "vm/flow_graph_allocator.h" | 16 #include "vm/flow_graph_allocator.h" |
| 17 #include "vm/flow_graph_builder.h" | 17 #include "vm/flow_graph_builder.h" |
| 18 #include "vm/flow_graph_compiler.h" | 18 #include "vm/flow_graph_compiler.h" |
| 19 #include "vm/flow_graph_optimizer.h" | 19 #include "vm/flow_graph_optimizer.h" |
| 20 #include "vm/longjump.h" | 20 #include "vm/longjump.h" |
| 21 #include "vm/object.h" | 21 #include "vm/object.h" |
| 22 #include "vm/object_store.h" | 22 #include "vm/object_store.h" |
| 23 #include "vm/opt_code_generator.h" | |
| 24 #include "vm/os.h" | 23 #include "vm/os.h" |
| 25 #include "vm/parser.h" | 24 #include "vm/parser.h" |
| 26 #include "vm/scanner.h" | 25 #include "vm/scanner.h" |
| 27 #include "vm/timer.h" | 26 #include "vm/timer.h" |
| 28 | 27 |
| 29 namespace dart { | 28 namespace dart { |
| 30 | 29 |
| 31 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); | 30 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); |
| 32 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 31 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
| 33 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, | 32 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, |
| 34 "How many times we allow deoptimization before we disallow" | 33 "How many times we allow deoptimization before we disallow" |
| 35 " certain optimizations"); | 34 " certain optimizations"); |
| 36 DEFINE_FLAG(bool, use_new_compiler, true, "Use the new compiler backend."); | 35 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
| 37 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from new compiler."); | |
| 38 DECLARE_FLAG(bool, use_ssa); | 36 DECLARE_FLAG(bool, use_ssa); |
| 39 | 37 |
| 40 | 38 |
| 41 // Compile a function. Should call only if the function has not been compiled. | 39 // Compile a function. Should call only if the function has not been compiled. |
| 42 // Arg0: function object. | 40 // Arg0: function object. |
| 43 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 41 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
| 44 ASSERT(arguments.Count() == kCompileFunctionRuntimeEntry.argument_count()); | 42 ASSERT(arguments.Count() == kCompileFunctionRuntimeEntry.argument_count()); |
| 45 const Function& function = Function::CheckedHandle(arguments.At(0)); | 43 const Function& function = Function::CheckedHandle(arguments.At(0)); |
| 46 ASSERT(!function.HasCode()); | 44 ASSERT(!function.HasCode()); |
| 47 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 45 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 48 if (!error.IsNull()) { | 46 if (!error.IsNull()) { |
| 49 Exceptions::PropagateError(error); | 47 Exceptions::PropagateError(error); |
| 50 } | 48 } |
| 51 } | 49 } |
| 52 | 50 |
| 53 | 51 |
| 54 // Extracts IC data associated with a node id. | |
| 55 // TODO(srdjan): Check performance impact of node id search loop. | |
| 56 static void ExtractTypeFeedback(const Code& code, | |
| 57 SequenceNode* sequence_node) { | |
| 58 ASSERT(!code.IsNull() && !code.is_optimized()); | |
| 59 GrowableArray<AstNode*> all_nodes; | |
| 60 sequence_node->CollectAllNodes(&all_nodes); | |
| 61 GrowableArray<intptr_t> node_ids; | |
| 62 const GrowableObjectArray& ic_data_objs = | |
| 63 GrowableObjectArray::Handle(GrowableObjectArray::New()); | |
| 64 code.ExtractIcDataArraysAtCalls(&node_ids, ic_data_objs); | |
| 65 ICData& ic_data_obj = ICData::Handle(); | |
| 66 for (intptr_t i = 0; i < node_ids.length(); i++) { | |
| 67 intptr_t node_id = node_ids[i]; | |
| 68 bool found_node = false; | |
| 69 for (intptr_t n = 0; n < all_nodes.length(); n++) { | |
| 70 if (all_nodes[n]->id() == node_id) { | |
| 71 found_node = true; | |
| 72 // Make sure we assign ic data array only once. | |
| 73 ASSERT(all_nodes[n]->ic_data().IsNull()); | |
| 74 ic_data_obj ^= ic_data_objs.At(i); | |
| 75 all_nodes[n]->set_ic_data(ic_data_obj); | |
| 76 } | |
| 77 } | |
| 78 ASSERT(found_node); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 | |
| 83 // Returns an array indexed by computation id, containing the extracted ICData. | 52 // Returns an array indexed by computation id, containing the extracted ICData. |
| 84 static RawArray* ExtractTypeFeedbackArray(const Code& code) { | 53 static RawArray* ExtractTypeFeedbackArray(const Code& code) { |
| 85 ASSERT(!code.IsNull() && !code.is_optimized()); | 54 ASSERT(!code.IsNull() && !code.is_optimized()); |
| 86 GrowableArray<intptr_t> computation_ids; | 55 GrowableArray<intptr_t> computation_ids; |
| 87 const GrowableObjectArray& ic_data_objs = | 56 const GrowableObjectArray& ic_data_objs = |
| 88 GrowableObjectArray::Handle(GrowableObjectArray::New()); | 57 GrowableObjectArray::Handle(GrowableObjectArray::New()); |
| 89 const intptr_t max_id = | 58 const intptr_t max_id = |
| 90 code.ExtractIcDataArraysAtCalls(&computation_ids, ic_data_objs); | 59 code.ExtractIcDataArraysAtCalls(&computation_ids, ic_data_objs); |
| 91 const Array& result = Array::Handle(Array::New(max_id + 1)); | 60 const Array& result = Array::Handle(Array::New(max_id + 1)); |
| 92 for (intptr_t i = 0; i < computation_ids.length(); i++) { | 61 for (intptr_t i = 0; i < computation_ids.length(); i++) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 function.SetCode(Code::Handle(function.unoptimized_code())); | 109 function.SetCode(Code::Handle(function.unoptimized_code())); |
| 141 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | 110 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); |
| 142 if (FLAG_trace_compiler) { | 111 if (FLAG_trace_compiler) { |
| 143 OS::Print("--> restoring entry at 0x%x\n", | 112 OS::Print("--> restoring entry at 0x%x\n", |
| 144 Code::Handle(function.unoptimized_code()).EntryPoint()); | 113 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 145 } | 114 } |
| 146 } | 115 } |
| 147 | 116 |
| 148 | 117 |
| 149 // Return false if bailed out. | 118 // Return false if bailed out. |
| 150 static bool CompileWithNewCompiler( | 119 static bool CompileParsedFunctionHelper( |
| 151 const ParsedFunction& parsed_function, bool optimized) { | 120 const ParsedFunction& parsed_function, bool optimized, bool use_ssa) { |
| 121 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
| 152 bool is_compiled = false; | 122 bool is_compiled = false; |
| 153 Isolate* isolate = Isolate::Current(); | 123 Isolate* isolate = Isolate::Current(); |
| 154 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null. | 124 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null. |
| 155 const intptr_t prev_cid = isolate->computation_id(); | 125 const intptr_t prev_cid = isolate->computation_id(); |
| 156 isolate->set_computation_id(0); | 126 isolate->set_computation_id(0); |
| 157 LongJump* old_base = isolate->long_jump_base(); | 127 LongJump* old_base = isolate->long_jump_base(); |
| 158 LongJump bailout_jump; | 128 LongJump bailout_jump; |
| 159 isolate->set_long_jump_base(&bailout_jump); | 129 isolate->set_long_jump_base(&bailout_jump); |
| 160 if (setjmp(*bailout_jump.Set()) == 0) { | 130 if (setjmp(*bailout_jump.Set()) == 0) { |
| 161 GrowableArray<BlockEntryInstr*> block_order; | 131 GrowableArray<BlockEntryInstr*> block_order; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 176 // deoptimized too often. | 146 // deoptimized too often. |
| 177 if (parsed_function.function().deoptimization_counter() < | 147 if (parsed_function.function().deoptimization_counter() < |
| 178 FLAG_deoptimization_counter_threshold) { | 148 FLAG_deoptimization_counter_threshold) { |
| 179 const Code& unoptimized_code = | 149 const Code& unoptimized_code = |
| 180 Code::Handle(parsed_function.function().unoptimized_code()); | 150 Code::Handle(parsed_function.function().unoptimized_code()); |
| 181 isolate->set_ic_data_array( | 151 isolate->set_ic_data_array( |
| 182 ExtractTypeFeedbackArray(unoptimized_code)); | 152 ExtractTypeFeedbackArray(unoptimized_code)); |
| 183 } | 153 } |
| 184 } | 154 } |
| 185 FlowGraphBuilder graph_builder(parsed_function); | 155 FlowGraphBuilder graph_builder(parsed_function); |
| 186 graph_builder.BuildGraph(optimized); | 156 graph_builder.BuildGraph(optimized, use_ssa); |
| 187 | 157 |
| 188 // The non-optimizing compiler compiles blocks in reverse postorder, | 158 // The non-optimizing compiler compiles blocks in reverse postorder, |
| 189 // because it is a 'natural' order for the human reader of the | 159 // because it is a 'natural' order for the human reader of the |
| 190 // generated code. | 160 // generated code. |
| 191 intptr_t length = graph_builder.postorder_block_entries().length(); | 161 intptr_t length = graph_builder.postorder_block_entries().length(); |
| 192 for (intptr_t i = length - 1; i >= 0; --i) { | 162 for (intptr_t i = length - 1; i >= 0; --i) { |
| 193 block_order.Add(graph_builder.postorder_block_entries()[i]); | 163 block_order.Add(graph_builder.postorder_block_entries()[i]); |
| 194 } | 164 } |
| 195 if (optimized) { | 165 if (optimized) { |
| 196 FlowGraphOptimizer optimizer(block_order); | 166 FlowGraphOptimizer optimizer(block_order); |
| 197 optimizer.ApplyICData(); | 167 optimizer.ApplyICData(); |
| 198 | 168 |
| 199 if (FLAG_use_ssa) { | 169 if (use_ssa) { |
| 200 // Perform register allocation on the SSA graph. | 170 // Perform register allocation on the SSA graph. |
| 201 FlowGraphAllocator allocator(graph_builder.postorder_block_entries(), | 171 FlowGraphAllocator allocator(graph_builder.postorder_block_entries(), |
| 202 graph_builder.current_ssa_temp_index()); | 172 graph_builder.current_ssa_temp_index()); |
| 203 allocator.ResolveConstraints(); | 173 allocator.ResolveConstraints(); |
| 204 allocator.AnalyzeLiveness(); | 174 allocator.AnalyzeLiveness(); |
| 205 | 175 |
| 206 // Temporary bailout until we support code generation from SSA form. | 176 // Temporary bailout until we support code generation from SSA form. |
| 207 graph_builder.Bailout("No SSA code generation support."); | 177 graph_builder.Bailout("No SSA code generation support."); |
| 208 } | 178 } |
| 209 } | 179 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 221 } |
| 252 is_compiled = true; | 222 is_compiled = true; |
| 253 } else { | 223 } else { |
| 254 // We bailed out. | 224 // We bailed out. |
| 255 Error& bailout_error = Error::Handle( | 225 Error& bailout_error = Error::Handle( |
| 256 isolate->object_store()->sticky_error()); | 226 isolate->object_store()->sticky_error()); |
| 257 isolate->object_store()->clear_sticky_error(); | 227 isolate->object_store()->clear_sticky_error(); |
| 258 if (FLAG_trace_bailout) { | 228 if (FLAG_trace_bailout) { |
| 259 OS::Print("%s\n", bailout_error.ToErrorCString()); | 229 OS::Print("%s\n", bailout_error.ToErrorCString()); |
| 260 } | 230 } |
| 231 // We only bail out from generating ssa code. |
| 232 ASSERT(optimized && use_ssa); |
| 261 is_compiled = false; | 233 is_compiled = false; |
| 262 } | 234 } |
| 263 // Reset global isolate state. | 235 // Reset global isolate state. |
| 264 isolate->set_ic_data_array(Array::null()); | 236 isolate->set_ic_data_array(Array::null()); |
| 265 isolate->set_long_jump_base(old_base); | 237 isolate->set_long_jump_base(old_base); |
| 266 isolate->set_computation_id(prev_cid); | 238 isolate->set_computation_id(prev_cid); |
| 267 return is_compiled; | 239 return is_compiled; |
| 268 } | 240 } |
| 269 | 241 |
| 270 | 242 |
| 271 static void CompileWithOldCompiler( | |
| 272 const ParsedFunction& parsed_function, bool optimized) { | |
| 273 const Function& function = parsed_function.function(); | |
| 274 Assembler assembler; | |
| 275 if (optimized) { | |
| 276 // Transition to optimized code only from unoptimized code ... | |
| 277 // for now. | |
| 278 ASSERT(function.HasCode()); | |
| 279 ASSERT(!function.HasOptimizedCode()); | |
| 280 // Do not use type feedback to optimize a function that was | |
| 281 // deoptimized too often. | |
| 282 if (parsed_function.function().deoptimization_counter() < | |
| 283 FLAG_deoptimization_counter_threshold) { | |
| 284 TimerScope timer(FLAG_compiler_stats, | |
| 285 &CompilerStats::graphbuilder_timer); | |
| 286 ExtractTypeFeedback( | |
| 287 Code::Handle(parsed_function.function().unoptimized_code()), | |
| 288 parsed_function.node_sequence()); | |
| 289 } | |
| 290 OptimizingCodeGenerator code_gen(&assembler, parsed_function); | |
| 291 { | |
| 292 TimerScope timer(FLAG_compiler_stats, | |
| 293 &CompilerStats::graphcompiler_timer); | |
| 294 code_gen.GenerateCode(); | |
| 295 } | |
| 296 { | |
| 297 TimerScope timer(FLAG_compiler_stats, | |
| 298 &CompilerStats::codefinalizer_timer); | |
| 299 Code& code = Code::Handle(Code::FinalizeCode(function, &assembler)); | |
| 300 code.set_is_optimized(true); | |
| 301 code_gen.FinalizePcDescriptors(code); | |
| 302 code_gen.FinalizeStackmaps(code); | |
| 303 code_gen.FinalizeExceptionHandlers(code); | |
| 304 code_gen.FinalizeComments(code); | |
| 305 function.SetCode(code); | |
| 306 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | |
| 307 } | |
| 308 if (FLAG_trace_compiler) { | |
| 309 OS::Print("--> patching entry 0x%x\n", | |
| 310 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
| 311 } | |
| 312 } else { | |
| 313 // Compile unoptimized code. | |
| 314 ASSERT(!function.HasCode()); | |
| 315 // Compiling first time. | |
| 316 CodeGenerator code_gen(&assembler, parsed_function); | |
| 317 { | |
| 318 TimerScope timer(FLAG_compiler_stats, | |
| 319 &CompilerStats::graphcompiler_timer); | |
| 320 code_gen.GenerateCode(); | |
| 321 } | |
| 322 { | |
| 323 TimerScope timer(FLAG_compiler_stats, | |
| 324 &CompilerStats::codefinalizer_timer); | |
| 325 const Code& code = Code::Handle(Code::FinalizeCode(function, &assembler)); | |
| 326 code.set_is_optimized(false); | |
| 327 code_gen.FinalizePcDescriptors(code); | |
| 328 code_gen.FinalizeStackmaps(code); | |
| 329 code_gen.FinalizeVarDescriptors(code); | |
| 330 code_gen.FinalizeExceptionHandlers(code); | |
| 331 code_gen.FinalizeComments(code); | |
| 332 function.set_unoptimized_code(code); | |
| 333 function.SetCode(code); | |
| 334 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
| 335 } | |
| 336 } | |
| 337 } | |
| 338 | |
| 339 static void CompileParsedFunctionHelper( | |
| 340 const ParsedFunction& parsed_function, bool optimized) { | |
| 341 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | |
| 342 bool is_compiled = false; | |
| 343 // TODO(srdjan): Remove once the old compiler has been ripped out. | |
| 344 #if defined(TARGET_ARCH_X64) | |
| 345 const bool use_new_compiler = true; | |
| 346 #else | |
| 347 const bool use_new_compiler = FLAG_use_new_compiler; | |
| 348 #endif | |
| 349 if (use_new_compiler) { | |
| 350 is_compiled = CompileWithNewCompiler(parsed_function, optimized); | |
| 351 if (!is_compiled && optimized) { | |
| 352 // When bailing out from the optimizing compiler, mark function as | |
| 353 // non-optimizable and return. | |
| 354 parsed_function.function().set_is_optimizable(false); | |
| 355 return; | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 if (!is_compiled) { | |
| 360 CompileWithOldCompiler(parsed_function, optimized); | |
| 361 } | |
| 362 } | |
| 363 | |
| 364 | |
| 365 static RawError* CompileFunctionHelper(const Function& function, | 243 static RawError* CompileFunctionHelper(const Function& function, |
| 366 bool optimized) { | 244 bool optimized) { |
| 367 Isolate* isolate = Isolate::Current(); | 245 Isolate* isolate = Isolate::Current(); |
| 368 LongJump* base = isolate->long_jump_base(); | 246 LongJump* base = isolate->long_jump_base(); |
| 369 LongJump jump; | 247 LongJump jump; |
| 370 isolate->set_long_jump_base(&jump); | 248 isolate->set_long_jump_base(&jump); |
| 371 // Skips parsing if we need to only install unoptimized code. | 249 // Skips parsing if we need to only install unoptimized code. |
| 372 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { | 250 if (!optimized && !Code::Handle(function.unoptimized_code()).IsNull()) { |
| 373 InstallUnoptimizedCode(function); | 251 InstallUnoptimizedCode(function); |
| 374 isolate->set_long_jump_base(base); | 252 isolate->set_long_jump_base(base); |
| 375 return Error::null(); | 253 return Error::null(); |
| 376 } | 254 } |
| 377 if (setjmp(*jump.Set()) == 0) { | 255 if (setjmp(*jump.Set()) == 0) { |
| 378 TIMERSCOPE(time_compilation); | 256 TIMERSCOPE(time_compilation); |
| 379 ParsedFunction parsed_function(function); | 257 ParsedFunction parsed_function(function); |
| 380 if (FLAG_trace_compiler) { | 258 if (FLAG_trace_compiler) { |
| 381 OS::Print("Compiling %sfunction: '%s' @ token %d\n", | 259 OS::Print("Compiling %sfunction: '%s' @ token %d\n", |
| 382 (optimized ? "optimized " : ""), | 260 (optimized ? "optimized " : ""), |
| 383 function.ToFullyQualifiedCString(), | 261 function.ToFullyQualifiedCString(), |
| 384 function.token_pos()); | 262 function.token_pos()); |
| 385 } | 263 } |
| 386 Parser::ParseFunction(&parsed_function); | 264 Parser::ParseFunction(&parsed_function); |
| 387 parsed_function.AllocateVariables(); | 265 parsed_function.AllocateVariables(); |
| 388 | 266 |
| 389 CompileParsedFunctionHelper(parsed_function, optimized); | 267 if (!CompileParsedFunctionHelper(parsed_function, |
| 268 optimized, |
| 269 FLAG_use_ssa)) { |
| 270 // Compile again using non-ssa code generation. |
| 271 CompileParsedFunctionHelper(parsed_function, optimized, false); |
| 272 } |
| 390 | 273 |
| 391 if (FLAG_trace_compiler) { | 274 if (FLAG_trace_compiler) { |
| 392 OS::Print("--> '%s' entry: 0x%x\n", | 275 OS::Print("--> '%s' entry: 0x%x\n", |
| 393 function.ToFullyQualifiedCString(), | 276 function.ToFullyQualifiedCString(), |
| 394 Code::Handle(function.CurrentCode()).EntryPoint()); | 277 Code::Handle(function.CurrentCode()).EntryPoint()); |
| 395 } | 278 } |
| 396 if (Isolate::Current()->debugger()->IsActive()) { | 279 if (Isolate::Current()->debugger()->IsActive()) { |
| 397 Isolate::Current()->debugger()->NotifyCompilation(function); | 280 Isolate::Current()->debugger()->NotifyCompilation(function); |
| 398 } | 281 } |
| 399 if (FLAG_disassemble) { | 282 if (FLAG_disassemble) { |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 } | 373 } |
| 491 | 374 |
| 492 | 375 |
| 493 RawError* Compiler::CompileParsedFunction( | 376 RawError* Compiler::CompileParsedFunction( |
| 494 const ParsedFunction& parsed_function) { | 377 const ParsedFunction& parsed_function) { |
| 495 Isolate* isolate = Isolate::Current(); | 378 Isolate* isolate = Isolate::Current(); |
| 496 LongJump* base = isolate->long_jump_base(); | 379 LongJump* base = isolate->long_jump_base(); |
| 497 LongJump jump; | 380 LongJump jump; |
| 498 isolate->set_long_jump_base(&jump); | 381 isolate->set_long_jump_base(&jump); |
| 499 if (setjmp(*jump.Set()) == 0) { | 382 if (setjmp(*jump.Set()) == 0) { |
| 500 CompileParsedFunctionHelper(parsed_function, false); // Non-optimized. | 383 // Non-optimized, non-ssa code generator. |
| 384 CompileParsedFunctionHelper(parsed_function, false, false); |
| 501 isolate->set_long_jump_base(base); | 385 isolate->set_long_jump_base(base); |
| 502 return Error::null(); | 386 return Error::null(); |
| 503 } else { | 387 } else { |
| 504 Error& error = Error::Handle(); | 388 Error& error = Error::Handle(); |
| 505 // We got an error during compilation. | 389 // We got an error during compilation. |
| 506 error = isolate->object_store()->sticky_error(); | 390 error = isolate->object_store()->sticky_error(); |
| 507 isolate->object_store()->clear_sticky_error(); | 391 isolate->object_store()->clear_sticky_error(); |
| 508 isolate->set_long_jump_base(base); | 392 isolate->set_long_jump_base(base); |
| 509 return error.raw(); | 393 return error.raw(); |
| 510 } | 394 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 // would compile func automatically. We are checking fewer invariants | 448 // would compile func automatically. We are checking fewer invariants |
| 565 // here. | 449 // here. |
| 566 ParsedFunction parsed_function(func); | 450 ParsedFunction parsed_function(func); |
| 567 parsed_function.SetNodeSequence(fragment); | 451 parsed_function.SetNodeSequence(fragment); |
| 568 parsed_function.set_default_parameter_values(Array::Handle()); | 452 parsed_function.set_default_parameter_values(Array::Handle()); |
| 569 parsed_function.set_expression_temp_var( | 453 parsed_function.set_expression_temp_var( |
| 570 ParsedFunction::CreateExpressionTempVar(0)); | 454 ParsedFunction::CreateExpressionTempVar(0)); |
| 571 fragment->scope()->AddVariable(parsed_function.expression_temp_var()); | 455 fragment->scope()->AddVariable(parsed_function.expression_temp_var()); |
| 572 parsed_function.AllocateVariables(); | 456 parsed_function.AllocateVariables(); |
| 573 | 457 |
| 574 CompileParsedFunctionHelper(parsed_function, false); // Non-optimized. | 458 // Non-optimized, non-ssa code generator. |
| 459 CompileParsedFunctionHelper(parsed_function, false, false); |
| 575 | 460 |
| 576 GrowableArray<const Object*> arguments; // no arguments. | 461 GrowableArray<const Object*> arguments; // no arguments. |
| 577 const Array& kNoArgumentNames = Array::Handle(); | 462 const Array& kNoArgumentNames = Array::Handle(); |
| 578 Object& result = Object::Handle(); | 463 Object& result = Object::Handle(); |
| 579 result = DartEntry::InvokeStatic(func, | 464 result = DartEntry::InvokeStatic(func, |
| 580 arguments, | 465 arguments, |
| 581 kNoArgumentNames); | 466 kNoArgumentNames); |
| 582 isolate->set_long_jump_base(base); | 467 isolate->set_long_jump_base(base); |
| 583 return result.raw(); | 468 return result.raw(); |
| 584 } else { | 469 } else { |
| 585 Object& result = Object::Handle(); | 470 Object& result = Object::Handle(); |
| 586 result = isolate->object_store()->sticky_error(); | 471 result = isolate->object_store()->sticky_error(); |
| 587 isolate->object_store()->clear_sticky_error(); | 472 isolate->object_store()->clear_sticky_error(); |
| 588 isolate->set_long_jump_base(base); | 473 isolate->set_long_jump_base(base); |
| 589 return result.raw(); | 474 return result.raw(); |
| 590 } | 475 } |
| 591 UNREACHABLE(); | 476 UNREACHABLE(); |
| 592 return Object::null(); | 477 return Object::null(); |
| 593 } | 478 } |
| 594 | 479 |
| 595 | 480 |
| 596 } // namespace dart | 481 } // namespace dart |
| OLD | NEW |