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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 __ nop(1); | 100 __ nop(1); |
101 __ nop(1); | 101 __ nop(1); |
102 __ nop(1); | 102 __ nop(1); |
103 __ nop(1); | 103 __ nop(1); |
104 __ nop(1); | 104 __ nop(1); |
105 __ nop(1); | 105 __ nop(1); |
106 __ nop(1); | 106 __ nop(1); |
107 __ nop(1); | 107 __ nop(1); |
108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
109 cid(), | 109 cid(), |
110 token_index(), | 110 token_pos(), |
111 CatchClauseNode::kInvalidTryIndex); | 111 CatchClauseNode::kInvalidTryIndex); |
112 } | 112 } |
113 | 113 |
114 | 114 |
115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
116 const intptr_t kNumInputs = 0; | 116 const intptr_t kNumInputs = 0; |
117 const intptr_t kNumTemps = 1; | 117 const intptr_t kNumTemps = 1; |
118 LocationSummary* result = new LocationSummary(kNumInputs, | 118 LocationSummary* result = new LocationSummary(kNumInputs, |
119 kNumTemps, | 119 kNumTemps, |
120 LocationSummary::kCall); | 120 LocationSummary::kCall); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 Register result = locs()->out().reg(); | 179 Register result = locs()->out().reg(); |
180 | 180 |
181 // Check that the type of the value is allowed in conditional context. | 181 // Check that the type of the value is allowed in conditional context. |
182 // Call the runtime if the object is not bool::true or bool::false. | 182 // Call the runtime if the object is not bool::true or bool::false. |
183 Label done; | 183 Label done; |
184 __ CompareObject(obj, compiler->bool_true()); | 184 __ CompareObject(obj, compiler->bool_true()); |
185 __ j(EQUAL, &done, Assembler::kNearJump); | 185 __ j(EQUAL, &done, Assembler::kNearJump); |
186 __ CompareObject(obj, compiler->bool_false()); | 186 __ CompareObject(obj, compiler->bool_false()); |
187 __ j(EQUAL, &done, Assembler::kNearJump); | 187 __ j(EQUAL, &done, Assembler::kNearJump); |
188 | 188 |
189 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. | 189 __ pushq(Immediate(Smi::RawValue(token_pos()))); // Source location. |
190 __ pushq(obj); // Push the source object. | 190 __ pushq(obj); // Push the source object. |
191 compiler->GenerateCallRuntime(cid(), | 191 compiler->GenerateCallRuntime(cid(), |
192 token_index(), | 192 token_pos(), |
193 try_index(), | 193 try_index(), |
194 kConditionTypeErrorRuntimeEntry); | 194 kConditionTypeErrorRuntimeEntry); |
195 // We should never return here. | 195 // We should never return here. |
196 __ int3(); | 196 __ int3(); |
197 | 197 |
198 __ Bind(&done); | 198 __ Bind(&done); |
199 ASSERT(obj == result); | 199 ASSERT(obj == result); |
200 } | 200 } |
201 | 201 |
202 | 202 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 return locs; | 249 return locs; |
250 } | 250 } |
251 | 251 |
252 | 252 |
253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
254 EqualityCompareComp* comp) { | 254 EqualityCompareComp* comp) { |
255 Register left = comp->locs()->in(0).reg(); | 255 Register left = comp->locs()->in(0).reg(); |
256 Register right = comp->locs()->in(1).reg(); | 256 Register right = comp->locs()->in(1).reg(); |
257 Register temp = comp->locs()->temp(0).reg(); | 257 Register temp = comp->locs()->temp(0).reg(); |
258 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 258 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
259 comp->token_index(), | 259 comp->token_pos(), |
260 comp->try_index(), | 260 comp->try_index(), |
261 kDeoptSmiCompareSmis, | 261 kDeoptSmiCompareSmis, |
262 left, | 262 left, |
263 right); | 263 right); |
264 // TODO(srdjan): Should we always include NULL test (common case)? | 264 // TODO(srdjan): Should we always include NULL test (common case)? |
265 __ movq(temp, left); | 265 __ movq(temp, left); |
266 __ orq(temp, right); | 266 __ orq(temp, right); |
267 __ testq(temp, Immediate(kSmiTagMask)); | 267 __ testq(temp, Immediate(kSmiTagMask)); |
268 __ j(NOT_ZERO, deopt); | 268 __ j(NOT_ZERO, deopt); |
269 __ cmpq(left, right); | 269 __ cmpq(left, right); |
270 if (comp->is_fused_with_branch()) { | 270 if (comp->is_fused_with_branch()) { |
271 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 271 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
272 } else { | 272 } else { |
273 Register result = comp->locs()->out().reg(); | 273 Register result = comp->locs()->out().reg(); |
274 Label load_true, done; | 274 Label load_true, done; |
275 __ j(EQUAL, &load_true, Assembler::kNearJump); | 275 __ j(EQUAL, &load_true, Assembler::kNearJump); |
276 __ LoadObject(result, compiler->bool_false()); | 276 __ LoadObject(result, compiler->bool_false()); |
277 __ jmp(&done, Assembler::kNearJump); | 277 __ jmp(&done, Assembler::kNearJump); |
278 __ Bind(&load_true); | 278 __ Bind(&load_true); |
279 __ LoadObject(result, compiler->bool_true()); | 279 __ LoadObject(result, compiler->bool_true()); |
280 __ Bind(&done); | 280 __ Bind(&done); |
281 } | 281 } |
282 } | 282 } |
283 | 283 |
284 | 284 |
285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
286 EqualityCompareComp* comp) { | 286 EqualityCompareComp* comp) { |
287 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 287 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
288 comp->cid(), | 288 comp->cid(), |
289 comp->token_index(), | 289 comp->token_pos(), |
290 comp->try_index()); | 290 comp->try_index()); |
291 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 291 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
292 const int kNumberOfArguments = 2; | 292 const int kNumberOfArguments = 2; |
293 const Array& kNoArgumentNames = Array::Handle(); | 293 const Array& kNoArgumentNames = Array::Handle(); |
294 const int kNumArgumentsChecked = 2; | 294 const int kNumArgumentsChecked = 2; |
295 | 295 |
296 compiler->GenerateInstanceCall(comp->cid(), | 296 compiler->GenerateInstanceCall(comp->cid(), |
297 comp->token_index(), | 297 comp->token_pos(), |
298 comp->try_index(), | 298 comp->try_index(), |
299 operator_name, | 299 operator_name, |
300 kNumberOfArguments, | 300 kNumberOfArguments, |
301 kNoArgumentNames, | 301 kNoArgumentNames, |
302 kNumArgumentsChecked); | 302 kNumArgumentsChecked); |
303 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | 303 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); |
304 | 304 |
305 if (comp->is_fused_with_branch()) { | 305 if (comp->is_fused_with_branch()) { |
306 __ CompareObject(RAX, compiler->bool_true()); | 306 __ CompareObject(RAX, compiler->bool_true()); |
307 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 307 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
308 } | 308 } |
309 } | 309 } |
310 | 310 |
311 | 311 |
312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
313 EqualityCompareComp* comp, | 313 EqualityCompareComp* comp, |
314 Register left, | 314 Register left, |
315 Register right) { | 315 Register right) { |
316 ASSERT(comp->HasICData()); | 316 ASSERT(comp->HasICData()); |
317 const ICData& ic_data = *comp->ic_data(); | 317 const ICData& ic_data = *comp->ic_data(); |
318 ASSERT(ic_data.NumberOfChecks() > 0); | 318 ASSERT(ic_data.NumberOfChecks() > 0); |
319 ASSERT(ic_data.num_args_tested() == 1); | 319 ASSERT(ic_data.num_args_tested() == 1); |
320 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 320 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
321 comp->token_index(), | 321 comp->token_pos(), |
322 comp->try_index(), | 322 comp->try_index(), |
323 kDeoptEquality); | 323 kDeoptEquality); |
324 __ testq(left, Immediate(kSmiTagMask)); | 324 __ testq(left, Immediate(kSmiTagMask)); |
325 Register temp = comp->locs()->temp(0).reg(); | 325 Register temp = comp->locs()->temp(0).reg(); |
326 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 326 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
327 Label done, load_class_id; | 327 Label done, load_class_id; |
328 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 328 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
329 __ movq(temp, Immediate(kSmi)); | 329 __ movq(temp, Immediate(kSmi)); |
330 __ jmp(&done, Assembler::kNearJump); | 330 __ jmp(&done, Assembler::kNearJump); |
331 __ Bind(&load_class_id); | 331 __ Bind(&load_class_id); |
(...skipping 24 matching lines...) Expand all Loading... |
356 __ j(EQUAL, &load_true, Assembler::kNearJump); | 356 __ j(EQUAL, &load_true, Assembler::kNearJump); |
357 __ LoadObject(result, compiler->bool_false()); | 357 __ LoadObject(result, compiler->bool_false()); |
358 __ jmp(&done); | 358 __ jmp(&done); |
359 __ Bind(&load_true); | 359 __ Bind(&load_true); |
360 __ LoadObject(result, compiler->bool_true()); | 360 __ LoadObject(result, compiler->bool_true()); |
361 } | 361 } |
362 } else { | 362 } else { |
363 const int kNumberOfArguments = 2; | 363 const int kNumberOfArguments = 2; |
364 const Array& kNoArgumentNames = Array::Handle(); | 364 const Array& kNoArgumentNames = Array::Handle(); |
365 compiler->GenerateStaticCall(comp->cid(), | 365 compiler->GenerateStaticCall(comp->cid(), |
366 comp->token_index(), | 366 comp->token_pos(), |
367 comp->try_index(), | 367 comp->try_index(), |
368 target, | 368 target, |
369 kNumberOfArguments, | 369 kNumberOfArguments, |
370 kNoArgumentNames); | 370 kNoArgumentNames); |
371 ASSERT(comp->is_fused_with_branch() || | 371 ASSERT(comp->is_fused_with_branch() || |
372 (comp->locs()->out().reg() == RAX)); | 372 (comp->locs()->out().reg() == RAX)); |
373 if (comp->is_fused_with_branch()) { | 373 if (comp->is_fused_with_branch()) { |
374 __ CompareObject(RAX, compiler->bool_true()); | 374 __ CompareObject(RAX, compiler->bool_true()); |
375 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 375 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
376 } | 376 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 } | 474 } |
475 } | 475 } |
476 | 476 |
477 | 477 |
478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
479 RelationalOpComp* comp) { | 479 RelationalOpComp* comp) { |
480 Register left = comp->locs()->in(0).reg(); | 480 Register left = comp->locs()->in(0).reg(); |
481 Register right = comp->locs()->in(1).reg(); | 481 Register right = comp->locs()->in(1).reg(); |
482 Register temp = comp->locs()->temp(0).reg(); | 482 Register temp = comp->locs()->temp(0).reg(); |
483 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 483 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
484 comp->token_index(), | 484 comp->token_pos(), |
485 comp->try_index(), | 485 comp->try_index(), |
486 kDeoptSmiCompareSmis, | 486 kDeoptSmiCompareSmis, |
487 left, | 487 left, |
488 right); | 488 right); |
489 __ movq(temp, left); | 489 __ movq(temp, left); |
490 __ orq(temp, right); | 490 __ orq(temp, right); |
491 __ testq(temp, Immediate(kSmiTagMask)); | 491 __ testq(temp, Immediate(kSmiTagMask)); |
492 __ j(NOT_ZERO, deopt); | 492 __ j(NOT_ZERO, deopt); |
493 | 493 |
494 Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 494 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
(...skipping 28 matching lines...) Expand all Loading... |
523 } | 523 } |
524 | 524 |
525 | 525 |
526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
527 RelationalOpComp* comp) { | 527 RelationalOpComp* comp) { |
528 Register left = comp->locs()->in(0).reg(); | 528 Register left = comp->locs()->in(0).reg(); |
529 Register right = comp->locs()->in(1).reg(); | 529 Register right = comp->locs()->in(1).reg(); |
530 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 530 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
531 Register temp = comp->locs()->temp(0).reg(); | 531 Register temp = comp->locs()->temp(0).reg(); |
532 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 532 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
533 comp->token_index(), | 533 comp->token_pos(), |
534 comp->try_index(), | 534 comp->try_index(), |
535 kDeoptDoubleComparison, | 535 kDeoptDoubleComparison, |
536 left, | 536 left, |
537 right); | 537 right); |
538 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 538 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
539 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 539 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
540 | 540 |
541 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 541 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
542 __ comisd(XMM0, XMM1); | 542 __ comisd(XMM0, XMM1); |
543 | 543 |
(...skipping 24 matching lines...) Expand all Loading... |
568 return; | 568 return; |
569 } | 569 } |
570 if (operands_class_id() == kDouble) { | 570 if (operands_class_id() == kDouble) { |
571 EmitDoubleRelationalOp(compiler, this); | 571 EmitDoubleRelationalOp(compiler, this); |
572 return; | 572 return; |
573 } | 573 } |
574 const String& function_name = | 574 const String& function_name = |
575 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 575 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
576 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 576 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
577 cid(), | 577 cid(), |
578 token_index(), | 578 token_pos(), |
579 try_index()); | 579 try_index()); |
580 const intptr_t kNumArguments = 2; | 580 const intptr_t kNumArguments = 2; |
581 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 581 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
582 compiler->GenerateInstanceCall(cid(), | 582 compiler->GenerateInstanceCall(cid(), |
583 token_index(), | 583 token_pos(), |
584 try_index(), | 584 try_index(), |
585 function_name, | 585 function_name, |
586 kNumArguments, | 586 kNumArguments, |
587 Array::ZoneHandle(), // No optional arguments. | 587 Array::ZoneHandle(), // No optional arguments. |
588 kNumArgsChecked); | 588 kNumArgsChecked); |
589 ASSERT(locs()->out().reg() == RAX); | 589 ASSERT(locs()->out().reg() == RAX); |
590 } | 590 } |
591 | 591 |
592 | 592 |
593 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 593 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
(...skipping 24 matching lines...) Expand all Loading... |
618 arg_count += 1; | 618 arg_count += 1; |
619 } | 619 } |
620 if (!has_optional_parameters() && !is_native_instance_closure()) { | 620 if (!has_optional_parameters() && !is_native_instance_closure()) { |
621 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); | 621 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); |
622 } else { | 622 } else { |
623 __ leaq(RAX, | 623 __ leaq(RAX, |
624 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 624 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
625 } | 625 } |
626 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 626 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
627 __ movq(R10, Immediate(arg_count)); | 627 __ movq(R10, Immediate(arg_count)); |
628 compiler->GenerateCall(token_index(), | 628 compiler->GenerateCall(token_pos(), |
629 try_index(), | 629 try_index(), |
630 &StubCode::CallNativeCFunctionLabel(), | 630 &StubCode::CallNativeCFunctionLabel(), |
631 PcDescriptors::kOther); | 631 PcDescriptors::kOther); |
632 __ popq(result); | 632 __ popq(result); |
633 } | 633 } |
634 | 634 |
635 | 635 |
636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
637 const intptr_t kNumInputs = 2; | 637 const intptr_t kNumInputs = 2; |
638 if (receiver_type() == kGrowableObjectArray) { | 638 if (receiver_type() == kGrowableObjectArray) { |
(...skipping 10 matching lines...) Expand all Loading... |
649 } else { | 649 } else { |
650 ASSERT(receiver_type() == kIllegalObjectKind); | 650 ASSERT(receiver_type() == kIllegalObjectKind); |
651 return MakeCallSummary(); | 651 return MakeCallSummary(); |
652 } | 652 } |
653 } | 653 } |
654 | 654 |
655 | 655 |
656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
657 LoadIndexedComp* comp) { | 657 LoadIndexedComp* comp) { |
658 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 658 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
659 comp->token_index(), | 659 comp->token_pos(), |
660 comp->try_index(), | 660 comp->try_index(), |
661 kDeoptLoadIndexedPolymorphic); | 661 kDeoptLoadIndexedPolymorphic); |
662 if (comp->ic_data()->NumberOfChecks() == 0) { | 662 if (comp->ic_data()->NumberOfChecks() == 0) { |
663 __ jmp(deopt); | 663 __ jmp(deopt); |
664 return; | 664 return; |
665 } | 665 } |
666 ASSERT(comp->HasICData()); | 666 ASSERT(comp->HasICData()); |
667 const ICData& ic_data = *comp->ic_data(); | 667 const ICData& ic_data = *comp->ic_data(); |
668 ASSERT(ic_data.num_args_tested() == 1); | 668 ASSERT(ic_data.num_args_tested() == 1); |
669 // No indexed access on Smi. | 669 // No indexed access on Smi. |
670 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 670 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
671 // Load receiver into RAX. | 671 // Load receiver into RAX. |
672 const intptr_t kNumArguments = 2; | 672 const intptr_t kNumArguments = 2; |
673 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 673 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
674 __ testq(RAX, Immediate(kSmiTagMask)); | 674 __ testq(RAX, Immediate(kSmiTagMask)); |
675 __ j(ZERO, deopt); | 675 __ j(ZERO, deopt); |
676 Label done; | 676 Label done; |
677 __ LoadClassId(RDI, RAX); | 677 __ LoadClassId(RDI, RAX); |
678 compiler->EmitTestAndCall(ic_data, | 678 compiler->EmitTestAndCall(ic_data, |
679 RDI, // Class id register. | 679 RDI, // Class id register. |
680 kNumArguments, | 680 kNumArguments, |
681 Array::Handle(), // No named arguments. | 681 Array::Handle(), // No named arguments. |
682 deopt, &done, // Labels. | 682 deopt, &done, // Labels. |
683 comp->cid(), | 683 comp->cid(), |
684 comp->token_index(), | 684 comp->token_pos(), |
685 comp->try_index()); | 685 comp->try_index()); |
686 __ Bind(&done); | 686 __ Bind(&done); |
687 } | 687 } |
688 | 688 |
689 | 689 |
690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
691 if (receiver_type() == kIllegalObjectKind) { | 691 if (receiver_type() == kIllegalObjectKind) { |
692 if (HasICData()) { | 692 if (HasICData()) { |
693 EmitLoadIndexedPolymorphic(compiler, this); | 693 EmitLoadIndexedPolymorphic(compiler, this); |
694 } else { | 694 } else { |
695 compiler->EmitLoadIndexedGeneric(this); | 695 compiler->EmitLoadIndexedGeneric(this); |
696 } | 696 } |
697 ASSERT(locs()->out().reg() == RAX); | 697 ASSERT(locs()->out().reg() == RAX); |
698 return; | 698 return; |
699 } | 699 } |
700 | 700 |
701 Register receiver = locs()->in(0).reg(); | 701 Register receiver = locs()->in(0).reg(); |
702 Register index = locs()->in(1).reg(); | 702 Register index = locs()->in(1).reg(); |
703 Register result = locs()->out().reg(); | 703 Register result = locs()->out().reg(); |
704 | 704 |
705 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 705 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
706 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 706 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
707 | 707 |
708 Label* deopt = compiler->AddDeoptStub(cid(), | 708 Label* deopt = compiler->AddDeoptStub(cid(), |
709 token_index(), | 709 token_pos(), |
710 try_index(), | 710 try_index(), |
711 deopt_reason, | 711 deopt_reason, |
712 receiver, | 712 receiver, |
713 index); | 713 index); |
714 | 714 |
715 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 715 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
716 __ j(ZERO, deopt); | 716 __ j(ZERO, deopt); |
717 __ CompareClassId(receiver, receiver_type()); | 717 __ CompareClassId(receiver, receiver_type()); |
718 __ j(NOT_EQUAL, deopt); | 718 __ j(NOT_EQUAL, deopt); |
719 | 719 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 } | 770 } |
771 | 771 |
772 | 772 |
773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
774 StoreIndexedComp* comp) { | 774 StoreIndexedComp* comp) { |
775 const String& function_name = | 775 const String& function_name = |
776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
777 | 777 |
778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
779 comp->cid(), | 779 comp->cid(), |
780 comp->token_index(), | 780 comp->token_pos(), |
781 comp->try_index()); | 781 comp->try_index()); |
782 | 782 |
783 const intptr_t kNumArguments = 3; | 783 const intptr_t kNumArguments = 3; |
784 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 784 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
785 compiler->GenerateInstanceCall(comp->cid(), | 785 compiler->GenerateInstanceCall(comp->cid(), |
786 comp->token_index(), | 786 comp->token_pos(), |
787 comp->try_index(), | 787 comp->try_index(), |
788 function_name, | 788 function_name, |
789 kNumArguments, | 789 kNumArguments, |
790 Array::ZoneHandle(), // No named arguments. | 790 Array::ZoneHandle(), // No named arguments. |
791 kNumArgsChecked); | 791 kNumArgsChecked); |
792 } | 792 } |
793 | 793 |
794 | 794 |
795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
796 StoreIndexedComp* comp) { | 796 StoreIndexedComp* comp) { |
797 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 797 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
798 comp->token_index(), | 798 comp->token_pos(), |
799 comp->try_index(), | 799 comp->try_index(), |
800 kDeoptStoreIndexedPolymorphic); | 800 kDeoptStoreIndexedPolymorphic); |
801 if (comp->ic_data()->NumberOfChecks() == 0) { | 801 if (comp->ic_data()->NumberOfChecks() == 0) { |
802 __ jmp(deopt); | 802 __ jmp(deopt); |
803 return; | 803 return; |
804 } | 804 } |
805 ASSERT(comp->HasICData()); | 805 ASSERT(comp->HasICData()); |
806 const ICData& ic_data = *comp->ic_data(); | 806 const ICData& ic_data = *comp->ic_data(); |
807 ASSERT(ic_data.num_args_tested() == 1); | 807 ASSERT(ic_data.num_args_tested() == 1); |
808 // No indexed access on Smi. | 808 // No indexed access on Smi. |
809 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 809 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
810 // Load receiver into RAX. | 810 // Load receiver into RAX. |
811 const intptr_t kNumArguments = 3; | 811 const intptr_t kNumArguments = 3; |
812 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 812 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
813 __ testq(RAX, Immediate(kSmiTagMask)); | 813 __ testq(RAX, Immediate(kSmiTagMask)); |
814 __ j(ZERO, deopt); | 814 __ j(ZERO, deopt); |
815 Label done; | 815 Label done; |
816 __ LoadClassId(RDI, RAX); | 816 __ LoadClassId(RDI, RAX); |
817 compiler->EmitTestAndCall(ic_data, | 817 compiler->EmitTestAndCall(ic_data, |
818 RDI, // Class id register. | 818 RDI, // Class id register. |
819 kNumArguments, | 819 kNumArguments, |
820 Array::Handle(), // No named arguments. | 820 Array::Handle(), // No named arguments. |
821 deopt, &done, // Labels. | 821 deopt, &done, // Labels. |
822 comp->cid(), | 822 comp->cid(), |
823 comp->token_index(), | 823 comp->token_pos(), |
824 comp->try_index()); | 824 comp->try_index()); |
825 __ Bind(&done); | 825 __ Bind(&done); |
826 } | 826 } |
827 | 827 |
828 | 828 |
829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
830 if (receiver_type() == kIllegalObjectKind) { | 830 if (receiver_type() == kIllegalObjectKind) { |
831 if (HasICData()) { | 831 if (HasICData()) { |
832 EmitStoreIndexedPolymorphic(compiler, this); | 832 EmitStoreIndexedPolymorphic(compiler, this); |
833 } else { | 833 } else { |
834 EmitStoreIndexedGeneric(compiler, this); | 834 EmitStoreIndexedGeneric(compiler, this); |
835 } | 835 } |
836 return; | 836 return; |
837 } | 837 } |
838 | 838 |
839 Register receiver = locs()->in(0).reg(); | 839 Register receiver = locs()->in(0).reg(); |
840 Register index = locs()->in(1).reg(); | 840 Register index = locs()->in(1).reg(); |
841 Register value = locs()->in(2).reg(); | 841 Register value = locs()->in(2).reg(); |
842 | 842 |
843 Label* deopt = compiler->AddDeoptStub(cid(), | 843 Label* deopt = compiler->AddDeoptStub(cid(), |
844 token_index(), | 844 token_pos(), |
845 try_index(), | 845 try_index(), |
846 kDeoptStoreIndexed, | 846 kDeoptStoreIndexed, |
847 receiver, | 847 receiver, |
848 index, | 848 index, |
849 value); | 849 value); |
850 | 850 |
851 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 851 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
852 __ j(ZERO, deopt); | 852 __ j(ZERO, deopt); |
853 __ CompareClassId(receiver, receiver_type()); | 853 __ CompareClassId(receiver, receiver_type()); |
854 __ j(NOT_EQUAL, deopt); | 854 __ j(NOT_EQUAL, deopt); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 return MakeCallSummary(); | 893 return MakeCallSummary(); |
894 } | 894 } |
895 | 895 |
896 | 896 |
897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
898 const String& function_name = | 898 const String& function_name = |
899 String::ZoneHandle(Field::SetterSymbol(field_name())); | 899 String::ZoneHandle(Field::SetterSymbol(field_name())); |
900 | 900 |
901 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 901 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
902 cid(), | 902 cid(), |
903 token_index(), | 903 token_pos(), |
904 try_index()); | 904 try_index()); |
905 const intptr_t kArgumentCount = 2; | 905 const intptr_t kArgumentCount = 2; |
906 const intptr_t kCheckedArgumentCount = 1; | 906 const intptr_t kCheckedArgumentCount = 1; |
907 compiler->GenerateInstanceCall(cid(), | 907 compiler->GenerateInstanceCall(cid(), |
908 token_index(), | 908 token_pos(), |
909 try_index(), | 909 try_index(), |
910 function_name, | 910 function_name, |
911 kArgumentCount, | 911 kArgumentCount, |
912 Array::ZoneHandle(), | 912 Array::ZoneHandle(), |
913 kCheckedArgumentCount); | 913 kCheckedArgumentCount); |
914 } | 914 } |
915 | 915 |
916 | 916 |
917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
918 const intptr_t kNumInputs = 1; | 918 const intptr_t kNumInputs = 1; |
919 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 919 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
920 } | 920 } |
921 | 921 |
922 | 922 |
923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
924 Register value = locs()->in(0).reg(); | 924 Register value = locs()->in(0).reg(); |
925 Register result = locs()->out().reg(); | 925 Register result = locs()->out().reg(); |
926 | 926 |
927 // Preserve the argument as the result of the computation, | 927 // Preserve the argument as the result of the computation, |
928 // then call the setter. | 928 // then call the setter. |
929 | 929 |
930 // Duplicate the argument. | 930 // Duplicate the argument. |
931 // TODO(fschneider): Avoid preserving the value if the result is not used. | 931 // TODO(fschneider): Avoid preserving the value if the result is not used. |
932 __ pushq(value); | 932 __ pushq(value); |
933 __ pushq(value); | 933 __ pushq(value); |
934 compiler->GenerateStaticCall(cid(), | 934 compiler->GenerateStaticCall(cid(), |
935 token_index(), | 935 token_pos(), |
936 try_index(), | 936 try_index(), |
937 setter_function(), | 937 setter_function(), |
938 1, | 938 1, |
939 Array::ZoneHandle()); | 939 Array::ZoneHandle()); |
940 __ popq(result); | 940 __ popq(result); |
941 } | 941 } |
942 | 942 |
943 | 943 |
944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
945 // TODO(fschneider): For this instruction the input register may be | 945 // TODO(fschneider): For this instruction the input register may be |
946 // reused for the result (but is not required to) because the input | 946 // reused for the result (but is not required to) because the input |
947 // is not used after the result is defined. We should consider adding | 947 // is not used after the result is defined. We should consider adding |
948 // this information to the input policy. | 948 // this information to the input policy. |
949 return LocationSummary::Make(1, Location::RequiresRegister()); | 949 return LocationSummary::Make(1, Location::RequiresRegister()); |
950 } | 950 } |
951 | 951 |
952 | 952 |
953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
954 Register instance_reg = locs()->in(0).reg(); | 954 Register instance_reg = locs()->in(0).reg(); |
955 Register result_reg = locs()->out().reg(); | 955 Register result_reg = locs()->out().reg(); |
956 | 956 |
957 if (HasICData()) { | 957 if (HasICData()) { |
958 ASSERT(original() != NULL); | 958 ASSERT(original() != NULL); |
959 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 959 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
960 original()->token_index(), | 960 original()->token_pos(), |
961 original()->try_index(), | 961 original()->try_index(), |
962 kDeoptInstanceGetterSameTarget, | 962 kDeoptInstanceGetterSameTarget, |
963 instance_reg); | 963 instance_reg); |
964 // Smis do not have instance fields (Smi class is always first). | 964 // Smis do not have instance fields (Smi class is always first). |
965 // Use 'result' as temporary register. | 965 // Use 'result' as temporary register. |
966 ASSERT(result_reg != instance_reg); | 966 ASSERT(result_reg != instance_reg); |
967 ASSERT(ic_data() != NULL); | 967 ASSERT(ic_data() != NULL); |
968 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 968 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
969 } | 969 } |
970 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 970 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); |
(...skipping 21 matching lines...) Expand all Loading... |
992 return summary; | 992 return summary; |
993 } | 993 } |
994 | 994 |
995 | 995 |
996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
997 ASSERT(locs()->in(0).reg() == RAX); // Value. | 997 ASSERT(locs()->in(0).reg() == RAX); // Value. |
998 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 998 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
999 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 999 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
1000 | 1000 |
1001 compiler->GenerateInstanceOf(cid(), | 1001 compiler->GenerateInstanceOf(cid(), |
1002 token_index(), | 1002 token_pos(), |
1003 try_index(), | 1003 try_index(), |
1004 type(), | 1004 type(), |
1005 negate_result()); | 1005 negate_result()); |
1006 ASSERT(locs()->out().reg() == RAX); | 1006 ASSERT(locs()->out().reg() == RAX); |
1007 } | 1007 } |
1008 | 1008 |
1009 | 1009 |
1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1011 // TODO(regis): The elements of the array could be considered as arguments to | 1011 // TODO(regis): The elements of the array could be considered as arguments to |
1012 // CreateArrayComp, thereby making CreateArrayComp a call. | 1012 // CreateArrayComp, thereby making CreateArrayComp a call. |
(...skipping 12 matching lines...) Expand all Loading... |
1025 | 1025 |
1026 | 1026 |
1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1028 Register temp_reg = locs()->temp(0).reg(); | 1028 Register temp_reg = locs()->temp(0).reg(); |
1029 Register result_reg = locs()->out().reg(); | 1029 Register result_reg = locs()->out().reg(); |
1030 | 1030 |
1031 // Allocate the array. R10 = length, RBX = element type. | 1031 // Allocate the array. R10 = length, RBX = element type. |
1032 ASSERT(temp_reg == R10); | 1032 ASSERT(temp_reg == R10); |
1033 ASSERT(locs()->in(0).reg() == RBX); | 1033 ASSERT(locs()->in(0).reg() == RBX); |
1034 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 1034 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
1035 compiler->GenerateCall(token_index(), | 1035 compiler->GenerateCall(token_pos(), |
1036 try_index(), | 1036 try_index(), |
1037 &StubCode::AllocateArrayLabel(), | 1037 &StubCode::AllocateArrayLabel(), |
1038 PcDescriptors::kOther); | 1038 PcDescriptors::kOther); |
1039 ASSERT(result_reg == RAX); | 1039 ASSERT(result_reg == RAX); |
1040 | 1040 |
1041 // Pop the element values from the stack into the array. | 1041 // Pop the element values from the stack into the array. |
1042 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1042 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
1043 for (int i = ElementCount() - 1; i >= 0; --i) { | 1043 for (int i = ElementCount() - 1; i >= 0; --i) { |
1044 ASSERT(ElementAt(i)->IsUse()); | 1044 ASSERT(ElementAt(i)->IsUse()); |
1045 __ popq(Address(temp_reg, i * kWordSize)); | 1045 __ popq(Address(temp_reg, i * kWordSize)); |
(...skipping 11 matching lines...) Expand all Loading... |
1057 | 1057 |
1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
1059 FlowGraphCompiler* compiler) { | 1059 FlowGraphCompiler* compiler) { |
1060 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1060 const Class& cls = Class::ZoneHandle(constructor().owner()); |
1061 Register type_arguments = locs()->in(0).reg(); | 1061 Register type_arguments = locs()->in(0).reg(); |
1062 Register instantiator_type_arguments = locs()->in(1).reg(); | 1062 Register instantiator_type_arguments = locs()->in(1).reg(); |
1063 Register result = locs()->out().reg(); | 1063 Register result = locs()->out().reg(); |
1064 | 1064 |
1065 // Push the result place holder initialized to NULL. | 1065 // Push the result place holder initialized to NULL. |
1066 __ PushObject(Object::ZoneHandle()); | 1066 __ PushObject(Object::ZoneHandle()); |
1067 __ pushq(Immediate(Smi::RawValue(token_index()))); | 1067 __ pushq(Immediate(Smi::RawValue(token_pos()))); |
1068 __ PushObject(cls); | 1068 __ PushObject(cls); |
1069 __ pushq(type_arguments); | 1069 __ pushq(type_arguments); |
1070 __ pushq(instantiator_type_arguments); | 1070 __ pushq(instantiator_type_arguments); |
1071 compiler->GenerateCallRuntime(cid(), | 1071 compiler->GenerateCallRuntime(cid(), |
1072 token_index(), | 1072 token_pos(), |
1073 try_index(), | 1073 try_index(), |
1074 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1074 kAllocateObjectWithBoundsCheckRuntimeEntry); |
1075 // Pop instantiator type arguments, type arguments, class, and | 1075 // Pop instantiator type arguments, type arguments, class, and |
1076 // source location. | 1076 // source location. |
1077 __ Drop(4); | 1077 __ Drop(4); |
1078 __ popq(result); // Pop new instance. | 1078 __ popq(result); // Pop new instance. |
1079 } | 1079 } |
1080 | 1080 |
1081 | 1081 |
1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1083 return LocationSummary::Make(1, Location::RequiresRegister()); | 1083 return LocationSummary::Make(1, Location::RequiresRegister()); |
1084 } | 1084 } |
1085 | 1085 |
1086 | 1086 |
1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1088 Register instance_reg = locs()->in(0).reg(); | 1088 Register instance_reg = locs()->in(0).reg(); |
1089 Register result_reg = locs()->out().reg(); | 1089 Register result_reg = locs()->out().reg(); |
1090 if (HasICData()) { | 1090 if (HasICData()) { |
1091 ASSERT(original() != NULL); | 1091 ASSERT(original() != NULL); |
1092 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1092 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
1093 original()->token_index(), | 1093 original()->token_pos(), |
1094 original()->try_index(), | 1094 original()->try_index(), |
1095 kDeoptInstanceGetterSameTarget, | 1095 kDeoptInstanceGetterSameTarget, |
1096 instance_reg); | 1096 instance_reg); |
1097 // Smis do not have instance fields (Smi class is always first). | 1097 // Smis do not have instance fields (Smi class is always first). |
1098 // Use 'result' as temporary register. | 1098 // Use 'result' as temporary register. |
1099 ASSERT(result_reg != instance_reg); | 1099 ASSERT(result_reg != instance_reg); |
1100 ASSERT(ic_data() != NULL); | 1100 ASSERT(ic_data() != NULL); |
1101 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1101 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1102 } | 1102 } |
1103 | 1103 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1148 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1148 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1149 Immediate(Smi::RawValue(len))); | 1149 Immediate(Smi::RawValue(len))); |
1150 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1150 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1151 __ Bind(&type_arguments_uninstantiated); | 1151 __ Bind(&type_arguments_uninstantiated); |
1152 } | 1152 } |
1153 // A runtime call to instantiate the type arguments is required. | 1153 // A runtime call to instantiate the type arguments is required. |
1154 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1154 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1155 __ PushObject(type_arguments()); | 1155 __ PushObject(type_arguments()); |
1156 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1156 __ pushq(instantiator_reg); // Push instantiator type arguments. |
1157 compiler->GenerateCallRuntime(cid(), | 1157 compiler->GenerateCallRuntime(cid(), |
1158 token_index(), | 1158 token_pos(), |
1159 try_index(), | 1159 try_index(), |
1160 kInstantiateTypeArgumentsRuntimeEntry); | 1160 kInstantiateTypeArgumentsRuntimeEntry); |
1161 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1161 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1162 __ popq(result_reg); // Pop instantiated type arguments. | 1162 __ popq(result_reg); // Pop instantiated type arguments. |
1163 __ Bind(&type_arguments_instantiated); | 1163 __ Bind(&type_arguments_instantiated); |
1164 ASSERT(instantiator_reg == result_reg); | 1164 ASSERT(instantiator_reg == result_reg); |
1165 // 'result_reg': Instantiated type arguments. | 1165 // 'result_reg': Instantiated type arguments. |
1166 } | 1166 } |
1167 | 1167 |
1168 | 1168 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 } | 1298 } |
1299 | 1299 |
1300 | 1300 |
1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1302 ASSERT(locs()->temp(0).reg() == R10); | 1302 ASSERT(locs()->temp(0).reg() == R10); |
1303 ASSERT(locs()->out().reg() == RAX); | 1303 ASSERT(locs()->out().reg() == RAX); |
1304 | 1304 |
1305 __ movq(R10, Immediate(num_context_variables())); | 1305 __ movq(R10, Immediate(num_context_variables())); |
1306 const ExternalLabel label("alloc_context", | 1306 const ExternalLabel label("alloc_context", |
1307 StubCode::AllocateContextEntryPoint()); | 1307 StubCode::AllocateContextEntryPoint()); |
1308 compiler->GenerateCall(token_index(), | 1308 compiler->GenerateCall(token_pos(), |
1309 try_index(), | 1309 try_index(), |
1310 &label, | 1310 &label, |
1311 PcDescriptors::kOther); | 1311 PcDescriptors::kOther); |
1312 } | 1312 } |
1313 | 1313 |
1314 | 1314 |
1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1316 return LocationSummary::Make(1, | 1316 return LocationSummary::Make(1, |
1317 Location::RequiresRegister(), | 1317 Location::RequiresRegister(), |
1318 LocationSummary::kCall); | 1318 LocationSummary::kCall); |
1319 } | 1319 } |
1320 | 1320 |
1321 | 1321 |
1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1323 Register context_value = locs()->in(0).reg(); | 1323 Register context_value = locs()->in(0).reg(); |
1324 Register result = locs()->out().reg(); | 1324 Register result = locs()->out().reg(); |
1325 | 1325 |
1326 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1326 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1327 __ pushq(context_value); | 1327 __ pushq(context_value); |
1328 compiler->GenerateCallRuntime(cid(), | 1328 compiler->GenerateCallRuntime(cid(), |
1329 token_index(), | 1329 token_pos(), |
1330 try_index(), | 1330 try_index(), |
1331 kCloneContextRuntimeEntry); | 1331 kCloneContextRuntimeEntry); |
1332 __ popq(result); // Remove argument. | 1332 __ popq(result); // Remove argument. |
1333 __ popq(result); // Get result (cloned context). | 1333 __ popq(result); // Get result (cloned context). |
1334 } | 1334 } |
1335 | 1335 |
1336 | 1336 |
1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1338 return LocationSummary::Make(0, Location::NoLocation()); | 1338 return LocationSummary::Make(0, Location::NoLocation()); |
1339 } | 1339 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1372 | 1372 |
1373 | 1373 |
1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1375 Register temp = locs()->temp(0).reg(); | 1375 Register temp = locs()->temp(0).reg(); |
1376 // Generate stack overflow check. | 1376 // Generate stack overflow check. |
1377 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1377 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
1378 __ cmpq(RSP, Address(temp, 0)); | 1378 __ cmpq(RSP, Address(temp, 0)); |
1379 Label no_stack_overflow; | 1379 Label no_stack_overflow; |
1380 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1380 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
1381 compiler->GenerateCallRuntime(cid(), | 1381 compiler->GenerateCallRuntime(cid(), |
1382 token_index(), | 1382 token_pos(), |
1383 try_index(), | 1383 try_index(), |
1384 kStackOverflowRuntimeEntry); | 1384 kStackOverflowRuntimeEntry); |
1385 __ Bind(&no_stack_overflow); | 1385 __ Bind(&no_stack_overflow); |
1386 } | 1386 } |
1387 | 1387 |
1388 | 1388 |
1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1390 const intptr_t kNumInputs = 2; | 1390 const intptr_t kNumInputs = 2; |
1391 | 1391 |
1392 if (operands_type() == kDoubleOperands) { | 1392 if (operands_type() == kDoubleOperands) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1448 } | 1448 } |
1449 | 1449 |
1450 | 1450 |
1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1452 Register left = comp->locs()->in(0).reg(); | 1452 Register left = comp->locs()->in(0).reg(); |
1453 Register right = comp->locs()->in(1).reg(); | 1453 Register right = comp->locs()->in(1).reg(); |
1454 Register result = comp->locs()->out().reg(); | 1454 Register result = comp->locs()->out().reg(); |
1455 Register temp = comp->locs()->temp(0).reg(); | 1455 Register temp = comp->locs()->temp(0).reg(); |
1456 ASSERT(left == result); | 1456 ASSERT(left == result); |
1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1458 comp->instance_call()->token_index(), | 1458 comp->instance_call()->token_pos(), |
1459 comp->instance_call()->try_index(), | 1459 comp->instance_call()->try_index(), |
1460 kDeoptSmiBinaryOp, | 1460 kDeoptSmiBinaryOp, |
1461 temp, | 1461 temp, |
1462 right); | 1462 right); |
1463 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1463 // TODO(vegorov): for many binary operations this pattern can be rearranged |
1464 // to save one move. | 1464 // to save one move. |
1465 __ movq(temp, left); | 1465 __ movq(temp, left); |
1466 __ orq(left, right); | 1466 __ orq(left, right); |
1467 __ testq(left, Immediate(kSmiTagMask)); | 1467 __ testq(left, Immediate(kSmiTagMask)); |
1468 __ j(NOT_ZERO, deopt); | 1468 __ j(NOT_ZERO, deopt); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1559 __ jmp(&done); | 1559 __ jmp(&done); |
1560 { | 1560 { |
1561 __ Bind(&call_method); | 1561 __ Bind(&call_method); |
1562 Function& target = Function::ZoneHandle( | 1562 Function& target = Function::ZoneHandle( |
1563 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1563 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1564 ASSERT(!target.IsNull()); | 1564 ASSERT(!target.IsNull()); |
1565 const intptr_t kArgumentCount = 2; | 1565 const intptr_t kArgumentCount = 2; |
1566 __ pushq(temp); | 1566 __ pushq(temp); |
1567 __ pushq(right); | 1567 __ pushq(right); |
1568 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1568 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1569 comp->instance_call()->token_index(), | 1569 comp->instance_call()->token_pos(), |
1570 comp->instance_call()->try_index(), | 1570 comp->instance_call()->try_index(), |
1571 target, | 1571 target, |
1572 kArgumentCount, | 1572 kArgumentCount, |
1573 Array::Handle()); // No argument names. | 1573 Array::Handle()); // No argument names. |
1574 ASSERT(result == RAX); | 1574 ASSERT(result == RAX); |
1575 } | 1575 } |
1576 __ Bind(&done); | 1576 __ Bind(&done); |
1577 break; | 1577 break; |
1578 } | 1578 } |
1579 case Token::kDIV: { | 1579 case Token::kDIV: { |
(...skipping 25 matching lines...) Expand all Loading... |
1605 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1605 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
1606 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1606 // receiver and a Mint or Smi argument. We fall back to the run time call if |
1607 // both receiver and argument are Mint or if one of them is Mint and the other | 1607 // both receiver and argument are Mint or if one of them is Mint and the other |
1608 // is a negative Smi. | 1608 // is a negative Smi. |
1609 Register left = comp->locs()->in(0).reg(); | 1609 Register left = comp->locs()->in(0).reg(); |
1610 Register right = comp->locs()->in(1).reg(); | 1610 Register right = comp->locs()->in(1).reg(); |
1611 Register result = comp->locs()->out().reg(); | 1611 Register result = comp->locs()->out().reg(); |
1612 ASSERT(left == result); | 1612 ASSERT(left == result); |
1613 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1613 ASSERT(comp->op_kind() == Token::kBIT_AND); |
1614 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1614 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1615 comp->instance_call()->token_index(), | 1615 comp->instance_call()->token_pos(), |
1616 comp->instance_call()->try_index(), | 1616 comp->instance_call()->try_index(), |
1617 kDeoptMintBinaryOp, | 1617 kDeoptMintBinaryOp, |
1618 left, | 1618 left, |
1619 right); | 1619 right); |
1620 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1620 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1621 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1621 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1622 __ j(NOT_ZERO, &non_smi); | 1622 __ j(NOT_ZERO, &non_smi); |
1623 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1623 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1624 __ j(ZERO, &smi_smi); | 1624 __ j(ZERO, &smi_smi); |
1625 __ CompareClassId(right, kMint); // Is argument Mint? | 1625 __ CompareClassId(right, kMint); // Is argument Mint? |
(...skipping 27 matching lines...) Expand all Loading... |
1653 __ Bind(&smi_static_call); | 1653 __ Bind(&smi_static_call); |
1654 { | 1654 { |
1655 Function& target = Function::ZoneHandle( | 1655 Function& target = Function::ZoneHandle( |
1656 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1656 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1657 if (target.IsNull()) { | 1657 if (target.IsNull()) { |
1658 __ jmp(deopt); | 1658 __ jmp(deopt); |
1659 } else { | 1659 } else { |
1660 __ pushq(left); | 1660 __ pushq(left); |
1661 __ pushq(right); | 1661 __ pushq(right); |
1662 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1662 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1663 comp->instance_call()->token_index(), | 1663 comp->instance_call()->token_pos(), |
1664 comp->instance_call()->try_index(), | 1664 comp->instance_call()->try_index(), |
1665 target, | 1665 target, |
1666 comp->instance_call()->ArgumentCount(), | 1666 comp->instance_call()->ArgumentCount(), |
1667 comp->instance_call()->argument_names()); | 1667 comp->instance_call()->argument_names()); |
1668 ASSERT(result == RAX); | 1668 ASSERT(result == RAX); |
1669 __ jmp(&done); | 1669 __ jmp(&done); |
1670 } | 1670 } |
1671 } | 1671 } |
1672 | 1672 |
1673 __ Bind(&mint_static_call); | 1673 __ Bind(&mint_static_call); |
1674 { | 1674 { |
1675 Function& target = Function::ZoneHandle( | 1675 Function& target = Function::ZoneHandle( |
1676 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1676 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
1677 if (target.IsNull()) { | 1677 if (target.IsNull()) { |
1678 __ jmp(deopt); | 1678 __ jmp(deopt); |
1679 } else { | 1679 } else { |
1680 __ pushq(left); | 1680 __ pushq(left); |
1681 __ pushq(right); | 1681 __ pushq(right); |
1682 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1682 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1683 comp->instance_call()->token_index(), | 1683 comp->instance_call()->token_pos(), |
1684 comp->instance_call()->try_index(), | 1684 comp->instance_call()->try_index(), |
1685 target, | 1685 target, |
1686 comp->instance_call()->ArgumentCount(), | 1686 comp->instance_call()->ArgumentCount(), |
1687 comp->instance_call()->argument_names()); | 1687 comp->instance_call()->argument_names()); |
1688 ASSERT(result == RAX); | 1688 ASSERT(result == RAX); |
1689 } | 1689 } |
1690 } | 1690 } |
1691 __ Bind(&done); | 1691 __ Bind(&done); |
1692 } | 1692 } |
1693 | 1693 |
1694 | 1694 |
1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
1696 BinaryOpComp* comp) { | 1696 BinaryOpComp* comp) { |
1697 Register left = RBX; | 1697 Register left = RBX; |
1698 Register right = RCX; | 1698 Register right = RCX; |
1699 Register temp = RDX; | 1699 Register temp = RDX; |
1700 Register result = comp->locs()->out().reg(); | 1700 Register result = comp->locs()->out().reg(); |
1701 | 1701 |
1702 const Class& double_class = compiler->double_class(); | 1702 const Class& double_class = compiler->double_class(); |
1703 const Code& stub = | 1703 const Code& stub = |
1704 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1704 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1705 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1705 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1706 compiler->GenerateCall(comp->instance_call()->token_index(), | 1706 compiler->GenerateCall(comp->instance_call()->token_pos(), |
1707 comp->instance_call()->try_index(), | 1707 comp->instance_call()->try_index(), |
1708 &label, | 1708 &label, |
1709 PcDescriptors::kOther); | 1709 PcDescriptors::kOther); |
1710 // Newly allocated object is now in the result register (RAX). | 1710 // Newly allocated object is now in the result register (RAX). |
1711 ASSERT(result == RAX); | 1711 ASSERT(result == RAX); |
1712 __ popq(right); | 1712 __ popq(right); |
1713 __ popq(left); | 1713 __ popq(left); |
1714 | 1714 |
1715 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1715 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1716 comp->instance_call()->token_index(), | 1716 comp->instance_call()->token_pos(), |
1717 comp->instance_call()->try_index(), | 1717 comp->instance_call()->try_index(), |
1718 kDeoptDoubleBinaryOp, | 1718 kDeoptDoubleBinaryOp, |
1719 left, | 1719 left, |
1720 right); | 1720 right); |
1721 | 1721 |
1722 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1722 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
1723 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1723 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
1724 | 1724 |
1725 switch (comp->op_kind()) { | 1725 switch (comp->op_kind()) { |
1726 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1726 case Token::kADD: __ addsd(XMM0, XMM1); break; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1771 // TODO(srdjan): Implement for more checks. | 1771 // TODO(srdjan): Implement for more checks. |
1772 ASSERT(ic_data.NumberOfChecks() == 1); | 1772 ASSERT(ic_data.NumberOfChecks() == 1); |
1773 intptr_t test_class_id; | 1773 intptr_t test_class_id; |
1774 Function& target = Function::Handle(); | 1774 Function& target = Function::Handle(); |
1775 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1775 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1776 | 1776 |
1777 Register value = locs()->in(0).reg(); | 1777 Register value = locs()->in(0).reg(); |
1778 Register result = locs()->out().reg(); | 1778 Register result = locs()->out().reg(); |
1779 ASSERT(value == result); | 1779 ASSERT(value == result); |
1780 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1780 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1781 instance_call()->token_index(), | 1781 instance_call()->token_pos(), |
1782 instance_call()->try_index(), | 1782 instance_call()->try_index(), |
1783 kDeoptUnaryOp, | 1783 kDeoptUnaryOp, |
1784 value); | 1784 value); |
1785 if (test_class_id == kSmi) { | 1785 if (test_class_id == kSmi) { |
1786 __ testq(value, Immediate(kSmiTagMask)); | 1786 __ testq(value, Immediate(kSmiTagMask)); |
1787 __ j(NOT_ZERO, deopt); | 1787 __ j(NOT_ZERO, deopt); |
1788 switch (op_kind()) { | 1788 switch (op_kind()) { |
1789 case Token::kNEGATE: | 1789 case Token::kNEGATE: |
1790 __ negq(value); | 1790 __ negq(value); |
1791 __ j(OVERFLOW, deopt); | 1791 __ j(OVERFLOW, deopt); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1824 // TODO(srdjan): Implement for more checks. | 1824 // TODO(srdjan): Implement for more checks. |
1825 ASSERT(ic_data.NumberOfChecks() == 1); | 1825 ASSERT(ic_data.NumberOfChecks() == 1); |
1826 intptr_t test_class_id; | 1826 intptr_t test_class_id; |
1827 Function& target = Function::Handle(); | 1827 Function& target = Function::Handle(); |
1828 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1828 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1829 | 1829 |
1830 Register value = locs()->in(0).reg(); | 1830 Register value = locs()->in(0).reg(); |
1831 Register result = locs()->out().reg(); | 1831 Register result = locs()->out().reg(); |
1832 ASSERT(value == result); | 1832 ASSERT(value == result); |
1833 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1833 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1834 instance_call()->token_index(), | 1834 instance_call()->token_pos(), |
1835 instance_call()->try_index(), | 1835 instance_call()->try_index(), |
1836 kDeoptUnaryOp, | 1836 kDeoptUnaryOp, |
1837 value); | 1837 value); |
1838 if (test_class_id == kDouble) { | 1838 if (test_class_id == kDouble) { |
1839 Register temp = locs()->temp(0).reg(); | 1839 Register temp = locs()->temp(0).reg(); |
1840 __ testq(value, Immediate(kSmiTagMask)); | 1840 __ testq(value, Immediate(kSmiTagMask)); |
1841 __ j(ZERO, deopt); // Smi. | 1841 __ j(ZERO, deopt); // Smi. |
1842 __ CompareClassId(value, kDouble); | 1842 __ CompareClassId(value, kDouble); |
1843 __ j(NOT_EQUAL, deopt); | 1843 __ j(NOT_EQUAL, deopt); |
1844 // Allocate result object. | 1844 // Allocate result object. |
1845 const Class& double_class = compiler->double_class(); | 1845 const Class& double_class = compiler->double_class(); |
1846 const Code& stub = | 1846 const Code& stub = |
1847 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1847 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1848 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1848 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1849 __ pushq(value); | 1849 __ pushq(value); |
1850 compiler->GenerateCall(instance_call()->token_index(), | 1850 compiler->GenerateCall(instance_call()->token_pos(), |
1851 instance_call()->try_index(), | 1851 instance_call()->try_index(), |
1852 &label, | 1852 &label, |
1853 PcDescriptors::kOther); | 1853 PcDescriptors::kOther); |
1854 // Result is in RAX. | 1854 // Result is in RAX. |
1855 ASSERT(result != temp); | 1855 ASSERT(result != temp); |
1856 __ movq(result, RAX); | 1856 __ movq(result, RAX); |
1857 __ popq(temp); | 1857 __ popq(temp); |
1858 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1858 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
1859 __ DoubleNegate(XMM0); | 1859 __ DoubleNegate(XMM0); |
1860 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1860 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
(...skipping 18 matching lines...) Expand all Loading... |
1879 } | 1879 } |
1880 | 1880 |
1881 | 1881 |
1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1883 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1883 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
1884 Register result = locs()->out().reg(); | 1884 Register result = locs()->out().reg(); |
1885 | 1885 |
1886 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1886 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1887 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1887 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1888 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1888 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1889 instance_call()->token_index(), | 1889 instance_call()->token_pos(), |
1890 instance_call()->try_index(), | 1890 instance_call()->try_index(), |
1891 deopt_reason, | 1891 deopt_reason, |
1892 value); | 1892 value); |
1893 | 1893 |
1894 if (from() == kDouble) { | 1894 if (from() == kDouble) { |
1895 __ testq(value, Immediate(kSmiTagMask)); | 1895 __ testq(value, Immediate(kSmiTagMask)); |
1896 __ j(ZERO, deopt); // Deoptimize if Smi. | 1896 __ j(ZERO, deopt); // Deoptimize if Smi. |
1897 __ CompareClassId(value, kDouble); | 1897 __ CompareClassId(value, kDouble); |
1898 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1898 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1899 ASSERT(value == result); | 1899 ASSERT(value == result); |
1900 return; | 1900 return; |
1901 } | 1901 } |
1902 | 1902 |
1903 ASSERT(from() == kSmi); | 1903 ASSERT(from() == kSmi); |
1904 | 1904 |
1905 const Class& double_class = compiler->double_class(); | 1905 const Class& double_class = compiler->double_class(); |
1906 const Code& stub = | 1906 const Code& stub = |
1907 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1907 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1908 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1908 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1909 | 1909 |
1910 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1910 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
1911 compiler->GenerateCall(instance_call()->token_index(), | 1911 compiler->GenerateCall(instance_call()->token_pos(), |
1912 instance_call()->try_index(), | 1912 instance_call()->try_index(), |
1913 &label, | 1913 &label, |
1914 PcDescriptors::kOther); | 1914 PcDescriptors::kOther); |
1915 ASSERT(result == RAX); | 1915 ASSERT(result == RAX); |
1916 __ popq(value); | 1916 __ popq(value); |
1917 | 1917 |
1918 __ testq(value, Immediate(kSmiTagMask)); | 1918 __ testq(value, Immediate(kSmiTagMask)); |
1919 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1919 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
1920 __ SmiUntag(value); | 1920 __ SmiUntag(value); |
1921 __ cvtsi2sd(XMM0, value); | 1921 __ cvtsi2sd(XMM0, value); |
1922 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1922 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1923 } | 1923 } |
1924 | 1924 |
1925 | 1925 |
1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
1927 return MakeCallSummary(); | 1927 return MakeCallSummary(); |
1928 } | 1928 } |
1929 | 1929 |
1930 | 1930 |
1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1932 ASSERT(instance_call()->VerifyComputation()); | 1932 ASSERT(instance_call()->VerifyComputation()); |
1933 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1933 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1934 instance_call()->token_index(), | 1934 instance_call()->token_pos(), |
1935 instance_call()->try_index(), | 1935 instance_call()->try_index(), |
1936 kDeoptPolymorphicInstanceCallTestFail); | 1936 kDeoptPolymorphicInstanceCallTestFail); |
1937 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1937 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1938 __ jmp(deopt); | 1938 __ jmp(deopt); |
1939 return; | 1939 return; |
1940 } | 1940 } |
1941 ASSERT(HasICData()); | 1941 ASSERT(HasICData()); |
1942 ASSERT(ic_data()->num_args_tested() == 1); | 1942 ASSERT(ic_data()->num_args_tested() == 1); |
1943 Label handle_smi; | 1943 Label handle_smi; |
1944 Label* is_smi_label = | 1944 Label* is_smi_label = |
1945 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1945 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
1946 | 1946 |
1947 // Load receiver into RAX. | 1947 // Load receiver into RAX. |
1948 __ movq(RAX, | 1948 __ movq(RAX, |
1949 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1949 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1950 __ testq(RAX, Immediate(kSmiTagMask)); | 1950 __ testq(RAX, Immediate(kSmiTagMask)); |
1951 __ j(ZERO, is_smi_label); | 1951 __ j(ZERO, is_smi_label); |
1952 Label done; | 1952 Label done; |
1953 __ LoadClassId(RDI, RAX); | 1953 __ LoadClassId(RDI, RAX); |
1954 compiler->EmitTestAndCall(*ic_data(), | 1954 compiler->EmitTestAndCall(*ic_data(), |
1955 RDI, // Class id register. | 1955 RDI, // Class id register. |
1956 instance_call()->ArgumentCount(), | 1956 instance_call()->ArgumentCount(), |
1957 instance_call()->argument_names(), | 1957 instance_call()->argument_names(), |
1958 deopt, &done, // Labels. | 1958 deopt, &done, // Labels. |
1959 instance_call()->cid(), | 1959 instance_call()->cid(), |
1960 instance_call()->token_index(), | 1960 instance_call()->token_pos(), |
1961 instance_call()->try_index()); | 1961 instance_call()->try_index()); |
1962 if (is_smi_label == &handle_smi) { | 1962 if (is_smi_label == &handle_smi) { |
1963 __ Bind(&handle_smi); | 1963 __ Bind(&handle_smi); |
1964 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1964 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
1965 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1965 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1966 compiler->GenerateStaticCall(instance_call()->cid(), | 1966 compiler->GenerateStaticCall(instance_call()->cid(), |
1967 instance_call()->token_index(), | 1967 instance_call()->token_pos(), |
1968 instance_call()->try_index(), | 1968 instance_call()->try_index(), |
1969 target, | 1969 target, |
1970 instance_call()->ArgumentCount(), | 1970 instance_call()->ArgumentCount(), |
1971 instance_call()->argument_names()); | 1971 instance_call()->argument_names()); |
1972 } | 1972 } |
1973 __ Bind(&done); | 1973 __ Bind(&done); |
1974 } | 1974 } |
1975 | 1975 |
1976 } // namespace dart | 1976 } // namespace dart |
1977 | 1977 |
1978 #undef __ | 1978 #undef __ |
1979 | 1979 |
1980 #endif // defined TARGET_ARCH_X64 | 1980 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |