| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 452 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 453 // - Class equality (only if class is not parameterized). | 453 // - Class equality (only if class is not parameterized). |
| 454 // Inputs: | 454 // Inputs: |
| 455 // - EAX: object. | 455 // - EAX: object. |
| 456 // - EDX: instantiator type arguments or raw_null. | 456 // - EDX: instantiator type arguments or raw_null. |
| 457 // - ECX: instantiator or raw_null. | 457 // - ECX: instantiator or raw_null. |
| 458 // Clobbers ECX and EDX. | 458 // Clobbers ECX and EDX. |
| 459 // Returns: | 459 // Returns: |
| 460 // - true or false in EAX. | 460 // - true or false in EAX. |
| 461 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, | 461 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, |
| 462 intptr_t deopt_id, |
| 462 const AbstractType& type, | 463 const AbstractType& type, |
| 463 bool negate_result, | 464 bool negate_result, |
| 464 LocationSummary* locs) { | 465 LocationSummary* locs) { |
| 465 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 466 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
| 466 | 467 |
| 467 const Immediate& raw_null = | 468 const Immediate& raw_null = |
| 468 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 469 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 469 Label is_instance, is_not_instance; | 470 Label is_instance, is_not_instance; |
| 470 __ pushl(ECX); // Store instantiator on stack. | 471 __ pushl(ECX); // Store instantiator on stack. |
| 471 __ pushl(EDX); // Store instantiator type arguments. | 472 __ pushl(EDX); // Store instantiator type arguments. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 494 // Generate runtime call. | 495 // Generate runtime call. |
| 495 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 496 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 496 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 497 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 497 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 498 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 498 __ pushl(EAX); // Push the instance. | 499 __ pushl(EAX); // Push the instance. |
| 499 __ PushObject(type); // Push the type. | 500 __ PushObject(type); // Push the type. |
| 500 __ pushl(ECX); // Instantiator. | 501 __ pushl(ECX); // Instantiator. |
| 501 __ pushl(EDX); // Instantiator type arguments. | 502 __ pushl(EDX); // Instantiator type arguments. |
| 502 __ LoadObject(EAX, test_cache); | 503 __ LoadObject(EAX, test_cache); |
| 503 __ pushl(EAX); | 504 __ pushl(EAX); |
| 504 GenerateCallRuntime(token_pos, kInstanceofRuntimeEntry, locs); | 505 GenerateCallRuntime(token_pos, deopt_id, kInstanceofRuntimeEntry, locs); |
| 505 // Pop the parameters supplied to the runtime entry. The result of the | 506 // Pop the parameters supplied to the runtime entry. The result of the |
| 506 // instanceof runtime call will be left as the result of the operation. | 507 // instanceof runtime call will be left as the result of the operation. |
| 507 __ Drop(5); | 508 __ Drop(5); |
| 508 if (negate_result) { | 509 if (negate_result) { |
| 509 __ popl(EDX); | 510 __ popl(EDX); |
| 510 __ LoadObject(EAX, Bool::True()); | 511 __ LoadObject(EAX, Bool::True()); |
| 511 __ cmpl(EDX, EAX); | 512 __ cmpl(EDX, EAX); |
| 512 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 513 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 513 __ LoadObject(EAX, Bool::False()); | 514 __ LoadObject(EAX, Bool::False()); |
| 514 } else { | 515 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 534 // - Class equality (only if class is not parameterized). | 535 // - Class equality (only if class is not parameterized). |
| 535 // Inputs: | 536 // Inputs: |
| 536 // - EAX: object. | 537 // - EAX: object. |
| 537 // - EDX: instantiator type arguments or raw_null. | 538 // - EDX: instantiator type arguments or raw_null. |
| 538 // - ECX: instantiator or raw_null. | 539 // - ECX: instantiator or raw_null. |
| 539 // Returns: | 540 // Returns: |
| 540 // - object in EAX for successful assignable check (or throws TypeError). | 541 // - object in EAX for successful assignable check (or throws TypeError). |
| 541 // Performance notes: positive checks must be quick, negative checks can be slow | 542 // Performance notes: positive checks must be quick, negative checks can be slow |
| 542 // as they throw an exception. | 543 // as they throw an exception. |
| 543 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, | 544 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, |
| 545 intptr_t deopt_id, |
| 544 const AbstractType& dst_type, | 546 const AbstractType& dst_type, |
| 545 const String& dst_name, | 547 const String& dst_name, |
| 546 LocationSummary* locs) { | 548 LocationSummary* locs) { |
| 547 ASSERT(token_pos >= 0); | 549 ASSERT(token_pos >= 0); |
| 548 ASSERT(!dst_type.IsNull()); | 550 ASSERT(!dst_type.IsNull()); |
| 549 ASSERT(dst_type.IsFinalized()); | 551 ASSERT(dst_type.IsFinalized()); |
| 550 // Assignable check is skipped in FlowGraphBuilder, not here. | 552 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 551 ASSERT(dst_type.IsMalformed() || | 553 ASSERT(dst_type.IsMalformed() || |
| 552 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 554 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 553 __ pushl(ECX); // Store instantiator. | 555 __ pushl(ECX); // Store instantiator. |
| 554 __ pushl(EDX); // Store instantiator type arguments. | 556 __ pushl(EDX); // Store instantiator type arguments. |
| 555 // A null object is always assignable and is returned as result. | 557 // A null object is always assignable and is returned as result. |
| 556 const Immediate& raw_null = | 558 const Immediate& raw_null = |
| 557 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 559 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 558 Label is_assignable, runtime_call; | 560 Label is_assignable, runtime_call; |
| 559 __ cmpl(EAX, raw_null); | 561 __ cmpl(EAX, raw_null); |
| 560 __ j(EQUAL, &is_assignable); | 562 __ j(EQUAL, &is_assignable); |
| 561 | 563 |
| 562 // Generate throw new TypeError() if the type is malformed. | 564 // Generate throw new TypeError() if the type is malformed. |
| 563 if (dst_type.IsMalformed()) { | 565 if (dst_type.IsMalformed()) { |
| 564 const Error& error = Error::Handle(dst_type.malformed_error()); | 566 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 565 const String& error_message = String::ZoneHandle( | 567 const String& error_message = String::ZoneHandle( |
| 566 Symbols::New(error.ToErrorCString())); | 568 Symbols::New(error.ToErrorCString())); |
| 567 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 569 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 568 __ pushl(EAX); // Push the source object. | 570 __ pushl(EAX); // Push the source object. |
| 569 __ PushObject(dst_name); // Push the name of the destination. | 571 __ PushObject(dst_name); // Push the name of the destination. |
| 570 __ PushObject(error_message); | 572 __ PushObject(error_message); |
| 571 GenerateCallRuntime(token_pos, | 573 GenerateCallRuntime(token_pos, |
| 574 deopt_id, |
| 572 kMalformedTypeErrorRuntimeEntry, | 575 kMalformedTypeErrorRuntimeEntry, |
| 573 locs); | 576 locs); |
| 574 // We should never return here. | 577 // We should never return here. |
| 575 __ int3(); | 578 __ int3(); |
| 576 | 579 |
| 577 __ Bind(&is_assignable); // For a null object. | 580 __ Bind(&is_assignable); // For a null object. |
| 578 __ popl(EDX); // Remove pushed instantiator type arguments. | 581 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 579 __ popl(ECX); // Remove pushed instantiator. | 582 __ popl(ECX); // Remove pushed instantiator. |
| 580 return; | 583 return; |
| 581 } | 584 } |
| 582 | 585 |
| 583 // Generate inline type check, linking to runtime call if not assignable. | 586 // Generate inline type check, linking to runtime call if not assignable. |
| 584 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 587 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
| 585 test_cache = GenerateInlineInstanceof(token_pos, dst_type, | 588 test_cache = GenerateInlineInstanceof(token_pos, dst_type, |
| 586 &is_assignable, &runtime_call); | 589 &is_assignable, &runtime_call); |
| 587 | 590 |
| 588 __ Bind(&runtime_call); | 591 __ Bind(&runtime_call); |
| 589 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 592 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
| 590 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. | 593 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. |
| 591 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 594 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 592 __ pushl(EAX); // Push the source object. | 595 __ pushl(EAX); // Push the source object. |
| 593 __ PushObject(dst_type); // Push the type of the destination. | 596 __ PushObject(dst_type); // Push the type of the destination. |
| 594 __ pushl(ECX); // Instantiator. | 597 __ pushl(ECX); // Instantiator. |
| 595 __ pushl(EDX); // Instantiator type arguments. | 598 __ pushl(EDX); // Instantiator type arguments. |
| 596 __ PushObject(dst_name); // Push the name of the destination. | 599 __ PushObject(dst_name); // Push the name of the destination. |
| 597 __ LoadObject(EAX, test_cache); | 600 __ LoadObject(EAX, test_cache); |
| 598 __ pushl(EAX); | 601 __ pushl(EAX); |
| 599 GenerateCallRuntime(token_pos, kTypeCheckRuntimeEntry, locs); | 602 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs); |
| 600 // Pop the parameters supplied to the runtime entry. The result of the | 603 // Pop the parameters supplied to the runtime entry. The result of the |
| 601 // type check runtime call is the checked value. | 604 // type check runtime call is the checked value. |
| 602 __ Drop(6); | 605 __ Drop(6); |
| 603 __ popl(EAX); | 606 __ popl(EAX); |
| 604 | 607 |
| 605 __ Bind(&is_assignable); | 608 __ Bind(&is_assignable); |
| 606 __ popl(EDX); // Remove pushed instantiator type arguments. | 609 __ popl(EDX); // Remove pushed instantiator type arguments. |
| 607 __ popl(ECX); // Remove pushed instantiator. | 610 __ popl(ECX); // Remove pushed instantiator. |
| 608 } | 611 } |
| 609 | 612 |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 // Add deoptimization continuation point after the call and before the | 1087 // Add deoptimization continuation point after the call and before the |
| 1085 // arguments are removed. | 1088 // arguments are removed. |
| 1086 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, | 1089 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, |
| 1087 deopt_id, | 1090 deopt_id, |
| 1088 token_pos); | 1091 token_pos); |
| 1089 } | 1092 } |
| 1090 } | 1093 } |
| 1091 | 1094 |
| 1092 | 1095 |
| 1093 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, | 1096 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, |
| 1097 intptr_t deopt_id, |
| 1094 const RuntimeEntry& entry, | 1098 const RuntimeEntry& entry, |
| 1095 LocationSummary* locs) { | 1099 LocationSummary* locs) { |
| 1096 __ CallRuntime(entry); | 1100 __ CallRuntime(entry); |
| 1097 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos); | 1101 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 1098 RecordSafepoint(locs); | 1102 RecordSafepoint(locs); |
| 1103 if (deopt_id != Isolate::kNoDeoptId) { |
| 1104 // Marks either the continuation point in unoptimized code or the |
| 1105 // deoptimization point in optimized code, after call. |
| 1106 if (is_optimizing()) { |
| 1107 AddDeoptIndexAtCall(deopt_id, token_pos); |
| 1108 } else { |
| 1109 // Add deoptimization continuation point after the call and before the |
| 1110 // arguments are removed. |
| 1111 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, |
| 1112 deopt_id, |
| 1113 token_pos); |
| 1114 } |
| 1115 } |
| 1099 } | 1116 } |
| 1100 | 1117 |
| 1101 | 1118 |
| 1102 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 1119 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
| 1103 ExternalLabel* target_label, | 1120 ExternalLabel* target_label, |
| 1104 const ICData& ic_data, | 1121 const ICData& ic_data, |
| 1105 const Array& arguments_descriptor, | 1122 const Array& arguments_descriptor, |
| 1106 intptr_t argument_count, | 1123 intptr_t argument_count, |
| 1107 intptr_t deopt_id, | 1124 intptr_t deopt_id, |
| 1108 intptr_t token_pos, | 1125 intptr_t token_pos, |
| (...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 __ popl(ECX); | 1730 __ popl(ECX); |
| 1714 __ popl(EAX); | 1731 __ popl(EAX); |
| 1715 } | 1732 } |
| 1716 | 1733 |
| 1717 | 1734 |
| 1718 #undef __ | 1735 #undef __ |
| 1719 | 1736 |
| 1720 } // namespace dart | 1737 } // namespace dart |
| 1721 | 1738 |
| 1722 #endif // defined TARGET_ARCH_IA32 | 1739 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |