| 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_index_table.h" | 10 #include "vm/code_index_table.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 116 TIMERSCOPE(time_compilation); | 116 TIMERSCOPE(time_compilation); |
| 117 ParsedFunction parsed_function(function); | 117 ParsedFunction parsed_function(function); |
| 118 const char* function_fullname = function.ToFullyQualifiedCString(); | 118 const char* function_fullname = function.ToFullyQualifiedCString(); |
| 119 if (FLAG_trace_compiler) { | 119 if (FLAG_trace_compiler) { |
| 120 OS::Print("Compiling %sfunction: '%s' @ token %d\n", | 120 OS::Print("Compiling %sfunction: '%s' @ token %d\n", |
| 121 (optimized ? "optimized " : ""), | 121 (optimized ? "optimized " : ""), |
| 122 function_fullname, | 122 function_fullname, |
| 123 function.token_index()); | 123 function.token_index()); |
| 124 } | 124 } |
| 125 Parser::ParseFunction(&parsed_function); | 125 Parser::ParseFunction(&parsed_function); |
| 126 |
| 127 CodeIndexTable* code_index_table = isolate->code_index_table(); |
| 128 ASSERT(code_index_table != NULL); |
| 129 int code_size = -1; // Assembled code size needed if --disassemble. |
| 130 bool is_compiled = false; |
| 126 if (FLAG_use_new_compiler) { | 131 if (FLAG_use_new_compiler) { |
| 127 ASSERT(!optimized); | 132 ASSERT(!optimized); |
| 128 LongJump* old_base = isolate->long_jump_base(); | 133 LongJump* old_base = isolate->long_jump_base(); |
| 129 LongJump bailout_jump; | 134 LongJump bailout_jump; |
| 130 isolate->set_long_jump_base(&bailout_jump); | 135 isolate->set_long_jump_base(&bailout_jump); |
| 131 if (setjmp(*bailout_jump.Set()) == 0) { | 136 if (setjmp(*bailout_jump.Set()) == 0) { |
| 132 FlowGraphBuilder graph_builder(parsed_function); | 137 FlowGraphBuilder graph_builder(parsed_function); |
| 133 graph_builder.BuildGraph(); | 138 graph_builder.BuildGraph(); |
| 134 | 139 |
| 135 // Try to compile on x64 (only for now). | |
| 136 #ifdef TARGET_ARCH_X64 | |
| 137 // TODO(kmillikin): Implement or stub out class FlowGraphCompiler | |
| 138 // for other architectures and remove the unsightly ifdef. | |
| 139 Assembler assembler; | 140 Assembler assembler; |
| 140 FlowGraphCompiler graph_compiler(&assembler, | 141 FlowGraphCompiler graph_compiler(&assembler, |
| 141 parsed_function, | 142 parsed_function, |
| 142 graph_builder.blocks()); | 143 graph_builder.blocks()); |
| 143 graph_compiler.CompileGraph(); | 144 graph_compiler.CompileGraph(); |
| 144 #endif | 145 const Code& code = |
| 145 | 146 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); |
| 147 code.set_is_optimized(false); |
| 148 graph_compiler.FinalizePcDescriptors(code); |
| 149 graph_compiler.FinalizeVarDescriptors(code); |
| 150 graph_compiler.FinalizeExceptionHandlers(code); |
| 151 function.set_unoptimized_code(code); |
| 152 function.SetCode(code); |
| 153 ASSERT(CodePatcher::CodeIsPatchable(code)); |
| 154 code_index_table->AddFunction(function); |
| 155 is_compiled = true; |
| 156 code_size = assembler.CodeSize(); |
| 146 } else { | 157 } else { |
| 147 // We bailed out. | 158 // We bailed out. |
| 148 Error& bailout_error = Error::Handle( | 159 Error& bailout_error = Error::Handle( |
| 149 isolate->object_store()->sticky_error()); | 160 isolate->object_store()->sticky_error()); |
| 150 isolate->object_store()->clear_sticky_error(); | 161 isolate->object_store()->clear_sticky_error(); |
| 151 if (FLAG_trace_bailout) { | 162 if (FLAG_trace_bailout) { |
| 152 OS::Print("%s\n", bailout_error.ToErrorCString()); | 163 OS::Print("%s\n", bailout_error.ToErrorCString()); |
| 153 } | 164 } |
| 154 } | 165 } |
| 155 isolate->set_long_jump_base(old_base); | 166 isolate->set_long_jump_base(old_base); |
| 156 // Currently, always fails and falls through to the old compiler. | |
| 157 } | 167 } |
| 158 CodeIndexTable* code_index_table = isolate->code_index_table(); | 168 |
| 159 ASSERT(code_index_table != NULL); | 169 if (!is_compiled) { |
| 160 Assembler assembler; | 170 Assembler assembler; |
| 161 if (optimized) { | 171 if (optimized) { |
| 162 // Transition to optimized code only from unoptimized code ... for now. | 172 // Transition to optimized code only from unoptimized code ... |
| 163 ASSERT(function.HasCode()); | 173 // for now. |
| 164 ASSERT(!Code::Handle(function.code()).is_optimized()); | 174 ASSERT(function.HasCode()); |
| 165 // Do not use type feedback to optimize a function that was deoptimized. | 175 ASSERT(!Code::Handle(function.code()).is_optimized()); |
| 166 if (parsed_function.function().deoptimization_counter() < | 176 // Do not use type feedback to optimize a function that was |
| 167 FLAG_deoptimization_counter_threshold) { | 177 // deoptimized. |
| 168 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), | 178 if (parsed_function.function().deoptimization_counter() < |
| 169 parsed_function.node_sequence()); | 179 FLAG_deoptimization_counter_threshold) { |
| 170 } | 180 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), |
| 171 OptimizingCodeGenerator code_gen(&assembler, parsed_function); | 181 parsed_function.node_sequence()); |
| 172 code_gen.GenerateCode(); | 182 } |
| 173 Code& code = Code::Handle( | 183 OptimizingCodeGenerator code_gen(&assembler, parsed_function); |
| 174 Code::FinalizeCode(function_fullname, &assembler)); | |
| 175 code.set_is_optimized(true); | |
| 176 code_gen.FinalizePcDescriptors(code); | |
| 177 code_gen.FinalizeExceptionHandlers(code); | |
| 178 function.SetCode(code); | |
| 179 code_index_table->AddFunction(function); | |
| 180 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); | |
| 181 if (FLAG_trace_compiler) { | |
| 182 OS::Print("--> patching entry 0x%x\n", | |
| 183 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
| 184 } | |
| 185 } else { | |
| 186 // Unoptimized code. | |
| 187 if (Code::Handle(function.unoptimized_code()).IsNull()) { | |
| 188 ASSERT(Code::Handle(function.code()).IsNull()); | |
| 189 // Compiling first time. | |
| 190 CodeGenerator code_gen(&assembler, parsed_function); | |
| 191 code_gen.GenerateCode(); | 184 code_gen.GenerateCode(); |
| 192 const Code& code = | 185 Code& code = Code::Handle( |
| 193 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | 186 Code::FinalizeCode(function_fullname, &assembler)); |
| 194 code.set_is_optimized(false); | 187 code.set_is_optimized(true); |
| 195 code_gen.FinalizePcDescriptors(code); | 188 code_gen.FinalizePcDescriptors(code); |
| 196 code_gen.FinalizeVarDescriptors(code); | |
| 197 code_gen.FinalizeExceptionHandlers(code); | 189 code_gen.FinalizeExceptionHandlers(code); |
| 198 function.set_unoptimized_code(code); | |
| 199 function.SetCode(code); | 190 function.SetCode(code); |
| 200 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
| 201 code_index_table->AddFunction(function); | 191 code_index_table->AddFunction(function); |
| 202 } else { | 192 CodePatcher::PatchEntry(Code::Handle(function.unoptimized_code())); |
| 203 // Disable optimized code. | |
| 204 const Code& optimized_code = Code::Handle(function.code()); | |
| 205 ASSERT(optimized_code.is_optimized()); | |
| 206 CodePatcher::PatchEntry(Code::Handle(function.code())); | |
| 207 if (FLAG_trace_compiler) { | 193 if (FLAG_trace_compiler) { |
| 208 OS::Print("--> patching entry 0x%x\n", | 194 OS::Print("--> patching entry 0x%x\n", |
| 209 Code::Handle(function.unoptimized_code()).EntryPoint()); | 195 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 210 } | 196 } |
| 211 // Use previously compiled code. | 197 } else { |
| 212 function.SetCode(Code::Handle(function.unoptimized_code())); | 198 // Unoptimized code. |
| 213 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | 199 if (Code::Handle(function.unoptimized_code()).IsNull()) { |
| 214 if (FLAG_trace_compiler) { | 200 ASSERT(Code::Handle(function.code()).IsNull()); |
| 215 OS::Print("--> restoring entry at 0x%x\n", | 201 // Compiling first time. |
| 216 Code::Handle(function.unoptimized_code()).EntryPoint()); | 202 CodeGenerator code_gen(&assembler, parsed_function); |
| 203 code_gen.GenerateCode(); |
| 204 const Code& code = |
| 205 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); |
| 206 code.set_is_optimized(false); |
| 207 code_gen.FinalizePcDescriptors(code); |
| 208 code_gen.FinalizeVarDescriptors(code); |
| 209 code_gen.FinalizeExceptionHandlers(code); |
| 210 function.set_unoptimized_code(code); |
| 211 function.SetCode(code); |
| 212 ASSERT(CodePatcher::CodeIsPatchable(code)); |
| 213 code_index_table->AddFunction(function); |
| 214 } else { |
| 215 // Disable optimized code. |
| 216 const Code& optimized_code = Code::Handle(function.code()); |
| 217 ASSERT(optimized_code.is_optimized()); |
| 218 CodePatcher::PatchEntry(Code::Handle(function.code())); |
| 219 if (FLAG_trace_compiler) { |
| 220 OS::Print("--> patching entry 0x%x\n", |
| 221 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 222 } |
| 223 // Use previously compiled code. |
| 224 function.SetCode(Code::Handle(function.unoptimized_code())); |
| 225 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); |
| 226 if (FLAG_trace_compiler) { |
| 227 OS::Print("--> restoring entry at 0x%x\n", |
| 228 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 229 } |
| 217 } | 230 } |
| 218 } | 231 } |
| 232 code_size = assembler.CodeSize(); |
| 219 } | 233 } |
| 220 if (FLAG_trace_compiler) { | 234 if (FLAG_trace_compiler) { |
| 221 OS::Print("--> '%s' entry: 0x%x\n", | 235 OS::Print("--> '%s' entry: 0x%x\n", |
| 222 function_fullname, Code::Handle(function.code()).EntryPoint()); | 236 function_fullname, Code::Handle(function.code()).EntryPoint()); |
| 223 } | 237 } |
| 224 if (FLAG_disassemble) { | 238 if (FLAG_disassemble) { |
| 225 OS::Print("Code for %sfunction '%s' {\n", | 239 OS::Print("Code for %sfunction '%s' {\n", |
| 226 optimized ? "optimized " : "", function_fullname); | 240 optimized ? "optimized " : "", function_fullname); |
| 227 const Code& code = Code::Handle(function.code()); | 241 const Code& code = Code::Handle(function.code()); |
| 228 const Instructions& instructions = | 242 const Instructions& instructions = |
| 229 Instructions::Handle(code.instructions()); | 243 Instructions::Handle(code.instructions()); |
| 230 uword start = instructions.EntryPoint(); | 244 uword start = instructions.EntryPoint(); |
| 231 Disassembler::Disassemble(start, start + assembler.CodeSize()); | 245 Disassembler::Disassemble(start, start + code_size); |
| 232 OS::Print("}\n"); | 246 OS::Print("}\n"); |
| 233 OS::Print("Pointer offsets for function: {\n"); | 247 OS::Print("Pointer offsets for function: {\n"); |
| 234 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { | 248 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { |
| 235 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | 249 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
| 236 Object& obj = Object::Handle(); | 250 Object& obj = Object::Handle(); |
| 237 obj = *reinterpret_cast<RawObject**>(addr); | 251 obj = *reinterpret_cast<RawObject**>(addr); |
| 238 OS::Print(" %d : 0x%x '%s'\n", | 252 OS::Print(" %d : 0x%x '%s'\n", |
| 239 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 253 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
| 240 } | 254 } |
| 241 OS::Print("}\n"); | 255 OS::Print("}\n"); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 } else { | 389 } else { |
| 376 result = isolate->object_store()->sticky_error(); | 390 result = isolate->object_store()->sticky_error(); |
| 377 isolate->object_store()->clear_sticky_error(); | 391 isolate->object_store()->clear_sticky_error(); |
| 378 } | 392 } |
| 379 isolate->set_long_jump_base(base); | 393 isolate->set_long_jump_base(base); |
| 380 return result.raw(); | 394 return result.raw(); |
| 381 } | 395 } |
| 382 | 396 |
| 383 | 397 |
| 384 } // namespace dart | 398 } // namespace dart |
| OLD | NEW |