| 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/globals.h" // Needed here to get TARGET_ARCH_XXX. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX. |
| 6 | 6 |
| 7 #include "vm/flow_graph_compiler.h" | 7 #include "vm/flow_graph_compiler.h" |
| 8 | 8 |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/debugger.h" | 10 #include "vm/debugger.h" |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 171 |
| 172 | 172 |
| 173 void FlowGraphCompiler::AddExceptionHandler(intptr_t try_index, | 173 void FlowGraphCompiler::AddExceptionHandler(intptr_t try_index, |
| 174 intptr_t pc_offset) { | 174 intptr_t pc_offset) { |
| 175 exception_handlers_list_->AddHandler(try_index, pc_offset); | 175 exception_handlers_list_->AddHandler(try_index, pc_offset); |
| 176 } | 176 } |
| 177 | 177 |
| 178 | 178 |
| 179 // Uses current pc position and try-index. | 179 // Uses current pc position and try-index. |
| 180 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, | 180 void FlowGraphCompiler::AddCurrentDescriptor(PcDescriptors::Kind kind, |
| 181 intptr_t cid, | 181 intptr_t deopt_id, |
| 182 intptr_t token_pos, | 182 intptr_t token_pos, |
| 183 intptr_t try_index) { | 183 intptr_t try_index) { |
| 184 ASSERT((kind != PcDescriptors::kDeopt) || | 184 ASSERT((kind != PcDescriptors::kDeopt) || |
| 185 frame_register_allocator()->IsSpilled()); | 185 frame_register_allocator()->IsSpilled()); |
| 186 pc_descriptors_list()->AddDescriptor(kind, | 186 pc_descriptors_list()->AddDescriptor(kind, |
| 187 assembler()->CodeSize(), | 187 assembler()->CodeSize(), |
| 188 cid, | 188 deopt_id, |
| 189 token_pos, | 189 token_pos, |
| 190 try_index); | 190 try_index); |
| 191 } | 191 } |
| 192 | 192 |
| 193 | 193 |
| 194 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, | 194 Label* FlowGraphCompiler::AddDeoptStub(intptr_t deopt_id, |
| 195 intptr_t deopt_token_pos, | 195 intptr_t deopt_token_pos, |
| 196 intptr_t try_index, | 196 intptr_t try_index, |
| 197 DeoptReasonId reason, | 197 DeoptReasonId reason, |
| 198 Register reg1, | 198 Register reg1, |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 // Even if an intrinsified version of the function was successfully | 292 // Even if an intrinsified version of the function was successfully |
| 293 // generated, it may fall through to the non-intrinsified method body. | 293 // generated, it may fall through to the non-intrinsified method body. |
| 294 if (!FLAG_trace_functions) { | 294 if (!FLAG_trace_functions) { |
| 295 return Intrinsifier::Intrinsify(parsed_function().function(), assembler()); | 295 return Intrinsifier::Intrinsify(parsed_function().function(), assembler()); |
| 296 } | 296 } |
| 297 return false; | 297 return false; |
| 298 } | 298 } |
| 299 | 299 |
| 300 | 300 |
| 301 void FlowGraphCompiler::GenerateInstanceCall( | 301 void FlowGraphCompiler::GenerateInstanceCall( |
| 302 intptr_t cid, | 302 intptr_t deopt_id, |
| 303 intptr_t token_pos, | 303 intptr_t token_pos, |
| 304 intptr_t try_index, | 304 intptr_t try_index, |
| 305 const String& function_name, | 305 const String& function_name, |
| 306 intptr_t argument_count, | 306 intptr_t argument_count, |
| 307 const Array& argument_names, | 307 const Array& argument_names, |
| 308 intptr_t checked_argument_count) { | 308 intptr_t checked_argument_count) { |
| 309 ASSERT(!IsLeaf()); | 309 ASSERT(!IsLeaf()); |
| 310 ASSERT(frame_register_allocator()->IsSpilled()); | 310 ASSERT(frame_register_allocator()->IsSpilled()); |
| 311 ICData& ic_data = | 311 ICData& ic_data = |
| 312 ICData::ZoneHandle(ICData::New(parsed_function().function(), | 312 ICData::ZoneHandle(ICData::New(parsed_function().function(), |
| 313 function_name, | 313 function_name, |
| 314 cid, | 314 deopt_id, |
| 315 checked_argument_count)); | 315 checked_argument_count)); |
| 316 const Array& arguments_descriptor = | 316 const Array& arguments_descriptor = |
| 317 DartEntry::ArgumentsDescriptor(argument_count, argument_names); | 317 DartEntry::ArgumentsDescriptor(argument_count, argument_names); |
| 318 uword label_address = 0; | 318 uword label_address = 0; |
| 319 switch (checked_argument_count) { | 319 switch (checked_argument_count) { |
| 320 case 1: | 320 case 1: |
| 321 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); | 321 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); |
| 322 break; | 322 break; |
| 323 case 2: | 323 case 2: |
| 324 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); | 324 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); |
| 325 break; | 325 break; |
| 326 default: | 326 default: |
| 327 UNIMPLEMENTED(); | 327 UNIMPLEMENTED(); |
| 328 } | 328 } |
| 329 ExternalLabel target_label("InlineCache", label_address); | 329 ExternalLabel target_label("InlineCache", label_address); |
| 330 | 330 |
| 331 const intptr_t descr_offset = EmitInstanceCall(&target_label, | 331 const intptr_t descr_offset = EmitInstanceCall(&target_label, |
| 332 ic_data, | 332 ic_data, |
| 333 arguments_descriptor, | 333 arguments_descriptor, |
| 334 argument_count); | 334 argument_count); |
| 335 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, | 335 pc_descriptors_list()->AddDescriptor(PcDescriptors::kIcCall, |
| 336 descr_offset, | 336 descr_offset, |
| 337 cid, | 337 deopt_id, |
| 338 token_pos, | 338 token_pos, |
| 339 try_index); | 339 try_index); |
| 340 } | 340 } |
| 341 | 341 |
| 342 | 342 |
| 343 void FlowGraphCompiler::GenerateStaticCall(intptr_t cid, | 343 void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, |
| 344 intptr_t token_pos, | 344 intptr_t token_pos, |
| 345 intptr_t try_index, | 345 intptr_t try_index, |
| 346 const Function& function, | 346 const Function& function, |
| 347 intptr_t argument_count, | 347 intptr_t argument_count, |
| 348 const Array& argument_names) { | 348 const Array& argument_names) { |
| 349 ASSERT(frame_register_allocator()->IsSpilled()); | 349 ASSERT(frame_register_allocator()->IsSpilled()); |
| 350 | 350 |
| 351 const Array& arguments_descriptor = | 351 const Array& arguments_descriptor = |
| 352 DartEntry::ArgumentsDescriptor(argument_count, argument_names); | 352 DartEntry::ArgumentsDescriptor(argument_count, argument_names); |
| 353 const intptr_t descr_offset = EmitStaticCall(function, | 353 const intptr_t descr_offset = EmitStaticCall(function, |
| 354 arguments_descriptor, | 354 arguments_descriptor, |
| 355 argument_count); | 355 argument_count); |
| 356 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, | 356 pc_descriptors_list()->AddDescriptor(PcDescriptors::kFuncCall, |
| 357 descr_offset, | 357 descr_offset, |
| 358 cid, | 358 deopt_id, |
| 359 token_pos, | 359 token_pos, |
| 360 try_index); | 360 try_index); |
| 361 } | 361 } |
| 362 | 362 |
| 363 | 363 |
| 364 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, | 364 void FlowGraphCompiler::GenerateNumberTypeCheck(Register kClassIdReg, |
| 365 const AbstractType& type, | 365 const AbstractType& type, |
| 366 Label* is_instance_lbl, | 366 Label* is_instance_lbl, |
| 367 Label* is_not_instance_lbl) { | 367 Label* is_not_instance_lbl) { |
| 368 GrowableArray<intptr_t> args; | 368 GrowableArray<intptr_t> args; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 instr->PrintTo(&f); | 412 instr->PrintTo(&f); |
| 413 assembler()->Comment("%s", buffer); | 413 assembler()->Comment("%s", buffer); |
| 414 } | 414 } |
| 415 | 415 |
| 416 | 416 |
| 417 void FlowGraphCompiler::EmitLoadIndexedGeneric(LoadIndexedComp* comp) { | 417 void FlowGraphCompiler::EmitLoadIndexedGeneric(LoadIndexedComp* comp) { |
| 418 const String& function_name = | 418 const String& function_name = |
| 419 String::ZoneHandle(Symbols::New(Token::Str(Token::kINDEX))); | 419 String::ZoneHandle(Symbols::New(Token::Str(Token::kINDEX))); |
| 420 | 420 |
| 421 AddCurrentDescriptor(PcDescriptors::kDeopt, | 421 AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 422 comp->cid(), | 422 comp->deopt_id(), |
| 423 comp->token_pos(), | 423 comp->token_pos(), |
| 424 comp->try_index()); | 424 comp->try_index()); |
| 425 | 425 |
| 426 const intptr_t kNumArguments = 2; | 426 const intptr_t kNumArguments = 2; |
| 427 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 427 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 428 GenerateInstanceCall(comp->cid(), | 428 GenerateInstanceCall(comp->deopt_id(), |
| 429 comp->token_pos(), | 429 comp->token_pos(), |
| 430 comp->try_index(), | 430 comp->try_index(), |
| 431 function_name, | 431 function_name, |
| 432 kNumArguments, | 432 kNumArguments, |
| 433 Array::ZoneHandle(), // No optional arguments. | 433 Array::ZoneHandle(), // No optional arguments. |
| 434 kNumArgsChecked); | 434 kNumArgsChecked); |
| 435 } | 435 } |
| 436 | 436 |
| 437 | 437 |
| 438 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 438 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
| 439 Register class_id_reg, | 439 Register class_id_reg, |
| 440 intptr_t arg_count, | 440 intptr_t arg_count, |
| 441 const Array& arg_names, | 441 const Array& arg_names, |
| 442 Label* deopt, | 442 Label* deopt, |
| 443 Label* done, | 443 Label* done, |
| 444 intptr_t cid, | 444 intptr_t deopt_id, |
| 445 intptr_t token_index, | 445 intptr_t token_index, |
| 446 intptr_t try_index) { | 446 intptr_t try_index) { |
| 447 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 447 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 448 Label match_found; | 448 Label match_found; |
| 449 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 449 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 450 const bool is_last_check = (i == (ic_data.NumberOfChecks() - 1)); | 450 const bool is_last_check = (i == (ic_data.NumberOfChecks() - 1)); |
| 451 Label next_test; | 451 Label next_test; |
| 452 assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i))); | 452 assembler()->cmpl(class_id_reg, Immediate(ic_data.GetReceiverClassIdAt(i))); |
| 453 if (is_last_check) { | 453 if (is_last_check) { |
| 454 assembler()->j(NOT_EQUAL, deopt); | 454 assembler()->j(NOT_EQUAL, deopt); |
| 455 } else { | 455 } else { |
| 456 assembler()->j(NOT_EQUAL, &next_test); | 456 assembler()->j(NOT_EQUAL, &next_test); |
| 457 } | 457 } |
| 458 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 458 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 459 GenerateStaticCall(cid, | 459 GenerateStaticCall(deopt_id, |
| 460 token_index, | 460 token_index, |
| 461 try_index, | 461 try_index, |
| 462 target, | 462 target, |
| 463 arg_count, | 463 arg_count, |
| 464 arg_names); | 464 arg_names); |
| 465 if (!is_last_check) { | 465 if (!is_last_check) { |
| 466 assembler()->jmp(&match_found); | 466 assembler()->jmp(&match_found); |
| 467 } | 467 } |
| 468 assembler()->Bind(&next_test); | 468 assembler()->Bind(&next_test); |
| 469 } | 469 } |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 return; | 801 return; |
| 802 } | 802 } |
| 803 } | 803 } |
| 804 | 804 |
| 805 // This move is not blocked. | 805 // This move is not blocked. |
| 806 EmitMove(index); | 806 EmitMove(index); |
| 807 } | 807 } |
| 808 | 808 |
| 809 | 809 |
| 810 } // namespace dart | 810 } // namespace dart |
| OLD | NEW |