Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(688)

Side by Side Diff: vm/intermediate_language_x64.cc

Issue 10632009: Make the parser agnostic to the TokenStream implementation. This is the first step towards compacti… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « vm/intermediate_language_ia32.cc ('k') | vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « vm/intermediate_language_ia32.cc ('k') | vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698