| 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/flow_graph_compiler_shared.h" | 5 #include "vm/flow_graph_compiler_shared.h" |
| 6 | 6 |
| 7 #include "vm/debugger.h" |
| 7 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/intrinsifier.h" |
| 10 #include "vm/longjump.h" |
| 8 #include "vm/parser.h" | 11 #include "vm/parser.h" |
| 12 #include "vm/stub_code.h" |
| 9 | 13 |
| 10 namespace dart { | 14 namespace dart { |
| 11 | 15 |
| 16 DECLARE_FLAG(bool, enable_type_checks); |
| 17 DECLARE_FLAG(bool, intrinsify); |
| 18 DECLARE_FLAG(int, optimization_counter_threshold); |
| 19 DECLARE_FLAG(bool, trace_functions); |
| 20 DECLARE_FLAG(bool, report_usage_count); |
| 21 |
| 12 FlowGraphCompilerShared::FlowGraphCompilerShared( | 22 FlowGraphCompilerShared::FlowGraphCompilerShared( |
| 13 Assembler* assembler, | 23 Assembler* assembler, |
| 14 const ParsedFunction& parsed_function, | 24 const ParsedFunction& parsed_function, |
| 15 const GrowableArray<BlockEntryInstr*>& block_order, | 25 const GrowableArray<BlockEntryInstr*>& block_order, |
| 16 bool is_optimizing) | 26 bool is_optimizing) |
| 17 : assembler_(assembler), | 27 : assembler_(assembler), |
| 18 parsed_function_(parsed_function), | 28 parsed_function_(parsed_function), |
| 19 block_order_(block_order), | 29 block_order_(block_order), |
| 20 current_block_(NULL), | 30 current_block_(NULL), |
| 21 exception_handlers_list_(NULL), | 31 exception_handlers_list_(NULL), |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 } | 139 } |
| 130 | 140 |
| 131 | 141 |
| 132 void FlowGraphCompilerShared::FinalizeVarDescriptors(const Code& code) { | 142 void FlowGraphCompilerShared::FinalizeVarDescriptors(const Code& code) { |
| 133 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( | 143 const LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle( |
| 134 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); | 144 parsed_function_.node_sequence()->scope()->GetVarDescriptors()); |
| 135 code.set_var_descriptors(var_descs); | 145 code.set_var_descriptors(var_descs); |
| 136 } | 146 } |
| 137 | 147 |
| 138 | 148 |
| 149 void FlowGraphCompilerShared::FinalizeComments(const Code& code) { |
| 150 code.set_comments(assembler()->GetCodeComments()); |
| 151 } |
| 152 |
| 153 |
| 139 void FlowGraphCompilerShared::GenerateDeferredCode() { | 154 void FlowGraphCompilerShared::GenerateDeferredCode() { |
| 140 for (intptr_t i = 0; i < deopt_stubs_.length(); i++) { | 155 for (intptr_t i = 0; i < deopt_stubs_.length(); i++) { |
| 141 deopt_stubs_[i]->GenerateCode(this); | 156 deopt_stubs_[i]->GenerateCode(this); |
| 142 } | 157 } |
| 143 } | 158 } |
| 144 | 159 |
| 145 | 160 |
| 161 void FlowGraphCompilerShared::GenerateInstanceCall( |
| 162 intptr_t cid, |
| 163 intptr_t token_index, |
| 164 intptr_t try_index, |
| 165 const String& function_name, |
| 166 intptr_t argument_count, |
| 167 const Array& argument_names, |
| 168 intptr_t checked_argument_count) { |
| 169 ICData& ic_data = |
| 170 ICData::ZoneHandle(ICData::New(parsed_function().function(), |
| 171 function_name, |
| 172 cid, |
| 173 checked_argument_count)); |
| 174 const Array& arguments_descriptor = |
| 175 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 176 uword label_address = 0; |
| 177 switch (checked_argument_count) { |
| 178 case 1: |
| 179 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| 180 break; |
| 181 case 2: |
| 182 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| 183 break; |
| 184 default: |
| 185 UNIMPLEMENTED(); |
| 186 } |
| 187 ExternalLabel target_label("InlineCache", label_address); |
| 188 |
| 189 const intptr_t descr_offset = EmitInstanceCall(&target_label, |
| 190 ic_data, |
| 191 arguments_descriptor, |
| 192 argument_count); |
| 193 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, |
| 194 descr_offset, |
| 195 cid, |
| 196 token_index, |
| 197 try_index); |
| 198 } |
| 199 |
| 200 |
| 201 void FlowGraphCompilerShared::GenerateStaticCall(intptr_t cid, |
| 202 intptr_t token_index, |
| 203 intptr_t try_index, |
| 204 const Function& function, |
| 205 intptr_t argument_count, |
| 206 const Array& argument_names) { |
| 207 const Array& arguments_descriptor = |
| 208 CodeGenerator::ArgumentsDescriptor(argument_count, argument_names); |
| 209 const intptr_t descr_offset = EmitStaticCall(function, |
| 210 arguments_descriptor, |
| 211 argument_count); |
| 212 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, |
| 213 descr_offset, |
| 214 cid, |
| 215 token_index, |
| 216 try_index); |
| 217 } |
| 218 |
| 219 |
| 220 void FlowGraphCompilerShared::Bailout(const char* reason) { |
| 221 const char* kFormat = "FlowGraphCompiler Bailout: %s %s."; |
| 222 const char* function_name = parsed_function().function().ToCString(); |
| 223 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 224 char* chars = reinterpret_cast<char*>( |
| 225 Isolate::Current()->current_zone()->Allocate(len)); |
| 226 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 227 const Error& error = Error::Handle( |
| 228 LanguageError::New(String::Handle(String::New(chars)))); |
| 229 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 230 } |
| 231 |
| 232 |
| 233 static bool CanOptimize() { |
| 234 return !FLAG_report_usage_count && |
| 235 (FLAG_optimization_counter_threshold >= 0) && |
| 236 !Isolate::Current()->debugger()->IsActive(); |
| 237 } |
| 238 |
| 239 // Returns 'true' if code generation for this function is complete, i.e., |
| 240 // no fall-through to regular code is needed. |
| 241 bool FlowGraphCompilerShared::TryIntrinsify() { |
| 242 if (!CanOptimize()) return false; |
| 243 // Intrinsification skips arguments checks, therefore disable if in checked |
| 244 // mode. |
| 245 if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) { |
| 246 if ((parsed_function().function().kind() == RawFunction::kImplicitGetter)) { |
| 247 IntrinsifyGetter(); |
| 248 return true; |
| 249 } |
| 250 if ((parsed_function().function().kind() == RawFunction::kImplicitSetter)) { |
| 251 IntrinsifySetter(); |
| 252 return true; |
| 253 } |
| 254 } |
| 255 // Even if an intrinsified version of the function was successfully |
| 256 // generated, it may fall through to the non-intrinsified method body. |
| 257 if (!FLAG_trace_functions) { |
| 258 return Intrinsifier::Intrinsify(parsed_function().function(), assembler()); |
| 259 } |
| 260 return false; |
| 261 } |
| 262 |
| 146 } // namespace dart | 263 } // namespace dart |
| 147 | 264 |
| 148 | 265 |
| OLD | NEW |