Chromium Code Reviews| 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. | |
|
srdjan
2012/02/28 00:23:39
Remove code_size, you can get it from Instructions
Kevin Millikin (Google)
2012/02/29 14:24:24
Done.
| |
| 130 bool is_compiled = false; | |
| 126 if (FLAG_use_new_compiler) { | 131 if (FLAG_use_new_compiler) { |
|
srdjan
2012/02/28 00:23:39
FLAG_use_new_compiler && !optimized or ASSERT (!o
| |
| 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). | 140 // Try to compile on x64 (only for now). |
| 136 #ifdef TARGET_ARCH_X64 | 141 #ifdef TARGET_ARCH_X64 |
| 137 // TODO(kmillikin): Implement or stub out class FlowGraphCompiler | 142 // TODO(kmillikin): Implement or stub out class FlowGraphCompiler |
| 138 // for other architectures and remove the unsightly ifdef. | 143 // for other architectures and remove the unsightly ifdef. |
| 139 Assembler assembler; | 144 Assembler assembler; |
| 140 FlowGraphCompiler graph_compiler(&assembler, | 145 FlowGraphCompiler graph_compiler(&assembler, |
| 141 parsed_function, | 146 parsed_function, |
| 142 graph_builder.blocks()); | 147 graph_builder.blocks()); |
| 143 graph_compiler.CompileGraph(); | 148 graph_compiler.CompileGraph(); |
| 149 const Code& code = | |
|
Kevin Millikin (Google)
2012/02/27 15:11:48
As long as the call to CompileGraph can bailout, I
| |
| 150 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | |
| 151 code.set_is_optimized(false); | |
| 152 graph_compiler.FinalizePcDescriptors(code); | |
| 153 graph_compiler.FinalizeVarDescriptors(code); | |
| 154 graph_compiler.FinalizeExceptionHandlers(code); | |
| 155 function.set_unoptimized_code(code); | |
| 156 function.SetCode(code); | |
| 157 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
| 158 code_index_table->AddFunction(function); | |
| 159 is_compiled = true; | |
| 160 code_size = assembler.CodeSize(); | |
| 144 #endif | 161 #endif |
| 145 | 162 |
| 146 } else { | 163 } else { |
| 147 // We bailed out. | 164 // We bailed out. |
| 148 Error& bailout_error = Error::Handle( | 165 Error& bailout_error = Error::Handle( |
| 149 isolate->object_store()->sticky_error()); | 166 isolate->object_store()->sticky_error()); |
| 150 isolate->object_store()->clear_sticky_error(); | 167 isolate->object_store()->clear_sticky_error(); |
| 151 if (FLAG_trace_bailout) { | 168 if (FLAG_trace_bailout) { |
| 152 OS::Print("%s\n", bailout_error.ToErrorCString()); | 169 OS::Print("%s\n", bailout_error.ToErrorCString()); |
| 153 } | 170 } |
| 154 } | 171 } |
| 155 isolate->set_long_jump_base(old_base); | 172 isolate->set_long_jump_base(old_base); |
| 156 // Currently, always fails and falls through to the old compiler. | |
| 157 } | 173 } |
| 158 CodeIndexTable* code_index_table = isolate->code_index_table(); | 174 |
| 159 ASSERT(code_index_table != NULL); | 175 if (!is_compiled) { |
|
srdjan
2012/02/28 00:23:39
This if is too long. A suggestion:
if (optimized
| |
| 160 Assembler assembler; | 176 Assembler assembler; |
| 161 if (optimized) { | 177 if (optimized) { |
| 162 // Transition to optimized code only from unoptimized code ... for now. | 178 // Transition to optimized code only from unoptimized code ... |
| 163 ASSERT(function.HasCode()); | 179 // for now. |
| 164 ASSERT(!Code::Handle(function.code()).is_optimized()); | 180 ASSERT(function.HasCode()); |
| 165 // Do not use type feedback to optimize a function that was deoptimized. | 181 ASSERT(!Code::Handle(function.code()).is_optimized()); |
| 166 if (parsed_function.function().deoptimization_counter() < | 182 // Do not use type feedback to optimize a function that was |
| 167 FLAG_deoptimization_counter_threshold) { | 183 // deoptimized. |
| 168 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), | 184 if (parsed_function.function().deoptimization_counter() < |
| 169 parsed_function.node_sequence()); | 185 FLAG_deoptimization_counter_threshold) { |
| 170 } | 186 ExtractTypeFeedback(Code::Handle(parsed_function.function().code()), |
| 171 OptimizingCodeGenerator code_gen(&assembler, parsed_function); | 187 parsed_function.node_sequence()); |
| 172 code_gen.GenerateCode(); | 188 } |
| 173 Code& code = Code::Handle( | 189 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(); | 190 code_gen.GenerateCode(); |
| 192 const Code& code = | 191 Code& code = Code::Handle( |
| 193 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | 192 Code::FinalizeCode(function_fullname, &assembler)); |
| 194 code.set_is_optimized(false); | 193 code.set_is_optimized(true); |
| 195 code_gen.FinalizePcDescriptors(code); | 194 code_gen.FinalizePcDescriptors(code); |
| 196 code_gen.FinalizeVarDescriptors(code); | |
| 197 code_gen.FinalizeExceptionHandlers(code); | 195 code_gen.FinalizeExceptionHandlers(code); |
| 198 function.set_unoptimized_code(code); | |
| 199 function.SetCode(code); | 196 function.SetCode(code); |
| 200 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
| 201 code_index_table->AddFunction(function); | 197 code_index_table->AddFunction(function); |
| 202 } else { | 198 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) { | 199 if (FLAG_trace_compiler) { |
| 208 OS::Print("--> patching entry 0x%x\n", | 200 OS::Print("--> patching entry 0x%x\n", |
| 209 Code::Handle(function.unoptimized_code()).EntryPoint()); | 201 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 210 } | 202 } |
| 211 // Use previously compiled code. | 203 } else { |
| 212 function.SetCode(Code::Handle(function.unoptimized_code())); | 204 // Unoptimized code. |
| 213 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | 205 if (Code::Handle(function.unoptimized_code()).IsNull()) { |
| 214 if (FLAG_trace_compiler) { | 206 ASSERT(Code::Handle(function.code()).IsNull()); |
| 215 OS::Print("--> restoring entry at 0x%x\n", | 207 // Compiling first time. |
| 216 Code::Handle(function.unoptimized_code()).EntryPoint()); | 208 CodeGenerator code_gen(&assembler, parsed_function); |
| 209 code_gen.GenerateCode(); | |
| 210 const Code& code = | |
| 211 Code::Handle(Code::FinalizeCode(function_fullname, &assembler)); | |
| 212 code.set_is_optimized(false); | |
| 213 code_gen.FinalizePcDescriptors(code); | |
| 214 code_gen.FinalizeVarDescriptors(code); | |
| 215 code_gen.FinalizeExceptionHandlers(code); | |
| 216 function.set_unoptimized_code(code); | |
| 217 function.SetCode(code); | |
| 218 ASSERT(CodePatcher::CodeIsPatchable(code)); | |
| 219 code_index_table->AddFunction(function); | |
| 220 } else { | |
| 221 // Disable optimized code. | |
| 222 const Code& optimized_code = Code::Handle(function.code()); | |
| 223 ASSERT(optimized_code.is_optimized()); | |
| 224 CodePatcher::PatchEntry(Code::Handle(function.code())); | |
| 225 if (FLAG_trace_compiler) { | |
| 226 OS::Print("--> patching entry 0x%x\n", | |
| 227 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
| 228 } | |
| 229 // Use previously compiled code. | |
| 230 function.SetCode(Code::Handle(function.unoptimized_code())); | |
| 231 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | |
| 232 if (FLAG_trace_compiler) { | |
| 233 OS::Print("--> restoring entry at 0x%x\n", | |
| 234 Code::Handle(function.unoptimized_code()).EntryPoint()); | |
| 235 } | |
| 217 } | 236 } |
| 218 } | 237 } |
| 238 code_size = assembler.CodeSize(); | |
| 219 } | 239 } |
| 220 if (FLAG_trace_compiler) { | 240 if (FLAG_trace_compiler) { |
| 221 OS::Print("--> '%s' entry: 0x%x\n", | 241 OS::Print("--> '%s' entry: 0x%x\n", |
| 222 function_fullname, Code::Handle(function.code()).EntryPoint()); | 242 function_fullname, Code::Handle(function.code()).EntryPoint()); |
| 223 } | 243 } |
| 224 if (FLAG_disassemble) { | 244 if (FLAG_disassemble) { |
| 225 OS::Print("Code for %sfunction '%s' {\n", | 245 OS::Print("Code for %sfunction '%s' {\n", |
| 226 optimized ? "optimized " : "", function_fullname); | 246 optimized ? "optimized " : "", function_fullname); |
| 227 const Code& code = Code::Handle(function.code()); | 247 const Code& code = Code::Handle(function.code()); |
| 228 const Instructions& instructions = | 248 const Instructions& instructions = |
| 229 Instructions::Handle(code.instructions()); | 249 Instructions::Handle(code.instructions()); |
| 230 uword start = instructions.EntryPoint(); | 250 uword start = instructions.EntryPoint(); |
| 231 Disassembler::Disassemble(start, start + assembler.CodeSize()); | 251 Disassembler::Disassemble(start, start + code_size); |
| 232 OS::Print("}\n"); | 252 OS::Print("}\n"); |
| 233 OS::Print("Pointer offsets for function: {\n"); | 253 OS::Print("Pointer offsets for function: {\n"); |
| 234 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { | 254 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) { |
| 235 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); | 255 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint(); |
| 236 Object& obj = Object::Handle(); | 256 Object& obj = Object::Handle(); |
| 237 obj = *reinterpret_cast<RawObject**>(addr); | 257 obj = *reinterpret_cast<RawObject**>(addr); |
| 238 OS::Print(" %d : 0x%x '%s'\n", | 258 OS::Print(" %d : 0x%x '%s'\n", |
| 239 code.GetPointerOffsetAt(i), addr, obj.ToCString()); | 259 code.GetPointerOffsetAt(i), addr, obj.ToCString()); |
| 240 } | 260 } |
| 241 OS::Print("}\n"); | 261 OS::Print("}\n"); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 } else { | 395 } else { |
| 376 result = isolate->object_store()->sticky_error(); | 396 result = isolate->object_store()->sticky_error(); |
| 377 isolate->object_store()->clear_sticky_error(); | 397 isolate->object_store()->clear_sticky_error(); |
| 378 } | 398 } |
| 379 isolate->set_long_jump_base(base); | 399 isolate->set_long_jump_base(base); |
| 380 return result.raw(); | 400 return result.raw(); |
| 381 } | 401 } |
| 382 | 402 |
| 383 | 403 |
| 384 } // namespace dart | 404 } // namespace dart |
| OLD | NEW |