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/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 80 } |
81 } | 81 } |
82 if (FLAG_trace_functions) { | 82 if (FLAG_trace_functions) { |
83 const Function& function = | 83 const Function& function = |
84 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 84 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
85 __ LoadObject(temp, function); | 85 __ LoadObject(temp, function); |
86 __ pushq(result); // Preserve result. | 86 __ pushq(result); // Preserve result. |
87 __ pushq(temp); | 87 __ pushq(temp); |
88 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, | 88 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
89 0, | 89 0, |
90 CatchClauseNode::kInvalidTryIndex, | |
91 kTraceFunctionExitRuntimeEntry, | 90 kTraceFunctionExitRuntimeEntry, |
92 NULL); | 91 NULL); |
93 __ popq(temp); // Remove argument. | 92 __ popq(temp); // Remove argument. |
94 __ popq(result); // Restore result. | 93 __ popq(result); // Restore result. |
95 } | 94 } |
96 #if defined(DEBUG) | 95 #if defined(DEBUG) |
97 // TODO(srdjan): Fix for functions with finally clause. | 96 // TODO(srdjan): Fix for functions with finally clause. |
98 // A finally clause may leave a previously pushed return value if it | 97 // A finally clause may leave a previously pushed return value if it |
99 // has its own return instruction. Method that have finally are currently | 98 // has its own return instruction. Method that have finally are currently |
100 // not optimized. | 99 // not optimized. |
(...skipping 17 matching lines...) Expand all Loading... |
118 __ nop(1); | 117 __ nop(1); |
119 __ nop(1); | 118 __ nop(1); |
120 __ nop(1); | 119 __ nop(1); |
121 __ nop(1); | 120 __ nop(1); |
122 __ nop(1); | 121 __ nop(1); |
123 __ nop(1); | 122 __ nop(1); |
124 __ nop(1); | 123 __ nop(1); |
125 __ nop(1); | 124 __ nop(1); |
126 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 125 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
127 deopt_id(), | 126 deopt_id(), |
128 token_pos(), | 127 token_pos()); |
129 CatchClauseNode::kInvalidTryIndex); | |
130 } | 128 } |
131 | 129 |
132 | 130 |
133 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 131 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
134 const intptr_t kNumInputs = 0; | 132 const intptr_t kNumInputs = 0; |
135 const intptr_t kNumTemps = 1; | 133 const intptr_t kNumTemps = 1; |
136 LocationSummary* result = | 134 LocationSummary* result = |
137 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 135 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
138 result->set_out(Location::RegisterLocation(RAX)); | 136 result->set_out(Location::RegisterLocation(RAX)); |
139 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. | 137 result->set_temp(0, Location::RegisterLocation(R10)); // Arg. descriptor. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 // Call the runtime if the object is not bool::true or bool::false. | 213 // Call the runtime if the object is not bool::true or bool::false. |
216 Label done; | 214 Label done; |
217 __ CompareObject(obj, compiler->bool_true()); | 215 __ CompareObject(obj, compiler->bool_true()); |
218 __ j(EQUAL, &done, Assembler::kNearJump); | 216 __ j(EQUAL, &done, Assembler::kNearJump); |
219 __ CompareObject(obj, compiler->bool_false()); | 217 __ CompareObject(obj, compiler->bool_false()); |
220 __ j(EQUAL, &done, Assembler::kNearJump); | 218 __ j(EQUAL, &done, Assembler::kNearJump); |
221 | 219 |
222 __ pushq(obj); // Push the source object. | 220 __ pushq(obj); // Push the source object. |
223 compiler->GenerateCallRuntime(deopt_id(), | 221 compiler->GenerateCallRuntime(deopt_id(), |
224 token_pos(), | 222 token_pos(), |
225 try_index(), | |
226 kConditionTypeErrorRuntimeEntry, | 223 kConditionTypeErrorRuntimeEntry, |
227 locs()); | 224 locs()); |
228 // We should never return here. | 225 // We should never return here. |
229 __ int3(); | 226 __ int3(); |
230 __ Bind(&done); | 227 __ Bind(&done); |
231 } | 228 } |
232 ASSERT(obj == result); | 229 ASSERT(obj == result); |
233 } | 230 } |
234 | 231 |
235 | 232 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 locs->set_in(0, Location::RegisterLocation(RCX)); | 277 locs->set_in(0, Location::RegisterLocation(RCX)); |
281 locs->set_in(1, Location::RegisterLocation(RDX)); | 278 locs->set_in(1, Location::RegisterLocation(RDX)); |
282 locs->set_out(Location::RegisterLocation(RAX)); | 279 locs->set_out(Location::RegisterLocation(RAX)); |
283 return locs; | 280 return locs; |
284 } | 281 } |
285 | 282 |
286 | 283 |
287 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 284 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
288 intptr_t deopt_id, | 285 intptr_t deopt_id, |
289 intptr_t token_pos, | 286 intptr_t token_pos, |
290 intptr_t try_index, | |
291 Token::Kind kind, | 287 Token::Kind kind, |
292 LocationSummary* locs) { | 288 LocationSummary* locs) { |
293 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 289 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
294 deopt_id, | 290 deopt_id, |
295 token_pos, | 291 token_pos); |
296 try_index); | |
297 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 292 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
298 const int kNumberOfArguments = 2; | 293 const int kNumberOfArguments = 2; |
299 const Array& kNoArgumentNames = Array::Handle(); | 294 const Array& kNoArgumentNames = Array::Handle(); |
300 const int kNumArgumentsChecked = 2; | 295 const int kNumArgumentsChecked = 2; |
301 | 296 |
302 Label done, false_label, true_label; | 297 Label done, false_label, true_label; |
303 Register left = locs->in(0).reg(); | 298 Register left = locs->in(0).reg(); |
304 Register right = locs->in(1).reg(); | 299 Register right = locs->in(1).reg(); |
305 __ popq(right); | 300 __ popq(right); |
306 __ popq(left); | 301 __ popq(left); |
(...skipping 17 matching lines...) Expand all Loading... |
324 } else { | 319 } else { |
325 ASSERT(kind == Token::kNE); | 320 ASSERT(kind == Token::kNE); |
326 __ jmp(&false_label); | 321 __ jmp(&false_label); |
327 } | 322 } |
328 | 323 |
329 __ Bind(&instance_call); | 324 __ Bind(&instance_call); |
330 __ pushq(left); | 325 __ pushq(left); |
331 __ pushq(right); | 326 __ pushq(right); |
332 compiler->GenerateInstanceCall(deopt_id, | 327 compiler->GenerateInstanceCall(deopt_id, |
333 token_pos, | 328 token_pos, |
334 try_index, | |
335 operator_name, | 329 operator_name, |
336 kNumberOfArguments, | 330 kNumberOfArguments, |
337 kNoArgumentNames, | 331 kNoArgumentNames, |
338 kNumArgumentsChecked, | 332 kNumArgumentsChecked, |
339 locs); | 333 locs); |
340 if (kind == Token::kNE) { | 334 if (kind == Token::kNE) { |
341 // Negate the condition: true label returns false and vice versa. | 335 // Negate the condition: true label returns false and vice versa. |
342 __ CompareObject(RAX, compiler->bool_true()); | 336 __ CompareObject(RAX, compiler->bool_true()); |
343 __ j(EQUAL, &true_label, Assembler::kNearJump); | 337 __ j(EQUAL, &true_label, Assembler::kNearJump); |
344 __ Bind(&false_label); | 338 __ Bind(&false_label); |
345 __ LoadObject(RAX, compiler->bool_true()); | 339 __ LoadObject(RAX, compiler->bool_true()); |
346 __ jmp(&done, Assembler::kNearJump); | 340 __ jmp(&done, Assembler::kNearJump); |
347 __ Bind(&true_label); | 341 __ Bind(&true_label); |
348 __ LoadObject(RAX, compiler->bool_false()); | 342 __ LoadObject(RAX, compiler->bool_false()); |
349 } | 343 } |
350 __ Bind(&done); | 344 __ Bind(&done); |
351 } | 345 } |
352 | 346 |
353 | 347 |
354 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 348 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
355 const ICData& orig_ic_data, | 349 const ICData& orig_ic_data, |
356 LocationSummary* locs, | 350 LocationSummary* locs, |
357 BranchInstr* branch, | 351 BranchInstr* branch, |
358 Token::Kind kind, | 352 Token::Kind kind, |
359 intptr_t deopt_id, | 353 intptr_t deopt_id, |
360 intptr_t token_pos, | 354 intptr_t token_pos) { |
361 intptr_t try_index) { | |
362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 355 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 356 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
364 ASSERT(ic_data.NumberOfChecks() > 0); | 357 ASSERT(ic_data.NumberOfChecks() > 0); |
365 ASSERT(ic_data.num_args_tested() == 1); | 358 ASSERT(ic_data.num_args_tested() == 1); |
366 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 359 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
367 Register left = locs->in(0).reg(); | 360 Register left = locs->in(0).reg(); |
368 Register right = locs->in(1).reg(); | 361 Register right = locs->in(1).reg(); |
369 __ testq(left, Immediate(kSmiTagMask)); | 362 __ testq(left, Immediate(kSmiTagMask)); |
370 Register temp = locs->temp(0).reg(); | 363 Register temp = locs->temp(0).reg(); |
371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 364 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 __ LoadObject(result, compiler->bool_false()); | 398 __ LoadObject(result, compiler->bool_false()); |
406 __ jmp(&done); | 399 __ jmp(&done); |
407 __ Bind(&load_true); | 400 __ Bind(&load_true); |
408 __ LoadObject(result, compiler->bool_true()); | 401 __ LoadObject(result, compiler->bool_true()); |
409 } | 402 } |
410 } else { | 403 } else { |
411 const int kNumberOfArguments = 2; | 404 const int kNumberOfArguments = 2; |
412 const Array& kNoArgumentNames = Array::Handle(); | 405 const Array& kNoArgumentNames = Array::Handle(); |
413 compiler->GenerateStaticCall(deopt_id, | 406 compiler->GenerateStaticCall(deopt_id, |
414 token_pos, | 407 token_pos, |
415 try_index, | |
416 target, | 408 target, |
417 kNumberOfArguments, | 409 kNumberOfArguments, |
418 kNoArgumentNames, | 410 kNoArgumentNames, |
419 locs); | 411 locs); |
420 if (branch == NULL) { | 412 if (branch == NULL) { |
421 if (kind == Token::kNE) { | 413 if (kind == Token::kNE) { |
422 Label false_label; | 414 Label false_label; |
423 __ CompareObject(RAX, compiler->bool_true()); | 415 __ CompareObject(RAX, compiler->bool_true()); |
424 __ j(EQUAL, &false_label, Assembler::kNearJump); | 416 __ j(EQUAL, &false_label, Assembler::kNearJump); |
425 __ LoadObject(RAX, compiler->bool_true()); | 417 __ LoadObject(RAX, compiler->bool_true()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 | 489 |
498 // First test if receiver is NULL, in which case === is applied. | 490 // First test if receiver is NULL, in which case === is applied. |
499 // If type feedback was provided (lists of <class-id, target>), do a | 491 // If type feedback was provided (lists of <class-id, target>), do a |
500 // type by type check (either === or static call to the operator. | 492 // type by type check (either === or static call to the operator. |
501 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 493 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
502 LocationSummary* locs, | 494 LocationSummary* locs, |
503 Token::Kind kind, | 495 Token::Kind kind, |
504 BranchInstr* branch, | 496 BranchInstr* branch, |
505 const ICData& ic_data, | 497 const ICData& ic_data, |
506 intptr_t deopt_id, | 498 intptr_t deopt_id, |
507 intptr_t token_pos, | 499 intptr_t token_pos) { |
508 intptr_t try_index) { | |
509 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 500 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
510 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 501 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
511 Register left = locs->in(0).reg(); | 502 Register left = locs->in(0).reg(); |
512 Register right = locs->in(1).reg(); | 503 Register right = locs->in(1).reg(); |
513 const Immediate raw_null = | 504 const Immediate raw_null = |
514 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 505 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
515 Label done, identity_compare, non_null_compare; | 506 Label done, identity_compare, non_null_compare; |
516 __ cmpq(right, raw_null); | 507 __ cmpq(right, raw_null); |
517 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 508 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
518 __ cmpq(left, raw_null); | 509 __ cmpq(left, raw_null); |
(...skipping 11 matching lines...) Expand all Loading... |
530 __ LoadObject(result, compiler->bool_false()); | 521 __ LoadObject(result, compiler->bool_false()); |
531 __ jmp(&done); | 522 __ jmp(&done); |
532 __ Bind(&load_true); | 523 __ Bind(&load_true); |
533 __ LoadObject(result, compiler->bool_true()); | 524 __ LoadObject(result, compiler->bool_true()); |
534 } | 525 } |
535 __ jmp(&done); | 526 __ jmp(&done); |
536 __ Bind(&non_null_compare); // Receiver is not null. | 527 __ Bind(&non_null_compare); // Receiver is not null. |
537 __ pushq(left); | 528 __ pushq(left); |
538 __ pushq(right); | 529 __ pushq(right); |
539 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 530 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
540 deopt_id, token_pos, try_index); | 531 deopt_id, token_pos); |
541 __ Bind(&done); | 532 __ Bind(&done); |
542 } | 533 } |
543 | 534 |
544 | 535 |
545 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 536 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
546 const LocationSummary& locs, | 537 const LocationSummary& locs, |
547 Token::Kind kind, | 538 Token::Kind kind, |
548 BranchInstr* branch, | 539 BranchInstr* branch, |
549 intptr_t deopt_id) { | 540 intptr_t deopt_id) { |
550 Register left = locs.in(0).reg(); | 541 Register left = locs.in(0).reg(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 } | 626 } |
636 const bool is_checked_strict_equal = | 627 const bool is_checked_strict_equal = |
637 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 628 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
638 if (is_checked_strict_equal) { | 629 if (is_checked_strict_equal) { |
639 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 630 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
640 deopt_id()); | 631 deopt_id()); |
641 return; | 632 return; |
642 } | 633 } |
643 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 634 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
644 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), | 635 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
645 deopt_id(), token_pos(), try_index()); | 636 deopt_id(), token_pos()); |
646 return; | 637 return; |
647 } | 638 } |
648 Register left = locs()->in(0).reg(); | 639 Register left = locs()->in(0).reg(); |
649 Register right = locs()->in(1).reg(); | 640 Register right = locs()->in(1).reg(); |
650 __ pushq(left); | 641 __ pushq(left); |
651 __ pushq(right); | 642 __ pushq(right); |
652 EmitEqualityAsInstanceCall(compiler, | 643 EmitEqualityAsInstanceCall(compiler, |
653 deopt_id(), | 644 deopt_id(), |
654 token_pos(), | 645 token_pos(), |
655 try_index(), | |
656 kind(), | 646 kind(), |
657 locs()); | 647 locs()); |
658 ASSERT(locs()->out().reg() == RAX); | 648 ASSERT(locs()->out().reg() == RAX); |
659 } | 649 } |
660 | 650 |
661 | 651 |
662 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 652 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, |
663 BranchInstr* branch) { | 653 BranchInstr* branch) { |
664 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 654 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
665 if (receiver_class_id() == kSmiCid) { | 655 if (receiver_class_id() == kSmiCid) { |
666 // Deoptimizes if both arguments not Smi. | 656 // Deoptimizes if both arguments not Smi. |
667 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 657 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
668 return; | 658 return; |
669 } | 659 } |
670 if (receiver_class_id() == kDoubleCid) { | 660 if (receiver_class_id() == kDoubleCid) { |
671 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 661 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
672 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 662 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
673 return; | 663 return; |
674 } | 664 } |
675 const bool is_checked_strict_equal = | 665 const bool is_checked_strict_equal = |
676 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 666 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
677 if (is_checked_strict_equal) { | 667 if (is_checked_strict_equal) { |
678 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 668 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
679 deopt_id()); | 669 deopt_id()); |
680 return; | 670 return; |
681 } | 671 } |
682 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 672 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
683 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), | 673 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), |
684 deopt_id(), token_pos(), try_index()); | 674 deopt_id(), token_pos()); |
685 return; | 675 return; |
686 } | 676 } |
687 Register left = locs()->in(0).reg(); | 677 Register left = locs()->in(0).reg(); |
688 Register right = locs()->in(1).reg(); | 678 Register right = locs()->in(1).reg(); |
689 __ pushq(left); | 679 __ pushq(left); |
690 __ pushq(right); | 680 __ pushq(right); |
691 EmitEqualityAsInstanceCall(compiler, | 681 EmitEqualityAsInstanceCall(compiler, |
692 deopt_id(), | 682 deopt_id(), |
693 token_pos(), | 683 token_pos(), |
694 try_index(), | |
695 Token::kEQ, // kNE reverse occurs at branch. | 684 Token::kEQ, // kNE reverse occurs at branch. |
696 locs()); | 685 locs()); |
697 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 686 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
698 __ CompareObject(RAX, compiler->bool_true()); | 687 __ CompareObject(RAX, compiler->bool_true()); |
699 branch->EmitBranchOnCondition(compiler, branch_condition); | 688 branch->EmitBranchOnCondition(compiler, branch_condition); |
700 } | 689 } |
701 | 690 |
702 | 691 |
703 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 692 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
704 const intptr_t kNumInputs = 2; | 693 const intptr_t kNumInputs = 2; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
753 __ LoadClassId(RDI, left); | 742 __ LoadClassId(RDI, left); |
754 __ Bind(&done); | 743 __ Bind(&done); |
755 const intptr_t kNumArguments = 2; | 744 const intptr_t kNumArguments = 2; |
756 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 745 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
757 RDI, // Class id register. | 746 RDI, // Class id register. |
758 kNumArguments, | 747 kNumArguments, |
759 Array::Handle(), // No named arguments. | 748 Array::Handle(), // No named arguments. |
760 deopt, // Deoptimize target. | 749 deopt, // Deoptimize target. |
761 deopt_id(), | 750 deopt_id(), |
762 token_pos(), | 751 token_pos(), |
763 try_index(), | |
764 locs()); | 752 locs()); |
765 return; | 753 return; |
766 } | 754 } |
767 const String& function_name = | 755 const String& function_name = |
768 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 756 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
769 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 757 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
770 deopt_id(), | 758 deopt_id(), |
771 token_pos(), | 759 token_pos()); |
772 try_index()); | |
773 const intptr_t kNumArguments = 2; | 760 const intptr_t kNumArguments = 2; |
774 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 761 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
775 compiler->GenerateInstanceCall(deopt_id(), | 762 compiler->GenerateInstanceCall(deopt_id(), |
776 token_pos(), | 763 token_pos(), |
777 try_index(), | |
778 function_name, | 764 function_name, |
779 kNumArguments, | 765 kNumArguments, |
780 Array::ZoneHandle(), // No optional arguments. | 766 Array::ZoneHandle(), // No optional arguments. |
781 kNumArgsChecked, | 767 kNumArgsChecked, |
782 locs()); | 768 locs()); |
783 } | 769 } |
784 | 770 |
785 | 771 |
786 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 772 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, |
787 BranchInstr* branch) { | 773 BranchInstr* branch) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 } | 813 } |
828 if (!has_optional_parameters() && !is_native_instance_closure()) { | 814 if (!has_optional_parameters() && !is_native_instance_closure()) { |
829 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); | 815 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); |
830 } else { | 816 } else { |
831 __ leaq(RAX, | 817 __ leaq(RAX, |
832 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 818 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
833 } | 819 } |
834 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 820 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
835 __ movq(R10, Immediate(arg_count)); | 821 __ movq(R10, Immediate(arg_count)); |
836 compiler->GenerateCall(token_pos(), | 822 compiler->GenerateCall(token_pos(), |
837 try_index(), | |
838 &StubCode::CallNativeCFunctionLabel(), | 823 &StubCode::CallNativeCFunctionLabel(), |
839 PcDescriptors::kOther, | 824 PcDescriptors::kOther, |
840 locs()); | 825 locs()); |
841 __ popq(result); | 826 __ popq(result); |
842 } | 827 } |
843 | 828 |
844 | 829 |
845 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 830 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
846 const intptr_t kNumInputs = 2; | 831 const intptr_t kNumInputs = 2; |
847 if (receiver_type() == kGrowableObjectArrayCid) { | 832 if (receiver_type() == kGrowableObjectArrayCid) { |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 } | 1035 } |
1051 | 1036 |
1052 | 1037 |
1053 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1038 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1054 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1039 ASSERT(locs()->in(0).reg() == RAX); // Value. |
1055 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 1040 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
1056 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 1041 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
1057 | 1042 |
1058 compiler->GenerateInstanceOf(deopt_id(), | 1043 compiler->GenerateInstanceOf(deopt_id(), |
1059 token_pos(), | 1044 token_pos(), |
1060 try_index(), | |
1061 type(), | 1045 type(), |
1062 negate_result(), | 1046 negate_result(), |
1063 locs()); | 1047 locs()); |
1064 ASSERT(locs()->out().reg() == RAX); | 1048 ASSERT(locs()->out().reg() == RAX); |
1065 } | 1049 } |
1066 | 1050 |
1067 | 1051 |
1068 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1052 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1069 const intptr_t kNumInputs = 1; | 1053 const intptr_t kNumInputs = 1; |
1070 const intptr_t kNumTemps = 0; | 1054 const intptr_t kNumTemps = 0; |
1071 LocationSummary* locs = | 1055 LocationSummary* locs = |
1072 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1056 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1073 locs->set_in(0, Location::RegisterLocation(RBX)); | 1057 locs->set_in(0, Location::RegisterLocation(RBX)); |
1074 locs->set_out(Location::RegisterLocation(RAX)); | 1058 locs->set_out(Location::RegisterLocation(RAX)); |
1075 return locs; | 1059 return locs; |
1076 } | 1060 } |
1077 | 1061 |
1078 | 1062 |
1079 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1063 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1080 // Allocate the array. R10 = length, RBX = element type. | 1064 // Allocate the array. R10 = length, RBX = element type. |
1081 ASSERT(locs()->in(0).reg() == RBX); | 1065 ASSERT(locs()->in(0).reg() == RBX); |
1082 __ movq(R10, Immediate(Smi::RawValue(ArgumentCount()))); | 1066 __ movq(R10, Immediate(Smi::RawValue(ArgumentCount()))); |
1083 compiler->GenerateCall(token_pos(), | 1067 compiler->GenerateCall(token_pos(), |
1084 try_index(), | |
1085 &StubCode::AllocateArrayLabel(), | 1068 &StubCode::AllocateArrayLabel(), |
1086 PcDescriptors::kOther, | 1069 PcDescriptors::kOther, |
1087 locs()); | 1070 locs()); |
1088 ASSERT(locs()->out().reg() == RAX); | 1071 ASSERT(locs()->out().reg() == RAX); |
1089 | 1072 |
1090 // Pop the element values from the stack into the array. | 1073 // Pop the element values from the stack into the array. |
1091 __ leaq(R10, FieldAddress(RAX, Array::data_offset())); | 1074 __ leaq(R10, FieldAddress(RAX, Array::data_offset())); |
1092 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1075 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
1093 ASSERT(ArgumentAt(i)->value()->IsUse()); | 1076 ASSERT(ArgumentAt(i)->value()->IsUse()); |
1094 __ popq(Address(R10, i * kWordSize)); | 1077 __ popq(Address(R10, i * kWordSize)); |
(...skipping 21 matching lines...) Expand all Loading... |
1116 Register instantiator_type_arguments = locs()->in(1).reg(); | 1099 Register instantiator_type_arguments = locs()->in(1).reg(); |
1117 Register result = locs()->out().reg(); | 1100 Register result = locs()->out().reg(); |
1118 | 1101 |
1119 // Push the result place holder initialized to NULL. | 1102 // Push the result place holder initialized to NULL. |
1120 __ PushObject(Object::ZoneHandle()); | 1103 __ PushObject(Object::ZoneHandle()); |
1121 __ PushObject(cls); | 1104 __ PushObject(cls); |
1122 __ pushq(type_arguments); | 1105 __ pushq(type_arguments); |
1123 __ pushq(instantiator_type_arguments); | 1106 __ pushq(instantiator_type_arguments); |
1124 compiler->GenerateCallRuntime(deopt_id(), | 1107 compiler->GenerateCallRuntime(deopt_id(), |
1125 token_pos(), | 1108 token_pos(), |
1126 try_index(), | |
1127 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1109 kAllocateObjectWithBoundsCheckRuntimeEntry, |
1128 locs()); | 1110 locs()); |
1129 // Pop instantiator type arguments, type arguments, and class. | 1111 // Pop instantiator type arguments, type arguments, and class. |
1130 __ Drop(3); | 1112 __ Drop(3); |
1131 __ popq(result); // Pop new instance. | 1113 __ popq(result); // Pop new instance. |
1132 } | 1114 } |
1133 | 1115 |
1134 | 1116 |
1135 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1117 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1136 return LocationSummary::Make(1, | 1118 return LocationSummary::Make(1, |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 Immediate(Smi::RawValue(len))); | 1182 Immediate(Smi::RawValue(len))); |
1201 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1183 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1202 __ Bind(&type_arguments_uninstantiated); | 1184 __ Bind(&type_arguments_uninstantiated); |
1203 } | 1185 } |
1204 // A runtime call to instantiate the type arguments is required. | 1186 // A runtime call to instantiate the type arguments is required. |
1205 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1187 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1206 __ PushObject(type_arguments()); | 1188 __ PushObject(type_arguments()); |
1207 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1189 __ pushq(instantiator_reg); // Push instantiator type arguments. |
1208 compiler->GenerateCallRuntime(deopt_id(), | 1190 compiler->GenerateCallRuntime(deopt_id(), |
1209 token_pos(), | 1191 token_pos(), |
1210 try_index(), | |
1211 kInstantiateTypeArgumentsRuntimeEntry, | 1192 kInstantiateTypeArgumentsRuntimeEntry, |
1212 locs()); | 1193 locs()); |
1213 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1194 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1214 __ popq(result_reg); // Pop instantiated type arguments. | 1195 __ popq(result_reg); // Pop instantiated type arguments. |
1215 __ Bind(&type_arguments_instantiated); | 1196 __ Bind(&type_arguments_instantiated); |
1216 ASSERT(instantiator_reg == result_reg); | 1197 ASSERT(instantiator_reg == result_reg); |
1217 // 'result_reg': Instantiated type arguments. | 1198 // 'result_reg': Instantiated type arguments. |
1218 } | 1199 } |
1219 | 1200 |
1220 | 1201 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 | 1333 |
1353 | 1334 |
1354 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1335 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1355 ASSERT(locs()->temp(0).reg() == R10); | 1336 ASSERT(locs()->temp(0).reg() == R10); |
1356 ASSERT(locs()->out().reg() == RAX); | 1337 ASSERT(locs()->out().reg() == RAX); |
1357 | 1338 |
1358 __ movq(R10, Immediate(num_context_variables())); | 1339 __ movq(R10, Immediate(num_context_variables())); |
1359 const ExternalLabel label("alloc_context", | 1340 const ExternalLabel label("alloc_context", |
1360 StubCode::AllocateContextEntryPoint()); | 1341 StubCode::AllocateContextEntryPoint()); |
1361 compiler->GenerateCall(token_pos(), | 1342 compiler->GenerateCall(token_pos(), |
1362 try_index(), | |
1363 &label, | 1343 &label, |
1364 PcDescriptors::kOther, | 1344 PcDescriptors::kOther, |
1365 locs()); | 1345 locs()); |
1366 } | 1346 } |
1367 | 1347 |
1368 | 1348 |
1369 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1349 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1370 const intptr_t kNumInputs = 1; | 1350 const intptr_t kNumInputs = 1; |
1371 const intptr_t kNumTemps = 0; | 1351 const intptr_t kNumTemps = 0; |
1372 LocationSummary* locs = | 1352 LocationSummary* locs = |
1373 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1353 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1374 locs->set_in(0, Location::RegisterLocation(RAX)); | 1354 locs->set_in(0, Location::RegisterLocation(RAX)); |
1375 locs->set_out(Location::RegisterLocation(RAX)); | 1355 locs->set_out(Location::RegisterLocation(RAX)); |
1376 return locs; | 1356 return locs; |
1377 } | 1357 } |
1378 | 1358 |
1379 | 1359 |
1380 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1360 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1381 Register context_value = locs()->in(0).reg(); | 1361 Register context_value = locs()->in(0).reg(); |
1382 Register result = locs()->out().reg(); | 1362 Register result = locs()->out().reg(); |
1383 | 1363 |
1384 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1364 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1385 __ pushq(context_value); | 1365 __ pushq(context_value); |
1386 compiler->GenerateCallRuntime(deopt_id(), | 1366 compiler->GenerateCallRuntime(deopt_id(), |
1387 token_pos(), | 1367 token_pos(), |
1388 try_index(), | |
1389 kCloneContextRuntimeEntry, | 1368 kCloneContextRuntimeEntry, |
1390 locs()); | 1369 locs()); |
1391 __ popq(result); // Remove argument. | 1370 __ popq(result); // Remove argument. |
1392 __ popq(result); // Get result (cloned context). | 1371 __ popq(result); // Get result (cloned context). |
1393 } | 1372 } |
1394 | 1373 |
1395 | 1374 |
1396 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1375 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1397 return LocationSummary::Make(0, | 1376 return LocationSummary::Make(0, |
1398 Location::NoLocation(), | 1377 Location::NoLocation(), |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1435 class CheckStackOverflowSlowPath : public SlowPathCode { | 1414 class CheckStackOverflowSlowPath : public SlowPathCode { |
1436 public: | 1415 public: |
1437 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1416 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) |
1438 : computation_(computation) { } | 1417 : computation_(computation) { } |
1439 | 1418 |
1440 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1419 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1441 __ Bind(entry_label()); | 1420 __ Bind(entry_label()); |
1442 compiler->SaveLiveRegisters(computation_->locs()); | 1421 compiler->SaveLiveRegisters(computation_->locs()); |
1443 compiler->GenerateCallRuntime(computation_->deopt_id(), | 1422 compiler->GenerateCallRuntime(computation_->deopt_id(), |
1444 computation_->token_pos(), | 1423 computation_->token_pos(), |
1445 computation_->try_index(), | |
1446 kStackOverflowRuntimeEntry, | 1424 kStackOverflowRuntimeEntry, |
1447 computation_->locs()); | 1425 computation_->locs()); |
1448 compiler->RestoreLiveRegisters(computation_->locs()); | 1426 compiler->RestoreLiveRegisters(computation_->locs()); |
1449 __ jmp(exit_label()); | 1427 __ jmp(exit_label()); |
1450 } | 1428 } |
1451 | 1429 |
1452 private: | 1430 private: |
1453 CheckStackOverflowComp* computation_; | 1431 CheckStackOverflowComp* computation_; |
1454 }; | 1432 }; |
1455 | 1433 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 __ Bind(&call_method); | 1603 __ Bind(&call_method); |
1626 Function& target = Function::ZoneHandle( | 1604 Function& target = Function::ZoneHandle( |
1627 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1605 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1628 ASSERT(!target.IsNull()); | 1606 ASSERT(!target.IsNull()); |
1629 const intptr_t kArgumentCount = 2; | 1607 const intptr_t kArgumentCount = 2; |
1630 __ pushq(temp); | 1608 __ pushq(temp); |
1631 __ pushq(right); | 1609 __ pushq(right); |
1632 compiler->GenerateStaticCall( | 1610 compiler->GenerateStaticCall( |
1633 instance_call()->deopt_id(), | 1611 instance_call()->deopt_id(), |
1634 instance_call()->token_pos(), | 1612 instance_call()->token_pos(), |
1635 instance_call()->try_index(), | |
1636 target, | 1613 target, |
1637 kArgumentCount, | 1614 kArgumentCount, |
1638 Array::Handle(), // No argument names. | 1615 Array::Handle(), // No argument names. |
1639 locs()); | 1616 locs()); |
1640 ASSERT(result == RAX); | 1617 ASSERT(result == RAX); |
1641 } | 1618 } |
1642 __ Bind(&done); | 1619 __ Bind(&done); |
1643 break; | 1620 break; |
1644 } | 1621 } |
1645 case Token::kDIV: { | 1622 case Token::kDIV: { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1730 Function& target = Function::ZoneHandle( | 1707 Function& target = Function::ZoneHandle( |
1731 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1708 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1732 if (target.IsNull()) { | 1709 if (target.IsNull()) { |
1733 __ jmp(deopt); | 1710 __ jmp(deopt); |
1734 } else { | 1711 } else { |
1735 __ pushq(left); | 1712 __ pushq(left); |
1736 __ pushq(right); | 1713 __ pushq(right); |
1737 compiler->GenerateStaticCall( | 1714 compiler->GenerateStaticCall( |
1738 instance_call()->deopt_id(), | 1715 instance_call()->deopt_id(), |
1739 instance_call()->token_pos(), | 1716 instance_call()->token_pos(), |
1740 instance_call()->try_index(), | |
1741 target, | 1717 target, |
1742 instance_call()->ArgumentCount(), | 1718 instance_call()->ArgumentCount(), |
1743 instance_call()->argument_names(), | 1719 instance_call()->argument_names(), |
1744 locs()); | 1720 locs()); |
1745 ASSERT(result == RAX); | 1721 ASSERT(result == RAX); |
1746 __ jmp(&done); | 1722 __ jmp(&done); |
1747 } | 1723 } |
1748 } | 1724 } |
1749 | 1725 |
1750 __ Bind(&mint_static_call); | 1726 __ Bind(&mint_static_call); |
1751 { | 1727 { |
1752 Function& target = Function::ZoneHandle( | 1728 Function& target = Function::ZoneHandle( |
1753 ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1729 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
1754 if (target.IsNull()) { | 1730 if (target.IsNull()) { |
1755 __ jmp(deopt); | 1731 __ jmp(deopt); |
1756 } else { | 1732 } else { |
1757 __ pushq(left); | 1733 __ pushq(left); |
1758 __ pushq(right); | 1734 __ pushq(right); |
1759 compiler->GenerateStaticCall( | 1735 compiler->GenerateStaticCall( |
1760 instance_call()->deopt_id(), | 1736 instance_call()->deopt_id(), |
1761 instance_call()->token_pos(), | 1737 instance_call()->token_pos(), |
1762 instance_call()->try_index(), | |
1763 target, | 1738 target, |
1764 instance_call()->ArgumentCount(), | 1739 instance_call()->ArgumentCount(), |
1765 instance_call()->argument_names(), | 1740 instance_call()->argument_names(), |
1766 locs()); | 1741 locs()); |
1767 ASSERT(result == RAX); | 1742 ASSERT(result == RAX); |
1768 } | 1743 } |
1769 } | 1744 } |
1770 __ Bind(&done); | 1745 __ Bind(&done); |
1771 } | 1746 } |
1772 | 1747 |
1773 | 1748 |
1774 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { | 1749 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
1775 return MakeCallSummary(); // Calls into a stub for allocation. | 1750 return MakeCallSummary(); // Calls into a stub for allocation. |
1776 } | 1751 } |
1777 | 1752 |
1778 | 1753 |
1779 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1754 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1780 Register left = RBX; | 1755 Register left = RBX; |
1781 Register right = RCX; | 1756 Register right = RCX; |
1782 Register temp = RDX; | 1757 Register temp = RDX; |
1783 Register result = locs()->out().reg(); | 1758 Register result = locs()->out().reg(); |
1784 | 1759 |
1785 const Class& double_class = compiler->double_class(); | 1760 const Class& double_class = compiler->double_class(); |
1786 const Code& stub = | 1761 const Code& stub = |
1787 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1762 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1788 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1763 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1789 compiler->GenerateCall(instance_call()->token_pos(), | 1764 compiler->GenerateCall(instance_call()->token_pos(), |
1790 instance_call()->try_index(), | |
1791 &label, | 1765 &label, |
1792 PcDescriptors::kOther, | 1766 PcDescriptors::kOther, |
1793 locs()); | 1767 locs()); |
1794 // Newly allocated object is now in the result register (RAX). | 1768 // Newly allocated object is now in the result register (RAX). |
1795 ASSERT(result == RAX); | 1769 ASSERT(result == RAX); |
1796 __ movq(right, Address(RSP, 0)); | 1770 __ movq(right, Address(RSP, 0)); |
1797 __ movq(left, Address(RSP, kWordSize)); | 1771 __ movq(left, Address(RSP, kWordSize)); |
1798 | 1772 |
1799 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1773 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1800 kDeoptBinaryDoubleOp); | 1774 kDeoptBinaryDoubleOp); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1873 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1847 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1874 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1848 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1875 | 1849 |
1876 // TODO(vegorov): here stack map needs to be set up correctly to skip | 1850 // TODO(vegorov): here stack map needs to be set up correctly to skip |
1877 // double registers. | 1851 // double registers. |
1878 LocationSummary* locs = computation_->locs(); | 1852 LocationSummary* locs = computation_->locs(); |
1879 locs->live_registers()->Remove(locs->out()); | 1853 locs->live_registers()->Remove(locs->out()); |
1880 | 1854 |
1881 compiler->SaveLiveRegisters(locs); | 1855 compiler->SaveLiveRegisters(locs); |
1882 compiler->GenerateCall(computation_->instance_call()->token_pos(), | 1856 compiler->GenerateCall(computation_->instance_call()->token_pos(), |
1883 computation_->instance_call()->try_index(), | |
1884 &label, | 1857 &label, |
1885 PcDescriptors::kOther, | 1858 PcDescriptors::kOther, |
1886 locs); | 1859 locs); |
1887 if (RAX != locs->out().reg()) __ movq(locs->out().reg(), RAX); | 1860 if (RAX != locs->out().reg()) __ movq(locs->out().reg(), RAX); |
1888 compiler->RestoreLiveRegisters(locs); | 1861 compiler->RestoreLiveRegisters(locs); |
1889 | 1862 |
1890 __ jmp(exit_label()); | 1863 __ jmp(exit_label()); |
1891 } | 1864 } |
1892 | 1865 |
1893 private: | 1866 private: |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2038 __ j(ZERO, deopt); // Smi. | 2011 __ j(ZERO, deopt); // Smi. |
2039 __ CompareClassId(value, kDoubleCid); | 2012 __ CompareClassId(value, kDoubleCid); |
2040 __ j(NOT_EQUAL, deopt); | 2013 __ j(NOT_EQUAL, deopt); |
2041 // Allocate result object. | 2014 // Allocate result object. |
2042 const Class& double_class = compiler->double_class(); | 2015 const Class& double_class = compiler->double_class(); |
2043 const Code& stub = | 2016 const Code& stub = |
2044 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2017 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
2045 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2018 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
2046 __ pushq(value); | 2019 __ pushq(value); |
2047 compiler->GenerateCall(instance_call()->token_pos(), | 2020 compiler->GenerateCall(instance_call()->token_pos(), |
2048 instance_call()->try_index(), | |
2049 &label, | 2021 &label, |
2050 PcDescriptors::kOther, | 2022 PcDescriptors::kOther, |
2051 instance_call()->locs()); | 2023 instance_call()->locs()); |
2052 // Result is in RAX. | 2024 // Result is in RAX. |
2053 ASSERT(result != temp); | 2025 ASSERT(result != temp); |
2054 __ movq(result, RAX); | 2026 __ movq(result, RAX); |
2055 __ popq(temp); | 2027 __ popq(temp); |
2056 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 2028 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
2057 __ DoubleNegate(XMM0); | 2029 __ DoubleNegate(XMM0); |
2058 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2030 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 kDeoptIntegerToDouble); | 2073 kDeoptIntegerToDouble); |
2102 | 2074 |
2103 const Class& double_class = compiler->double_class(); | 2075 const Class& double_class = compiler->double_class(); |
2104 const Code& stub = | 2076 const Code& stub = |
2105 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2077 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
2106 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2078 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
2107 | 2079 |
2108 // TODO(fschneider): Inline new-space allocation and move the call into | 2080 // TODO(fschneider): Inline new-space allocation and move the call into |
2109 // deferred code. | 2081 // deferred code. |
2110 compiler->GenerateCall(instance_call()->token_pos(), | 2082 compiler->GenerateCall(instance_call()->token_pos(), |
2111 instance_call()->try_index(), | |
2112 &label, | 2083 &label, |
2113 PcDescriptors::kOther, | 2084 PcDescriptors::kOther, |
2114 locs()); | 2085 locs()); |
2115 ASSERT(result == RAX); | 2086 ASSERT(result == RAX); |
2116 Register value = RBX; | 2087 Register value = RBX; |
2117 // Preserve argument on the stack until after the deoptimization point. | 2088 // Preserve argument on the stack until after the deoptimization point. |
2118 __ movq(value, Address(RSP, 0)); | 2089 __ movq(value, Address(RSP, 0)); |
2119 | 2090 |
2120 __ testq(value, Immediate(kSmiTagMask)); | 2091 __ testq(value, Immediate(kSmiTagMask)); |
2121 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 2092 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
(...skipping 15 matching lines...) Expand all Loading... |
2137 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2108 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
2138 __ jmp(deopt); | 2109 __ jmp(deopt); |
2139 return; | 2110 return; |
2140 } | 2111 } |
2141 ASSERT(HasICData()); | 2112 ASSERT(HasICData()); |
2142 ASSERT(ic_data()->num_args_tested() == 1); | 2113 ASSERT(ic_data()->num_args_tested() == 1); |
2143 if (!with_checks()) { | 2114 if (!with_checks()) { |
2144 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2115 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
2145 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2116 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
2146 instance_call()->token_pos(), | 2117 instance_call()->token_pos(), |
2147 instance_call()->try_index(), | |
2148 target, | 2118 target, |
2149 instance_call()->ArgumentCount(), | 2119 instance_call()->ArgumentCount(), |
2150 instance_call()->argument_names(), | 2120 instance_call()->argument_names(), |
2151 locs()); | 2121 locs()); |
2152 return; | 2122 return; |
2153 } | 2123 } |
2154 | 2124 |
2155 // Load receiver into RAX. | 2125 // Load receiver into RAX. |
2156 __ movq(RAX, | 2126 __ movq(RAX, |
2157 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 2127 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
2158 Label done; | 2128 Label done; |
2159 __ movq(RDI, Immediate(kSmiCid)); | 2129 __ movq(RDI, Immediate(kSmiCid)); |
2160 __ testq(RAX, Immediate(kSmiTagMask)); | 2130 __ testq(RAX, Immediate(kSmiTagMask)); |
2161 __ j(ZERO, &done); | 2131 __ j(ZERO, &done); |
2162 __ LoadClassId(RDI, RAX); | 2132 __ LoadClassId(RDI, RAX); |
2163 __ Bind(&done); | 2133 __ Bind(&done); |
2164 compiler->EmitTestAndCall(*ic_data(), | 2134 compiler->EmitTestAndCall(*ic_data(), |
2165 RDI, // Class id register. | 2135 RDI, // Class id register. |
2166 instance_call()->ArgumentCount(), | 2136 instance_call()->ArgumentCount(), |
2167 instance_call()->argument_names(), | 2137 instance_call()->argument_names(), |
2168 deopt, | 2138 deopt, |
2169 instance_call()->deopt_id(), | 2139 instance_call()->deopt_id(), |
2170 instance_call()->token_pos(), | 2140 instance_call()->token_pos(), |
2171 instance_call()->try_index(), | |
2172 locs()); | 2141 locs()); |
2173 } | 2142 } |
2174 | 2143 |
2175 | 2144 |
2176 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2145 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2177 computation()->EmitBranchCode(compiler, this); | 2146 computation()->EmitBranchCode(compiler, this); |
2178 } | 2147 } |
2179 | 2148 |
2180 | 2149 |
2181 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2150 LocationSummary* CheckClassComp::MakeLocationSummary() const { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2264 } | 2233 } |
2265 __ j(ABOVE_EQUAL, deopt); | 2234 __ j(ABOVE_EQUAL, deopt); |
2266 } | 2235 } |
2267 | 2236 |
2268 | 2237 |
2269 } // namespace dart | 2238 } // namespace dart |
2270 | 2239 |
2271 #undef __ | 2240 #undef __ |
2272 | 2241 |
2273 #endif // defined TARGET_ARCH_X64 | 2242 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |