| 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_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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 locs->set_temp(0, Location::RegisterLocation(ECX)); | 328 locs->set_temp(0, Location::RegisterLocation(ECX)); |
| 329 locs->set_out(Location::RegisterLocation(EAX)); | 329 locs->set_out(Location::RegisterLocation(EAX)); |
| 330 return locs; | 330 return locs; |
| 331 } | 331 } |
| 332 | 332 |
| 333 | 333 |
| 334 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 334 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 335 intptr_t deopt_id, | 335 intptr_t deopt_id, |
| 336 intptr_t token_pos, | 336 intptr_t token_pos, |
| 337 Token::Kind kind, | 337 Token::Kind kind, |
| 338 LocationSummary* locs) { | 338 LocationSummary* locs, |
| 339 const ICData& original_ic_data) { |
| 339 if (!compiler->is_optimizing()) { | 340 if (!compiler->is_optimizing()) { |
| 340 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | 341 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 341 deopt_id, | 342 deopt_id, |
| 342 token_pos); | 343 token_pos); |
| 343 } | 344 } |
| 344 const String& operator_name = String::ZoneHandle(Symbols::EqualOperator()); | 345 const String& operator_name = String::ZoneHandle(Symbols::EqualOperator()); |
| 345 const int kNumberOfArguments = 2; | 346 const int kNumberOfArguments = 2; |
| 346 const Array& kNoArgumentNames = Array::Handle(); | 347 const Array& kNoArgumentNames = Array::Handle(); |
| 347 const int kNumArgumentsChecked = 2; | 348 const int kNumArgumentsChecked = 2; |
| 348 | 349 |
| 349 const Immediate raw_null = | 350 const Immediate raw_null = |
| 350 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 351 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 351 Label check_identity; | 352 Label check_identity; |
| 352 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); | 353 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); |
| 353 __ j(EQUAL, &check_identity, Assembler::kNearJump); | 354 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 354 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); | 355 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); |
| 355 __ j(EQUAL, &check_identity, Assembler::kNearJump); | 356 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 356 | 357 |
| 357 const ICData& ic_data = compiler->GenerateInstanceCall(deopt_id, | 358 ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); |
| 358 token_pos, | 359 if (equality_ic_data.IsNull()) { |
| 359 operator_name, | 360 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 360 kNumberOfArguments, | 361 operator_name, |
| 361 kNoArgumentNames, | 362 deopt_id, |
| 362 kNumArgumentsChecked, | 363 kNumArgumentsChecked); |
| 363 locs); | 364 } |
| 365 compiler->GenerateInstanceCall(deopt_id, |
| 366 token_pos, |
| 367 kNumberOfArguments, |
| 368 kNoArgumentNames, |
| 369 locs, |
| 370 equality_ic_data); |
| 364 Label check_ne; | 371 Label check_ne; |
| 365 __ jmp(&check_ne); | 372 __ jmp(&check_ne); |
| 366 | 373 |
| 367 __ Bind(&check_identity); | 374 __ Bind(&check_identity); |
| 368 // Call stub, load IC data in register. The stub will update ICData if | 375 // Call stub, load IC data in register. The stub will update ICData if |
| 369 // necessary. | 376 // necessary. |
| 370 Register ic_data_reg = locs->temp(0).reg(); | 377 Register ic_data_reg = locs->temp(0).reg(); |
| 371 ASSERT(ic_data_reg == ECX); // Stub depends on it. | 378 ASSERT(ic_data_reg == ECX); // Stub depends on it. |
| 372 __ LoadObject(ic_data_reg, ic_data); | 379 __ LoadObject(ic_data_reg, equality_ic_data); |
| 373 compiler->GenerateCall(token_pos, | 380 compiler->GenerateCall(token_pos, |
| 374 &StubCode::EqualityWithNullArgLabel(), | 381 &StubCode::EqualityWithNullArgLabel(), |
| 375 PcDescriptors::kOther, | 382 PcDescriptors::kOther, |
| 376 locs); | 383 locs); |
| 377 __ Drop(2); | 384 __ Drop(2); |
| 378 __ Bind(&check_ne); | 385 __ Bind(&check_ne); |
| 379 if (kind == Token::kNE) { | 386 if (kind == Token::kNE) { |
| 380 Label false_label, true_label, done; | 387 Label false_label, true_label, done; |
| 381 // Negate the condition: true label returns false and vice versa. | 388 // Negate the condition: true label returns false and vice versa. |
| 382 __ CompareObject(EAX, compiler->bool_true()); | 389 __ CompareObject(EAX, compiler->bool_true()); |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 740 } | 747 } |
| 741 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 748 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 742 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), | 749 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
| 743 deopt_id(), token_pos()); | 750 deopt_id(), token_pos()); |
| 744 return; | 751 return; |
| 745 } | 752 } |
| 746 Register left = locs()->in(0).reg(); | 753 Register left = locs()->in(0).reg(); |
| 747 Register right = locs()->in(1).reg(); | 754 Register right = locs()->in(1).reg(); |
| 748 __ pushl(left); | 755 __ pushl(left); |
| 749 __ pushl(right); | 756 __ pushl(right); |
| 750 EmitEqualityAsInstanceCall(compiler, deopt_id(), token_pos(), kind(), locs()); | 757 EmitEqualityAsInstanceCall(compiler, |
| 758 deopt_id(), |
| 759 token_pos(), |
| 760 kind(), |
| 761 locs(), |
| 762 *ic_data()); |
| 751 ASSERT(locs()->out().reg() == EAX); | 763 ASSERT(locs()->out().reg() == EAX); |
| 752 } | 764 } |
| 753 | 765 |
| 754 | 766 |
| 755 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 767 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 756 BranchInstr* branch) { | 768 BranchInstr* branch) { |
| 757 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 769 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 758 if (receiver_class_id() == kSmiCid) { | 770 if (receiver_class_id() == kSmiCid) { |
| 759 // Deoptimizes if both arguments not Smi. | 771 // Deoptimizes if both arguments not Smi. |
| 760 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 772 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 781 return; | 793 return; |
| 782 } | 794 } |
| 783 Register left = locs()->in(0).reg(); | 795 Register left = locs()->in(0).reg(); |
| 784 Register right = locs()->in(1).reg(); | 796 Register right = locs()->in(1).reg(); |
| 785 __ pushl(left); | 797 __ pushl(left); |
| 786 __ pushl(right); | 798 __ pushl(right); |
| 787 EmitEqualityAsInstanceCall(compiler, | 799 EmitEqualityAsInstanceCall(compiler, |
| 788 deopt_id(), | 800 deopt_id(), |
| 789 token_pos(), | 801 token_pos(), |
| 790 Token::kEQ, // kNE reverse occurs at branch. | 802 Token::kEQ, // kNE reverse occurs at branch. |
| 791 locs()); | 803 locs(), |
| 804 *ic_data()); |
| 792 if (branch->is_checked()) { | 805 if (branch->is_checked()) { |
| 793 EmitAssertBoolean(EAX, token_pos(), locs(), compiler); | 806 EmitAssertBoolean(EAX, token_pos(), locs(), compiler); |
| 794 } | 807 } |
| 795 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 808 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 796 __ CompareObject(EAX, compiler->bool_true()); | 809 __ CompareObject(EAX, compiler->bool_true()); |
| 797 branch->EmitBranchOnCondition(compiler, branch_condition); | 810 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 798 } | 811 } |
| 799 | 812 |
| 800 | 813 |
| 801 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { | 814 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 867 } | 880 } |
| 868 const String& function_name = | 881 const String& function_name = |
| 869 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 882 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 870 if (!compiler->is_optimizing()) { | 883 if (!compiler->is_optimizing()) { |
| 871 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | 884 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 872 deopt_id(), | 885 deopt_id(), |
| 873 token_pos()); | 886 token_pos()); |
| 874 } | 887 } |
| 875 const intptr_t kNumArguments = 2; | 888 const intptr_t kNumArguments = 2; |
| 876 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 889 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 890 ICData& relational_ic_data = ICData::ZoneHandle(ic_data()->raw()); |
| 891 if (relational_ic_data.IsNull()) { |
| 892 relational_ic_data = ICData::New(compiler->parsed_function().function(), |
| 893 function_name, |
| 894 deopt_id(), |
| 895 kNumArgsChecked); |
| 896 } |
| 877 compiler->GenerateInstanceCall(deopt_id(), | 897 compiler->GenerateInstanceCall(deopt_id(), |
| 878 token_pos(), | 898 token_pos(), |
| 879 function_name, | |
| 880 kNumArguments, | 899 kNumArguments, |
| 881 Array::ZoneHandle(), // No optional arguments. | 900 Array::ZoneHandle(), // No optional arguments. |
| 882 kNumArgsChecked, | 901 locs(), |
| 883 locs()); | 902 relational_ic_data); |
| 884 } | 903 } |
| 885 | 904 |
| 886 | 905 |
| 887 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 906 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 888 BranchInstr* branch) { | 907 BranchInstr* branch) { |
| 889 if (operands_class_id() == kSmiCid) { | 908 if (operands_class_id() == kSmiCid) { |
| 890 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); | 909 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); |
| 891 return; | 910 return; |
| 892 } | 911 } |
| 893 if (operands_class_id() == kDoubleCid) { | 912 if (operands_class_id() == kDoubleCid) { |
| (...skipping 1664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2558 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. | 2577 __ pcmpeqq(XMM0, XMM0); // Generate all 1's. |
| 2559 __ pxor(value, XMM0); | 2578 __ pxor(value, XMM0); |
| 2560 } | 2579 } |
| 2561 | 2580 |
| 2562 | 2581 |
| 2563 } // namespace dart | 2582 } // namespace dart |
| 2564 | 2583 |
| 2565 #undef __ | 2584 #undef __ |
| 2566 | 2585 |
| 2567 #endif // defined TARGET_ARCH_X64 | 2586 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |