| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 } | 442 } |
| 443 | 443 |
| 444 | 444 |
| 445 void FlowGraphCompiler::GenerateInstantiatorTypeArguments( | 445 void FlowGraphCompiler::GenerateInstantiatorTypeArguments( |
| 446 intptr_t token_index) { | 446 intptr_t token_index) { |
| 447 Bailout("FlowGraphCompiler::GenerateInstantiatorTypeArguments"); | 447 Bailout("FlowGraphCompiler::GenerateInstantiatorTypeArguments"); |
| 448 } | 448 } |
| 449 | 449 |
| 450 | 450 |
| 451 // Copied from CodeGenerator. | 451 // Copied from CodeGenerator. |
| 452 // Optimize instanceof type test by adding inlined tests for: | 452 // If instanceof type test cannot be performed successfully at compile time and |
| 453 // therefore eliminated, optimize it by adding inlined tests for: |
| 453 // - NULL -> return false. | 454 // - NULL -> return false. |
| 454 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 455 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 455 // - Class equality (only if class is not parameterized). | 456 // - Class equality (only if class is not parameterized). |
| 456 // Inputs: | 457 // Inputs: |
| 457 // - RAX: object. | 458 // - RAX: object. |
| 458 // Destroys RCX. | 459 // Destroys RCX. |
| 459 // Returns: | 460 // Returns: |
| 460 // - true or false in RAX. | 461 // - true or false in RAX. |
| 461 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, | 462 void FlowGraphCompiler::GenerateInstanceOf(intptr_t node_id, |
| 462 intptr_t token_index, | 463 intptr_t token_index, |
| 463 intptr_t try_index, | 464 intptr_t try_index, |
| 465 Value* value, |
| 464 const AbstractType& type, | 466 const AbstractType& type, |
| 465 bool negate_result) { | 467 bool negate_result) { |
| 466 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 468 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 467 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 469 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 468 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 470 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
| 469 | 471 |
| 470 // All instances are of a subtype of the Object type. | 472 // All objects are instances of type T if Object type is a subtype of type T. |
| 471 const Type& object_type = | 473 const Type& object_type = |
| 472 Type::Handle(Isolate::Current()->object_store()->object_type()); | 474 Type::Handle(Isolate::Current()->object_store()->object_type()); |
| 473 Error& malformed_error = Error::Handle(); | 475 Error& malformed_error = Error::Handle(); |
| 474 if (type.IsInstantiated() && | 476 if (type.IsInstantiated() && |
| 475 object_type.IsSubtypeOf(type, &malformed_error)) { | 477 object_type.IsSubtypeOf(type, &malformed_error)) { |
| 476 __ LoadObject(RAX, negate_result ? bool_false : bool_true); | 478 __ LoadObject(RAX, negate_result ? bool_false : bool_true); |
| 477 return; | 479 return; |
| 478 } | 480 } |
| 479 | 481 |
| 482 // Eliminate the test if it can be performed successfully at compile time. |
| 483 if ((value != NULL) && value->IsConstant() && type.IsInstantiated()) { |
| 484 // TODO(regis): A constant value should be an instance, not an object. |
| 485 Instance& literal_value = Instance::Handle(); |
| 486 literal_value ^= value->AsConstant()->value().raw(); |
| 487 const Class& cls = Class::Handle(literal_value.clazz()); |
| 488 if (cls.IsNullClass()) { |
| 489 ASSERT(literal_value.IsNull() || |
| 490 (literal_value.raw() == Object::sentinel()) || |
| 491 (literal_value.raw() == Object::transition_sentinel())); |
| 492 // A null object is only an instance of Object and Dynamic, which has |
| 493 // already been checked above (if the type is instantiated). So we can |
| 494 // return false here if the instance is null (and if the type is |
| 495 // instantiated). |
| 496 __ PushObject(negate_result ? bool_true : bool_false); |
| 497 } else { |
| 498 Error& malformed_error = Error::Handle(); |
| 499 if (literal_value.IsInstanceOf(type, |
| 500 TypeArguments::Handle(), |
| 501 &malformed_error)) { |
| 502 __ PushObject(negate_result ? bool_false : bool_true); |
| 503 } else { |
| 504 ASSERT(malformed_error.IsNull()); |
| 505 __ PushObject(negate_result ? bool_true : bool_false); |
| 506 } |
| 507 } |
| 508 return; |
| 509 } |
| 510 |
| 480 const Immediate raw_null = | 511 const Immediate raw_null = |
| 481 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 512 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 482 Label done; | 513 Label done; |
| 483 // If type is instantiated and non-parameterized, we can inline code | 514 // If type is instantiated and non-parameterized, we can inline code |
| 484 // checking whether the tested instance is a Smi. | 515 // checking whether the tested instance is a Smi. |
| 485 if (type.IsInstantiated()) { | 516 if (type.IsInstantiated()) { |
| 486 // A null object is only an instance of Object and Dynamic, which has | 517 // A null object is only an instance of Object and Dynamic, which has |
| 487 // already been checked above (if the type is instantiated). So we can | 518 // already been checked above (if the type is instantiated). So we can |
| 488 // return false here if the instance is null (and if the type is | 519 // return false here if the instance is null (and if the type is |
| 489 // instantiated). | 520 // instantiated). |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 528 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); | 559 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); |
| 529 __ CompareObject(RCX, type_class); | 560 __ CompareObject(RCX, type_class); |
| 530 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); | 561 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 531 __ PushObject(negate_result ? bool_false : bool_true); | 562 __ PushObject(negate_result ? bool_false : bool_true); |
| 532 __ jmp(&done); | 563 __ jmp(&done); |
| 533 } | 564 } |
| 534 } | 565 } |
| 535 __ Bind(&runtime_call); | 566 __ Bind(&runtime_call); |
| 536 // Fall through to runtime call. | 567 // Fall through to runtime call. |
| 537 } else { | 568 } else { |
| 569 ASSERT(!requires_type_arguments); |
| 570 // Test if object is Smi and for a couple known test-classes. |
| 538 Label compare_classes; | 571 Label compare_classes; |
| 539 __ testq(RAX, Immediate(kSmiTagMask)); | 572 __ testq(RAX, Immediate(kSmiTagMask)); |
| 540 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 573 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 541 // Object is Smi. | 574 // Object is Smi. |
| 542 const Class& smi_class = Class::Handle(Smi::Class()); | 575 const Class& smi_class = Class::Handle(Smi::Class()); |
| 543 // TODO(regis): We should introduce a SmiType. | 576 // TODO(regis): We should introduce a SmiType. |
| 544 Error& malformed_error = Error::Handle(); | 577 Error& malformed_error = Error::Handle(); |
| 545 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 578 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| 546 type_class, | 579 type_class, |
| 547 TypeArguments::Handle(), | 580 TypeArguments::Handle(), |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 __ Bind(&done); | 639 __ Bind(&done); |
| 607 __ popq(RAX); | 640 __ popq(RAX); |
| 608 } | 641 } |
| 609 | 642 |
| 610 | 643 |
| 611 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { | 644 void FlowGraphCompiler::VisitInstanceOf(InstanceOfComp* comp) { |
| 612 __ popq(RAX); | 645 __ popq(RAX); |
| 613 GenerateInstanceOf(comp->node_id(), | 646 GenerateInstanceOf(comp->node_id(), |
| 614 comp->token_index(), | 647 comp->token_index(), |
| 615 comp->try_index(), | 648 comp->try_index(), |
| 649 comp->value(), |
| 616 comp->type(), | 650 comp->type(), |
| 617 comp->negate_result()); | 651 comp->negate_result()); |
| 618 } | 652 } |
| 619 | 653 |
| 620 | 654 |
| 621 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { | 655 void FlowGraphCompiler::VisitAllocateObject(AllocateObjectComp* comp) { |
| 622 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); | 656 const Class& cls = Class::ZoneHandle(comp->constructor().owner()); |
| 623 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 657 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 624 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 658 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 625 GenerateCall(comp->token_index(), comp->try_index(), &label, | 659 GenerateCall(comp->token_index(), comp->try_index(), &label, |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 ASSERT(exception_handlers_list_ != NULL); | 1395 ASSERT(exception_handlers_list_ != NULL); |
| 1362 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( | 1396 const ExceptionHandlers& handlers = ExceptionHandlers::Handle( |
| 1363 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); | 1397 exception_handlers_list_->FinalizeExceptionHandlers(code.EntryPoint())); |
| 1364 code.set_exception_handlers(handlers); | 1398 code.set_exception_handlers(handlers); |
| 1365 } | 1399 } |
| 1366 | 1400 |
| 1367 | 1401 |
| 1368 } // namespace dart | 1402 } // namespace dart |
| 1369 | 1403 |
| 1370 #endif // defined TARGET_ARCH_X64 | 1404 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |