Chromium Code Reviews| 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 } | 84 } |
| 85 if (FLAG_trace_functions) { | 85 if (FLAG_trace_functions) { |
| 86 const Function& function = | 86 const Function& function = |
| 87 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 87 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 88 __ LoadObject(temp, function); | 88 __ LoadObject(temp, function); |
| 89 __ pushl(result); // Preserve result. | 89 __ pushl(result); // Preserve result. |
| 90 __ pushl(temp); | 90 __ pushl(temp); |
| 91 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, | 91 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
| 92 0, | 92 0, |
| 93 CatchClauseNode::kInvalidTryIndex, | 93 CatchClauseNode::kInvalidTryIndex, |
| 94 kTraceFunctionExitRuntimeEntry); | 94 kTraceFunctionExitRuntimeEntry, |
| 95 locs()->stack_bitmap()); | |
|
Vyacheslav Egorov (Google)
2012/08/13 12:54:46
ReturnInstr is marked as NoCall. This code is susp
Kevin Millikin (Google)
2012/08/13 15:10:37
I know. We really don't want it to be a call beca
| |
| 95 __ popl(temp); // Remove argument. | 96 __ popl(temp); // Remove argument. |
| 96 __ popl(result); // Restore result. | 97 __ popl(result); // Restore result. |
| 97 } | 98 } |
| 98 #if defined(DEBUG) | 99 #if defined(DEBUG) |
| 99 // TODO(srdjan): Fix for functions with finally clause. | 100 // TODO(srdjan): Fix for functions with finally clause. |
| 100 // A finally clause may leave a previously pushed return value if it | 101 // A finally clause may leave a previously pushed return value if it |
| 101 // has its own return instruction. Method that have finally are currently | 102 // has its own return instruction. Method that have finally are currently |
| 102 // not optimized. | 103 // not optimized. |
| 103 if (!compiler->HasFinally()) { | 104 if (!compiler->HasFinally()) { |
| 104 Label done; | 105 Label done; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 Label done; | 210 Label done; |
| 210 __ CompareObject(obj, compiler->bool_true()); | 211 __ CompareObject(obj, compiler->bool_true()); |
| 211 __ j(EQUAL, &done, Assembler::kNearJump); | 212 __ j(EQUAL, &done, Assembler::kNearJump); |
| 212 __ CompareObject(obj, compiler->bool_false()); | 213 __ CompareObject(obj, compiler->bool_false()); |
| 213 __ j(EQUAL, &done, Assembler::kNearJump); | 214 __ j(EQUAL, &done, Assembler::kNearJump); |
| 214 | 215 |
| 215 __ pushl(obj); // Push the source object. | 216 __ pushl(obj); // Push the source object. |
| 216 compiler->GenerateCallRuntime(deopt_id(), | 217 compiler->GenerateCallRuntime(deopt_id(), |
| 217 token_pos(), | 218 token_pos(), |
| 218 try_index(), | 219 try_index(), |
| 219 kConditionTypeErrorRuntimeEntry); | 220 kConditionTypeErrorRuntimeEntry, |
| 221 locs()->stack_bitmap()); | |
| 220 // We should never return here. | 222 // We should never return here. |
| 221 __ int3(); | 223 __ int3(); |
| 222 | 224 |
| 223 __ Bind(&done); | 225 __ Bind(&done); |
| 224 ASSERT(obj == result); | 226 ASSERT(obj == result); |
| 225 } | 227 } |
| 226 | 228 |
| 227 | 229 |
| 228 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 230 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 229 switch (kind) { | 231 switch (kind) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 284 const int kNumberOfArguments = 2; | 286 const int kNumberOfArguments = 2; |
| 285 const Array& kNoArgumentNames = Array::Handle(); | 287 const Array& kNoArgumentNames = Array::Handle(); |
| 286 const int kNumArgumentsChecked = 2; | 288 const int kNumArgumentsChecked = 2; |
| 287 | 289 |
| 288 compiler->GenerateInstanceCall(comp->deopt_id(), | 290 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 289 comp->token_pos(), | 291 comp->token_pos(), |
| 290 comp->try_index(), | 292 comp->try_index(), |
| 291 operator_name, | 293 operator_name, |
| 292 kNumberOfArguments, | 294 kNumberOfArguments, |
| 293 kNoArgumentNames, | 295 kNoArgumentNames, |
| 294 kNumArgumentsChecked); | 296 kNumArgumentsChecked, |
| 297 comp->locs()->stack_bitmap()); | |
| 295 ASSERT(comp->locs()->out().reg() == EAX); | 298 ASSERT(comp->locs()->out().reg() == EAX); |
| 296 if (comp->kind() == Token::kNE) { | 299 if (comp->kind() == Token::kNE) { |
| 297 Label done, false_label; | 300 Label done, false_label; |
| 298 __ CompareObject(EAX, compiler->bool_true()); | 301 __ CompareObject(EAX, compiler->bool_true()); |
| 299 __ j(EQUAL, &false_label, Assembler::kNearJump); | 302 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 300 __ LoadObject(EAX, compiler->bool_true()); | 303 __ LoadObject(EAX, compiler->bool_true()); |
| 301 __ jmp(&done, Assembler::kNearJump); | 304 __ jmp(&done, Assembler::kNearJump); |
| 302 __ Bind(&false_label); | 305 __ Bind(&false_label); |
| 303 __ LoadObject(EAX, compiler->bool_false()); | 306 __ LoadObject(EAX, compiler->bool_false()); |
| 304 __ Bind(&done); | 307 __ Bind(&done); |
| 305 } | 308 } |
| 306 } | 309 } |
| 307 | 310 |
| 308 | 311 |
| 309 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 310 const ICData& orig_ic_data, | 313 const ICData& orig_ic_data, |
| 311 const LocationSummary& locs, | 314 const LocationSummary& locs, |
| 312 BranchInstr* branch, | 315 BranchInstr* branch, |
| 313 Token::Kind kind, | 316 Token::Kind kind, |
| 314 intptr_t deopt_id, | 317 intptr_t deopt_id, |
| 315 intptr_t token_pos, | 318 intptr_t token_pos, |
| 316 intptr_t try_index) { | 319 intptr_t try_index, |
| 320 BitmapBuilder* stack_bitmap) { | |
| 317 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 321 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 318 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 322 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 319 ASSERT(ic_data.NumberOfChecks() > 0); | 323 ASSERT(ic_data.NumberOfChecks() > 0); |
| 320 ASSERT(ic_data.num_args_tested() == 1); | 324 ASSERT(ic_data.num_args_tested() == 1); |
| 321 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); | 325 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); |
| 322 Register left = locs.in(0).reg(); | 326 Register left = locs.in(0).reg(); |
| 323 Register right = locs.in(1).reg(); | 327 Register right = locs.in(1).reg(); |
| 324 __ testl(left, Immediate(kSmiTagMask)); | 328 __ testl(left, Immediate(kSmiTagMask)); |
| 325 Register temp = locs.temp(0).reg(); | 329 Register temp = locs.temp(0).reg(); |
| 326 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 330 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 __ LoadObject(result, compiler->bool_true()); | 365 __ LoadObject(result, compiler->bool_true()); |
| 362 } | 366 } |
| 363 } else { | 367 } else { |
| 364 const int kNumberOfArguments = 2; | 368 const int kNumberOfArguments = 2; |
| 365 const Array& kNoArgumentNames = Array::Handle(); | 369 const Array& kNoArgumentNames = Array::Handle(); |
| 366 compiler->GenerateStaticCall(deopt_id, | 370 compiler->GenerateStaticCall(deopt_id, |
| 367 token_pos, | 371 token_pos, |
| 368 try_index, | 372 try_index, |
| 369 target, | 373 target, |
| 370 kNumberOfArguments, | 374 kNumberOfArguments, |
| 371 kNoArgumentNames); | 375 kNoArgumentNames, |
| 376 stack_bitmap); | |
| 372 if (branch == NULL) { | 377 if (branch == NULL) { |
| 373 if (kind == Token::kNE) { | 378 if (kind == Token::kNE) { |
| 374 Label false_label; | 379 Label false_label; |
| 375 __ CompareObject(EAX, compiler->bool_true()); | 380 __ CompareObject(EAX, compiler->bool_true()); |
| 376 __ j(EQUAL, &false_label, Assembler::kNearJump); | 381 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 377 __ LoadObject(EAX, compiler->bool_true()); | 382 __ LoadObject(EAX, compiler->bool_true()); |
| 378 __ jmp(&done); | 383 __ jmp(&done); |
| 379 __ Bind(&false_label); | 384 __ Bind(&false_label); |
| 380 __ LoadObject(EAX, compiler->bool_false()); | 385 __ LoadObject(EAX, compiler->bool_false()); |
| 381 __ jmp(&done); | 386 __ jmp(&done); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 __ LoadObject(result, compiler->bool_false()); | 431 __ LoadObject(result, compiler->bool_false()); |
| 427 __ jmp(&done); | 432 __ jmp(&done); |
| 428 __ Bind(&load_true); | 433 __ Bind(&load_true); |
| 429 __ LoadObject(result, compiler->bool_true()); | 434 __ LoadObject(result, compiler->bool_true()); |
| 430 } | 435 } |
| 431 __ jmp(&done); | 436 __ jmp(&done); |
| 432 __ Bind(&non_null_compare); // Receiver is not null. | 437 __ Bind(&non_null_compare); // Receiver is not null. |
| 433 __ pushl(left); | 438 __ pushl(left); |
| 434 __ pushl(right); | 439 __ pushl(right); |
| 435 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 440 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 436 deopt_id, token_pos, try_index); | 441 deopt_id, token_pos, try_index, |
| 442 locs.stack_bitmap()); | |
| 437 __ Bind(&done); | 443 __ Bind(&done); |
| 438 } | 444 } |
| 439 | 445 |
| 440 | 446 |
| 441 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 447 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 442 const LocationSummary& locs, | 448 const LocationSummary& locs, |
| 443 Token::Kind kind, | 449 Token::Kind kind, |
| 444 BranchInstr* branch, | 450 BranchInstr* branch, |
| 445 intptr_t deopt_id, | 451 intptr_t deopt_id, |
| 446 intptr_t token_pos, | 452 intptr_t token_pos, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 587 __ LoadClassId(EDI, EAX); | 593 __ LoadClassId(EDI, EAX); |
| 588 __ Bind(&done); | 594 __ Bind(&done); |
| 589 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 595 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 590 EDI, // Class id register. | 596 EDI, // Class id register. |
| 591 kNumArguments, | 597 kNumArguments, |
| 592 Array::Handle(), // No named arguments. | 598 Array::Handle(), // No named arguments. |
| 593 deopt, // Deoptimize target. | 599 deopt, // Deoptimize target. |
| 594 NULL, // Fallthrough when done. | 600 NULL, // Fallthrough when done. |
| 595 deopt_id(), | 601 deopt_id(), |
| 596 token_pos(), | 602 token_pos(), |
| 597 try_index()); | 603 try_index(), |
| 604 locs()->stack_bitmap()); | |
| 598 return; | 605 return; |
| 599 } | 606 } |
| 600 const String& function_name = | 607 const String& function_name = |
| 601 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 608 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 602 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 609 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 603 deopt_id(), | 610 deopt_id(), |
| 604 token_pos(), | 611 token_pos(), |
| 605 try_index()); | 612 try_index()); |
| 606 const intptr_t kNumArguments = 2; | 613 const intptr_t kNumArguments = 2; |
| 607 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 614 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 608 compiler->GenerateInstanceCall(deopt_id(), | 615 compiler->GenerateInstanceCall(deopt_id(), |
| 609 token_pos(), | 616 token_pos(), |
| 610 try_index(), | 617 try_index(), |
| 611 function_name, | 618 function_name, |
| 612 kNumArguments, | 619 kNumArguments, |
| 613 Array::ZoneHandle(), // No optional arguments. | 620 Array::ZoneHandle(), // No optional arguments. |
| 614 kNumArgsChecked); | 621 kNumArgsChecked, |
| 622 locs()->stack_bitmap()); | |
| 615 ASSERT(locs()->out().reg() == EAX); | 623 ASSERT(locs()->out().reg() == EAX); |
| 616 } | 624 } |
| 617 | 625 |
| 618 | 626 |
| 619 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 627 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 620 const intptr_t kNumInputs = 0; | 628 const intptr_t kNumInputs = 0; |
| 621 const intptr_t kNumTemps = 3; | 629 const intptr_t kNumTemps = 3; |
| 622 LocationSummary* locs = | 630 LocationSummary* locs = |
| 623 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 631 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 624 locs->set_temp(0, Location::RegisterLocation(EAX)); | 632 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 646 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 654 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
| 647 } else { | 655 } else { |
| 648 __ leal(EAX, | 656 __ leal(EAX, |
| 649 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 657 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 650 } | 658 } |
| 651 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 659 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 652 __ movl(EDX, Immediate(arg_count)); | 660 __ movl(EDX, Immediate(arg_count)); |
| 653 compiler->GenerateCall(token_pos(), | 661 compiler->GenerateCall(token_pos(), |
| 654 try_index(), | 662 try_index(), |
| 655 &StubCode::CallNativeCFunctionLabel(), | 663 &StubCode::CallNativeCFunctionLabel(), |
| 656 PcDescriptors::kOther); | 664 PcDescriptors::kOther, |
| 665 locs()->stack_bitmap()); | |
| 657 __ popl(result); | 666 __ popl(result); |
| 658 } | 667 } |
| 659 | 668 |
| 660 | 669 |
| 661 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 670 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 662 const intptr_t kNumInputs = 2; | 671 const intptr_t kNumInputs = 2; |
| 663 if ((receiver_type() == kGrowableObjectArrayCid) || | 672 if ((receiver_type() == kGrowableObjectArrayCid) || |
| 664 (receiver_type() == kArrayCid) || | 673 (receiver_type() == kArrayCid) || |
| 665 (receiver_type() == kImmutableArrayCid)) { | 674 (receiver_type() == kImmutableArrayCid)) { |
| 666 const intptr_t kNumTemps = 1; | 675 const intptr_t kNumTemps = 1; |
| 667 LocationSummary* locs = | 676 LocationSummary* locs = |
| 668 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 677 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 669 locs->set_in(0, Location::RequiresRegister()); | 678 locs->set_in(0, Location::RequiresRegister()); |
| 670 locs->set_in(1, Location::RequiresRegister()); | 679 locs->set_in(1, Location::RequiresRegister()); |
| 671 locs->set_temp(0, Location::RequiresRegister()); | 680 locs->set_temp(0, Location::RequiresRegister()); |
| 672 locs->set_out(Location::RequiresRegister()); | 681 locs->set_out(Location::RequiresRegister()); |
| 673 return locs; | 682 return locs; |
| 674 } else { | 683 } else { |
| 675 ASSERT(receiver_type() == kIllegalCid); | 684 ASSERT(receiver_type() == kIllegalCid); |
| 676 return MakeCallSummary(); | 685 return MakeCallSummary(); |
| 677 } | 686 } |
| 678 } | 687 } |
| 679 | 688 |
| 680 | 689 |
| 681 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 690 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 682 LoadIndexedComp* comp) { | 691 LoadIndexedComp* comp) { |
| 683 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 692 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 684 comp->try_index(), | 693 comp->try_index(), |
| 685 kDeoptLoadIndexedPolymorphic); | 694 kDeoptLoadIndexedPolymorphic); |
| 686 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 695 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 687 ASSERT(comp->HasICData()); | 696 ASSERT(comp->HasICData()); |
| 688 const ICData& ic_data = *comp->ic_data(); | 697 const ICData& ic_data = *comp->ic_data(); |
| 689 ASSERT(ic_data.num_args_tested() == 1); | 698 ASSERT(ic_data.num_args_tested() == 1); |
| 690 // No indexed access on Smi. | 699 // No indexed access on Smi. |
| 691 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); | 700 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 692 // Load receiver into EAX. | 701 // Load receiver into EAX. |
| 693 const intptr_t kNumArguments = 2; | 702 const intptr_t kNumArguments = 2; |
| 694 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 703 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 695 __ testl(EAX, Immediate(kSmiTagMask)); | 704 __ testl(EAX, Immediate(kSmiTagMask)); |
| 696 __ j(ZERO, deopt); | 705 __ j(ZERO, deopt); |
| 697 __ LoadClassId(EDI, EAX); | 706 __ LoadClassId(EDI, EAX); |
| 698 compiler->EmitTestAndCall(ic_data, | 707 compiler->EmitTestAndCall(ic_data, |
| 699 EDI, // Class id register. | 708 EDI, // Class id register. |
| 700 kNumArguments, | 709 kNumArguments, |
| 701 Array::Handle(), // No named arguments. | 710 Array::Handle(), // No named arguments. |
| 702 deopt, // Deoptimize target. | 711 deopt, // Deoptimize target. |
| 703 NULL, // Fallthrough when done. | 712 NULL, // Fallthrough when done. |
| 704 comp->deopt_id(), | 713 comp->deopt_id(), |
| 705 comp->token_pos(), | 714 comp->token_pos(), |
| 706 comp->try_index()); | 715 comp->try_index(), |
| 716 comp->locs()->stack_bitmap()); | |
| 707 } | 717 } |
| 708 | 718 |
| 709 | 719 |
| 710 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 720 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 711 if (receiver_type() == kIllegalCid) { | 721 if (receiver_type() == kIllegalCid) { |
| 712 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 722 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 713 EmitLoadIndexedPolymorphic(compiler, this); | 723 EmitLoadIndexedPolymorphic(compiler, this); |
| 714 } else { | 724 } else { |
| 715 compiler->EmitLoadIndexedGeneric(this); | 725 compiler->EmitLoadIndexedGeneric(this); |
| 716 } | 726 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 comp->try_index()); | 812 comp->try_index()); |
| 803 | 813 |
| 804 const intptr_t kNumArguments = 3; | 814 const intptr_t kNumArguments = 3; |
| 805 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 815 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 806 compiler->GenerateInstanceCall(comp->deopt_id(), | 816 compiler->GenerateInstanceCall(comp->deopt_id(), |
| 807 comp->token_pos(), | 817 comp->token_pos(), |
| 808 comp->try_index(), | 818 comp->try_index(), |
| 809 function_name, | 819 function_name, |
| 810 kNumArguments, | 820 kNumArguments, |
| 811 Array::ZoneHandle(), // No named arguments. | 821 Array::ZoneHandle(), // No named arguments. |
| 812 kNumArgsChecked); | 822 kNumArgsChecked, |
| 823 comp->locs()->stack_bitmap()); | |
| 813 } | 824 } |
| 814 | 825 |
| 815 | 826 |
| 816 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 827 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 817 StoreIndexedComp* comp) { | 828 StoreIndexedComp* comp) { |
| 818 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), | 829 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(), |
| 819 comp->try_index(), | 830 comp->try_index(), |
| 820 kDeoptStoreIndexedPolymorphic); | 831 kDeoptStoreIndexedPolymorphic); |
| 821 ASSERT(comp->ic_data()->NumberOfChecks() > 0); | 832 ASSERT(comp->ic_data()->NumberOfChecks() > 0); |
| 822 ASSERT(comp->HasICData()); | 833 ASSERT(comp->HasICData()); |
| 823 const ICData& ic_data = *comp->ic_data(); | 834 const ICData& ic_data = *comp->ic_data(); |
| 824 ASSERT(ic_data.num_args_tested() == 1); | 835 ASSERT(ic_data.num_args_tested() == 1); |
| 825 // No indexed access on Smi. | 836 // No indexed access on Smi. |
| 826 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); | 837 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmiCid); |
| 827 // Load receiver into EAX. | 838 // Load receiver into EAX. |
| 828 const intptr_t kNumArguments = 3; | 839 const intptr_t kNumArguments = 3; |
| 829 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 840 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 830 __ testl(EAX, Immediate(kSmiTagMask)); | 841 __ testl(EAX, Immediate(kSmiTagMask)); |
| 831 __ j(ZERO, deopt); | 842 __ j(ZERO, deopt); |
| 832 __ LoadClassId(EDI, EAX); | 843 __ LoadClassId(EDI, EAX); |
| 833 compiler->EmitTestAndCall(ic_data, | 844 compiler->EmitTestAndCall(ic_data, |
| 834 EDI, // Class id register. | 845 EDI, // Class id register. |
| 835 kNumArguments, | 846 kNumArguments, |
| 836 Array::Handle(), // No named arguments. | 847 Array::Handle(), // No named arguments. |
| 837 deopt, // Deoptimize target. | 848 deopt, // Deoptimize target. |
| 838 NULL, // Fallthrough when done. | 849 NULL, // Fallthrough when done. |
| 839 comp->deopt_id(), | 850 comp->deopt_id(), |
| 840 comp->token_pos(), | 851 comp->token_pos(), |
| 841 comp->try_index()); | 852 comp->try_index(), |
| 853 comp->locs()->stack_bitmap()); | |
| 842 } | 854 } |
| 843 | 855 |
| 844 | 856 |
| 845 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 857 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 846 if (receiver_type() == kIllegalCid) { | 858 if (receiver_type() == kIllegalCid) { |
| 847 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 859 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 848 EmitStoreIndexedPolymorphic(compiler, this); | 860 EmitStoreIndexedPolymorphic(compiler, this); |
| 849 } else { | 861 } else { |
| 850 EmitStoreIndexedGeneric(compiler, this); | 862 EmitStoreIndexedGeneric(compiler, this); |
| 851 } | 863 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 964 | 976 |
| 965 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 977 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 966 ASSERT(locs()->in(0).reg() == EAX); // Value. | 978 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 967 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 979 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 968 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 980 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 969 | 981 |
| 970 compiler->GenerateInstanceOf(deopt_id(), | 982 compiler->GenerateInstanceOf(deopt_id(), |
| 971 token_pos(), | 983 token_pos(), |
| 972 try_index(), | 984 try_index(), |
| 973 type(), | 985 type(), |
| 974 negate_result()); | 986 negate_result(), |
| 987 locs()->stack_bitmap()); | |
| 975 ASSERT(locs()->out().reg() == EAX); | 988 ASSERT(locs()->out().reg() == EAX); |
| 976 } | 989 } |
| 977 | 990 |
| 978 | 991 |
| 979 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 992 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 980 const intptr_t kNumInputs = 1; | 993 const intptr_t kNumInputs = 1; |
| 981 const intptr_t kNumTemps = 0; | 994 const intptr_t kNumTemps = 0; |
| 982 LocationSummary* locs = | 995 LocationSummary* locs = |
| 983 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 996 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 984 locs->set_in(0, Location::RegisterLocation(ECX)); | 997 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 985 locs->set_out(Location::RegisterLocation(EAX)); | 998 locs->set_out(Location::RegisterLocation(EAX)); |
| 986 return locs; | 999 return locs; |
| 987 } | 1000 } |
| 988 | 1001 |
| 989 | 1002 |
| 990 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1003 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 991 // Allocate the array. EDX = length, ECX = element type. | 1004 // Allocate the array. EDX = length, ECX = element type. |
| 992 ASSERT(locs()->in(0).reg() == ECX); | 1005 ASSERT(locs()->in(0).reg() == ECX); |
| 993 __ movl(EDX, Immediate(Smi::RawValue(ElementCount()))); | 1006 __ movl(EDX, Immediate(Smi::RawValue(ElementCount()))); |
| 994 compiler->GenerateCall(token_pos(), | 1007 compiler->GenerateCall(token_pos(), |
| 995 try_index(), | 1008 try_index(), |
| 996 &StubCode::AllocateArrayLabel(), | 1009 &StubCode::AllocateArrayLabel(), |
| 997 PcDescriptors::kOther); | 1010 PcDescriptors::kOther, |
| 1011 locs()->stack_bitmap()); | |
| 998 ASSERT(locs()->out().reg() == EAX); | 1012 ASSERT(locs()->out().reg() == EAX); |
| 999 | 1013 |
| 1000 // Pop the element values from the stack into the array. | 1014 // Pop the element values from the stack into the array. |
| 1001 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); | 1015 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); |
| 1002 for (int i = ElementCount() - 1; i >= 0; --i) { | 1016 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 1003 ASSERT(ElementAt(i)->IsUse()); | 1017 ASSERT(ElementAt(i)->IsUse()); |
| 1004 __ popl(Address(EDX, i * kWordSize)); | 1018 __ popl(Address(EDX, i * kWordSize)); |
| 1005 } | 1019 } |
| 1006 } | 1020 } |
| 1007 | 1021 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1027 Register result = locs()->out().reg(); | 1041 Register result = locs()->out().reg(); |
| 1028 | 1042 |
| 1029 // Push the result place holder initialized to NULL. | 1043 // Push the result place holder initialized to NULL. |
| 1030 __ PushObject(Object::ZoneHandle()); | 1044 __ PushObject(Object::ZoneHandle()); |
| 1031 __ PushObject(cls); | 1045 __ PushObject(cls); |
| 1032 __ pushl(type_arguments); | 1046 __ pushl(type_arguments); |
| 1033 __ pushl(instantiator_type_arguments); | 1047 __ pushl(instantiator_type_arguments); |
| 1034 compiler->GenerateCallRuntime(deopt_id(), | 1048 compiler->GenerateCallRuntime(deopt_id(), |
| 1035 token_pos(), | 1049 token_pos(), |
| 1036 try_index(), | 1050 try_index(), |
| 1037 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1051 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1052 locs()->stack_bitmap()); | |
| 1038 // Pop instantiator type arguments, type arguments, and class. | 1053 // Pop instantiator type arguments, type arguments, and class. |
| 1039 // source location. | 1054 // source location. |
| 1040 __ Drop(3); | 1055 __ Drop(3); |
| 1041 __ popl(result); // Pop new instance. | 1056 __ popl(result); // Pop new instance. |
| 1042 } | 1057 } |
| 1043 | 1058 |
| 1044 | 1059 |
| 1045 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1060 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1046 return LocationSummary::Make(1, | 1061 return LocationSummary::Make(1, |
| 1047 Location::RequiresRegister(), | 1062 Location::RequiresRegister(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1115 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1130 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1116 __ Bind(&type_arguments_uninstantiated); | 1131 __ Bind(&type_arguments_uninstantiated); |
| 1117 } | 1132 } |
| 1118 // A runtime call to instantiate the type arguments is required. | 1133 // A runtime call to instantiate the type arguments is required. |
| 1119 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1134 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1120 __ PushObject(type_arguments()); | 1135 __ PushObject(type_arguments()); |
| 1121 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1136 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1122 compiler->GenerateCallRuntime(deopt_id(), | 1137 compiler->GenerateCallRuntime(deopt_id(), |
| 1123 token_pos(), | 1138 token_pos(), |
| 1124 try_index(), | 1139 try_index(), |
| 1125 kInstantiateTypeArgumentsRuntimeEntry); | 1140 kInstantiateTypeArgumentsRuntimeEntry, |
| 1141 locs()->stack_bitmap()); | |
| 1126 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1142 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1127 __ popl(result_reg); // Pop instantiated type arguments. | 1143 __ popl(result_reg); // Pop instantiated type arguments. |
| 1128 __ Bind(&type_arguments_instantiated); | 1144 __ Bind(&type_arguments_instantiated); |
| 1129 ASSERT(instantiator_reg == result_reg); | 1145 ASSERT(instantiator_reg == result_reg); |
| 1130 // 'result_reg': Instantiated type arguments. | 1146 // 'result_reg': Instantiated type arguments. |
| 1131 } | 1147 } |
| 1132 | 1148 |
| 1133 | 1149 |
| 1134 LocationSummary* | 1150 LocationSummary* |
| 1135 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 1151 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1271 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1287 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1272 ASSERT(locs()->temp(0).reg() == EDX); | 1288 ASSERT(locs()->temp(0).reg() == EDX); |
| 1273 ASSERT(locs()->out().reg() == EAX); | 1289 ASSERT(locs()->out().reg() == EAX); |
| 1274 | 1290 |
| 1275 __ movl(EDX, Immediate(num_context_variables())); | 1291 __ movl(EDX, Immediate(num_context_variables())); |
| 1276 const ExternalLabel label("alloc_context", | 1292 const ExternalLabel label("alloc_context", |
| 1277 StubCode::AllocateContextEntryPoint()); | 1293 StubCode::AllocateContextEntryPoint()); |
| 1278 compiler->GenerateCall(token_pos(), | 1294 compiler->GenerateCall(token_pos(), |
| 1279 try_index(), | 1295 try_index(), |
| 1280 &label, | 1296 &label, |
| 1281 PcDescriptors::kOther); | 1297 PcDescriptors::kOther, |
| 1298 locs()->stack_bitmap()); | |
| 1282 } | 1299 } |
| 1283 | 1300 |
| 1284 | 1301 |
| 1285 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1302 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1286 const intptr_t kNumInputs = 1; | 1303 const intptr_t kNumInputs = 1; |
| 1287 const intptr_t kNumTemps = 0; | 1304 const intptr_t kNumTemps = 0; |
| 1288 LocationSummary* locs = | 1305 LocationSummary* locs = |
| 1289 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1306 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1290 locs->set_in(0, Location::RegisterLocation(EAX)); | 1307 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1291 locs->set_out(Location::RegisterLocation(EAX)); | 1308 locs->set_out(Location::RegisterLocation(EAX)); |
| 1292 return locs; | 1309 return locs; |
| 1293 } | 1310 } |
| 1294 | 1311 |
| 1295 | 1312 |
| 1296 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1313 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1297 Register context_value = locs()->in(0).reg(); | 1314 Register context_value = locs()->in(0).reg(); |
| 1298 Register result = locs()->out().reg(); | 1315 Register result = locs()->out().reg(); |
| 1299 | 1316 |
| 1300 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1317 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1301 __ pushl(context_value); | 1318 __ pushl(context_value); |
| 1302 compiler->GenerateCallRuntime(deopt_id(), | 1319 compiler->GenerateCallRuntime(deopt_id(), |
| 1303 token_pos(), | 1320 token_pos(), |
| 1304 try_index(), | 1321 try_index(), |
| 1305 kCloneContextRuntimeEntry); | 1322 kCloneContextRuntimeEntry, |
| 1323 locs()->stack_bitmap()); | |
| 1306 __ popl(result); // Remove argument. | 1324 __ popl(result); // Remove argument. |
| 1307 __ popl(result); // Get result (cloned context). | 1325 __ popl(result); // Get result (cloned context). |
| 1308 } | 1326 } |
| 1309 | 1327 |
| 1310 | 1328 |
| 1311 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1329 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1312 return LocationSummary::Make(0, | 1330 return LocationSummary::Make(0, |
| 1313 Location::NoLocation(), | 1331 Location::NoLocation(), |
| 1314 LocationSummary::kNoCall); | 1332 LocationSummary::kNoCall); |
| 1315 } | 1333 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1346 | 1364 |
| 1347 | 1365 |
| 1348 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1366 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1349 __ cmpl(ESP, | 1367 __ cmpl(ESP, |
| 1350 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1368 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1351 Label no_stack_overflow; | 1369 Label no_stack_overflow; |
| 1352 __ j(ABOVE, &no_stack_overflow); | 1370 __ j(ABOVE, &no_stack_overflow); |
| 1353 compiler->GenerateCallRuntime(deopt_id(), | 1371 compiler->GenerateCallRuntime(deopt_id(), |
| 1354 token_pos(), | 1372 token_pos(), |
| 1355 try_index(), | 1373 try_index(), |
| 1356 kStackOverflowRuntimeEntry); | 1374 kStackOverflowRuntimeEntry, |
| 1375 locs()->stack_bitmap()); | |
| 1357 __ Bind(&no_stack_overflow); | 1376 __ Bind(&no_stack_overflow); |
| 1358 } | 1377 } |
| 1359 | 1378 |
| 1360 | 1379 |
| 1361 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1380 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1362 const intptr_t kNumInputs = 2; | 1381 const intptr_t kNumInputs = 2; |
| 1363 | 1382 |
| 1364 // Double operation are handled in DoubleBinaryOpComp. | 1383 // Double operation are handled in DoubleBinaryOpComp. |
| 1365 ASSERT(operands_type() != kDoubleOperands); | 1384 ASSERT(operands_type() != kDoubleOperands); |
| 1366 | 1385 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1532 __ shll(left, right_temp); | 1551 __ shll(left, right_temp); |
| 1533 __ jmp(&done); | 1552 __ jmp(&done); |
| 1534 { | 1553 { |
| 1535 __ Bind(&call_method); | 1554 __ Bind(&call_method); |
| 1536 Function& target = Function::ZoneHandle( | 1555 Function& target = Function::ZoneHandle( |
| 1537 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1556 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1538 ASSERT(!target.IsNull()); | 1557 ASSERT(!target.IsNull()); |
| 1539 const intptr_t kArgumentCount = 2; | 1558 const intptr_t kArgumentCount = 2; |
| 1540 __ pushl(temp); | 1559 __ pushl(temp); |
| 1541 __ pushl(right); | 1560 __ pushl(right); |
| 1542 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1561 compiler->GenerateStaticCall( |
| 1543 comp->instance_call()->token_pos(), | 1562 comp->instance_call()->deopt_id(), |
| 1544 comp->instance_call()->try_index(), | 1563 comp->instance_call()->token_pos(), |
| 1545 target, | 1564 comp->instance_call()->try_index(), |
| 1546 kArgumentCount, | 1565 target, |
| 1547 Array::Handle()); // No argument names. | 1566 kArgumentCount, |
| 1567 Array::Handle(), // No argument names. | |
| 1568 comp->locs()->stack_bitmap()); | |
| 1548 ASSERT(result == EAX); | 1569 ASSERT(result == EAX); |
| 1549 } | 1570 } |
| 1550 __ Bind(&done); | 1571 __ Bind(&done); |
| 1551 break; | 1572 break; |
| 1552 } | 1573 } |
| 1553 case Token::kDIV: { | 1574 case Token::kDIV: { |
| 1554 // Dispatches to 'Double./'. | 1575 // Dispatches to 'Double./'. |
| 1555 // TODO(srdjan): Implement as conversion to double and double division. | 1576 // TODO(srdjan): Implement as conversion to double and double division. |
| 1556 UNREACHABLE(); | 1577 UNREACHABLE(); |
| 1557 break; | 1578 break; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1626 | 1647 |
| 1627 __ Bind(&smi_static_call); | 1648 __ Bind(&smi_static_call); |
| 1628 { | 1649 { |
| 1629 Function& target = Function::ZoneHandle( | 1650 Function& target = Function::ZoneHandle( |
| 1630 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1651 comp->ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1631 if (target.IsNull()) { | 1652 if (target.IsNull()) { |
| 1632 __ jmp(deopt); | 1653 __ jmp(deopt); |
| 1633 } else { | 1654 } else { |
| 1634 __ pushl(left); | 1655 __ pushl(left); |
| 1635 __ pushl(right); | 1656 __ pushl(right); |
| 1636 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1657 compiler->GenerateStaticCall( |
| 1637 comp->instance_call()->token_pos(), | 1658 comp->instance_call()->deopt_id(), |
| 1638 comp->instance_call()->try_index(), | 1659 comp->instance_call()->token_pos(), |
| 1639 target, | 1660 comp->instance_call()->try_index(), |
| 1640 comp->instance_call()->ArgumentCount(), | 1661 target, |
| 1641 comp->instance_call()->argument_names()); | 1662 comp->instance_call()->ArgumentCount(), |
| 1663 comp->instance_call()->argument_names(), | |
| 1664 comp->locs()->stack_bitmap()); | |
| 1642 ASSERT(result == EAX); | 1665 ASSERT(result == EAX); |
| 1643 __ jmp(&done); | 1666 __ jmp(&done); |
| 1644 } | 1667 } |
| 1645 } | 1668 } |
| 1646 | 1669 |
| 1647 __ Bind(&mint_static_call); | 1670 __ Bind(&mint_static_call); |
| 1648 { | 1671 { |
| 1649 Function& target = Function::ZoneHandle( | 1672 Function& target = Function::ZoneHandle( |
| 1650 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1673 comp->ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1651 if (target.IsNull()) { | 1674 if (target.IsNull()) { |
| 1652 __ jmp(deopt); | 1675 __ jmp(deopt); |
| 1653 } else { | 1676 } else { |
| 1654 __ pushl(left); | 1677 __ pushl(left); |
| 1655 __ pushl(right); | 1678 __ pushl(right); |
| 1656 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(), | 1679 compiler->GenerateStaticCall( |
| 1657 comp->instance_call()->token_pos(), | 1680 comp->instance_call()->deopt_id(), |
| 1658 comp->instance_call()->try_index(), | 1681 comp->instance_call()->token_pos(), |
| 1659 target, | 1682 comp->instance_call()->try_index(), |
| 1660 comp->instance_call()->ArgumentCount(), | 1683 target, |
| 1661 comp->instance_call()->argument_names()); | 1684 comp->instance_call()->ArgumentCount(), |
| 1685 comp->instance_call()->argument_names(), | |
| 1686 comp->locs()->stack_bitmap()); | |
| 1662 ASSERT(result == EAX); | 1687 ASSERT(result == EAX); |
| 1663 } | 1688 } |
| 1664 } | 1689 } |
| 1665 __ Bind(&done); | 1690 __ Bind(&done); |
| 1666 } | 1691 } |
| 1667 | 1692 |
| 1668 | 1693 |
| 1669 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1694 void BinaryOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1670 switch (operands_type()) { | 1695 switch (operands_type()) { |
| 1671 case kSmiOperands: | 1696 case kSmiOperands: |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1693 Register temp = EDX; | 1718 Register temp = EDX; |
| 1694 Register result = locs()->out().reg(); | 1719 Register result = locs()->out().reg(); |
| 1695 | 1720 |
| 1696 const Class& double_class = compiler->double_class(); | 1721 const Class& double_class = compiler->double_class(); |
| 1697 const Code& stub = | 1722 const Code& stub = |
| 1698 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1723 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1699 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1724 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1700 compiler->GenerateCall(instance_call()->token_pos(), | 1725 compiler->GenerateCall(instance_call()->token_pos(), |
| 1701 instance_call()->try_index(), | 1726 instance_call()->try_index(), |
| 1702 &label, | 1727 &label, |
| 1703 PcDescriptors::kOther); | 1728 PcDescriptors::kOther, |
| 1729 locs()->stack_bitmap()); | |
| 1704 // Newly allocated object is now in the result register (RAX). | 1730 // Newly allocated object is now in the result register (RAX). |
| 1705 ASSERT(result == EAX); | 1731 ASSERT(result == EAX); |
| 1706 __ popl(right); | 1732 __ popl(right); |
| 1707 __ popl(left); | 1733 __ popl(left); |
| 1708 | 1734 |
| 1709 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1735 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1710 instance_call()->try_index(), | 1736 instance_call()->try_index(), |
| 1711 kDeoptDoubleBinaryOp, | 1737 kDeoptDoubleBinaryOp, |
| 1712 left, | 1738 left, |
| 1713 right); | 1739 right); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1820 __ j(NOT_EQUAL, deopt); | 1846 __ j(NOT_EQUAL, deopt); |
| 1821 // Allocate result object. | 1847 // Allocate result object. |
| 1822 const Class& double_class = compiler->double_class(); | 1848 const Class& double_class = compiler->double_class(); |
| 1823 const Code& stub = | 1849 const Code& stub = |
| 1824 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1850 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1825 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1851 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1826 __ pushl(value); | 1852 __ pushl(value); |
| 1827 compiler->GenerateCall(instance_call()->token_pos(), | 1853 compiler->GenerateCall(instance_call()->token_pos(), |
| 1828 instance_call()->try_index(), | 1854 instance_call()->try_index(), |
| 1829 &label, | 1855 &label, |
| 1830 PcDescriptors::kOther); | 1856 PcDescriptors::kOther, |
| 1857 locs()->stack_bitmap()); | |
| 1831 // Result is in EAX. | 1858 // Result is in EAX. |
| 1832 ASSERT(result != temp); | 1859 ASSERT(result != temp); |
| 1833 __ movl(result, EAX); | 1860 __ movl(result, EAX); |
| 1834 __ popl(temp); | 1861 __ popl(temp); |
| 1835 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1862 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1836 __ DoubleNegate(XMM0); | 1863 __ DoubleNegate(XMM0); |
| 1837 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1864 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1838 } else { | 1865 } else { |
| 1839 UNREACHABLE(); | 1866 UNREACHABLE(); |
| 1840 } | 1867 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1884 | 1911 |
| 1885 const Class& double_class = compiler->double_class(); | 1912 const Class& double_class = compiler->double_class(); |
| 1886 const Code& stub = | 1913 const Code& stub = |
| 1887 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1914 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1888 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1915 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1889 | 1916 |
| 1890 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1917 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 1891 compiler->GenerateCall(instance_call()->token_pos(), | 1918 compiler->GenerateCall(instance_call()->token_pos(), |
| 1892 instance_call()->try_index(), | 1919 instance_call()->try_index(), |
| 1893 &label, | 1920 &label, |
| 1894 PcDescriptors::kOther); | 1921 PcDescriptors::kOther, |
| 1922 locs()->stack_bitmap()); | |
| 1895 ASSERT(result == EAX); | 1923 ASSERT(result == EAX); |
| 1896 __ popl(value); | 1924 __ popl(value); |
| 1897 | 1925 |
| 1898 __ testl(value, Immediate(kSmiTagMask)); | 1926 __ testl(value, Immediate(kSmiTagMask)); |
| 1899 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1927 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1900 __ SmiUntag(value); | 1928 __ SmiUntag(value); |
| 1901 __ cvtsi2sd(XMM0, value); | 1929 __ cvtsi2sd(XMM0, value); |
| 1902 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1930 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1903 } | 1931 } |
| 1904 | 1932 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1930 Label done; | 1958 Label done; |
| 1931 __ LoadClassId(EDI, EAX); | 1959 __ LoadClassId(EDI, EAX); |
| 1932 compiler->EmitTestAndCall(*ic_data(), | 1960 compiler->EmitTestAndCall(*ic_data(), |
| 1933 EDI, // Class id register. | 1961 EDI, // Class id register. |
| 1934 instance_call()->ArgumentCount(), | 1962 instance_call()->ArgumentCount(), |
| 1935 instance_call()->argument_names(), | 1963 instance_call()->argument_names(), |
| 1936 deopt, | 1964 deopt, |
| 1937 (is_smi_label == &handle_smi) ? &done : NULL, | 1965 (is_smi_label == &handle_smi) ? &done : NULL, |
| 1938 instance_call()->deopt_id(), | 1966 instance_call()->deopt_id(), |
| 1939 instance_call()->token_pos(), | 1967 instance_call()->token_pos(), |
| 1940 instance_call()->try_index()); | 1968 instance_call()->try_index(), |
| 1969 locs()->stack_bitmap()); | |
| 1941 if (is_smi_label == &handle_smi) { | 1970 if (is_smi_label == &handle_smi) { |
| 1942 __ Bind(&handle_smi); | 1971 __ Bind(&handle_smi); |
| 1943 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); | 1972 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
| 1944 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1973 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1945 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1974 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1946 instance_call()->token_pos(), | 1975 instance_call()->token_pos(), |
| 1947 instance_call()->try_index(), | 1976 instance_call()->try_index(), |
| 1948 target, | 1977 target, |
| 1949 instance_call()->ArgumentCount(), | 1978 instance_call()->ArgumentCount(), |
| 1950 instance_call()->argument_names()); | 1979 instance_call()->argument_names(), |
| 1980 locs()->stack_bitmap()); | |
| 1951 } | 1981 } |
| 1952 __ Bind(&done); | 1982 __ Bind(&done); |
| 1953 } | 1983 } |
| 1954 | 1984 |
| 1955 | 1985 |
| 1956 // TODO(srdjan): Move to shared. | 1986 // TODO(srdjan): Move to shared. |
| 1957 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { | 1987 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { |
| 1958 if (ic_data.num_args_tested() != 2) return false; | 1988 if (ic_data.num_args_tested() != 2) return false; |
| 1959 if (ic_data.NumberOfChecks() != 1) return false; | 1989 if (ic_data.NumberOfChecks() != 1) return false; |
| 1960 Function& target = Function::Handle(); | 1990 Function& target = Function::Handle(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2042 token_pos(), | 2072 token_pos(), |
| 2043 try_index()); | 2073 try_index()); |
| 2044 const intptr_t kNumArguments = 2; | 2074 const intptr_t kNumArguments = 2; |
| 2045 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2075 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 2046 compiler->GenerateInstanceCall(deopt_id(), | 2076 compiler->GenerateInstanceCall(deopt_id(), |
| 2047 token_pos(), | 2077 token_pos(), |
| 2048 try_index(), | 2078 try_index(), |
| 2049 function_name, | 2079 function_name, |
| 2050 kNumArguments, | 2080 kNumArguments, |
| 2051 Array::ZoneHandle(), // No optional arguments. | 2081 Array::ZoneHandle(), // No optional arguments. |
| 2052 kNumArgsChecked); | 2082 kNumArgsChecked, |
| 2083 locs()->stack_bitmap()); | |
| 2053 ASSERT(locs()->out().reg() == EAX); | 2084 ASSERT(locs()->out().reg() == EAX); |
| 2054 __ CompareObject(locs()->out().reg(), compiler->bool_true()); | 2085 __ CompareObject(locs()->out().reg(), compiler->bool_true()); |
| 2055 EmitBranchOnCondition(compiler, branch_condition); | 2086 EmitBranchOnCondition(compiler, branch_condition); |
| 2056 } | 2087 } |
| 2057 | 2088 |
| 2058 } // namespace dart | 2089 } // namespace dart |
| 2059 | 2090 |
| 2060 #undef __ | 2091 #undef __ |
| 2061 | 2092 |
| 2062 #endif // defined TARGET_ARCH_X64 | 2093 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |