| 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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 const ICData& original_ic_data) { | 303 const ICData& original_ic_data) { |
| 304 if (!compiler->is_optimizing()) { | 304 if (!compiler->is_optimizing()) { |
| 305 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 305 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 306 deopt_id, | 306 deopt_id, |
| 307 token_pos); | 307 token_pos); |
| 308 } | 308 } |
| 309 const int kNumberOfArguments = 2; | 309 const int kNumberOfArguments = 2; |
| 310 const Array& kNoArgumentNames = Object::null_array(); | 310 const Array& kNoArgumentNames = Object::null_array(); |
| 311 const int kNumArgumentsChecked = 2; | 311 const int kNumArgumentsChecked = 2; |
| 312 | 312 |
| 313 const Immediate& raw_null = | |
| 314 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 315 Label check_identity; | |
| 316 __ cmpl(Address(ESP, 0 * kWordSize), raw_null); | |
| 317 __ j(EQUAL, &check_identity); | |
| 318 __ cmpl(Address(ESP, 1 * kWordSize), raw_null); | |
| 319 __ j(EQUAL, &check_identity); | |
| 320 | |
| 321 ICData& equality_ic_data = ICData::ZoneHandle(); | 313 ICData& equality_ic_data = ICData::ZoneHandle(); |
| 322 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { | 314 if (compiler->is_optimizing() && FLAG_propagate_ic_data) { |
| 323 ASSERT(!original_ic_data.IsNull()); | 315 ASSERT(!original_ic_data.IsNull()); |
| 324 if (original_ic_data.NumberOfChecks() == 0) { | 316 if (original_ic_data.NumberOfChecks() == 0) { |
| 325 // IC call for reoptimization populates original ICData. | 317 // IC call for reoptimization populates original ICData. |
| 326 equality_ic_data = original_ic_data.raw(); | 318 equality_ic_data = original_ic_data.raw(); |
| 327 } else { | 319 } else { |
| 328 // Megamorphic call. | 320 // Megamorphic call. |
| 329 equality_ic_data = original_ic_data.AsUnaryClassChecks(); | 321 equality_ic_data = original_ic_data.AsUnaryClassChecks(); |
| 330 } | 322 } |
| 331 } else { | 323 } else { |
| 332 const Array& arguments_descriptor = | 324 const Array& arguments_descriptor = |
| 333 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, | 325 Array::Handle(ArgumentsDescriptor::New(kNumberOfArguments, |
| 334 kNoArgumentNames)); | 326 kNoArgumentNames)); |
| 335 equality_ic_data = ICData::New(compiler->parsed_function().function(), | 327 equality_ic_data = ICData::New(compiler->parsed_function().function(), |
| 336 Symbols::EqualOperator(), | 328 Symbols::EqualOperator(), |
| 337 arguments_descriptor, | 329 arguments_descriptor, |
| 338 deopt_id, | 330 deopt_id, |
| 339 kNumArgumentsChecked); | 331 kNumArgumentsChecked); |
| 340 } | 332 } |
| 341 compiler->GenerateInstanceCall(deopt_id, | 333 compiler->GenerateInstanceCall(deopt_id, |
| 342 token_pos, | 334 token_pos, |
| 343 kNumberOfArguments, | 335 kNumberOfArguments, |
| 344 kNoArgumentNames, | 336 kNoArgumentNames, |
| 345 locs, | 337 locs, |
| 346 equality_ic_data); | 338 equality_ic_data); |
| 347 Label check_ne; | |
| 348 __ jmp(&check_ne); | |
| 349 | |
| 350 __ Bind(&check_identity); | |
| 351 Label equality_done; | |
| 352 if (compiler->is_optimizing()) { | |
| 353 // No need to update IC data. | |
| 354 Label is_true; | |
| 355 __ popl(EAX); | |
| 356 __ popl(EDX); | |
| 357 __ cmpl(EAX, EDX); | |
| 358 __ j(EQUAL, &is_true); | |
| 359 __ LoadObject(EAX, Bool::Get(kind != Token::kEQ)); | |
| 360 __ jmp(&equality_done); | |
| 361 __ Bind(&is_true); | |
| 362 __ LoadObject(EAX, Bool::Get(kind == Token::kEQ)); | |
| 363 if (kind == Token::kNE) { | |
| 364 // Skip not-equal result conversion. | |
| 365 __ jmp(&equality_done); | |
| 366 } | |
| 367 } else { | |
| 368 // Call stub, load IC data in register. The stub will update ICData if | |
| 369 // necessary. | |
| 370 Register ic_data_reg = locs->temp(0).reg(); | |
| 371 ASSERT(ic_data_reg == ECX); // Stub depends on it. | |
| 372 __ LoadObject(ic_data_reg, equality_ic_data); | |
| 373 compiler->GenerateCall(token_pos, | |
| 374 &StubCode::EqualityWithNullArgLabel(), | |
| 375 PcDescriptors::kRuntimeCall, | |
| 376 locs); | |
| 377 __ Drop(2); | |
| 378 } | |
| 379 __ Bind(&check_ne); | |
| 380 if (kind == Token::kNE) { | 339 if (kind == Token::kNE) { |
| 381 Label true_label, done; | 340 Label true_label, done; |
| 382 // Negate the condition: true label returns false and vice versa. | 341 // Negate the condition: true label returns false and vice versa. |
| 383 __ CompareObject(EAX, Bool::True()); | 342 __ CompareObject(EAX, Bool::True()); |
| 384 __ j(EQUAL, &true_label, Assembler::kNearJump); | 343 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 385 __ LoadObject(EAX, Bool::True()); | 344 __ LoadObject(EAX, Bool::True()); |
| 386 __ jmp(&done, Assembler::kNearJump); | 345 __ jmp(&done, Assembler::kNearJump); |
| 387 __ Bind(&true_label); | 346 __ Bind(&true_label); |
| 388 __ LoadObject(EAX, Bool::False()); | 347 __ LoadObject(EAX, Bool::False()); |
| 389 __ Bind(&done); | 348 __ Bind(&done); |
| 390 } | 349 } |
| 391 __ Bind(&equality_done); | |
| 392 } | 350 } |
| 393 | 351 |
| 394 | 352 |
| 395 static void LoadValueCid(FlowGraphCompiler* compiler, | 353 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 396 Register value_cid_reg, | 354 Register value_cid_reg, |
| 397 Register value_reg, | 355 Register value_reg, |
| 398 Label* value_is_smi = NULL) { | 356 Label* value_is_smi = NULL) { |
| 399 Label done; | 357 Label done; |
| 400 if (value_is_smi == NULL) { | 358 if (value_is_smi == NULL) { |
| 401 __ movl(value_cid_reg, Immediate(kSmiCid)); | 359 __ movl(value_cid_reg, Immediate(kSmiCid)); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 LocationSummary* locs, | 513 LocationSummary* locs, |
| 556 Token::Kind kind, | 514 Token::Kind kind, |
| 557 BranchInstr* branch, | 515 BranchInstr* branch, |
| 558 const ICData& ic_data, | 516 const ICData& ic_data, |
| 559 intptr_t deopt_id, | 517 intptr_t deopt_id, |
| 560 intptr_t token_pos) { | 518 intptr_t token_pos) { |
| 561 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 519 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 562 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 520 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 563 Register left = locs->in(0).reg(); | 521 Register left = locs->in(0).reg(); |
| 564 Register right = locs->in(1).reg(); | 522 Register right = locs->in(1).reg(); |
| 565 const Immediate& raw_null = | |
| 566 Immediate(reinterpret_cast<intptr_t>(Object::null())); | |
| 567 Label done, identity_compare, non_null_compare; | |
| 568 __ cmpl(right, raw_null); | |
| 569 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | |
| 570 __ cmpl(left, raw_null); | |
| 571 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | |
| 572 // Comparison with NULL is "===". | |
| 573 __ Bind(&identity_compare); | |
| 574 __ cmpl(left, right); | |
| 575 Condition cond = TokenKindToSmiCondition(kind); | |
| 576 if (branch != NULL) { | |
| 577 branch->EmitBranchOnCondition(compiler, cond); | |
| 578 } else { | |
| 579 Register result = locs->out().reg(); | |
| 580 Label load_true; | |
| 581 __ j(cond, &load_true, Assembler::kNearJump); | |
| 582 __ LoadObject(result, Bool::False()); | |
| 583 __ jmp(&done); | |
| 584 __ Bind(&load_true); | |
| 585 __ LoadObject(result, Bool::True()); | |
| 586 } | |
| 587 __ jmp(&done); | |
| 588 __ Bind(&non_null_compare); // Receiver is not null. | |
| 589 __ pushl(left); | 523 __ pushl(left); |
| 590 __ pushl(right); | 524 __ pushl(right); |
| 591 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 525 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 592 deopt_id, token_pos); | 526 deopt_id, token_pos); |
| 593 __ Bind(&done); | |
| 594 } | 527 } |
| 595 | 528 |
| 596 | 529 |
| 597 static Condition FlipCondition(Condition condition) { | 530 static Condition FlipCondition(Condition condition) { |
| 598 switch (condition) { | 531 switch (condition) { |
| 599 case EQUAL: return EQUAL; | 532 case EQUAL: return EQUAL; |
| 600 case NOT_EQUAL: return NOT_EQUAL; | 533 case NOT_EQUAL: return NOT_EQUAL; |
| 601 case LESS: return GREATER; | 534 case LESS: return GREATER; |
| 602 case LESS_EQUAL: return GREATER_EQUAL; | 535 case LESS_EQUAL: return GREATER_EQUAL; |
| 603 case GREATER: return LESS; | 536 case GREATER: return LESS; |
| (...skipping 4629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5233 PcDescriptors::kOther, | 5166 PcDescriptors::kOther, |
| 5234 locs()); | 5167 locs()); |
| 5235 __ Drop(2); // Discard type arguments and receiver. | 5168 __ Drop(2); // Discard type arguments and receiver. |
| 5236 } | 5169 } |
| 5237 | 5170 |
| 5238 } // namespace dart | 5171 } // namespace dart |
| 5239 | 5172 |
| 5240 #undef __ | 5173 #undef __ |
| 5241 | 5174 |
| 5242 #endif // defined TARGET_ARCH_IA32 | 5175 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |