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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 } | 79 } |
80 } | 80 } |
81 if (FLAG_trace_functions) { | 81 if (FLAG_trace_functions) { |
82 const Function& function = | 82 const Function& function = |
83 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
84 __ LoadObject(temp, function); | 84 __ LoadObject(temp, function); |
85 __ pushl(result); // Preserve result. | 85 __ pushl(result); // Preserve result. |
86 __ pushl(temp); | 86 __ pushl(temp); |
87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, | 87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
88 0, | 88 0, |
89 CatchClauseNode::kInvalidTryIndex, | |
90 kTraceFunctionExitRuntimeEntry, | 89 kTraceFunctionExitRuntimeEntry, |
91 locs()); | 90 locs()); |
92 __ popl(temp); // Remove argument. | 91 __ popl(temp); // Remove argument. |
93 __ popl(result); // Restore result. | 92 __ popl(result); // Restore result. |
94 } | 93 } |
95 #if defined(DEBUG) | 94 #if defined(DEBUG) |
96 // TODO(srdjan): Fix for functions with finally clause. | 95 // TODO(srdjan): Fix for functions with finally clause. |
97 // A finally clause may leave a previously pushed return value if it | 96 // A finally clause may leave a previously pushed return value if it |
98 // has its own return instruction. Method that have finally are currently | 97 // has its own return instruction. Method that have finally are currently |
99 // not optimized. | 98 // not optimized. |
100 if (!compiler->HasFinally()) { | 99 if (!compiler->HasFinally()) { |
101 Label done; | 100 Label done; |
102 __ movl(EDI, EBP); | 101 __ movl(EDI, EBP); |
103 __ subl(EDI, ESP); | 102 __ subl(EDI, ESP); |
104 // + 1 for Pc marker. | 103 // + 1 for Pc marker. |
105 __ cmpl(EDI, Immediate((compiler->StackSize() + 1) * kWordSize)); | 104 __ cmpl(EDI, Immediate((compiler->StackSize() + 1) * kWordSize)); |
106 __ j(EQUAL, &done, Assembler::kNearJump); | 105 __ j(EQUAL, &done, Assembler::kNearJump); |
107 __ int3(); | 106 __ int3(); |
108 __ Bind(&done); | 107 __ Bind(&done); |
109 } | 108 } |
110 #endif | 109 #endif |
111 __ LeaveFrame(); | 110 __ LeaveFrame(); |
112 __ ret(); | 111 __ ret(); |
113 | 112 |
114 // Generate 1 byte NOP so that the debugger can patch the | 113 // Generate 1 byte NOP so that the debugger can patch the |
115 // return pattern with a call to the debug stub. | 114 // return pattern with a call to the debug stub. |
116 __ nop(1); | 115 __ nop(1); |
117 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 116 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
118 deopt_id(), | 117 deopt_id(), |
119 token_pos(), | 118 token_pos()); |
120 CatchClauseNode::kInvalidTryIndex); | |
121 } | 119 } |
122 | 120 |
123 | 121 |
124 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 122 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
125 const intptr_t kNumInputs = 0; | 123 const intptr_t kNumInputs = 0; |
126 const intptr_t kNumTemps = 1; | 124 const intptr_t kNumTemps = 1; |
127 LocationSummary* result = | 125 LocationSummary* result = |
128 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 126 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
129 result->set_out(Location::RegisterLocation(EAX)); | 127 result->set_out(Location::RegisterLocation(EAX)); |
130 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. | 128 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // Call the runtime if the object is not bool::true or bool::false. | 204 // Call the runtime if the object is not bool::true or bool::false. |
207 Label done; | 205 Label done; |
208 __ CompareObject(obj, compiler->bool_true()); | 206 __ CompareObject(obj, compiler->bool_true()); |
209 __ j(EQUAL, &done, Assembler::kNearJump); | 207 __ j(EQUAL, &done, Assembler::kNearJump); |
210 __ CompareObject(obj, compiler->bool_false()); | 208 __ CompareObject(obj, compiler->bool_false()); |
211 __ j(EQUAL, &done, Assembler::kNearJump); | 209 __ j(EQUAL, &done, Assembler::kNearJump); |
212 | 210 |
213 __ pushl(obj); // Push the source object. | 211 __ pushl(obj); // Push the source object. |
214 compiler->GenerateCallRuntime(deopt_id(), | 212 compiler->GenerateCallRuntime(deopt_id(), |
215 token_pos(), | 213 token_pos(), |
216 try_index(), | |
217 kConditionTypeErrorRuntimeEntry, | 214 kConditionTypeErrorRuntimeEntry, |
218 locs()); | 215 locs()); |
219 // We should never return here. | 216 // We should never return here. |
220 __ int3(); | 217 __ int3(); |
221 __ Bind(&done); | 218 __ Bind(&done); |
222 } | 219 } |
223 ASSERT(obj == result); | 220 ASSERT(obj == result); |
224 } | 221 } |
225 | 222 |
226 | 223 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 locs->set_in(0, Location::RegisterLocation(ECX)); | 268 locs->set_in(0, Location::RegisterLocation(ECX)); |
272 locs->set_in(1, Location::RegisterLocation(EDX)); | 269 locs->set_in(1, Location::RegisterLocation(EDX)); |
273 locs->set_out(Location::RegisterLocation(EAX)); | 270 locs->set_out(Location::RegisterLocation(EAX)); |
274 return locs; | 271 return locs; |
275 } | 272 } |
276 | 273 |
277 | 274 |
278 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 275 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
279 intptr_t deopt_id, | 276 intptr_t deopt_id, |
280 intptr_t token_pos, | 277 intptr_t token_pos, |
281 intptr_t try_index, | |
282 Token::Kind kind, | 278 Token::Kind kind, |
283 LocationSummary* locs) { | 279 LocationSummary* locs) { |
284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 280 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
285 deopt_id, | 281 deopt_id, |
286 token_pos, | 282 token_pos); |
287 try_index); | |
288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 283 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
289 const int kNumberOfArguments = 2; | 284 const int kNumberOfArguments = 2; |
290 const Array& kNoArgumentNames = Array::Handle(); | 285 const Array& kNoArgumentNames = Array::Handle(); |
291 const int kNumArgumentsChecked = 2; | 286 const int kNumArgumentsChecked = 2; |
292 | 287 |
293 Label done, false_label, true_label; | 288 Label done, false_label, true_label; |
294 Register left = locs->in(0).reg(); | 289 Register left = locs->in(0).reg(); |
295 Register right = locs->in(1).reg(); | 290 Register right = locs->in(1).reg(); |
296 __ popl(right); | 291 __ popl(right); |
297 __ popl(left); | 292 __ popl(left); |
(...skipping 17 matching lines...) Expand all Loading... |
315 } else { | 310 } else { |
316 ASSERT(kind == Token::kNE); | 311 ASSERT(kind == Token::kNE); |
317 __ jmp(&false_label); | 312 __ jmp(&false_label); |
318 } | 313 } |
319 | 314 |
320 __ Bind(&instance_call); | 315 __ Bind(&instance_call); |
321 __ pushl(left); | 316 __ pushl(left); |
322 __ pushl(right); | 317 __ pushl(right); |
323 compiler->GenerateInstanceCall(deopt_id, | 318 compiler->GenerateInstanceCall(deopt_id, |
324 token_pos, | 319 token_pos, |
325 try_index, | |
326 operator_name, | 320 operator_name, |
327 kNumberOfArguments, | 321 kNumberOfArguments, |
328 kNoArgumentNames, | 322 kNoArgumentNames, |
329 kNumArgumentsChecked, | 323 kNumArgumentsChecked, |
330 locs); | 324 locs); |
331 if (kind == Token::kNE) { | 325 if (kind == Token::kNE) { |
332 // Negate the condition: true label returns false and vice versa. | 326 // Negate the condition: true label returns false and vice versa. |
333 __ CompareObject(EAX, compiler->bool_true()); | 327 __ CompareObject(EAX, compiler->bool_true()); |
334 __ j(EQUAL, &true_label, Assembler::kNearJump); | 328 __ j(EQUAL, &true_label, Assembler::kNearJump); |
335 __ Bind(&false_label); | 329 __ Bind(&false_label); |
336 __ LoadObject(EAX, compiler->bool_true()); | 330 __ LoadObject(EAX, compiler->bool_true()); |
337 __ jmp(&done, Assembler::kNearJump); | 331 __ jmp(&done, Assembler::kNearJump); |
338 __ Bind(&true_label); | 332 __ Bind(&true_label); |
339 __ LoadObject(EAX, compiler->bool_false()); | 333 __ LoadObject(EAX, compiler->bool_false()); |
340 } | 334 } |
341 __ Bind(&done); | 335 __ Bind(&done); |
342 } | 336 } |
343 | 337 |
344 | 338 |
345 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 339 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
346 const ICData& orig_ic_data, | 340 const ICData& orig_ic_data, |
347 LocationSummary* locs, | 341 LocationSummary* locs, |
348 BranchInstr* branch, | 342 BranchInstr* branch, |
349 Token::Kind kind, | 343 Token::Kind kind, |
350 intptr_t deopt_id, | 344 intptr_t deopt_id, |
351 intptr_t token_pos, | 345 intptr_t token_pos) { |
352 intptr_t try_index) { | |
353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 346 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 347 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
355 ASSERT(ic_data.NumberOfChecks() > 0); | 348 ASSERT(ic_data.NumberOfChecks() > 0); |
356 ASSERT(ic_data.num_args_tested() == 1); | 349 ASSERT(ic_data.num_args_tested() == 1); |
357 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 350 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
358 Register left = locs->in(0).reg(); | 351 Register left = locs->in(0).reg(); |
359 Register right = locs->in(1).reg(); | 352 Register right = locs->in(1).reg(); |
360 __ testl(left, Immediate(kSmiTagMask)); | 353 __ testl(left, Immediate(kSmiTagMask)); |
361 Register temp = locs->temp(0).reg(); | 354 Register temp = locs->temp(0).reg(); |
362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 355 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 __ LoadObject(result, compiler->bool_false()); | 388 __ LoadObject(result, compiler->bool_false()); |
396 __ jmp(&done); | 389 __ jmp(&done); |
397 __ Bind(&load_true); | 390 __ Bind(&load_true); |
398 __ LoadObject(result, compiler->bool_true()); | 391 __ LoadObject(result, compiler->bool_true()); |
399 } | 392 } |
400 } else { | 393 } else { |
401 const int kNumberOfArguments = 2; | 394 const int kNumberOfArguments = 2; |
402 const Array& kNoArgumentNames = Array::Handle(); | 395 const Array& kNoArgumentNames = Array::Handle(); |
403 compiler->GenerateStaticCall(deopt_id, | 396 compiler->GenerateStaticCall(deopt_id, |
404 token_pos, | 397 token_pos, |
405 try_index, | |
406 target, | 398 target, |
407 kNumberOfArguments, | 399 kNumberOfArguments, |
408 kNoArgumentNames, | 400 kNoArgumentNames, |
409 locs); | 401 locs); |
410 if (branch == NULL) { | 402 if (branch == NULL) { |
411 if (kind == Token::kNE) { | 403 if (kind == Token::kNE) { |
412 Label false_label; | 404 Label false_label; |
413 __ CompareObject(EAX, compiler->bool_true()); | 405 __ CompareObject(EAX, compiler->bool_true()); |
414 __ j(EQUAL, &false_label, Assembler::kNearJump); | 406 __ j(EQUAL, &false_label, Assembler::kNearJump); |
415 __ LoadObject(EAX, compiler->bool_true()); | 407 __ LoadObject(EAX, compiler->bool_true()); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 | 479 |
488 // First test if receiver is NULL, in which case === is applied. | 480 // First test if receiver is NULL, in which case === is applied. |
489 // If type feedback was provided (lists of <class-id, target>), do a | 481 // If type feedback was provided (lists of <class-id, target>), do a |
490 // type by type check (either === or static call to the operator. | 482 // type by type check (either === or static call to the operator. |
491 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 483 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
492 LocationSummary* locs, | 484 LocationSummary* locs, |
493 Token::Kind kind, | 485 Token::Kind kind, |
494 BranchInstr* branch, | 486 BranchInstr* branch, |
495 const ICData& ic_data, | 487 const ICData& ic_data, |
496 intptr_t deopt_id, | 488 intptr_t deopt_id, |
497 intptr_t token_pos, | 489 intptr_t token_pos) { |
498 intptr_t try_index) { | |
499 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 490 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
500 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 491 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
501 Register left = locs->in(0).reg(); | 492 Register left = locs->in(0).reg(); |
502 Register right = locs->in(1).reg(); | 493 Register right = locs->in(1).reg(); |
503 const Immediate raw_null = | 494 const Immediate raw_null = |
504 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 495 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
505 Label done, identity_compare, non_null_compare; | 496 Label done, identity_compare, non_null_compare; |
506 __ cmpl(right, raw_null); | 497 __ cmpl(right, raw_null); |
507 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 498 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
508 __ cmpl(left, raw_null); | 499 __ cmpl(left, raw_null); |
(...skipping 11 matching lines...) Expand all Loading... |
520 __ LoadObject(result, compiler->bool_false()); | 511 __ LoadObject(result, compiler->bool_false()); |
521 __ jmp(&done); | 512 __ jmp(&done); |
522 __ Bind(&load_true); | 513 __ Bind(&load_true); |
523 __ LoadObject(result, compiler->bool_true()); | 514 __ LoadObject(result, compiler->bool_true()); |
524 } | 515 } |
525 __ jmp(&done); | 516 __ jmp(&done); |
526 __ Bind(&non_null_compare); // Receiver is not null. | 517 __ Bind(&non_null_compare); // Receiver is not null. |
527 __ pushl(left); | 518 __ pushl(left); |
528 __ pushl(right); | 519 __ pushl(right); |
529 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 520 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
530 deopt_id, token_pos, try_index); | 521 deopt_id, token_pos); |
531 __ Bind(&done); | 522 __ Bind(&done); |
532 } | 523 } |
533 | 524 |
534 | 525 |
535 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 526 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
536 const LocationSummary& locs, | 527 const LocationSummary& locs, |
537 Token::Kind kind, | 528 Token::Kind kind, |
538 BranchInstr* branch, | 529 BranchInstr* branch, |
539 intptr_t deopt_id) { | 530 intptr_t deopt_id) { |
540 Register left = locs.in(0).reg(); | 531 Register left = locs.in(0).reg(); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 } | 616 } |
626 const bool is_checked_strict_equal = | 617 const bool is_checked_strict_equal = |
627 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 618 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
628 if (is_checked_strict_equal) { | 619 if (is_checked_strict_equal) { |
629 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 620 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
630 deopt_id()); | 621 deopt_id()); |
631 return; | 622 return; |
632 } | 623 } |
633 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 624 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
634 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), | 625 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
635 deopt_id(), token_pos(), try_index()); | 626 deopt_id(), token_pos()); |
636 return; | 627 return; |
637 } | 628 } |
638 Register left = locs()->in(0).reg(); | 629 Register left = locs()->in(0).reg(); |
639 Register right = locs()->in(1).reg(); | 630 Register right = locs()->in(1).reg(); |
640 __ pushl(left); | 631 __ pushl(left); |
641 __ pushl(right); | 632 __ pushl(right); |
642 EmitEqualityAsInstanceCall(compiler, | 633 EmitEqualityAsInstanceCall(compiler, deopt_id(), token_pos(), kind(), locs()); |
643 deopt_id(), | |
644 token_pos(), | |
645 try_index(), | |
646 kind(), | |
647 locs()); | |
648 ASSERT(locs()->out().reg() == EAX); | 634 ASSERT(locs()->out().reg() == EAX); |
649 } | 635 } |
650 | 636 |
651 | 637 |
652 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 638 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, |
653 BranchInstr* branch) { | 639 BranchInstr* branch) { |
654 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 640 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
655 if (receiver_class_id() == kSmiCid) { | 641 if (receiver_class_id() == kSmiCid) { |
656 // Deoptimizes if both arguments not Smi. | 642 // Deoptimizes if both arguments not Smi. |
657 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 643 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
658 return; | 644 return; |
659 } | 645 } |
660 if (receiver_class_id() == kDoubleCid) { | 646 if (receiver_class_id() == kDoubleCid) { |
661 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 647 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
662 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 648 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
663 return; | 649 return; |
664 } | 650 } |
665 const bool is_checked_strict_equal = | 651 const bool is_checked_strict_equal = |
666 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 652 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
667 if (is_checked_strict_equal) { | 653 if (is_checked_strict_equal) { |
668 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 654 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
669 deopt_id()); | 655 deopt_id()); |
670 return; | 656 return; |
671 } | 657 } |
672 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 658 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
673 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), | 659 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), |
674 deopt_id(), token_pos(), try_index()); | 660 deopt_id(), token_pos()); |
675 return; | 661 return; |
676 } | 662 } |
677 Register left = locs()->in(0).reg(); | 663 Register left = locs()->in(0).reg(); |
678 Register right = locs()->in(1).reg(); | 664 Register right = locs()->in(1).reg(); |
679 __ pushl(left); | 665 __ pushl(left); |
680 __ pushl(right); | 666 __ pushl(right); |
681 EmitEqualityAsInstanceCall(compiler, | 667 EmitEqualityAsInstanceCall(compiler, |
682 deopt_id(), | 668 deopt_id(), |
683 token_pos(), | 669 token_pos(), |
684 try_index(), | |
685 Token::kEQ, // kNE reverse occurs at branch. | 670 Token::kEQ, // kNE reverse occurs at branch. |
686 locs()); | 671 locs()); |
687 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 672 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
688 __ CompareObject(EAX, compiler->bool_true()); | 673 __ CompareObject(EAX, compiler->bool_true()); |
689 branch->EmitBranchOnCondition(compiler, branch_condition); | 674 branch->EmitBranchOnCondition(compiler, branch_condition); |
690 } | 675 } |
691 | 676 |
692 | 677 |
693 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 678 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
694 const intptr_t kNumInputs = 2; | 679 const intptr_t kNumInputs = 2; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 __ j(ZERO, &done); | 727 __ j(ZERO, &done); |
743 __ LoadClassId(EDI, left); | 728 __ LoadClassId(EDI, left); |
744 __ Bind(&done); | 729 __ Bind(&done); |
745 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 730 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
746 EDI, // Class id register. | 731 EDI, // Class id register. |
747 kNumArguments, | 732 kNumArguments, |
748 Array::Handle(), // No named arguments. | 733 Array::Handle(), // No named arguments. |
749 deopt, // Deoptimize target. | 734 deopt, // Deoptimize target. |
750 deopt_id(), | 735 deopt_id(), |
751 token_pos(), | 736 token_pos(), |
752 try_index(), | |
753 locs()); | 737 locs()); |
754 return; | 738 return; |
755 } | 739 } |
756 const String& function_name = | 740 const String& function_name = |
757 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 741 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
758 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 742 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
759 deopt_id(), | 743 deopt_id(), |
760 token_pos(), | 744 token_pos()); |
761 try_index()); | |
762 const intptr_t kNumArguments = 2; | 745 const intptr_t kNumArguments = 2; |
763 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 746 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
764 compiler->GenerateInstanceCall(deopt_id(), | 747 compiler->GenerateInstanceCall(deopt_id(), |
765 token_pos(), | 748 token_pos(), |
766 try_index(), | |
767 function_name, | 749 function_name, |
768 kNumArguments, | 750 kNumArguments, |
769 Array::ZoneHandle(), // No optional arguments. | 751 Array::ZoneHandle(), // No optional arguments. |
770 kNumArgsChecked, | 752 kNumArgsChecked, |
771 locs()); | 753 locs()); |
772 } | 754 } |
773 | 755 |
774 | 756 |
775 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 757 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, |
776 BranchInstr* branch) { | 758 BranchInstr* branch) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 } | 798 } |
817 if (!has_optional_parameters() && !is_native_instance_closure()) { | 799 if (!has_optional_parameters() && !is_native_instance_closure()) { |
818 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 800 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
819 } else { | 801 } else { |
820 __ leal(EAX, | 802 __ leal(EAX, |
821 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 803 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
822 } | 804 } |
823 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 805 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
824 __ movl(EDX, Immediate(arg_count)); | 806 __ movl(EDX, Immediate(arg_count)); |
825 compiler->GenerateCall(token_pos(), | 807 compiler->GenerateCall(token_pos(), |
826 try_index(), | |
827 &StubCode::CallNativeCFunctionLabel(), | 808 &StubCode::CallNativeCFunctionLabel(), |
828 PcDescriptors::kOther, | 809 PcDescriptors::kOther, |
829 locs()); | 810 locs()); |
830 __ popl(result); | 811 __ popl(result); |
831 } | 812 } |
832 | 813 |
833 | 814 |
834 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 815 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
835 ASSERT((receiver_type() == kGrowableObjectArrayCid) || | 816 ASSERT((receiver_type() == kGrowableObjectArrayCid) || |
836 (receiver_type() == kArrayCid) || | 817 (receiver_type() == kArrayCid) || |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1033 } | 1014 } |
1034 | 1015 |
1035 | 1016 |
1036 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1017 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1037 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1018 ASSERT(locs()->in(0).reg() == EAX); // Value. |
1038 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1019 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
1039 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1020 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
1040 | 1021 |
1041 compiler->GenerateInstanceOf(deopt_id(), | 1022 compiler->GenerateInstanceOf(deopt_id(), |
1042 token_pos(), | 1023 token_pos(), |
1043 try_index(), | |
1044 type(), | 1024 type(), |
1045 negate_result(), | 1025 negate_result(), |
1046 locs()); | 1026 locs()); |
1047 ASSERT(locs()->out().reg() == EAX); | 1027 ASSERT(locs()->out().reg() == EAX); |
1048 } | 1028 } |
1049 | 1029 |
1050 | 1030 |
1051 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1031 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1052 const intptr_t kNumInputs = 1; | 1032 const intptr_t kNumInputs = 1; |
1053 const intptr_t kNumTemps = 0; | 1033 const intptr_t kNumTemps = 0; |
1054 LocationSummary* locs = | 1034 LocationSummary* locs = |
1055 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1035 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1056 locs->set_in(0, Location::RegisterLocation(ECX)); | 1036 locs->set_in(0, Location::RegisterLocation(ECX)); |
1057 locs->set_out(Location::RegisterLocation(EAX)); | 1037 locs->set_out(Location::RegisterLocation(EAX)); |
1058 return locs; | 1038 return locs; |
1059 } | 1039 } |
1060 | 1040 |
1061 | 1041 |
1062 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1042 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1063 // Allocate the array. EDX = length, ECX = element type. | 1043 // Allocate the array. EDX = length, ECX = element type. |
1064 ASSERT(locs()->in(0).reg() == ECX); | 1044 ASSERT(locs()->in(0).reg() == ECX); |
1065 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); | 1045 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); |
1066 compiler->GenerateCall(token_pos(), | 1046 compiler->GenerateCall(token_pos(), |
1067 try_index(), | |
1068 &StubCode::AllocateArrayLabel(), | 1047 &StubCode::AllocateArrayLabel(), |
1069 PcDescriptors::kOther, | 1048 PcDescriptors::kOther, |
1070 locs()); | 1049 locs()); |
1071 ASSERT(locs()->out().reg() == EAX); | 1050 ASSERT(locs()->out().reg() == EAX); |
1072 | 1051 |
1073 // Pop the element values from the stack into the array. | 1052 // Pop the element values from the stack into the array. |
1074 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); | 1053 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); |
1075 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1054 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
1076 ASSERT(ArgumentAt(i)->value()->IsUse()); | 1055 ASSERT(ArgumentAt(i)->value()->IsUse()); |
1077 __ popl(Address(EDX, i * kWordSize)); | 1056 __ popl(Address(EDX, i * kWordSize)); |
(...skipping 21 matching lines...) Expand all Loading... |
1099 Register instantiator_type_arguments = locs()->in(1).reg(); | 1078 Register instantiator_type_arguments = locs()->in(1).reg(); |
1100 Register result = locs()->out().reg(); | 1079 Register result = locs()->out().reg(); |
1101 | 1080 |
1102 // Push the result place holder initialized to NULL. | 1081 // Push the result place holder initialized to NULL. |
1103 __ PushObject(Object::ZoneHandle()); | 1082 __ PushObject(Object::ZoneHandle()); |
1104 __ PushObject(cls); | 1083 __ PushObject(cls); |
1105 __ pushl(type_arguments); | 1084 __ pushl(type_arguments); |
1106 __ pushl(instantiator_type_arguments); | 1085 __ pushl(instantiator_type_arguments); |
1107 compiler->GenerateCallRuntime(deopt_id(), | 1086 compiler->GenerateCallRuntime(deopt_id(), |
1108 token_pos(), | 1087 token_pos(), |
1109 try_index(), | |
1110 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1088 kAllocateObjectWithBoundsCheckRuntimeEntry, |
1111 locs()); | 1089 locs()); |
1112 // Pop instantiator type arguments, type arguments, and class. | 1090 // Pop instantiator type arguments, type arguments, and class. |
1113 // source location. | 1091 // source location. |
1114 __ Drop(3); | 1092 __ Drop(3); |
1115 __ popl(result); // Pop new instance. | 1093 __ popl(result); // Pop new instance. |
1116 } | 1094 } |
1117 | 1095 |
1118 | 1096 |
1119 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1097 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 Immediate(Smi::RawValue(len))); | 1164 Immediate(Smi::RawValue(len))); |
1187 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1165 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1188 __ Bind(&type_arguments_uninstantiated); | 1166 __ Bind(&type_arguments_uninstantiated); |
1189 } | 1167 } |
1190 // A runtime call to instantiate the type arguments is required. | 1168 // A runtime call to instantiate the type arguments is required. |
1191 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1169 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1192 __ PushObject(type_arguments()); | 1170 __ PushObject(type_arguments()); |
1193 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1171 __ pushl(instantiator_reg); // Push instantiator type arguments. |
1194 compiler->GenerateCallRuntime(deopt_id(), | 1172 compiler->GenerateCallRuntime(deopt_id(), |
1195 token_pos(), | 1173 token_pos(), |
1196 try_index(), | |
1197 kInstantiateTypeArgumentsRuntimeEntry, | 1174 kInstantiateTypeArgumentsRuntimeEntry, |
1198 locs()); | 1175 locs()); |
1199 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1176 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1200 __ popl(result_reg); // Pop instantiated type arguments. | 1177 __ popl(result_reg); // Pop instantiated type arguments. |
1201 __ Bind(&type_arguments_instantiated); | 1178 __ Bind(&type_arguments_instantiated); |
1202 ASSERT(instantiator_reg == result_reg); | 1179 ASSERT(instantiator_reg == result_reg); |
1203 // 'result_reg': Instantiated type arguments. | 1180 // 'result_reg': Instantiated type arguments. |
1204 } | 1181 } |
1205 | 1182 |
1206 | 1183 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1342 | 1319 |
1343 | 1320 |
1344 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1321 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1345 ASSERT(locs()->temp(0).reg() == EDX); | 1322 ASSERT(locs()->temp(0).reg() == EDX); |
1346 ASSERT(locs()->out().reg() == EAX); | 1323 ASSERT(locs()->out().reg() == EAX); |
1347 | 1324 |
1348 __ movl(EDX, Immediate(num_context_variables())); | 1325 __ movl(EDX, Immediate(num_context_variables())); |
1349 const ExternalLabel label("alloc_context", | 1326 const ExternalLabel label("alloc_context", |
1350 StubCode::AllocateContextEntryPoint()); | 1327 StubCode::AllocateContextEntryPoint()); |
1351 compiler->GenerateCall(token_pos(), | 1328 compiler->GenerateCall(token_pos(), |
1352 try_index(), | |
1353 &label, | 1329 &label, |
1354 PcDescriptors::kOther, | 1330 PcDescriptors::kOther, |
1355 locs()); | 1331 locs()); |
1356 } | 1332 } |
1357 | 1333 |
1358 | 1334 |
1359 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1335 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1360 const intptr_t kNumInputs = 1; | 1336 const intptr_t kNumInputs = 1; |
1361 const intptr_t kNumTemps = 0; | 1337 const intptr_t kNumTemps = 0; |
1362 LocationSummary* locs = | 1338 LocationSummary* locs = |
1363 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1339 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
1364 locs->set_in(0, Location::RegisterLocation(EAX)); | 1340 locs->set_in(0, Location::RegisterLocation(EAX)); |
1365 locs->set_out(Location::RegisterLocation(EAX)); | 1341 locs->set_out(Location::RegisterLocation(EAX)); |
1366 return locs; | 1342 return locs; |
1367 } | 1343 } |
1368 | 1344 |
1369 | 1345 |
1370 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1346 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1371 Register context_value = locs()->in(0).reg(); | 1347 Register context_value = locs()->in(0).reg(); |
1372 Register result = locs()->out().reg(); | 1348 Register result = locs()->out().reg(); |
1373 | 1349 |
1374 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1350 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1375 __ pushl(context_value); | 1351 __ pushl(context_value); |
1376 compiler->GenerateCallRuntime(deopt_id(), | 1352 compiler->GenerateCallRuntime(deopt_id(), |
1377 token_pos(), | 1353 token_pos(), |
1378 try_index(), | |
1379 kCloneContextRuntimeEntry, | 1354 kCloneContextRuntimeEntry, |
1380 locs()); | 1355 locs()); |
1381 __ popl(result); // Remove argument. | 1356 __ popl(result); // Remove argument. |
1382 __ popl(result); // Get result (cloned context). | 1357 __ popl(result); // Get result (cloned context). |
1383 } | 1358 } |
1384 | 1359 |
1385 | 1360 |
1386 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1361 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1387 return LocationSummary::Make(0, | 1362 return LocationSummary::Make(0, |
1388 Location::NoLocation(), | 1363 Location::NoLocation(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 class CheckStackOverflowSlowPath : public SlowPathCode { | 1399 class CheckStackOverflowSlowPath : public SlowPathCode { |
1425 public: | 1400 public: |
1426 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1401 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) |
1427 : computation_(computation) { } | 1402 : computation_(computation) { } |
1428 | 1403 |
1429 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1404 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
1430 __ Bind(entry_label()); | 1405 __ Bind(entry_label()); |
1431 compiler->SaveLiveRegisters(computation_->locs()); | 1406 compiler->SaveLiveRegisters(computation_->locs()); |
1432 compiler->GenerateCallRuntime(computation_->deopt_id(), | 1407 compiler->GenerateCallRuntime(computation_->deopt_id(), |
1433 computation_->token_pos(), | 1408 computation_->token_pos(), |
1434 computation_->try_index(), | |
1435 kStackOverflowRuntimeEntry, | 1409 kStackOverflowRuntimeEntry, |
1436 computation_->locs()); | 1410 computation_->locs()); |
1437 compiler->RestoreLiveRegisters(computation_->locs()); | 1411 compiler->RestoreLiveRegisters(computation_->locs()); |
1438 __ jmp(exit_label()); | 1412 __ jmp(exit_label()); |
1439 } | 1413 } |
1440 | 1414 |
1441 private: | 1415 private: |
1442 CheckStackOverflowComp* computation_; | 1416 CheckStackOverflowComp* computation_; |
1443 }; | 1417 }; |
1444 | 1418 |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1613 __ Bind(&call_method); | 1587 __ Bind(&call_method); |
1614 Function& target = Function::ZoneHandle( | 1588 Function& target = Function::ZoneHandle( |
1615 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1589 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1616 ASSERT(!target.IsNull()); | 1590 ASSERT(!target.IsNull()); |
1617 const intptr_t kArgumentCount = 2; | 1591 const intptr_t kArgumentCount = 2; |
1618 __ pushl(temp); | 1592 __ pushl(temp); |
1619 __ pushl(right); | 1593 __ pushl(right); |
1620 compiler->GenerateStaticCall( | 1594 compiler->GenerateStaticCall( |
1621 instance_call()->deopt_id(), | 1595 instance_call()->deopt_id(), |
1622 instance_call()->token_pos(), | 1596 instance_call()->token_pos(), |
1623 instance_call()->try_index(), | |
1624 target, | 1597 target, |
1625 kArgumentCount, | 1598 kArgumentCount, |
1626 Array::Handle(), // No argument names. | 1599 Array::Handle(), // No argument names. |
1627 locs()); | 1600 locs()); |
1628 ASSERT(result == EAX); | 1601 ASSERT(result == EAX); |
1629 } | 1602 } |
1630 __ Bind(&done); | 1603 __ Bind(&done); |
1631 break; | 1604 break; |
1632 } | 1605 } |
1633 case Token::kDIV: { | 1606 case Token::kDIV: { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1720 Function& target = Function::ZoneHandle( | 1693 Function& target = Function::ZoneHandle( |
1721 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1694 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
1722 if (target.IsNull()) { | 1695 if (target.IsNull()) { |
1723 __ jmp(deopt); | 1696 __ jmp(deopt); |
1724 } else { | 1697 } else { |
1725 __ pushl(left); | 1698 __ pushl(left); |
1726 __ pushl(right); | 1699 __ pushl(right); |
1727 compiler->GenerateStaticCall( | 1700 compiler->GenerateStaticCall( |
1728 instance_call()->deopt_id(), | 1701 instance_call()->deopt_id(), |
1729 instance_call()->token_pos(), | 1702 instance_call()->token_pos(), |
1730 instance_call()->try_index(), | |
1731 target, | 1703 target, |
1732 instance_call()->ArgumentCount(), | 1704 instance_call()->ArgumentCount(), |
1733 instance_call()->argument_names(), | 1705 instance_call()->argument_names(), |
1734 locs()); | 1706 locs()); |
1735 ASSERT(result == EAX); | 1707 ASSERT(result == EAX); |
1736 __ jmp(&done); | 1708 __ jmp(&done); |
1737 } | 1709 } |
1738 } | 1710 } |
1739 | 1711 |
1740 __ Bind(&mint_static_call); | 1712 __ Bind(&mint_static_call); |
1741 { | 1713 { |
1742 Function& target = Function::ZoneHandle( | 1714 Function& target = Function::ZoneHandle( |
1743 ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1715 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
1744 if (target.IsNull()) { | 1716 if (target.IsNull()) { |
1745 __ jmp(deopt); | 1717 __ jmp(deopt); |
1746 } else { | 1718 } else { |
1747 __ pushl(left); | 1719 __ pushl(left); |
1748 __ pushl(right); | 1720 __ pushl(right); |
1749 compiler->GenerateStaticCall( | 1721 compiler->GenerateStaticCall( |
1750 instance_call()->deopt_id(), | 1722 instance_call()->deopt_id(), |
1751 instance_call()->token_pos(), | 1723 instance_call()->token_pos(), |
1752 instance_call()->try_index(), | |
1753 target, | 1724 target, |
1754 instance_call()->ArgumentCount(), | 1725 instance_call()->ArgumentCount(), |
1755 instance_call()->argument_names(), | 1726 instance_call()->argument_names(), |
1756 locs()); | 1727 locs()); |
1757 ASSERT(result == EAX); | 1728 ASSERT(result == EAX); |
1758 } | 1729 } |
1759 } | 1730 } |
1760 __ Bind(&done); | 1731 __ Bind(&done); |
1761 } | 1732 } |
1762 | 1733 |
1763 | 1734 |
1764 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { | 1735 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
1765 return MakeCallSummary(); // Calls into a stub for allocation. | 1736 return MakeCallSummary(); // Calls into a stub for allocation. |
1766 } | 1737 } |
1767 | 1738 |
1768 | 1739 |
1769 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1740 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1770 Register left = EBX; | 1741 Register left = EBX; |
1771 Register right = ECX; | 1742 Register right = ECX; |
1772 Register temp = EDX; | 1743 Register temp = EDX; |
1773 Register result = locs()->out().reg(); | 1744 Register result = locs()->out().reg(); |
1774 | 1745 |
1775 const Class& double_class = compiler->double_class(); | 1746 const Class& double_class = compiler->double_class(); |
1776 const Code& stub = | 1747 const Code& stub = |
1777 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1748 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1778 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1749 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1779 compiler->GenerateCall(instance_call()->token_pos(), | 1750 compiler->GenerateCall(instance_call()->token_pos(), |
1780 instance_call()->try_index(), | |
1781 &label, | 1751 &label, |
1782 PcDescriptors::kOther, | 1752 PcDescriptors::kOther, |
1783 locs()); | 1753 locs()); |
1784 // Newly allocated object is now in the result register (RAX). | 1754 // Newly allocated object is now in the result register (RAX). |
1785 ASSERT(result == EAX); | 1755 ASSERT(result == EAX); |
1786 __ movl(right, Address(ESP, 0)); | 1756 __ movl(right, Address(ESP, 0)); |
1787 __ movl(left, Address(ESP, kWordSize)); | 1757 __ movl(left, Address(ESP, kWordSize)); |
1788 | 1758 |
1789 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1759 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
1790 kDeoptBinaryDoubleOp); | 1760 kDeoptBinaryDoubleOp); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1833 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1864 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1834 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1865 | 1835 |
1866 // TODO(vegorov): here stack map needs to be set up correctly to skip | 1836 // TODO(vegorov): here stack map needs to be set up correctly to skip |
1867 // double registers. | 1837 // double registers. |
1868 LocationSummary* locs = computation_->locs(); | 1838 LocationSummary* locs = computation_->locs(); |
1869 locs->live_registers()->Remove(locs->out()); | 1839 locs->live_registers()->Remove(locs->out()); |
1870 | 1840 |
1871 compiler->SaveLiveRegisters(locs); | 1841 compiler->SaveLiveRegisters(locs); |
1872 compiler->GenerateCall(computation_->instance_call()->token_pos(), | 1842 compiler->GenerateCall(computation_->instance_call()->token_pos(), |
1873 computation_->instance_call()->try_index(), | |
1874 &label, | 1843 &label, |
1875 PcDescriptors::kOther, | 1844 PcDescriptors::kOther, |
1876 locs); | 1845 locs); |
1877 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); | 1846 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); |
1878 compiler->RestoreLiveRegisters(locs); | 1847 compiler->RestoreLiveRegisters(locs); |
1879 | 1848 |
1880 __ jmp(exit_label()); | 1849 __ jmp(exit_label()); |
1881 } | 1850 } |
1882 | 1851 |
1883 private: | 1852 private: |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2028 __ j(ZERO, deopt); // Smi. | 1997 __ j(ZERO, deopt); // Smi. |
2029 __ CompareClassId(value, kDoubleCid, temp); | 1998 __ CompareClassId(value, kDoubleCid, temp); |
2030 __ j(NOT_EQUAL, deopt); | 1999 __ j(NOT_EQUAL, deopt); |
2031 // Allocate result object. | 2000 // Allocate result object. |
2032 const Class& double_class = compiler->double_class(); | 2001 const Class& double_class = compiler->double_class(); |
2033 const Code& stub = | 2002 const Code& stub = |
2034 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2003 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
2035 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2004 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
2036 __ pushl(value); | 2005 __ pushl(value); |
2037 compiler->GenerateCall(instance_call()->token_pos(), | 2006 compiler->GenerateCall(instance_call()->token_pos(), |
2038 instance_call()->try_index(), | |
2039 &label, | 2007 &label, |
2040 PcDescriptors::kOther, | 2008 PcDescriptors::kOther, |
2041 locs()); | 2009 locs()); |
2042 // Result is in EAX. | 2010 // Result is in EAX. |
2043 ASSERT(result != temp); | 2011 ASSERT(result != temp); |
2044 __ movl(result, EAX); | 2012 __ movl(result, EAX); |
2045 __ popl(temp); | 2013 __ popl(temp); |
2046 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 2014 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
2047 __ DoubleNegate(XMM0); | 2015 __ DoubleNegate(XMM0); |
2048 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2016 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2091 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2059 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
2092 kDeoptIntegerToDouble); | 2060 kDeoptIntegerToDouble); |
2093 | 2061 |
2094 const Class& double_class = compiler->double_class(); | 2062 const Class& double_class = compiler->double_class(); |
2095 const Code& stub = | 2063 const Code& stub = |
2096 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2064 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
2097 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2065 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
2098 | 2066 |
2099 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 2067 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
2100 compiler->GenerateCall(instance_call()->token_pos(), | 2068 compiler->GenerateCall(instance_call()->token_pos(), |
2101 instance_call()->try_index(), | |
2102 &label, | 2069 &label, |
2103 PcDescriptors::kOther, | 2070 PcDescriptors::kOther, |
2104 locs()); | 2071 locs()); |
2105 ASSERT(result == EAX); | 2072 ASSERT(result == EAX); |
2106 Register value = EBX; | 2073 Register value = EBX; |
2107 // Preserve argument on the stack until after the deoptimization point. | 2074 // Preserve argument on the stack until after the deoptimization point. |
2108 __ movl(value, Address(ESP, 0)); | 2075 __ movl(value, Address(ESP, 0)); |
2109 | 2076 |
2110 __ testl(value, Immediate(kSmiTagMask)); | 2077 __ testl(value, Immediate(kSmiTagMask)); |
2111 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 2078 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
(...skipping 15 matching lines...) Expand all Loading... |
2127 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2094 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
2128 __ jmp(deopt); | 2095 __ jmp(deopt); |
2129 return; | 2096 return; |
2130 } | 2097 } |
2131 ASSERT(HasICData()); | 2098 ASSERT(HasICData()); |
2132 ASSERT(ic_data()->num_args_tested() == 1); | 2099 ASSERT(ic_data()->num_args_tested() == 1); |
2133 if (!with_checks()) { | 2100 if (!with_checks()) { |
2134 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2101 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
2135 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2102 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
2136 instance_call()->token_pos(), | 2103 instance_call()->token_pos(), |
2137 instance_call()->try_index(), | |
2138 target, | 2104 target, |
2139 instance_call()->ArgumentCount(), | 2105 instance_call()->ArgumentCount(), |
2140 instance_call()->argument_names(), | 2106 instance_call()->argument_names(), |
2141 locs()); | 2107 locs()); |
2142 return; | 2108 return; |
2143 } | 2109 } |
2144 | 2110 |
2145 // Load receiver into EAX. | 2111 // Load receiver into EAX. |
2146 __ movl(EAX, | 2112 __ movl(EAX, |
2147 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 2113 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
2148 | 2114 |
2149 Label done; | 2115 Label done; |
2150 __ movl(EDI, Immediate(kSmiCid)); | 2116 __ movl(EDI, Immediate(kSmiCid)); |
2151 __ testl(EAX, Immediate(kSmiTagMask)); | 2117 __ testl(EAX, Immediate(kSmiTagMask)); |
2152 __ j(ZERO, &done); | 2118 __ j(ZERO, &done); |
2153 __ LoadClassId(EDI, EAX); | 2119 __ LoadClassId(EDI, EAX); |
2154 __ Bind(&done); | 2120 __ Bind(&done); |
2155 | 2121 |
2156 compiler->EmitTestAndCall(*ic_data(), | 2122 compiler->EmitTestAndCall(*ic_data(), |
2157 EDI, // Class id register. | 2123 EDI, // Class id register. |
2158 instance_call()->ArgumentCount(), | 2124 instance_call()->ArgumentCount(), |
2159 instance_call()->argument_names(), | 2125 instance_call()->argument_names(), |
2160 deopt, | 2126 deopt, |
2161 instance_call()->deopt_id(), | 2127 instance_call()->deopt_id(), |
2162 instance_call()->token_pos(), | 2128 instance_call()->token_pos(), |
2163 instance_call()->try_index(), | |
2164 locs()); | 2129 locs()); |
2165 } | 2130 } |
2166 | 2131 |
2167 | 2132 |
2168 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2133 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
2169 computation()->EmitBranchCode(compiler, this); | 2134 computation()->EmitBranchCode(compiler, this); |
2170 } | 2135 } |
2171 | 2136 |
2172 | 2137 |
2173 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2138 LocationSummary* CheckClassComp::MakeLocationSummary() const { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2256 } | 2221 } |
2257 __ j(ABOVE_EQUAL, deopt); | 2222 __ j(ABOVE_EQUAL, deopt); |
2258 } | 2223 } |
2259 | 2224 |
2260 | 2225 |
2261 } // namespace dart | 2226 } // namespace dart |
2262 | 2227 |
2263 #undef __ | 2228 #undef __ |
2264 | 2229 |
2265 #endif // defined TARGET_ARCH_X64 | 2230 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |