OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 __ popl(result); // Restore result. | 92 __ popl(result); // Restore result. |
93 } | 93 } |
94 __ LeaveFrame(); | 94 __ LeaveFrame(); |
95 __ ret(); | 95 __ ret(); |
96 | 96 |
97 // Generate 1 byte NOP so that the debugger can patch the | 97 // Generate 1 byte NOP so that the debugger can patch the |
98 // return pattern with a call to the debug stub. | 98 // return pattern with a call to the debug stub. |
99 __ nop(1); | 99 __ nop(1); |
100 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 100 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
101 cid(), | 101 cid(), |
102 token_index(), | 102 token_pos(), |
103 CatchClauseNode::kInvalidTryIndex); | 103 CatchClauseNode::kInvalidTryIndex); |
104 } | 104 } |
105 | 105 |
106 | 106 |
107 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 107 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
108 const intptr_t kNumInputs = 0; | 108 const intptr_t kNumInputs = 0; |
109 const intptr_t kNumTemps = 1; | 109 const intptr_t kNumTemps = 1; |
110 LocationSummary* result = new LocationSummary(kNumInputs, | 110 LocationSummary* result = new LocationSummary(kNumInputs, |
111 kNumTemps, | 111 kNumTemps, |
112 LocationSummary::kCall); | 112 LocationSummary::kCall); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 Register result = locs()->out().reg(); | 171 Register result = locs()->out().reg(); |
172 | 172 |
173 // Check that the type of the value is allowed in conditional context. | 173 // Check that the type of the value is allowed in conditional context. |
174 // Call the runtime if the object is not bool::true or bool::false. | 174 // Call the runtime if the object is not bool::true or bool::false. |
175 Label done; | 175 Label done; |
176 __ CompareObject(obj, compiler->bool_true()); | 176 __ CompareObject(obj, compiler->bool_true()); |
177 __ j(EQUAL, &done, Assembler::kNearJump); | 177 __ j(EQUAL, &done, Assembler::kNearJump); |
178 __ CompareObject(obj, compiler->bool_false()); | 178 __ CompareObject(obj, compiler->bool_false()); |
179 __ j(EQUAL, &done, Assembler::kNearJump); | 179 __ j(EQUAL, &done, Assembler::kNearJump); |
180 | 180 |
181 __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location. | 181 __ pushl(Immediate(Smi::RawValue(token_pos()))); // Source location. |
182 __ pushl(obj); // Push the source object. | 182 __ pushl(obj); // Push the source object. |
183 compiler->GenerateCallRuntime(cid(), | 183 compiler->GenerateCallRuntime(cid(), |
184 token_index(), | 184 token_pos(), |
185 try_index(), | 185 try_index(), |
186 kConditionTypeErrorRuntimeEntry); | 186 kConditionTypeErrorRuntimeEntry); |
187 // We should never return here. | 187 // We should never return here. |
188 __ int3(); | 188 __ int3(); |
189 | 189 |
190 __ Bind(&done); | 190 __ Bind(&done); |
191 ASSERT(obj == result); | 191 ASSERT(obj == result); |
192 } | 192 } |
193 | 193 |
194 | 194 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 return locs; | 241 return locs; |
242 } | 242 } |
243 | 243 |
244 | 244 |
245 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 245 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
246 EqualityCompareComp* comp) { | 246 EqualityCompareComp* comp) { |
247 Register left = comp->locs()->in(0).reg(); | 247 Register left = comp->locs()->in(0).reg(); |
248 Register right = comp->locs()->in(1).reg(); | 248 Register right = comp->locs()->in(1).reg(); |
249 Register temp = comp->locs()->temp(0).reg(); | 249 Register temp = comp->locs()->temp(0).reg(); |
250 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 250 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
251 comp->token_index(), | 251 comp->token_pos(), |
252 comp->try_index(), | 252 comp->try_index(), |
253 kDeoptSmiCompareSmis, | 253 kDeoptSmiCompareSmis, |
254 left, | 254 left, |
255 right); | 255 right); |
256 // TODO(srdjan): Should we always include NULL test (common case)? | 256 // TODO(srdjan): Should we always include NULL test (common case)? |
257 __ movl(temp, left); | 257 __ movl(temp, left); |
258 __ orl(temp, right); | 258 __ orl(temp, right); |
259 __ testl(temp, Immediate(kSmiTagMask)); | 259 __ testl(temp, Immediate(kSmiTagMask)); |
260 __ j(NOT_ZERO, deopt); | 260 __ j(NOT_ZERO, deopt); |
261 __ cmpl(left, right); | 261 __ cmpl(left, right); |
262 if (comp->is_fused_with_branch()) { | 262 if (comp->is_fused_with_branch()) { |
263 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 263 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
264 } else { | 264 } else { |
265 Register result = comp->locs()->out().reg(); | 265 Register result = comp->locs()->out().reg(); |
266 Label load_true, done; | 266 Label load_true, done; |
267 __ j(EQUAL, &load_true, Assembler::kNearJump); | 267 __ j(EQUAL, &load_true, Assembler::kNearJump); |
268 __ LoadObject(result, compiler->bool_false()); | 268 __ LoadObject(result, compiler->bool_false()); |
269 __ jmp(&done, Assembler::kNearJump); | 269 __ jmp(&done, Assembler::kNearJump); |
270 __ Bind(&load_true); | 270 __ Bind(&load_true); |
271 __ LoadObject(result, compiler->bool_true()); | 271 __ LoadObject(result, compiler->bool_true()); |
272 __ Bind(&done); | 272 __ Bind(&done); |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 | 276 |
277 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 277 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
278 EqualityCompareComp* comp) { | 278 EqualityCompareComp* comp) { |
279 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 279 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
280 comp->cid(), | 280 comp->cid(), |
281 comp->token_index(), | 281 comp->token_pos(), |
282 comp->try_index()); | 282 comp->try_index()); |
283 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 283 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
284 const int kNumberOfArguments = 2; | 284 const int kNumberOfArguments = 2; |
285 const Array& kNoArgumentNames = Array::Handle(); | 285 const Array& kNoArgumentNames = Array::Handle(); |
286 const int kNumArgumentsChecked = 2; | 286 const int kNumArgumentsChecked = 2; |
287 | 287 |
288 compiler->GenerateInstanceCall(comp->cid(), | 288 compiler->GenerateInstanceCall(comp->cid(), |
289 comp->token_index(), | 289 comp->token_pos(), |
290 comp->try_index(), | 290 comp->try_index(), |
291 operator_name, | 291 operator_name, |
292 kNumberOfArguments, | 292 kNumberOfArguments, |
293 kNoArgumentNames, | 293 kNoArgumentNames, |
294 kNumArgumentsChecked); | 294 kNumArgumentsChecked); |
295 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX)); | 295 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX)); |
296 | 296 |
297 if (comp->is_fused_with_branch()) { | 297 if (comp->is_fused_with_branch()) { |
298 __ CompareObject(EAX, compiler->bool_true()); | 298 __ CompareObject(EAX, compiler->bool_true()); |
299 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 299 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
300 } | 300 } |
301 } | 301 } |
302 | 302 |
303 | 303 |
304 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 304 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
305 EqualityCompareComp* comp, | 305 EqualityCompareComp* comp, |
306 Register left, | 306 Register left, |
307 Register right) { | 307 Register right) { |
308 ASSERT(comp->HasICData()); | 308 ASSERT(comp->HasICData()); |
309 const ICData& ic_data = *comp->ic_data(); | 309 const ICData& ic_data = *comp->ic_data(); |
310 ASSERT(ic_data.NumberOfChecks() > 0); | 310 ASSERT(ic_data.NumberOfChecks() > 0); |
311 ASSERT(ic_data.num_args_tested() == 1); | 311 ASSERT(ic_data.num_args_tested() == 1); |
312 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 312 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
313 comp->token_index(), | 313 comp->token_pos(), |
314 comp->try_index(), | 314 comp->try_index(), |
315 kDeoptEquality); | 315 kDeoptEquality); |
316 __ testl(left, Immediate(kSmiTagMask)); | 316 __ testl(left, Immediate(kSmiTagMask)); |
317 Register temp = comp->locs()->temp(0).reg(); | 317 Register temp = comp->locs()->temp(0).reg(); |
318 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 318 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
319 Label done, load_class_id; | 319 Label done, load_class_id; |
320 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 320 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
321 __ movl(temp, Immediate(kSmi)); | 321 __ movl(temp, Immediate(kSmi)); |
322 __ jmp(&done, Assembler::kNearJump); | 322 __ jmp(&done, Assembler::kNearJump); |
323 __ Bind(&load_class_id); | 323 __ Bind(&load_class_id); |
(...skipping 24 matching lines...) Expand all Loading... |
348 __ j(EQUAL, &load_true, Assembler::kNearJump); | 348 __ j(EQUAL, &load_true, Assembler::kNearJump); |
349 __ LoadObject(result, compiler->bool_false()); | 349 __ LoadObject(result, compiler->bool_false()); |
350 __ jmp(&done); | 350 __ jmp(&done); |
351 __ Bind(&load_true); | 351 __ Bind(&load_true); |
352 __ LoadObject(result, compiler->bool_true()); | 352 __ LoadObject(result, compiler->bool_true()); |
353 } | 353 } |
354 } else { | 354 } else { |
355 const int kNumberOfArguments = 2; | 355 const int kNumberOfArguments = 2; |
356 const Array& kNoArgumentNames = Array::Handle(); | 356 const Array& kNoArgumentNames = Array::Handle(); |
357 compiler->GenerateStaticCall(comp->cid(), | 357 compiler->GenerateStaticCall(comp->cid(), |
358 comp->token_index(), | 358 comp->token_pos(), |
359 comp->try_index(), | 359 comp->try_index(), |
360 target, | 360 target, |
361 kNumberOfArguments, | 361 kNumberOfArguments, |
362 kNoArgumentNames); | 362 kNoArgumentNames); |
363 ASSERT(comp->is_fused_with_branch() || | 363 ASSERT(comp->is_fused_with_branch() || |
364 (comp->locs()->out().reg() == EAX)); | 364 (comp->locs()->out().reg() == EAX)); |
365 if (comp->is_fused_with_branch()) { | 365 if (comp->is_fused_with_branch()) { |
366 __ CompareObject(EAX, compiler->bool_true()); | 366 __ CompareObject(EAX, compiler->bool_true()); |
367 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 367 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
368 } | 368 } |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 } | 466 } |
467 } | 467 } |
468 | 468 |
469 | 469 |
470 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 470 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
471 RelationalOpComp* comp) { | 471 RelationalOpComp* comp) { |
472 Register left = comp->locs()->in(0).reg(); | 472 Register left = comp->locs()->in(0).reg(); |
473 Register right = comp->locs()->in(1).reg(); | 473 Register right = comp->locs()->in(1).reg(); |
474 Register temp = comp->locs()->temp(0).reg(); | 474 Register temp = comp->locs()->temp(0).reg(); |
475 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 475 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
476 comp->token_index(), | 476 comp->token_pos(), |
477 comp->try_index(), | 477 comp->try_index(), |
478 kDeoptSmiCompareSmis, | 478 kDeoptSmiCompareSmis, |
479 left, | 479 left, |
480 right); | 480 right); |
481 __ movl(temp, left); | 481 __ movl(temp, left); |
482 __ orl(temp, right); | 482 __ orl(temp, right); |
483 __ testl(temp, Immediate(kSmiTagMask)); | 483 __ testl(temp, Immediate(kSmiTagMask)); |
484 __ j(NOT_ZERO, deopt); | 484 __ j(NOT_ZERO, deopt); |
485 | 485 |
486 Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 486 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
(...skipping 28 matching lines...) Expand all Loading... |
515 } | 515 } |
516 | 516 |
517 | 517 |
518 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 518 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
519 RelationalOpComp* comp) { | 519 RelationalOpComp* comp) { |
520 Register left = comp->locs()->in(0).reg(); | 520 Register left = comp->locs()->in(0).reg(); |
521 Register right = comp->locs()->in(1).reg(); | 521 Register right = comp->locs()->in(1).reg(); |
522 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 522 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
523 Register temp = comp->locs()->temp(0).reg(); | 523 Register temp = comp->locs()->temp(0).reg(); |
524 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 524 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
525 comp->token_index(), | 525 comp->token_pos(), |
526 comp->try_index(), | 526 comp->try_index(), |
527 kDeoptDoubleComparison, | 527 kDeoptDoubleComparison, |
528 left, | 528 left, |
529 right); | 529 right); |
530 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 530 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
531 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 531 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
532 | 532 |
533 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 533 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
534 __ comisd(XMM0, XMM1); | 534 __ comisd(XMM0, XMM1); |
535 | 535 |
(...skipping 24 matching lines...) Expand all Loading... |
560 return; | 560 return; |
561 } | 561 } |
562 if (operands_class_id() == kDouble) { | 562 if (operands_class_id() == kDouble) { |
563 EmitDoubleRelationalOp(compiler, this); | 563 EmitDoubleRelationalOp(compiler, this); |
564 return; | 564 return; |
565 } | 565 } |
566 const String& function_name = | 566 const String& function_name = |
567 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 567 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
568 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 568 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
569 cid(), | 569 cid(), |
570 token_index(), | 570 token_pos(), |
571 try_index()); | 571 try_index()); |
572 const intptr_t kNumArguments = 2; | 572 const intptr_t kNumArguments = 2; |
573 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 573 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
574 compiler->GenerateInstanceCall(cid(), | 574 compiler->GenerateInstanceCall(cid(), |
575 token_index(), | 575 token_pos(), |
576 try_index(), | 576 try_index(), |
577 function_name, | 577 function_name, |
578 kNumArguments, | 578 kNumArguments, |
579 Array::ZoneHandle(), // No optional arguments. | 579 Array::ZoneHandle(), // No optional arguments. |
580 kNumArgsChecked); | 580 kNumArgsChecked); |
581 ASSERT(locs()->out().reg() == EAX); | 581 ASSERT(locs()->out().reg() == EAX); |
582 } | 582 } |
583 | 583 |
584 | 584 |
585 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 585 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
(...skipping 24 matching lines...) Expand all Loading... |
610 arg_count += 1; | 610 arg_count += 1; |
611 } | 611 } |
612 if (!has_optional_parameters() && !is_native_instance_closure()) { | 612 if (!has_optional_parameters() && !is_native_instance_closure()) { |
613 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 613 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
614 } else { | 614 } else { |
615 __ leal(EAX, | 615 __ leal(EAX, |
616 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 616 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
617 } | 617 } |
618 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 618 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
619 __ movl(EDX, Immediate(arg_count)); | 619 __ movl(EDX, Immediate(arg_count)); |
620 compiler->GenerateCall(token_index(), | 620 compiler->GenerateCall(token_pos(), |
621 try_index(), | 621 try_index(), |
622 &StubCode::CallNativeCFunctionLabel(), | 622 &StubCode::CallNativeCFunctionLabel(), |
623 PcDescriptors::kOther); | 623 PcDescriptors::kOther); |
624 __ popl(result); | 624 __ popl(result); |
625 } | 625 } |
626 | 626 |
627 | 627 |
628 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 628 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
629 const intptr_t kNumInputs = 2; | 629 const intptr_t kNumInputs = 2; |
630 if ((receiver_type() == kGrowableObjectArray) || | 630 if ((receiver_type() == kGrowableObjectArray) || |
631 (receiver_type() == kArray) || | 631 (receiver_type() == kArray) || |
632 (receiver_type() == kImmutableArray)) { | 632 (receiver_type() == kImmutableArray)) { |
633 const intptr_t kNumTemps = 1; | 633 const intptr_t kNumTemps = 1; |
634 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 634 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
635 locs->set_in(0, Location::RequiresRegister()); | 635 locs->set_in(0, Location::RequiresRegister()); |
636 locs->set_in(1, Location::RequiresRegister()); | 636 locs->set_in(1, Location::RequiresRegister()); |
637 locs->set_temp(0, Location::RequiresRegister()); | 637 locs->set_temp(0, Location::RequiresRegister()); |
638 locs->set_out(Location::RequiresRegister()); | 638 locs->set_out(Location::RequiresRegister()); |
639 return locs; | 639 return locs; |
640 } else { | 640 } else { |
641 ASSERT(receiver_type() == kIllegalObjectKind); | 641 ASSERT(receiver_type() == kIllegalObjectKind); |
642 return MakeCallSummary(); | 642 return MakeCallSummary(); |
643 } | 643 } |
644 } | 644 } |
645 | 645 |
646 | 646 |
647 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 647 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
648 LoadIndexedComp* comp) { | 648 LoadIndexedComp* comp) { |
649 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 649 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
650 comp->token_index(), | 650 comp->token_pos(), |
651 comp->try_index(), | 651 comp->try_index(), |
652 kDeoptLoadIndexedPolymorphic); | 652 kDeoptLoadIndexedPolymorphic); |
653 if (comp->ic_data()->NumberOfChecks() == 0) { | 653 if (comp->ic_data()->NumberOfChecks() == 0) { |
654 __ jmp(deopt); | 654 __ jmp(deopt); |
655 return; | 655 return; |
656 } | 656 } |
657 ASSERT(comp->HasICData()); | 657 ASSERT(comp->HasICData()); |
658 const ICData& ic_data = *comp->ic_data(); | 658 const ICData& ic_data = *comp->ic_data(); |
659 ASSERT(ic_data.num_args_tested() == 1); | 659 ASSERT(ic_data.num_args_tested() == 1); |
660 // No indexed access on Smi. | 660 // No indexed access on Smi. |
661 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 661 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
662 // Load receiver into EAX. | 662 // Load receiver into EAX. |
663 const intptr_t kNumArguments = 2; | 663 const intptr_t kNumArguments = 2; |
664 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 664 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
665 __ testl(EAX, Immediate(kSmiTagMask)); | 665 __ testl(EAX, Immediate(kSmiTagMask)); |
666 __ j(ZERO, deopt); | 666 __ j(ZERO, deopt); |
667 Label done; | 667 Label done; |
668 __ LoadClassId(EDI, EAX); | 668 __ LoadClassId(EDI, EAX); |
669 compiler->EmitTestAndCall(ic_data, | 669 compiler->EmitTestAndCall(ic_data, |
670 EDI, // Class id register. | 670 EDI, // Class id register. |
671 kNumArguments, | 671 kNumArguments, |
672 Array::Handle(), // No named arguments. | 672 Array::Handle(), // No named arguments. |
673 deopt, &done, // Labels. | 673 deopt, &done, // Labels. |
674 comp->cid(), | 674 comp->cid(), |
675 comp->token_index(), | 675 comp->token_pos(), |
676 comp->try_index()); | 676 comp->try_index()); |
677 __ Bind(&done); | 677 __ Bind(&done); |
678 } | 678 } |
679 | 679 |
680 | 680 |
681 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 681 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
682 if (receiver_type() == kIllegalObjectKind) { | 682 if (receiver_type() == kIllegalObjectKind) { |
683 if (HasICData()) { | 683 if (HasICData()) { |
684 EmitLoadIndexedPolymorphic(compiler, this); | 684 EmitLoadIndexedPolymorphic(compiler, this); |
685 } else { | 685 } else { |
686 compiler->EmitLoadIndexedGeneric(this); | 686 compiler->EmitLoadIndexedGeneric(this); |
687 } | 687 } |
688 ASSERT(locs()->out().reg() == EAX); | 688 ASSERT(locs()->out().reg() == EAX); |
689 return; | 689 return; |
690 } | 690 } |
691 | 691 |
692 Register receiver = locs()->in(0).reg(); | 692 Register receiver = locs()->in(0).reg(); |
693 Register index = locs()->in(1).reg(); | 693 Register index = locs()->in(1).reg(); |
694 Register result = locs()->out().reg(); | 694 Register result = locs()->out().reg(); |
695 Register temp = locs()->temp(0).reg(); | 695 Register temp = locs()->temp(0).reg(); |
696 | 696 |
697 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 697 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
698 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 698 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
699 | 699 |
700 Label* deopt = compiler->AddDeoptStub(cid(), | 700 Label* deopt = compiler->AddDeoptStub(cid(), |
701 token_index(), | 701 token_pos(), |
702 try_index(), | 702 try_index(), |
703 deopt_reason, | 703 deopt_reason, |
704 receiver, | 704 receiver, |
705 index); | 705 index); |
706 | 706 |
707 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 707 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
708 __ j(ZERO, deopt); | 708 __ j(ZERO, deopt); |
709 __ CompareClassId(receiver, receiver_type(), temp); | 709 __ CompareClassId(receiver, receiver_type(), temp); |
710 __ j(NOT_EQUAL, deopt); | 710 __ j(NOT_EQUAL, deopt); |
711 | 711 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 } | 761 } |
762 | 762 |
763 | 763 |
764 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 764 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
765 StoreIndexedComp* comp) { | 765 StoreIndexedComp* comp) { |
766 const String& function_name = | 766 const String& function_name = |
767 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 767 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
768 | 768 |
769 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 769 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
770 comp->cid(), | 770 comp->cid(), |
771 comp->token_index(), | 771 comp->token_pos(), |
772 comp->try_index()); | 772 comp->try_index()); |
773 | 773 |
774 const intptr_t kNumArguments = 3; | 774 const intptr_t kNumArguments = 3; |
775 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 775 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
776 compiler->GenerateInstanceCall(comp->cid(), | 776 compiler->GenerateInstanceCall(comp->cid(), |
777 comp->token_index(), | 777 comp->token_pos(), |
778 comp->try_index(), | 778 comp->try_index(), |
779 function_name, | 779 function_name, |
780 kNumArguments, | 780 kNumArguments, |
781 Array::ZoneHandle(), // No named arguments. | 781 Array::ZoneHandle(), // No named arguments. |
782 kNumArgsChecked); | 782 kNumArgsChecked); |
783 } | 783 } |
784 | 784 |
785 | 785 |
786 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 786 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
787 StoreIndexedComp* comp) { | 787 StoreIndexedComp* comp) { |
788 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 788 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
789 comp->token_index(), | 789 comp->token_pos(), |
790 comp->try_index(), | 790 comp->try_index(), |
791 kDeoptStoreIndexedPolymorphic); | 791 kDeoptStoreIndexedPolymorphic); |
792 if (comp->ic_data()->NumberOfChecks() == 0) { | 792 if (comp->ic_data()->NumberOfChecks() == 0) { |
793 __ jmp(deopt); | 793 __ jmp(deopt); |
794 return; | 794 return; |
795 } | 795 } |
796 ASSERT(comp->HasICData()); | 796 ASSERT(comp->HasICData()); |
797 const ICData& ic_data = *comp->ic_data(); | 797 const ICData& ic_data = *comp->ic_data(); |
798 ASSERT(ic_data.num_args_tested() == 1); | 798 ASSERT(ic_data.num_args_tested() == 1); |
799 // No indexed access on Smi. | 799 // No indexed access on Smi. |
800 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 800 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
801 // Load receiver into EAX. | 801 // Load receiver into EAX. |
802 const intptr_t kNumArguments = 3; | 802 const intptr_t kNumArguments = 3; |
803 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 803 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
804 __ testl(EAX, Immediate(kSmiTagMask)); | 804 __ testl(EAX, Immediate(kSmiTagMask)); |
805 __ j(ZERO, deopt); | 805 __ j(ZERO, deopt); |
806 Label done; | 806 Label done; |
807 __ LoadClassId(EDI, EAX); | 807 __ LoadClassId(EDI, EAX); |
808 compiler->EmitTestAndCall(ic_data, | 808 compiler->EmitTestAndCall(ic_data, |
809 EDI, // Class id register. | 809 EDI, // Class id register. |
810 kNumArguments, | 810 kNumArguments, |
811 Array::Handle(), // No named arguments. | 811 Array::Handle(), // No named arguments. |
812 deopt, &done, // Labels. | 812 deopt, &done, // Labels. |
813 comp->cid(), | 813 comp->cid(), |
814 comp->token_index(), | 814 comp->token_pos(), |
815 comp->try_index()); | 815 comp->try_index()); |
816 __ Bind(&done); | 816 __ Bind(&done); |
817 } | 817 } |
818 | 818 |
819 | 819 |
820 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 820 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
821 if (receiver_type() == kIllegalObjectKind) { | 821 if (receiver_type() == kIllegalObjectKind) { |
822 if (HasICData()) { | 822 if (HasICData()) { |
823 EmitStoreIndexedPolymorphic(compiler, this); | 823 EmitStoreIndexedPolymorphic(compiler, this); |
824 } else { | 824 } else { |
825 EmitStoreIndexedGeneric(compiler, this); | 825 EmitStoreIndexedGeneric(compiler, this); |
826 } | 826 } |
827 return; | 827 return; |
828 } | 828 } |
829 | 829 |
830 Register receiver = locs()->in(0).reg(); | 830 Register receiver = locs()->in(0).reg(); |
831 Register index = locs()->in(1).reg(); | 831 Register index = locs()->in(1).reg(); |
832 Register value = locs()->in(2).reg(); | 832 Register value = locs()->in(2).reg(); |
833 Register temp = locs()->temp(0).reg(); | 833 Register temp = locs()->temp(0).reg(); |
834 | 834 |
835 Label* deopt = compiler->AddDeoptStub(cid(), | 835 Label* deopt = compiler->AddDeoptStub(cid(), |
836 token_index(), | 836 token_pos(), |
837 try_index(), | 837 try_index(), |
838 kDeoptStoreIndexed, | 838 kDeoptStoreIndexed, |
839 receiver, | 839 receiver, |
840 index, | 840 index, |
841 value); | 841 value); |
842 | 842 |
843 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 843 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
844 __ j(ZERO, deopt); | 844 __ j(ZERO, deopt); |
845 __ CompareClassId(receiver, receiver_type(), temp); | 845 __ CompareClassId(receiver, receiver_type(), temp); |
846 __ j(NOT_EQUAL, deopt); | 846 __ j(NOT_EQUAL, deopt); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 return MakeCallSummary(); | 884 return MakeCallSummary(); |
885 } | 885 } |
886 | 886 |
887 | 887 |
888 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 888 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
889 const String& function_name = | 889 const String& function_name = |
890 String::ZoneHandle(Field::SetterSymbol(field_name())); | 890 String::ZoneHandle(Field::SetterSymbol(field_name())); |
891 | 891 |
892 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 892 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
893 cid(), | 893 cid(), |
894 token_index(), | 894 token_pos(), |
895 try_index()); | 895 try_index()); |
896 const intptr_t kArgumentCount = 2; | 896 const intptr_t kArgumentCount = 2; |
897 const intptr_t kCheckedArgumentCount = 1; | 897 const intptr_t kCheckedArgumentCount = 1; |
898 compiler->GenerateInstanceCall(cid(), | 898 compiler->GenerateInstanceCall(cid(), |
899 token_index(), | 899 token_pos(), |
900 try_index(), | 900 try_index(), |
901 function_name, | 901 function_name, |
902 kArgumentCount, | 902 kArgumentCount, |
903 Array::ZoneHandle(), | 903 Array::ZoneHandle(), |
904 kCheckedArgumentCount); | 904 kCheckedArgumentCount); |
905 } | 905 } |
906 | 906 |
907 | 907 |
908 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 908 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
909 const intptr_t kNumInputs = 1; | 909 const intptr_t kNumInputs = 1; |
910 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 910 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
911 } | 911 } |
912 | 912 |
913 | 913 |
914 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 914 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
915 Register value = locs()->in(0).reg(); | 915 Register value = locs()->in(0).reg(); |
916 Register result = locs()->out().reg(); | 916 Register result = locs()->out().reg(); |
917 | 917 |
918 // Preserve the argument as the result of the computation, | 918 // Preserve the argument as the result of the computation, |
919 // then call the setter. | 919 // then call the setter. |
920 | 920 |
921 // Duplicate the argument. | 921 // Duplicate the argument. |
922 // TODO(fschneider): Avoid preserving the value if the result is not used. | 922 // TODO(fschneider): Avoid preserving the value if the result is not used. |
923 __ pushl(value); | 923 __ pushl(value); |
924 __ pushl(value); | 924 __ pushl(value); |
925 compiler->GenerateStaticCall(cid(), | 925 compiler->GenerateStaticCall(cid(), |
926 token_index(), | 926 token_pos(), |
927 try_index(), | 927 try_index(), |
928 setter_function(), | 928 setter_function(), |
929 1, | 929 1, |
930 Array::ZoneHandle()); | 930 Array::ZoneHandle()); |
931 __ popl(result); | 931 __ popl(result); |
932 } | 932 } |
933 | 933 |
934 | 934 |
935 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 935 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
936 // TODO(fschneider): For this instruction the input register may be | 936 // TODO(fschneider): For this instruction the input register may be |
937 // reused for the result (but is not required to) because the input | 937 // reused for the result (but is not required to) because the input |
938 // is not used after the result is defined. We should consider adding | 938 // is not used after the result is defined. We should consider adding |
939 // this information to the input policy. | 939 // this information to the input policy. |
940 return LocationSummary::Make(1, Location::RequiresRegister()); | 940 return LocationSummary::Make(1, Location::RequiresRegister()); |
941 } | 941 } |
942 | 942 |
943 | 943 |
944 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 944 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
945 Register instance_reg = locs()->in(0).reg(); | 945 Register instance_reg = locs()->in(0).reg(); |
946 Register result_reg = locs()->out().reg(); | 946 Register result_reg = locs()->out().reg(); |
947 | 947 |
948 if (HasICData()) { | 948 if (HasICData()) { |
949 ASSERT(original() != NULL); | 949 ASSERT(original() != NULL); |
950 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 950 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
951 original()->token_index(), | 951 original()->token_pos(), |
952 original()->try_index(), | 952 original()->try_index(), |
953 kDeoptInstanceGetterSameTarget, | 953 kDeoptInstanceGetterSameTarget, |
954 instance_reg); | 954 instance_reg); |
955 // Smis do not have instance fields (Smi class is always first). | 955 // Smis do not have instance fields (Smi class is always first). |
956 // Use 'result' as temporary register. | 956 // Use 'result' as temporary register. |
957 ASSERT(result_reg != instance_reg); | 957 ASSERT(result_reg != instance_reg); |
958 ASSERT(ic_data() != NULL); | 958 ASSERT(ic_data() != NULL); |
959 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 959 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
960 } | 960 } |
961 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); | 961 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); |
(...skipping 21 matching lines...) Expand all Loading... |
983 return summary; | 983 return summary; |
984 } | 984 } |
985 | 985 |
986 | 986 |
987 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 987 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
988 ASSERT(locs()->in(0).reg() == EAX); // Value. | 988 ASSERT(locs()->in(0).reg() == EAX); // Value. |
989 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 989 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
990 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 990 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
991 | 991 |
992 compiler->GenerateInstanceOf(cid(), | 992 compiler->GenerateInstanceOf(cid(), |
993 token_index(), | 993 token_pos(), |
994 try_index(), | 994 try_index(), |
995 type(), | 995 type(), |
996 negate_result()); | 996 negate_result()); |
997 ASSERT(locs()->out().reg() == EAX); | 997 ASSERT(locs()->out().reg() == EAX); |
998 } | 998 } |
999 | 999 |
1000 | 1000 |
1001 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1001 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
1002 // TODO(regis): The elements of the array could be considered as arguments to | 1002 // TODO(regis): The elements of the array could be considered as arguments to |
1003 // CreateArrayComp, thereby making CreateArrayComp a call. | 1003 // CreateArrayComp, thereby making CreateArrayComp a call. |
(...skipping 12 matching lines...) Expand all Loading... |
1016 | 1016 |
1017 | 1017 |
1018 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1018 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1019 Register temp_reg = locs()->temp(0).reg(); | 1019 Register temp_reg = locs()->temp(0).reg(); |
1020 Register result_reg = locs()->out().reg(); | 1020 Register result_reg = locs()->out().reg(); |
1021 | 1021 |
1022 // Allocate the array. EDX = length, ECX = element type. | 1022 // Allocate the array. EDX = length, ECX = element type. |
1023 ASSERT(temp_reg == EDX); | 1023 ASSERT(temp_reg == EDX); |
1024 ASSERT(locs()->in(0).reg() == ECX); | 1024 ASSERT(locs()->in(0).reg() == ECX); |
1025 __ movl(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 1025 __ movl(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
1026 compiler->GenerateCall(token_index(), | 1026 compiler->GenerateCall(token_pos(), |
1027 try_index(), | 1027 try_index(), |
1028 &StubCode::AllocateArrayLabel(), | 1028 &StubCode::AllocateArrayLabel(), |
1029 PcDescriptors::kOther); | 1029 PcDescriptors::kOther); |
1030 ASSERT(result_reg == EAX); | 1030 ASSERT(result_reg == EAX); |
1031 | 1031 |
1032 // Pop the element values from the stack into the array. | 1032 // Pop the element values from the stack into the array. |
1033 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1033 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
1034 for (int i = ElementCount() - 1; i >= 0; --i) { | 1034 for (int i = ElementCount() - 1; i >= 0; --i) { |
1035 ASSERT(ElementAt(i)->IsUse()); | 1035 ASSERT(ElementAt(i)->IsUse()); |
1036 __ popl(Address(temp_reg, i * kWordSize)); | 1036 __ popl(Address(temp_reg, i * kWordSize)); |
(...skipping 11 matching lines...) Expand all Loading... |
1048 | 1048 |
1049 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1049 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
1050 FlowGraphCompiler* compiler) { | 1050 FlowGraphCompiler* compiler) { |
1051 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1051 const Class& cls = Class::ZoneHandle(constructor().owner()); |
1052 Register type_arguments = locs()->in(0).reg(); | 1052 Register type_arguments = locs()->in(0).reg(); |
1053 Register instantiator_type_arguments = locs()->in(1).reg(); | 1053 Register instantiator_type_arguments = locs()->in(1).reg(); |
1054 Register result = locs()->out().reg(); | 1054 Register result = locs()->out().reg(); |
1055 | 1055 |
1056 // Push the result place holder initialized to NULL. | 1056 // Push the result place holder initialized to NULL. |
1057 __ PushObject(Object::ZoneHandle()); | 1057 __ PushObject(Object::ZoneHandle()); |
1058 __ pushl(Immediate(Smi::RawValue(token_index()))); | 1058 __ pushl(Immediate(Smi::RawValue(token_pos()))); |
1059 __ PushObject(cls); | 1059 __ PushObject(cls); |
1060 __ pushl(type_arguments); | 1060 __ pushl(type_arguments); |
1061 __ pushl(instantiator_type_arguments); | 1061 __ pushl(instantiator_type_arguments); |
1062 compiler->GenerateCallRuntime(cid(), | 1062 compiler->GenerateCallRuntime(cid(), |
1063 token_index(), | 1063 token_pos(), |
1064 try_index(), | 1064 try_index(), |
1065 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1065 kAllocateObjectWithBoundsCheckRuntimeEntry); |
1066 // Pop instantiator type arguments, type arguments, class, and | 1066 // Pop instantiator type arguments, type arguments, class, and |
1067 // source location. | 1067 // source location. |
1068 __ Drop(4); | 1068 __ Drop(4); |
1069 __ popl(result); // Pop new instance. | 1069 __ popl(result); // Pop new instance. |
1070 } | 1070 } |
1071 | 1071 |
1072 | 1072 |
1073 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1073 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
1074 return LocationSummary::Make(1, Location::RequiresRegister()); | 1074 return LocationSummary::Make(1, Location::RequiresRegister()); |
1075 } | 1075 } |
1076 | 1076 |
1077 | 1077 |
1078 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1078 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1079 Register instance_reg = locs()->in(0).reg(); | 1079 Register instance_reg = locs()->in(0).reg(); |
1080 Register result_reg = locs()->out().reg(); | 1080 Register result_reg = locs()->out().reg(); |
1081 if (HasICData()) { | 1081 if (HasICData()) { |
1082 ASSERT(original() != NULL); | 1082 ASSERT(original() != NULL); |
1083 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1083 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
1084 original()->token_index(), | 1084 original()->token_pos(), |
1085 original()->try_index(), | 1085 original()->try_index(), |
1086 kDeoptInstanceGetterSameTarget, | 1086 kDeoptInstanceGetterSameTarget, |
1087 instance_reg); | 1087 instance_reg); |
1088 // Smis do not have instance fields (Smi class is always first). | 1088 // Smis do not have instance fields (Smi class is always first). |
1089 // Use 'result' as temporary register. | 1089 // Use 'result' as temporary register. |
1090 ASSERT(result_reg != instance_reg); | 1090 ASSERT(result_reg != instance_reg); |
1091 ASSERT(ic_data() != NULL); | 1091 ASSERT(ic_data() != NULL); |
1092 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1092 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
1093 } | 1093 } |
1094 | 1094 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1141 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
1142 Immediate(Smi::RawValue(len))); | 1142 Immediate(Smi::RawValue(len))); |
1143 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1143 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
1144 __ Bind(&type_arguments_uninstantiated); | 1144 __ Bind(&type_arguments_uninstantiated); |
1145 } | 1145 } |
1146 // A runtime call to instantiate the type arguments is required. | 1146 // A runtime call to instantiate the type arguments is required. |
1147 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1147 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1148 __ PushObject(type_arguments()); | 1148 __ PushObject(type_arguments()); |
1149 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1149 __ pushl(instantiator_reg); // Push instantiator type arguments. |
1150 compiler->GenerateCallRuntime(cid(), | 1150 compiler->GenerateCallRuntime(cid(), |
1151 token_index(), | 1151 token_pos(), |
1152 try_index(), | 1152 try_index(), |
1153 kInstantiateTypeArgumentsRuntimeEntry); | 1153 kInstantiateTypeArgumentsRuntimeEntry); |
1154 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1154 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
1155 __ popl(result_reg); // Pop instantiated type arguments. | 1155 __ popl(result_reg); // Pop instantiated type arguments. |
1156 __ Bind(&type_arguments_instantiated); | 1156 __ Bind(&type_arguments_instantiated); |
1157 ASSERT(instantiator_reg == result_reg); | 1157 ASSERT(instantiator_reg == result_reg); |
1158 // 'result_reg': Instantiated type arguments. | 1158 // 'result_reg': Instantiated type arguments. |
1159 } | 1159 } |
1160 | 1160 |
1161 | 1161 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1295 } | 1295 } |
1296 | 1296 |
1297 | 1297 |
1298 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1298 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1299 ASSERT(locs()->temp(0).reg() == EDX); | 1299 ASSERT(locs()->temp(0).reg() == EDX); |
1300 ASSERT(locs()->out().reg() == EAX); | 1300 ASSERT(locs()->out().reg() == EAX); |
1301 | 1301 |
1302 __ movl(EDX, Immediate(num_context_variables())); | 1302 __ movl(EDX, Immediate(num_context_variables())); |
1303 const ExternalLabel label("alloc_context", | 1303 const ExternalLabel label("alloc_context", |
1304 StubCode::AllocateContextEntryPoint()); | 1304 StubCode::AllocateContextEntryPoint()); |
1305 compiler->GenerateCall(token_index(), | 1305 compiler->GenerateCall(token_pos(), |
1306 try_index(), | 1306 try_index(), |
1307 &label, | 1307 &label, |
1308 PcDescriptors::kOther); | 1308 PcDescriptors::kOther); |
1309 } | 1309 } |
1310 | 1310 |
1311 | 1311 |
1312 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1312 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
1313 return LocationSummary::Make(1, | 1313 return LocationSummary::Make(1, |
1314 Location::RequiresRegister(), | 1314 Location::RequiresRegister(), |
1315 LocationSummary::kCall); | 1315 LocationSummary::kCall); |
1316 } | 1316 } |
1317 | 1317 |
1318 | 1318 |
1319 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1319 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1320 Register context_value = locs()->in(0).reg(); | 1320 Register context_value = locs()->in(0).reg(); |
1321 Register result = locs()->out().reg(); | 1321 Register result = locs()->out().reg(); |
1322 | 1322 |
1323 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1323 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
1324 __ pushl(context_value); | 1324 __ pushl(context_value); |
1325 compiler->GenerateCallRuntime(cid(), | 1325 compiler->GenerateCallRuntime(cid(), |
1326 token_index(), | 1326 token_pos(), |
1327 try_index(), | 1327 try_index(), |
1328 kCloneContextRuntimeEntry); | 1328 kCloneContextRuntimeEntry); |
1329 __ popl(result); // Remove argument. | 1329 __ popl(result); // Remove argument. |
1330 __ popl(result); // Get result (cloned context). | 1330 __ popl(result); // Get result (cloned context). |
1331 } | 1331 } |
1332 | 1332 |
1333 | 1333 |
1334 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1334 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
1335 return LocationSummary::Make(0, Location::NoLocation()); | 1335 return LocationSummary::Make(0, Location::NoLocation()); |
1336 } | 1336 } |
(...skipping 25 matching lines...) Expand all Loading... |
1362 LocationSummary::kCall); | 1362 LocationSummary::kCall); |
1363 } | 1363 } |
1364 | 1364 |
1365 | 1365 |
1366 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1366 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1367 __ cmpl(ESP, | 1367 __ cmpl(ESP, |
1368 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1368 Address::Absolute(Isolate::Current()->stack_limit_address())); |
1369 Label no_stack_overflow; | 1369 Label no_stack_overflow; |
1370 __ j(ABOVE, &no_stack_overflow); | 1370 __ j(ABOVE, &no_stack_overflow); |
1371 compiler->GenerateCallRuntime(cid(), | 1371 compiler->GenerateCallRuntime(cid(), |
1372 token_index(), | 1372 token_pos(), |
1373 try_index(), | 1373 try_index(), |
1374 kStackOverflowRuntimeEntry); | 1374 kStackOverflowRuntimeEntry); |
1375 __ Bind(&no_stack_overflow); | 1375 __ Bind(&no_stack_overflow); |
1376 } | 1376 } |
1377 | 1377 |
1378 | 1378 |
1379 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1379 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
1380 const intptr_t kNumInputs = 2; | 1380 const intptr_t kNumInputs = 2; |
1381 | 1381 |
1382 if (operands_type() == kDoubleOperands) { | 1382 if (operands_type() == kDoubleOperands) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 } | 1439 } |
1440 | 1440 |
1441 | 1441 |
1442 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1442 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
1443 Register left = comp->locs()->in(0).reg(); | 1443 Register left = comp->locs()->in(0).reg(); |
1444 Register right = comp->locs()->in(1).reg(); | 1444 Register right = comp->locs()->in(1).reg(); |
1445 Register result = comp->locs()->out().reg(); | 1445 Register result = comp->locs()->out().reg(); |
1446 Register temp = comp->locs()->temp(0).reg(); | 1446 Register temp = comp->locs()->temp(0).reg(); |
1447 ASSERT(left == result); | 1447 ASSERT(left == result); |
1448 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1448 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1449 comp->instance_call()->token_index(), | 1449 comp->instance_call()->token_pos(), |
1450 comp->instance_call()->try_index(), | 1450 comp->instance_call()->try_index(), |
1451 kDeoptSmiBinaryOp, | 1451 kDeoptSmiBinaryOp, |
1452 temp, | 1452 temp, |
1453 right); | 1453 right); |
1454 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1454 // TODO(vegorov): for many binary operations this pattern can be rearranged |
1455 // to save one move. | 1455 // to save one move. |
1456 __ movl(temp, left); | 1456 __ movl(temp, left); |
1457 __ orl(left, right); | 1457 __ orl(left, right); |
1458 __ testl(left, Immediate(kSmiTagMask)); | 1458 __ testl(left, Immediate(kSmiTagMask)); |
1459 __ j(NOT_ZERO, deopt); | 1459 __ j(NOT_ZERO, deopt); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1550 __ jmp(&done); | 1550 __ jmp(&done); |
1551 { | 1551 { |
1552 __ Bind(&call_method); | 1552 __ Bind(&call_method); |
1553 Function& target = Function::ZoneHandle( | 1553 Function& target = Function::ZoneHandle( |
1554 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1554 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1555 ASSERT(!target.IsNull()); | 1555 ASSERT(!target.IsNull()); |
1556 const intptr_t kArgumentCount = 2; | 1556 const intptr_t kArgumentCount = 2; |
1557 __ pushl(temp); | 1557 __ pushl(temp); |
1558 __ pushl(right); | 1558 __ pushl(right); |
1559 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1559 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1560 comp->instance_call()->token_index(), | 1560 comp->instance_call()->token_pos(), |
1561 comp->instance_call()->try_index(), | 1561 comp->instance_call()->try_index(), |
1562 target, | 1562 target, |
1563 kArgumentCount, | 1563 kArgumentCount, |
1564 Array::Handle()); // No argument names. | 1564 Array::Handle()); // No argument names. |
1565 ASSERT(result == EAX); | 1565 ASSERT(result == EAX); |
1566 } | 1566 } |
1567 __ Bind(&done); | 1567 __ Bind(&done); |
1568 break; | 1568 break; |
1569 } | 1569 } |
1570 case Token::kDIV: { | 1570 case Token::kDIV: { |
(...skipping 26 matching lines...) Expand all Loading... |
1597 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1597 // receiver and a Mint or Smi argument. We fall back to the run time call if |
1598 // both receiver and argument are Mint or if one of them is Mint and the other | 1598 // both receiver and argument are Mint or if one of them is Mint and the other |
1599 // is a negative Smi. | 1599 // is a negative Smi. |
1600 Register left = comp->locs()->in(0).reg(); | 1600 Register left = comp->locs()->in(0).reg(); |
1601 Register right = comp->locs()->in(1).reg(); | 1601 Register right = comp->locs()->in(1).reg(); |
1602 Register result = comp->locs()->out().reg(); | 1602 Register result = comp->locs()->out().reg(); |
1603 Register temp = comp->locs()->temp(0).reg(); | 1603 Register temp = comp->locs()->temp(0).reg(); |
1604 ASSERT(left == result); | 1604 ASSERT(left == result); |
1605 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1605 ASSERT(comp->op_kind() == Token::kBIT_AND); |
1606 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1606 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1607 comp->instance_call()->token_index(), | 1607 comp->instance_call()->token_pos(), |
1608 comp->instance_call()->try_index(), | 1608 comp->instance_call()->try_index(), |
1609 kDeoptMintBinaryOp, | 1609 kDeoptMintBinaryOp, |
1610 left, | 1610 left, |
1611 right); | 1611 right); |
1612 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1612 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
1613 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1613 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
1614 __ j(NOT_ZERO, &non_smi); | 1614 __ j(NOT_ZERO, &non_smi); |
1615 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1615 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
1616 __ j(ZERO, &smi_smi); | 1616 __ j(ZERO, &smi_smi); |
1617 __ CompareClassId(right, kMint, temp); // Is argument Mint? | 1617 __ CompareClassId(right, kMint, temp); // Is argument Mint? |
(...skipping 27 matching lines...) Expand all Loading... |
1645 __ Bind(&smi_static_call); | 1645 __ Bind(&smi_static_call); |
1646 { | 1646 { |
1647 Function& target = Function::ZoneHandle( | 1647 Function& target = Function::ZoneHandle( |
1648 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1648 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
1649 if (target.IsNull()) { | 1649 if (target.IsNull()) { |
1650 __ jmp(deopt); | 1650 __ jmp(deopt); |
1651 } else { | 1651 } else { |
1652 __ pushl(left); | 1652 __ pushl(left); |
1653 __ pushl(right); | 1653 __ pushl(right); |
1654 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1654 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1655 comp->instance_call()->token_index(), | 1655 comp->instance_call()->token_pos(), |
1656 comp->instance_call()->try_index(), | 1656 comp->instance_call()->try_index(), |
1657 target, | 1657 target, |
1658 comp->instance_call()->ArgumentCount(), | 1658 comp->instance_call()->ArgumentCount(), |
1659 comp->instance_call()->argument_names()); | 1659 comp->instance_call()->argument_names()); |
1660 ASSERT(result == EAX); | 1660 ASSERT(result == EAX); |
1661 __ jmp(&done); | 1661 __ jmp(&done); |
1662 } | 1662 } |
1663 } | 1663 } |
1664 | 1664 |
1665 __ Bind(&mint_static_call); | 1665 __ Bind(&mint_static_call); |
1666 { | 1666 { |
1667 Function& target = Function::ZoneHandle( | 1667 Function& target = Function::ZoneHandle( |
1668 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1668 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
1669 if (target.IsNull()) { | 1669 if (target.IsNull()) { |
1670 __ jmp(deopt); | 1670 __ jmp(deopt); |
1671 } else { | 1671 } else { |
1672 __ pushl(left); | 1672 __ pushl(left); |
1673 __ pushl(right); | 1673 __ pushl(right); |
1674 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1674 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
1675 comp->instance_call()->token_index(), | 1675 comp->instance_call()->token_pos(), |
1676 comp->instance_call()->try_index(), | 1676 comp->instance_call()->try_index(), |
1677 target, | 1677 target, |
1678 comp->instance_call()->ArgumentCount(), | 1678 comp->instance_call()->ArgumentCount(), |
1679 comp->instance_call()->argument_names()); | 1679 comp->instance_call()->argument_names()); |
1680 ASSERT(result == EAX); | 1680 ASSERT(result == EAX); |
1681 } | 1681 } |
1682 } | 1682 } |
1683 __ Bind(&done); | 1683 __ Bind(&done); |
1684 } | 1684 } |
1685 | 1685 |
1686 | 1686 |
1687 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1687 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
1688 BinaryOpComp* comp) { | 1688 BinaryOpComp* comp) { |
1689 Register left = EBX; | 1689 Register left = EBX; |
1690 Register right = ECX; | 1690 Register right = ECX; |
1691 Register temp = EDX; | 1691 Register temp = EDX; |
1692 Register result = comp->locs()->out().reg(); | 1692 Register result = comp->locs()->out().reg(); |
1693 | 1693 |
1694 const Class& double_class = compiler->double_class(); | 1694 const Class& double_class = compiler->double_class(); |
1695 const Code& stub = | 1695 const Code& stub = |
1696 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1696 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1697 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1697 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1698 compiler->GenerateCall(comp->instance_call()->token_index(), | 1698 compiler->GenerateCall(comp->instance_call()->token_pos(), |
1699 comp->instance_call()->try_index(), | 1699 comp->instance_call()->try_index(), |
1700 &label, | 1700 &label, |
1701 PcDescriptors::kOther); | 1701 PcDescriptors::kOther); |
1702 // Newly allocated object is now in the result register (RAX). | 1702 // Newly allocated object is now in the result register (RAX). |
1703 ASSERT(result == EAX); | 1703 ASSERT(result == EAX); |
1704 __ popl(right); | 1704 __ popl(right); |
1705 __ popl(left); | 1705 __ popl(left); |
1706 | 1706 |
1707 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1707 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
1708 comp->instance_call()->token_index(), | 1708 comp->instance_call()->token_pos(), |
1709 comp->instance_call()->try_index(), | 1709 comp->instance_call()->try_index(), |
1710 kDeoptDoubleBinaryOp, | 1710 kDeoptDoubleBinaryOp, |
1711 left, | 1711 left, |
1712 right); | 1712 right); |
1713 | 1713 |
1714 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1714 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
1715 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1715 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
1716 | 1716 |
1717 switch (comp->op_kind()) { | 1717 switch (comp->op_kind()) { |
1718 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1718 case Token::kADD: __ addsd(XMM0, XMM1); break; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 // TODO(srdjan): Implement for more checks. | 1763 // TODO(srdjan): Implement for more checks. |
1764 ASSERT(ic_data.NumberOfChecks() == 1); | 1764 ASSERT(ic_data.NumberOfChecks() == 1); |
1765 intptr_t test_class_id; | 1765 intptr_t test_class_id; |
1766 Function& target = Function::Handle(); | 1766 Function& target = Function::Handle(); |
1767 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1767 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1768 | 1768 |
1769 Register value = locs()->in(0).reg(); | 1769 Register value = locs()->in(0).reg(); |
1770 Register result = locs()->out().reg(); | 1770 Register result = locs()->out().reg(); |
1771 ASSERT(value == result); | 1771 ASSERT(value == result); |
1772 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1772 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1773 instance_call()->token_index(), | 1773 instance_call()->token_pos(), |
1774 instance_call()->try_index(), | 1774 instance_call()->try_index(), |
1775 kDeoptUnaryOp, | 1775 kDeoptUnaryOp, |
1776 value); | 1776 value); |
1777 if (test_class_id == kSmi) { | 1777 if (test_class_id == kSmi) { |
1778 __ testl(value, Immediate(kSmiTagMask)); | 1778 __ testl(value, Immediate(kSmiTagMask)); |
1779 __ j(NOT_ZERO, deopt); | 1779 __ j(NOT_ZERO, deopt); |
1780 switch (op_kind()) { | 1780 switch (op_kind()) { |
1781 case Token::kNEGATE: | 1781 case Token::kNEGATE: |
1782 __ negl(value); | 1782 __ negl(value); |
1783 __ j(OVERFLOW, deopt); | 1783 __ j(OVERFLOW, deopt); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 // TODO(srdjan): Implement for more checks. | 1816 // TODO(srdjan): Implement for more checks. |
1817 ASSERT(ic_data.NumberOfChecks() == 1); | 1817 ASSERT(ic_data.NumberOfChecks() == 1); |
1818 intptr_t test_class_id; | 1818 intptr_t test_class_id; |
1819 Function& target = Function::Handle(); | 1819 Function& target = Function::Handle(); |
1820 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1820 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
1821 | 1821 |
1822 Register value = locs()->in(0).reg(); | 1822 Register value = locs()->in(0).reg(); |
1823 Register result = locs()->out().reg(); | 1823 Register result = locs()->out().reg(); |
1824 ASSERT(value == result); | 1824 ASSERT(value == result); |
1825 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1825 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1826 instance_call()->token_index(), | 1826 instance_call()->token_pos(), |
1827 instance_call()->try_index(), | 1827 instance_call()->try_index(), |
1828 kDeoptUnaryOp, | 1828 kDeoptUnaryOp, |
1829 value); | 1829 value); |
1830 if (test_class_id == kDouble) { | 1830 if (test_class_id == kDouble) { |
1831 Register temp = locs()->temp(0).reg(); | 1831 Register temp = locs()->temp(0).reg(); |
1832 __ testl(value, Immediate(kSmiTagMask)); | 1832 __ testl(value, Immediate(kSmiTagMask)); |
1833 __ j(ZERO, deopt); // Smi. | 1833 __ j(ZERO, deopt); // Smi. |
1834 __ CompareClassId(value, kDouble, temp); | 1834 __ CompareClassId(value, kDouble, temp); |
1835 __ j(NOT_EQUAL, deopt); | 1835 __ j(NOT_EQUAL, deopt); |
1836 // Allocate result object. | 1836 // Allocate result object. |
1837 const Class& double_class = compiler->double_class(); | 1837 const Class& double_class = compiler->double_class(); |
1838 const Code& stub = | 1838 const Code& stub = |
1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1841 __ pushl(value); | 1841 __ pushl(value); |
1842 compiler->GenerateCall(instance_call()->token_index(), | 1842 compiler->GenerateCall(instance_call()->token_pos(), |
1843 instance_call()->try_index(), | 1843 instance_call()->try_index(), |
1844 &label, | 1844 &label, |
1845 PcDescriptors::kOther); | 1845 PcDescriptors::kOther); |
1846 // Result is in EAX. | 1846 // Result is in EAX. |
1847 ASSERT(result != temp); | 1847 ASSERT(result != temp); |
1848 __ movl(result, EAX); | 1848 __ movl(result, EAX); |
1849 __ popl(temp); | 1849 __ popl(temp); |
1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
1851 __ DoubleNegate(XMM0); | 1851 __ DoubleNegate(XMM0); |
1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
(...skipping 20 matching lines...) Expand all Loading... |
1873 } | 1873 } |
1874 | 1874 |
1875 | 1875 |
1876 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1876 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1877 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | 1877 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; |
1878 Register result = locs()->out().reg(); | 1878 Register result = locs()->out().reg(); |
1879 | 1879 |
1880 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1880 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
1881 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1881 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
1882 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1882 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1883 instance_call()->token_index(), | 1883 instance_call()->token_pos(), |
1884 instance_call()->try_index(), | 1884 instance_call()->try_index(), |
1885 deopt_reason, | 1885 deopt_reason, |
1886 value); | 1886 value); |
1887 | 1887 |
1888 if (from() == kDouble) { | 1888 if (from() == kDouble) { |
1889 Register temp = locs()->temp(0).reg(); | 1889 Register temp = locs()->temp(0).reg(); |
1890 __ testl(value, Immediate(kSmiTagMask)); | 1890 __ testl(value, Immediate(kSmiTagMask)); |
1891 __ j(ZERO, deopt); // Deoptimize if Smi. | 1891 __ j(ZERO, deopt); // Deoptimize if Smi. |
1892 __ CompareClassId(value, kDouble, temp); | 1892 __ CompareClassId(value, kDouble, temp); |
1893 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1893 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
1894 ASSERT(value == result); | 1894 ASSERT(value == result); |
1895 return; | 1895 return; |
1896 } | 1896 } |
1897 | 1897 |
1898 ASSERT(from() == kSmi); | 1898 ASSERT(from() == kSmi); |
1899 | 1899 |
1900 const Class& double_class = compiler->double_class(); | 1900 const Class& double_class = compiler->double_class(); |
1901 const Code& stub = | 1901 const Code& stub = |
1902 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1902 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
1903 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1903 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
1904 | 1904 |
1905 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1905 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
1906 compiler->GenerateCall(instance_call()->token_index(), | 1906 compiler->GenerateCall(instance_call()->token_pos(), |
1907 instance_call()->try_index(), | 1907 instance_call()->try_index(), |
1908 &label, | 1908 &label, |
1909 PcDescriptors::kOther); | 1909 PcDescriptors::kOther); |
1910 ASSERT(result == EAX); | 1910 ASSERT(result == EAX); |
1911 __ popl(value); | 1911 __ popl(value); |
1912 | 1912 |
1913 __ testl(value, Immediate(kSmiTagMask)); | 1913 __ testl(value, Immediate(kSmiTagMask)); |
1914 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1914 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
1915 __ SmiUntag(value); | 1915 __ SmiUntag(value); |
1916 __ cvtsi2sd(XMM0, value); | 1916 __ cvtsi2sd(XMM0, value); |
1917 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1917 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
1918 } | 1918 } |
1919 | 1919 |
1920 | 1920 |
1921 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1921 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
1922 return MakeCallSummary(); | 1922 return MakeCallSummary(); |
1923 } | 1923 } |
1924 | 1924 |
1925 | 1925 |
1926 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1926 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
1927 ASSERT(instance_call()->VerifyComputation()); | 1927 ASSERT(instance_call()->VerifyComputation()); |
1928 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1928 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
1929 instance_call()->token_index(), | 1929 instance_call()->token_pos(), |
1930 instance_call()->try_index(), | 1930 instance_call()->try_index(), |
1931 kDeoptPolymorphicInstanceCallTestFail); | 1931 kDeoptPolymorphicInstanceCallTestFail); |
1932 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1932 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
1933 __ jmp(deopt); | 1933 __ jmp(deopt); |
1934 return; | 1934 return; |
1935 } | 1935 } |
1936 ASSERT(HasICData()); | 1936 ASSERT(HasICData()); |
1937 ASSERT(ic_data()->num_args_tested() == 1); | 1937 ASSERT(ic_data()->num_args_tested() == 1); |
1938 Label handle_smi; | 1938 Label handle_smi; |
1939 Label* is_smi_label = | 1939 Label* is_smi_label = |
1940 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1940 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
1941 | 1941 |
1942 // Load receiver into EAX. | 1942 // Load receiver into EAX. |
1943 __ movl(EAX, | 1943 __ movl(EAX, |
1944 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1944 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
1945 __ testl(EAX, Immediate(kSmiTagMask)); | 1945 __ testl(EAX, Immediate(kSmiTagMask)); |
1946 __ j(ZERO, is_smi_label); | 1946 __ j(ZERO, is_smi_label); |
1947 Label done; | 1947 Label done; |
1948 __ LoadClassId(EDI, EAX); | 1948 __ LoadClassId(EDI, EAX); |
1949 compiler->EmitTestAndCall(*ic_data(), | 1949 compiler->EmitTestAndCall(*ic_data(), |
1950 EDI, // Class id register. | 1950 EDI, // Class id register. |
1951 instance_call()->ArgumentCount(), | 1951 instance_call()->ArgumentCount(), |
1952 instance_call()->argument_names(), | 1952 instance_call()->argument_names(), |
1953 deopt, &done, // Labels. | 1953 deopt, &done, // Labels. |
1954 instance_call()->cid(), | 1954 instance_call()->cid(), |
1955 instance_call()->token_index(), | 1955 instance_call()->token_pos(), |
1956 instance_call()->try_index()); | 1956 instance_call()->try_index()); |
1957 if (is_smi_label == &handle_smi) { | 1957 if (is_smi_label == &handle_smi) { |
1958 __ Bind(&handle_smi); | 1958 __ Bind(&handle_smi); |
1959 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1959 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
1960 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1960 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
1961 compiler->GenerateStaticCall(instance_call()->cid(), | 1961 compiler->GenerateStaticCall(instance_call()->cid(), |
1962 instance_call()->token_index(), | 1962 instance_call()->token_pos(), |
1963 instance_call()->try_index(), | 1963 instance_call()->try_index(), |
1964 target, | 1964 target, |
1965 instance_call()->ArgumentCount(), | 1965 instance_call()->ArgumentCount(), |
1966 instance_call()->argument_names()); | 1966 instance_call()->argument_names()); |
1967 } | 1967 } |
1968 __ Bind(&done); | 1968 __ Bind(&done); |
1969 } | 1969 } |
1970 | 1970 |
1971 } // namespace dart | 1971 } // namespace dart |
1972 | 1972 |
1973 #undef __ | 1973 #undef __ |
1974 | 1974 |
1975 #endif // defined TARGET_ARCH_X64 | 1975 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |