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

Side by Side Diff: runtime/vm/intermediate_language_x64.cc

Issue 10832150: Get rid of ast node ids. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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
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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 __ Bind(&not_yet_hot); 81 __ Bind(&not_yet_hot);
82 __ Bind(&already_optimized); 82 __ Bind(&already_optimized);
83 } 83 }
84 } 84 }
85 if (FLAG_trace_functions) { 85 if (FLAG_trace_functions) {
86 const Function& function = 86 const Function& function =
87 Function::ZoneHandle(compiler->parsed_function().function().raw()); 87 Function::ZoneHandle(compiler->parsed_function().function().raw());
88 __ LoadObject(temp, function); 88 __ LoadObject(temp, function);
89 __ pushq(result); // Preserve result. 89 __ pushq(result); // Preserve result.
90 __ pushq(temp); 90 __ pushq(temp);
91 compiler->GenerateCallRuntime(AstNode::kNoId, 91 compiler->GenerateCallRuntime(Isolate::kNoDeoptId,
92 0, 92 0,
93 CatchClauseNode::kInvalidTryIndex, 93 CatchClauseNode::kInvalidTryIndex,
94 kTraceFunctionExitRuntimeEntry); 94 kTraceFunctionExitRuntimeEntry);
95 __ popq(temp); // Remove argument. 95 __ popq(temp); // Remove argument.
96 __ popq(result); // Restore result. 96 __ popq(result); // Restore result.
97 } 97 }
98 __ LeaveFrame(); 98 __ LeaveFrame();
99 __ ret(); 99 __ ret();
100 100
101 // Generate 8 bytes of NOPs so that the debugger can patch the 101 // Generate 8 bytes of NOPs so that the debugger can patch the
102 // return pattern with a call to the debug stub. 102 // return pattern with a call to the debug stub.
103 // Note that the nop(8) byte pattern is not recognized by the debugger. 103 // Note that the nop(8) byte pattern is not recognized by the debugger.
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 __ nop(1); 108 __ nop(1);
109 __ nop(1); 109 __ nop(1);
110 __ nop(1); 110 __ nop(1);
111 __ nop(1); 111 __ nop(1);
112 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 112 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
113 cid(), 113 deopt_id(),
114 token_pos(), 114 token_pos(),
115 CatchClauseNode::kInvalidTryIndex); 115 CatchClauseNode::kInvalidTryIndex);
116 } 116 }
117 117
118 118
119 LocationSummary* ClosureCallComp::MakeLocationSummary() const { 119 LocationSummary* ClosureCallComp::MakeLocationSummary() const {
120 const intptr_t kNumInputs = 0; 120 const intptr_t kNumInputs = 0;
121 const intptr_t kNumTemps = 1; 121 const intptr_t kNumTemps = 1;
122 LocationSummary* result = 122 LocationSummary* result =
123 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 123 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 198
199 // Check that the type of the value is allowed in conditional context. 199 // Check that the type of the value is allowed in conditional context.
200 // Call the runtime if the object is not bool::true or bool::false. 200 // Call the runtime if the object is not bool::true or bool::false.
201 Label done; 201 Label done;
202 __ CompareObject(obj, compiler->bool_true()); 202 __ CompareObject(obj, compiler->bool_true());
203 __ j(EQUAL, &done, Assembler::kNearJump); 203 __ j(EQUAL, &done, Assembler::kNearJump);
204 __ CompareObject(obj, compiler->bool_false()); 204 __ CompareObject(obj, compiler->bool_false());
205 __ j(EQUAL, &done, Assembler::kNearJump); 205 __ j(EQUAL, &done, Assembler::kNearJump);
206 206
207 __ pushq(obj); // Push the source object. 207 __ pushq(obj); // Push the source object.
208 compiler->GenerateCallRuntime(cid(), 208 compiler->GenerateCallRuntime(deopt_id(),
209 token_pos(), 209 token_pos(),
210 try_index(), 210 try_index(),
211 kConditionTypeErrorRuntimeEntry); 211 kConditionTypeErrorRuntimeEntry);
212 // We should never return here. 212 // We should never return here.
213 __ int3(); 213 __ int3();
214 214
215 __ Bind(&done); 215 __ Bind(&done);
216 ASSERT(obj == result); 216 ASSERT(obj == result);
217 } 217 }
218 218
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 268 }
269 269
270 270
271 // Optional integer arguments can often be null. Null is not collected 271 // Optional integer arguments can often be null. Null is not collected
272 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well? 272 // by IC data. TODO(srdjan): Shall we collect null classes in ICData as well?
273 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, 273 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler,
274 EqualityCompareComp* comp) { 274 EqualityCompareComp* comp) {
275 Register left = comp->locs()->in(0).reg(); 275 Register left = comp->locs()->in(0).reg();
276 Register right = comp->locs()->in(1).reg(); 276 Register right = comp->locs()->in(1).reg();
277 Register temp = comp->locs()->temp(0).reg(); 277 Register temp = comp->locs()->temp(0).reg();
278 Label* deopt = compiler->AddDeoptStub(comp->cid(), 278 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
279 comp->token_pos(), 279 comp->token_pos(),
280 comp->try_index(), 280 comp->try_index(),
281 kDeoptSmiCompareSmi, 281 kDeoptSmiCompareSmi,
282 left, 282 left,
283 right); 283 right);
284 __ movq(temp, left); 284 __ movq(temp, left);
285 __ orq(temp, right); 285 __ orq(temp, right);
286 __ testq(temp, Immediate(kSmiTagMask)); 286 __ testq(temp, Immediate(kSmiTagMask));
287 __ j(NOT_ZERO, deopt); 287 __ j(NOT_ZERO, deopt);
288 __ cmpq(left, right); 288 __ cmpq(left, right);
289 Register result = comp->locs()->out().reg(); 289 Register result = comp->locs()->out().reg();
290 Label load_true, done; 290 Label load_true, done;
291 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump); 291 __ j(TokenKindToSmiCondition(comp->kind()), &load_true, Assembler::kNearJump);
292 __ LoadObject(result, compiler->bool_false()); 292 __ LoadObject(result, compiler->bool_false());
293 __ jmp(&done, Assembler::kNearJump); 293 __ jmp(&done, Assembler::kNearJump);
294 __ Bind(&load_true); 294 __ Bind(&load_true);
295 __ LoadObject(result, compiler->bool_true()); 295 __ LoadObject(result, compiler->bool_true());
296 __ Bind(&done); 296 __ Bind(&done);
297 } 297 }
298 298
299 299
300 // TODO(srdjan): Add support for mixed Smi/Double equality 300 // TODO(srdjan): Add support for mixed Smi/Double equality
301 // (see LoadDoubleOrSmiToXmm). 301 // (see LoadDoubleOrSmiToXmm).
302 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler, 302 static void EmitDoubleEqualityCompare(FlowGraphCompiler* compiler,
303 EqualityCompareComp* comp) { 303 EqualityCompareComp* comp) {
304 Register left = comp->locs()->in(0).reg(); 304 Register left = comp->locs()->in(0).reg();
305 Register right = comp->locs()->in(1).reg(); 305 Register right = comp->locs()->in(1).reg();
306 Label* deopt = compiler->AddDeoptStub(comp->cid(), 306 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
307 comp->token_pos(), 307 comp->token_pos(),
308 comp->try_index(), 308 comp->try_index(),
309 kDeoptDoubleCompareDouble, 309 kDeoptDoubleCompareDouble,
310 left, 310 left,
311 right); 311 right);
312 __ CompareClassId(left, kDouble); 312 __ CompareClassId(left, kDouble);
313 __ j(NOT_EQUAL, deopt); 313 __ j(NOT_EQUAL, deopt);
314 __ CompareClassId(right, kDouble); 314 __ CompareClassId(right, kDouble);
315 __ j(NOT_EQUAL, deopt); 315 __ j(NOT_EQUAL, deopt);
316 __ movsd(XMM0, FieldAddress(left, Double::value_offset())); 316 __ movsd(XMM0, FieldAddress(left, Double::value_offset()));
317 __ movsd(XMM1, FieldAddress(right, Double::value_offset())); 317 __ movsd(XMM1, FieldAddress(right, Double::value_offset()));
318 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()), 318 compiler->EmitDoubleCompareBool(TokenKindToSmiCondition(comp->kind()),
319 XMM0, XMM1, 319 XMM0, XMM1,
320 comp->locs()->out().reg()); 320 comp->locs()->out().reg());
321 } 321 }
322 322
323 323
324 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, 324 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler,
325 EqualityCompareComp* comp) { 325 EqualityCompareComp* comp) {
326 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 326 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
327 comp->cid(), 327 comp->deopt_id(),
328 comp->token_pos(), 328 comp->token_pos(),
329 comp->try_index()); 329 comp->try_index());
330 const String& operator_name = String::ZoneHandle(Symbols::New("==")); 330 const String& operator_name = String::ZoneHandle(Symbols::New("=="));
331 const int kNumberOfArguments = 2; 331 const int kNumberOfArguments = 2;
332 const Array& kNoArgumentNames = Array::Handle(); 332 const Array& kNoArgumentNames = Array::Handle();
333 const int kNumArgumentsChecked = 2; 333 const int kNumArgumentsChecked = 2;
334 334
335 compiler->GenerateInstanceCall(comp->cid(), 335 compiler->GenerateInstanceCall(comp->deopt_id(),
336 comp->token_pos(), 336 comp->token_pos(),
337 comp->try_index(), 337 comp->try_index(),
338 operator_name, 338 operator_name,
339 kNumberOfArguments, 339 kNumberOfArguments,
340 kNoArgumentNames, 340 kNoArgumentNames,
341 kNumArgumentsChecked); 341 kNumArgumentsChecked);
342 ASSERT(comp->locs()->out().reg() == RAX); 342 ASSERT(comp->locs()->out().reg() == RAX);
343 if (comp->kind() == Token::kNE) { 343 if (comp->kind() == Token::kNE) {
344 Label done, false_label; 344 Label done, false_label;
345 __ CompareObject(RAX, compiler->bool_true()); 345 __ CompareObject(RAX, compiler->bool_true());
346 __ j(EQUAL, &false_label, Assembler::kNearJump); 346 __ j(EQUAL, &false_label, Assembler::kNearJump);
347 __ LoadObject(RAX, compiler->bool_true()); 347 __ LoadObject(RAX, compiler->bool_true());
348 __ jmp(&done, Assembler::kNearJump); 348 __ jmp(&done, Assembler::kNearJump);
349 __ Bind(&false_label); 349 __ Bind(&false_label);
350 __ LoadObject(RAX, compiler->bool_false()); 350 __ LoadObject(RAX, compiler->bool_false());
351 __ Bind(&done); 351 __ Bind(&done);
352 } 352 }
353 } 353 }
354 354
355 355
356 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, 356 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler,
357 const ICData& orig_ic_data, 357 const ICData& orig_ic_data,
358 const LocationSummary& locs, 358 const LocationSummary& locs,
359 BranchInstr* branch, 359 BranchInstr* branch,
360 Token::Kind kind, 360 Token::Kind kind,
361 intptr_t cid, 361 intptr_t deopt_id,
362 intptr_t token_pos, 362 intptr_t token_pos,
363 intptr_t try_index) { 363 intptr_t try_index) {
364 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 364 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
365 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 365 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
366 ASSERT(ic_data.NumberOfChecks() > 0); 366 ASSERT(ic_data.NumberOfChecks() > 0);
367 ASSERT(ic_data.num_args_tested() == 1); 367 ASSERT(ic_data.num_args_tested() == 1);
368 Label* deopt = compiler->AddDeoptStub(cid, 368 Label* deopt = compiler->AddDeoptStub(deopt_id,
369 token_pos, 369 token_pos,
370 try_index, 370 try_index,
371 kDeoptEquality); 371 kDeoptEquality);
372 Register left = locs.in(0).reg(); 372 Register left = locs.in(0).reg();
373 Register right = locs.in(1).reg(); 373 Register right = locs.in(1).reg();
374 __ testq(left, Immediate(kSmiTagMask)); 374 __ testq(left, Immediate(kSmiTagMask));
375 Register temp = locs.temp(0).reg(); 375 Register temp = locs.temp(0).reg();
376 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { 376 if (ic_data.GetReceiverClassIdAt(0) == kSmi) {
377 Label done, load_class_id; 377 Label done, load_class_id;
378 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); 378 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump);
(...skipping 27 matching lines...) Expand all
406 Label load_true; 406 Label load_true;
407 __ j(cond, &load_true, Assembler::kNearJump); 407 __ j(cond, &load_true, Assembler::kNearJump);
408 __ LoadObject(result, compiler->bool_false()); 408 __ LoadObject(result, compiler->bool_false());
409 __ jmp(&done); 409 __ jmp(&done);
410 __ Bind(&load_true); 410 __ Bind(&load_true);
411 __ LoadObject(result, compiler->bool_true()); 411 __ LoadObject(result, compiler->bool_true());
412 } 412 }
413 } else { 413 } else {
414 const int kNumberOfArguments = 2; 414 const int kNumberOfArguments = 2;
415 const Array& kNoArgumentNames = Array::Handle(); 415 const Array& kNoArgumentNames = Array::Handle();
416 compiler->GenerateStaticCall(cid, 416 compiler->GenerateStaticCall(deopt_id,
417 token_pos, 417 token_pos,
418 try_index, 418 try_index,
419 target, 419 target,
420 kNumberOfArguments, 420 kNumberOfArguments,
421 kNoArgumentNames); 421 kNoArgumentNames);
422 if (branch == NULL) { 422 if (branch == NULL) {
423 if (kind == Token::kNE) { 423 if (kind == Token::kNE) {
424 Label false_label; 424 Label false_label;
425 __ CompareObject(RAX, compiler->bool_true()); 425 __ CompareObject(RAX, compiler->bool_true());
426 __ j(EQUAL, &false_label, Assembler::kNearJump); 426 __ j(EQUAL, &false_label, Assembler::kNearJump);
(...skipping 18 matching lines...) Expand all
445 445
446 446
447 // First test if receiver is NULL, in which case === is applied. 447 // First test if receiver is NULL, in which case === is applied.
448 // If type feedback was provided (lists of <class-id, target>), do a 448 // If type feedback was provided (lists of <class-id, target>), do a
449 // type by type check (either === or static call to the operator. 449 // type by type check (either === or static call to the operator.
450 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, 450 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler,
451 const LocationSummary& locs, 451 const LocationSummary& locs,
452 Token::Kind kind, 452 Token::Kind kind,
453 BranchInstr* branch, 453 BranchInstr* branch,
454 const ICData& ic_data, 454 const ICData& ic_data,
455 intptr_t cid, 455 intptr_t deopt_id,
456 intptr_t token_pos, 456 intptr_t token_pos,
457 intptr_t try_index) { 457 intptr_t try_index) {
458 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 458 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
459 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 459 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
460 Register left = locs.in(0).reg(); 460 Register left = locs.in(0).reg();
461 Register right = locs.in(1).reg(); 461 Register right = locs.in(1).reg();
462 const Immediate raw_null = 462 const Immediate raw_null =
463 Immediate(reinterpret_cast<intptr_t>(Object::null())); 463 Immediate(reinterpret_cast<intptr_t>(Object::null()));
464 Label done, non_null_compare; 464 Label done, non_null_compare;
465 __ cmpq(left, raw_null); 465 __ cmpq(left, raw_null);
(...skipping 10 matching lines...) Expand all
476 __ LoadObject(result, compiler->bool_false()); 476 __ LoadObject(result, compiler->bool_false());
477 __ jmp(&done); 477 __ jmp(&done);
478 __ Bind(&load_true); 478 __ Bind(&load_true);
479 __ LoadObject(result, compiler->bool_true()); 479 __ LoadObject(result, compiler->bool_true());
480 } 480 }
481 __ jmp(&done); 481 __ jmp(&done);
482 __ Bind(&non_null_compare); // Receiver is not null. 482 __ Bind(&non_null_compare); // Receiver is not null.
483 __ pushq(left); 483 __ pushq(left);
484 __ pushq(right); 484 __ pushq(right);
485 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, 485 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind,
486 cid, token_pos, try_index); 486 deopt_id, token_pos, try_index);
487 __ Bind(&done); 487 __ Bind(&done);
488 } 488 }
489 489
490 490
491 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { 491 void EqualityCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) {
492 if (receiver_class_id() == kSmi) { 492 if (receiver_class_id() == kSmi) {
493 EmitSmiEqualityCompare(compiler, this); 493 EmitSmiEqualityCompare(compiler, this);
494 return; 494 return;
495 } 495 }
496 if (receiver_class_id() == kDouble) { 496 if (receiver_class_id() == kDouble) {
497 EmitDoubleEqualityCompare(compiler, this); 497 EmitDoubleEqualityCompare(compiler, this);
498 return; 498 return;
499 } 499 }
500 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 500 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
501 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, 501 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(),
502 *ic_data(), cid(), token_pos(), try_index()); 502 deopt_id(), token_pos(), try_index());
503 } else { 503 } else {
504 Register left = locs()->in(0).reg(); 504 Register left = locs()->in(0).reg();
505 Register right = locs()->in(1).reg(); 505 Register right = locs()->in(1).reg();
506 __ pushq(left); 506 __ pushq(left);
507 __ pushq(right); 507 __ pushq(right);
508 EmitEqualityAsInstanceCall(compiler, this); 508 EmitEqualityAsInstanceCall(compiler, this);
509 } 509 }
510 } 510 }
511 511
512 512
(...skipping 11 matching lines...) Expand all
524 } 524 }
525 ASSERT(operands_class_id() == kObject); 525 ASSERT(operands_class_id() == kObject);
526 return MakeCallSummary(); 526 return MakeCallSummary();
527 } 527 }
528 528
529 529
530 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, 530 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler,
531 const LocationSummary& locs, 531 const LocationSummary& locs,
532 Token::Kind kind, 532 Token::Kind kind,
533 BranchInstr* branch, 533 BranchInstr* branch,
534 intptr_t cid, 534 intptr_t deopt_id,
535 intptr_t token_pos, 535 intptr_t token_pos,
536 intptr_t try_index) { 536 intptr_t try_index) {
537 Register left = locs.in(0).reg(); 537 Register left = locs.in(0).reg();
538 Register right = locs.in(1).reg(); 538 Register right = locs.in(1).reg();
539 Register temp = locs.temp(0).reg(); 539 Register temp = locs.temp(0).reg();
540 Label* deopt = compiler->AddDeoptStub(cid, 540 Label* deopt = compiler->AddDeoptStub(deopt_id,
541 token_pos, 541 token_pos,
542 try_index, 542 try_index,
543 kDeoptSmiCompareSmi, 543 kDeoptSmiCompareSmi,
544 left, 544 left,
545 right); 545 right);
546 __ movq(temp, left); 546 __ movq(temp, left);
547 __ orq(temp, right); 547 __ orq(temp, right);
548 __ testq(temp, Immediate(kSmiTagMask)); 548 __ testq(temp, Immediate(kSmiTagMask));
549 __ j(NOT_ZERO, deopt); 549 __ j(NOT_ZERO, deopt);
550 550
(...skipping 27 matching lines...) Expand all
578 UNREACHABLE(); 578 UNREACHABLE();
579 return OVERFLOW; 579 return OVERFLOW;
580 } 580 }
581 } 581 }
582 582
583 583
584 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler, 584 static void EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
585 const LocationSummary& locs, 585 const LocationSummary& locs,
586 Token::Kind kind, 586 Token::Kind kind,
587 BranchInstr* branch, 587 BranchInstr* branch,
588 intptr_t cid, 588 intptr_t deopt_id,
589 intptr_t token_pos, 589 intptr_t token_pos,
590 intptr_t try_index) { 590 intptr_t try_index) {
591 Register left = locs.in(0).reg(); 591 Register left = locs.in(0).reg();
592 Register right = locs.in(1).reg(); 592 Register right = locs.in(1).reg();
593 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. 593 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs.
594 Register temp = locs.temp(0).reg(); 594 Register temp = locs.temp(0).reg();
595 Label* deopt = compiler->AddDeoptStub(cid, 595 Label* deopt = compiler->AddDeoptStub(deopt_id,
596 token_pos, 596 token_pos,
597 try_index, 597 try_index,
598 kDeoptDoubleComparison, 598 kDeoptDoubleComparison,
599 left, 599 left,
600 right); 600 right);
601 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 601 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
602 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 602 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
603 603
604 Condition true_condition = TokenKindToDoubleCondition(kind); 604 Condition true_condition = TokenKindToDoubleCondition(kind);
605 if (branch != NULL) { 605 if (branch != NULL) {
606 compiler->EmitDoubleCompareBranch( 606 compiler->EmitDoubleCompareBranch(
607 true_condition, XMM0, XMM1, branch); 607 true_condition, XMM0, XMM1, branch);
608 } else { 608 } else {
609 compiler->EmitDoubleCompareBool( 609 compiler->EmitDoubleCompareBool(
610 true_condition, XMM0, XMM1, locs.out().reg()); 610 true_condition, XMM0, XMM1, locs.out().reg());
611 } 611 }
612 } 612 }
613 613
614 614
615 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { 615 void RelationalOpComp::EmitNativeCode(FlowGraphCompiler* compiler) {
616 if (operands_class_id() == kSmi) { 616 if (operands_class_id() == kSmi) {
617 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL, 617 EmitSmiComparisonOp(compiler, *locs(), kind(), NULL,
618 cid(), token_pos(), try_index()); 618 deopt_id(), token_pos(), try_index());
619 return; 619 return;
620 } 620 }
621 if (operands_class_id() == kDouble) { 621 if (operands_class_id() == kDouble) {
622 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL, 622 EmitDoubleComparisonOp(compiler, *locs(), kind(), NULL,
623 cid(), token_pos(), try_index()); 623 deopt_id(), token_pos(), try_index());
624 return; 624 return;
625 } 625 }
626 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 626 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
627 Label* deopt = compiler->AddDeoptStub(cid(), 627 Label* deopt = compiler->AddDeoptStub(deopt_id(),
628 token_pos(), 628 token_pos(),
629 try_index(), 629 try_index(),
630 kDeoptRelationalOp); 630 kDeoptRelationalOp);
631 // Load receiver into RAX, class into RDI. 631 // Load receiver into RAX, class into RDI.
632 Label done; 632 Label done;
633 const intptr_t kNumArguments = 2; 633 const intptr_t kNumArguments = 2;
634 __ movq(RDI, Immediate(kSmi)); 634 __ movq(RDI, Immediate(kSmi));
635 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); 635 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize));
636 __ testq(RAX, Immediate(kSmiTagMask)); 636 __ testq(RAX, Immediate(kSmiTagMask));
637 __ j(ZERO, &done); 637 __ j(ZERO, &done);
638 __ LoadClassId(RDI, RAX); 638 __ LoadClassId(RDI, RAX);
639 __ Bind(&done); 639 __ Bind(&done);
640 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), 640 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()),
641 RDI, // Class id register. 641 RDI, // Class id register.
642 kNumArguments, 642 kNumArguments,
643 Array::Handle(), // No named arguments. 643 Array::Handle(), // No named arguments.
644 deopt, // Deoptimize target. 644 deopt, // Deoptimize target.
645 NULL, // Fallthrough when done. 645 NULL, // Fallthrough when done.
646 cid(), 646 deopt_id(),
647 token_pos(), 647 token_pos(),
648 try_index()); 648 try_index());
649 return; 649 return;
650 } 650 }
651 const String& function_name = 651 const String& function_name =
652 String::ZoneHandle(Symbols::New(Token::Str(kind()))); 652 String::ZoneHandle(Symbols::New(Token::Str(kind())));
653 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 653 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
654 cid(), 654 deopt_id(),
655 token_pos(), 655 token_pos(),
656 try_index()); 656 try_index());
657 const intptr_t kNumArguments = 2; 657 const intptr_t kNumArguments = 2;
658 const intptr_t kNumArgsChecked = 2; // Type-feedback. 658 const intptr_t kNumArgsChecked = 2; // Type-feedback.
659 compiler->GenerateInstanceCall(cid(), 659 compiler->GenerateInstanceCall(deopt_id(),
660 token_pos(), 660 token_pos(),
661 try_index(), 661 try_index(),
662 function_name, 662 function_name,
663 kNumArguments, 663 kNumArguments,
664 Array::ZoneHandle(), // No optional arguments. 664 Array::ZoneHandle(), // No optional arguments.
665 kNumArgsChecked); 665 kNumArgsChecked);
666 ASSERT(locs()->out().reg() == RAX); 666 ASSERT(locs()->out().reg() == RAX);
667 } 667 }
668 668
669 669
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 LocationSummary::kNoCall); 727 LocationSummary::kNoCall);
728 } else { 728 } else {
729 ASSERT(receiver_type() == kIllegalObjectKind); 729 ASSERT(receiver_type() == kIllegalObjectKind);
730 return MakeCallSummary(); 730 return MakeCallSummary();
731 } 731 }
732 } 732 }
733 733
734 734
735 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, 735 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler,
736 LoadIndexedComp* comp) { 736 LoadIndexedComp* comp) {
737 Label* deopt = compiler->AddDeoptStub(comp->cid(), 737 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
738 comp->token_pos(), 738 comp->token_pos(),
739 comp->try_index(), 739 comp->try_index(),
740 kDeoptLoadIndexedPolymorphic); 740 kDeoptLoadIndexedPolymorphic);
741 ASSERT(comp->ic_data()->NumberOfChecks() > 0); 741 ASSERT(comp->ic_data()->NumberOfChecks() > 0);
742 ASSERT(comp->HasICData()); 742 ASSERT(comp->HasICData());
743 const ICData& ic_data = *comp->ic_data(); 743 const ICData& ic_data = *comp->ic_data();
744 ASSERT(ic_data.num_args_tested() == 1); 744 ASSERT(ic_data.num_args_tested() == 1);
745 // No indexed access on Smi. 745 // No indexed access on Smi.
746 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); 746 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
747 // Load receiver into RAX. 747 // Load receiver into RAX.
748 const intptr_t kNumArguments = 2; 748 const intptr_t kNumArguments = 2;
749 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); 749 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize));
750 __ testq(RAX, Immediate(kSmiTagMask)); 750 __ testq(RAX, Immediate(kSmiTagMask));
751 __ j(ZERO, deopt); 751 __ j(ZERO, deopt);
752 __ LoadClassId(RDI, RAX); 752 __ LoadClassId(RDI, RAX);
753 compiler->EmitTestAndCall(ic_data, 753 compiler->EmitTestAndCall(ic_data,
754 RDI, // Class id register. 754 RDI, // Class id register.
755 kNumArguments, 755 kNumArguments,
756 Array::Handle(), // No named arguments. 756 Array::Handle(), // No named arguments.
757 deopt, // Deoptimize target. 757 deopt, // Deoptimize target.
758 NULL, // Fallthrough when done. 758 NULL, // Fallthrough when done.
759 comp->cid(), 759 comp->deopt_id(),
760 comp->token_pos(), 760 comp->token_pos(),
761 comp->try_index()); 761 comp->try_index());
762 } 762 }
763 763
764 764
765 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { 765 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
766 if (receiver_type() == kIllegalObjectKind) { 766 if (receiver_type() == kIllegalObjectKind) {
767 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 767 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
768 EmitLoadIndexedPolymorphic(compiler, this); 768 EmitLoadIndexedPolymorphic(compiler, this);
769 } else { 769 } else {
770 compiler->EmitLoadIndexedGeneric(this); 770 compiler->EmitLoadIndexedGeneric(this);
771 } 771 }
772 ASSERT(locs()->out().reg() == RAX); 772 ASSERT(locs()->out().reg() == RAX);
773 return; 773 return;
774 } 774 }
775 775
776 Register receiver = locs()->in(0).reg(); 776 Register receiver = locs()->in(0).reg();
777 Register index = locs()->in(1).reg(); 777 Register index = locs()->in(1).reg();
778 Register result = locs()->out().reg(); 778 Register result = locs()->out().reg();
779 779
780 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? 780 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ?
781 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; 781 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray;
782 782
783 Label* deopt = compiler->AddDeoptStub(cid(), 783 Label* deopt = compiler->AddDeoptStub(deopt_id(),
784 token_pos(), 784 token_pos(),
785 try_index(), 785 try_index(),
786 deopt_reason, 786 deopt_reason,
787 receiver, 787 receiver,
788 index); 788 index);
789 789
790 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. 790 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi.
791 __ j(ZERO, deopt); 791 __ j(ZERO, deopt);
792 __ CompareClassId(receiver, receiver_type()); 792 __ CompareClassId(receiver, receiver_type());
793 __ j(NOT_EQUAL, deopt); 793 __ j(NOT_EQUAL, deopt);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
847 } 847 }
848 } 848 }
849 849
850 850
851 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, 851 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler,
852 StoreIndexedComp* comp) { 852 StoreIndexedComp* comp) {
853 const String& function_name = 853 const String& function_name =
854 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX))); 854 String::ZoneHandle(Symbols::New(Token::Str(Token::kASSIGN_INDEX)));
855 855
856 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 856 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
857 comp->cid(), 857 comp->deopt_id(),
858 comp->token_pos(), 858 comp->token_pos(),
859 comp->try_index()); 859 comp->try_index());
860 860
861 const intptr_t kNumArguments = 3; 861 const intptr_t kNumArguments = 3;
862 const intptr_t kNumArgsChecked = 1; // Type-feedback. 862 const intptr_t kNumArgsChecked = 1; // Type-feedback.
863 compiler->GenerateInstanceCall(comp->cid(), 863 compiler->GenerateInstanceCall(comp->deopt_id(),
864 comp->token_pos(), 864 comp->token_pos(),
865 comp->try_index(), 865 comp->try_index(),
866 function_name, 866 function_name,
867 kNumArguments, 867 kNumArguments,
868 Array::ZoneHandle(), // No named arguments. 868 Array::ZoneHandle(), // No named arguments.
869 kNumArgsChecked); 869 kNumArgsChecked);
870 } 870 }
871 871
872 872
873 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, 873 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler,
874 StoreIndexedComp* comp) { 874 StoreIndexedComp* comp) {
875 Label* deopt = compiler->AddDeoptStub(comp->cid(), 875 Label* deopt = compiler->AddDeoptStub(comp->deopt_id(),
876 comp->token_pos(), 876 comp->token_pos(),
877 comp->try_index(), 877 comp->try_index(),
878 kDeoptStoreIndexedPolymorphic); 878 kDeoptStoreIndexedPolymorphic);
879 ASSERT(comp->ic_data()->NumberOfChecks() > 0); 879 ASSERT(comp->ic_data()->NumberOfChecks() > 0);
880 ASSERT(comp->HasICData()); 880 ASSERT(comp->HasICData());
881 const ICData& ic_data = *comp->ic_data(); 881 const ICData& ic_data = *comp->ic_data();
882 ASSERT(ic_data.num_args_tested() == 1); 882 ASSERT(ic_data.num_args_tested() == 1);
883 // No indexed access on Smi. 883 // No indexed access on Smi.
884 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); 884 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi);
885 // Load receiver into RAX. 885 // Load receiver into RAX.
886 const intptr_t kNumArguments = 3; 886 const intptr_t kNumArguments = 3;
887 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); 887 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize));
888 __ testq(RAX, Immediate(kSmiTagMask)); 888 __ testq(RAX, Immediate(kSmiTagMask));
889 __ j(ZERO, deopt); 889 __ j(ZERO, deopt);
890 __ LoadClassId(RDI, RAX); 890 __ LoadClassId(RDI, RAX);
891 compiler->EmitTestAndCall(ic_data, 891 compiler->EmitTestAndCall(ic_data,
892 RDI, // Class id register. 892 RDI, // Class id register.
893 kNumArguments, 893 kNumArguments,
894 Array::Handle(), // No named arguments. 894 Array::Handle(), // No named arguments.
895 deopt, // deoptimize label. 895 deopt, // deoptimize label.
896 NULL, // fallthrough when done. 896 NULL, // fallthrough when done.
897 comp->cid(), 897 comp->deopt_id(),
898 comp->token_pos(), 898 comp->token_pos(),
899 comp->try_index()); 899 comp->try_index());
900 } 900 }
901 901
902 902
903 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { 903 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) {
904 if (receiver_type() == kIllegalObjectKind) { 904 if (receiver_type() == kIllegalObjectKind) {
905 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 905 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
906 EmitStoreIndexedPolymorphic(compiler, this); 906 EmitStoreIndexedPolymorphic(compiler, this);
907 } else { 907 } else {
908 EmitStoreIndexedGeneric(compiler, this); 908 EmitStoreIndexedGeneric(compiler, this);
909 } 909 }
910 return; 910 return;
911 } 911 }
912 912
913 Register receiver = locs()->in(0).reg(); 913 Register receiver = locs()->in(0).reg();
914 Register index = locs()->in(1).reg(); 914 Register index = locs()->in(1).reg();
915 Register value = locs()->in(2).reg(); 915 Register value = locs()->in(2).reg();
916 916
917 Label* deopt = compiler->AddDeoptStub(cid(), 917 Label* deopt = compiler->AddDeoptStub(deopt_id(),
918 token_pos(), 918 token_pos(),
919 try_index(), 919 try_index(),
920 kDeoptStoreIndexed, 920 kDeoptStoreIndexed,
921 receiver, 921 receiver,
922 index, 922 index,
923 value); 923 value);
924 924
925 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. 925 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi.
926 __ j(ZERO, deopt); 926 __ j(ZERO, deopt);
927 __ CompareClassId(receiver, receiver_type()); 927 __ CompareClassId(receiver, receiver_type());
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 964
965 965
966 LocationSummary* InstanceSetterComp::MakeLocationSummary() const { 966 LocationSummary* InstanceSetterComp::MakeLocationSummary() const {
967 return MakeCallSummary(); 967 return MakeCallSummary();
968 } 968 }
969 969
970 970
971 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { 971 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) {
972 Label* deopt = NULL; 972 Label* deopt = NULL;
973 if (compiler->is_optimizing()) { 973 if (compiler->is_optimizing()) {
974 deopt = compiler->AddDeoptStub(cid(), 974 deopt = compiler->AddDeoptStub(deopt_id(),
975 token_pos(), 975 token_pos(),
976 try_index(), 976 try_index(),
977 kDeoptInstanceSetter); 977 kDeoptInstanceSetter);
978 } 978 }
979 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 979 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
980 // No index-setter on Smi's. 980 // No index-setter on Smi's.
981 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi); 981 ASSERT(ic_data()->GetReceiverClassIdAt(0) != kSmi);
982 // Load receiver into RAX. 982 // Load receiver into RAX.
983 const intptr_t kNumArguments = 2; 983 const intptr_t kNumArguments = 2;
984 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); 984 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize));
985 __ testq(RAX, Immediate(kSmiTagMask)); 985 __ testq(RAX, Immediate(kSmiTagMask));
986 __ j(ZERO, deopt); 986 __ j(ZERO, deopt);
987 __ LoadClassId(RDI, RAX); 987 __ LoadClassId(RDI, RAX);
988 compiler->EmitTestAndCall(*ic_data(), 988 compiler->EmitTestAndCall(*ic_data(),
989 RDI, // Class id register. 989 RDI, // Class id register.
990 kNumArguments, 990 kNumArguments,
991 Array::Handle(), // No named arguments. 991 Array::Handle(), // No named arguments.
992 deopt, // Deoptimize target. 992 deopt, // Deoptimize target.
993 NULL, // Fallthrough when done. 993 NULL, // Fallthrough when done.
994 cid(), 994 deopt_id(),
995 token_pos(), 995 token_pos(),
996 try_index()); 996 try_index());
997 997
998 } else if (compiler->is_optimizing()) { 998 } else if (compiler->is_optimizing()) {
999 // Get some IC data then optimize again. 999 // Get some IC data then optimize again.
1000 __ jmp(deopt); 1000 __ jmp(deopt);
1001 } else { 1001 } else {
1002 // Unoptimized code. 1002 // Unoptimized code.
1003 const String& function_name = 1003 const String& function_name =
1004 String::ZoneHandle(Field::SetterSymbol(field_name())); 1004 String::ZoneHandle(Field::SetterSymbol(field_name()));
1005 1005
1006 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 1006 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
1007 cid(), 1007 deopt_id(),
1008 token_pos(), 1008 token_pos(),
1009 try_index()); 1009 try_index());
1010 const intptr_t kArgumentCount = 2; 1010 const intptr_t kArgumentCount = 2;
1011 const intptr_t kCheckedArgumentCount = 1; 1011 const intptr_t kCheckedArgumentCount = 1;
1012 compiler->GenerateInstanceCall(cid(), 1012 compiler->GenerateInstanceCall(deopt_id(),
1013 token_pos(), 1013 token_pos(),
1014 try_index(), 1014 try_index(),
1015 function_name, 1015 function_name,
1016 kArgumentCount, 1016 kArgumentCount,
1017 Array::ZoneHandle(), 1017 Array::ZoneHandle(),
1018 kCheckedArgumentCount); 1018 kCheckedArgumentCount);
1019 } 1019 }
1020 } 1020 }
1021 1021
1022 1022
1023 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { 1023 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const {
1024 // TODO(fschneider): For this instruction the input register may be 1024 // TODO(fschneider): For this instruction the input register may be
1025 // reused for the result (but is not required to) because the input 1025 // reused for the result (but is not required to) because the input
1026 // is not used after the result is defined. We should consider adding 1026 // is not used after the result is defined. We should consider adding
1027 // this information to the input policy. 1027 // this information to the input policy.
1028 return LocationSummary::Make(1, 1028 return LocationSummary::Make(1,
1029 Location::RequiresRegister(), 1029 Location::RequiresRegister(),
1030 LocationSummary::kNoCall); 1030 LocationSummary::kNoCall);
1031 } 1031 }
1032 1032
1033 1033
1034 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1034 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1035 Register instance_reg = locs()->in(0).reg(); 1035 Register instance_reg = locs()->in(0).reg();
1036 Register result_reg = locs()->out().reg(); 1036 Register result_reg = locs()->out().reg();
1037 1037
1038 if (HasICData()) { 1038 if (HasICData()) {
1039 ASSERT(original() != NULL); 1039 ASSERT(original() != NULL);
1040 Label* deopt = compiler->AddDeoptStub(original()->cid(), 1040 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1041 original()->token_pos(), 1041 original()->token_pos(),
1042 original()->try_index(), 1042 original()->try_index(),
1043 kDeoptInstanceGetterSameTarget, 1043 kDeoptInstanceGetterSameTarget,
1044 instance_reg); 1044 instance_reg);
1045 // Smis do not have instance fields (Smi class is always first). 1045 // Smis do not have instance fields (Smi class is always first).
1046 // Use 'result' as temporary register. 1046 // Use 'result' as temporary register.
1047 ASSERT(result_reg != instance_reg); 1047 ASSERT(result_reg != instance_reg);
1048 ASSERT(ic_data() != NULL); 1048 ASSERT(ic_data() != NULL);
1049 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1049 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1050 } 1050 }
(...skipping 26 matching lines...) Expand all
1077 summary->set_out(Location::RegisterLocation(RAX)); 1077 summary->set_out(Location::RegisterLocation(RAX));
1078 return summary; 1078 return summary;
1079 } 1079 }
1080 1080
1081 1081
1082 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1082 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1083 ASSERT(locs()->in(0).reg() == RAX); // Value. 1083 ASSERT(locs()->in(0).reg() == RAX); // Value.
1084 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. 1084 ASSERT(locs()->in(1).reg() == RCX); // Instantiator.
1085 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. 1085 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments.
1086 1086
1087 compiler->GenerateInstanceOf(cid(), 1087 compiler->GenerateInstanceOf(deopt_id(),
1088 token_pos(), 1088 token_pos(),
1089 try_index(), 1089 try_index(),
1090 type(), 1090 type(),
1091 negate_result()); 1091 negate_result());
1092 ASSERT(locs()->out().reg() == RAX); 1092 ASSERT(locs()->out().reg() == RAX);
1093 } 1093 }
1094 1094
1095 1095
1096 LocationSummary* CreateArrayComp::MakeLocationSummary() const { 1096 LocationSummary* CreateArrayComp::MakeLocationSummary() const {
1097 // TODO(regis): The elements of the array could be considered as arguments to 1097 // TODO(regis): The elements of the array could be considered as arguments to
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 const Class& cls = Class::ZoneHandle(constructor().owner()); 1150 const Class& cls = Class::ZoneHandle(constructor().owner());
1151 Register type_arguments = locs()->in(0).reg(); 1151 Register type_arguments = locs()->in(0).reg();
1152 Register instantiator_type_arguments = locs()->in(1).reg(); 1152 Register instantiator_type_arguments = locs()->in(1).reg();
1153 Register result = locs()->out().reg(); 1153 Register result = locs()->out().reg();
1154 1154
1155 // Push the result place holder initialized to NULL. 1155 // Push the result place holder initialized to NULL.
1156 __ PushObject(Object::ZoneHandle()); 1156 __ PushObject(Object::ZoneHandle());
1157 __ PushObject(cls); 1157 __ PushObject(cls);
1158 __ pushq(type_arguments); 1158 __ pushq(type_arguments);
1159 __ pushq(instantiator_type_arguments); 1159 __ pushq(instantiator_type_arguments);
1160 compiler->GenerateCallRuntime(cid(), 1160 compiler->GenerateCallRuntime(deopt_id(),
1161 token_pos(), 1161 token_pos(),
1162 try_index(), 1162 try_index(),
1163 kAllocateObjectWithBoundsCheckRuntimeEntry); 1163 kAllocateObjectWithBoundsCheckRuntimeEntry);
1164 // Pop instantiator type arguments, type arguments, and class. 1164 // Pop instantiator type arguments, type arguments, and class.
1165 __ Drop(3); 1165 __ Drop(3);
1166 __ popq(result); // Pop new instance. 1166 __ popq(result); // Pop new instance.
1167 } 1167 }
1168 1168
1169 1169
1170 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { 1170 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const {
1171 return LocationSummary::Make(1, 1171 return LocationSummary::Make(1,
1172 Location::RequiresRegister(), 1172 Location::RequiresRegister(),
1173 LocationSummary::kNoCall); 1173 LocationSummary::kNoCall);
1174 } 1174 }
1175 1175
1176 1176
1177 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1177 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1178 Register instance_reg = locs()->in(0).reg(); 1178 Register instance_reg = locs()->in(0).reg();
1179 Register result_reg = locs()->out().reg(); 1179 Register result_reg = locs()->out().reg();
1180 if (HasICData()) { 1180 if (HasICData()) {
1181 ASSERT(original() != NULL); 1181 ASSERT(original() != NULL);
1182 Label* deopt = compiler->AddDeoptStub(original()->cid(), 1182 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1183 original()->token_pos(), 1183 original()->token_pos(),
1184 original()->try_index(), 1184 original()->try_index(),
1185 kDeoptInstanceGetterSameTarget, 1185 kDeoptInstanceGetterSameTarget,
1186 instance_reg); 1186 instance_reg);
1187 // Smis do not have instance fields (Smi class is always first). 1187 // Smis do not have instance fields (Smi class is always first).
1188 // Use 'result' as temporary register. 1188 // Use 'result' as temporary register.
1189 ASSERT(result_reg != instance_reg); 1189 ASSERT(result_reg != instance_reg);
1190 ASSERT(ic_data() != NULL); 1190 ASSERT(ic_data() != NULL);
1191 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1191 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1192 } 1192 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 1236 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
1237 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), 1237 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
1238 Immediate(Smi::RawValue(len))); 1238 Immediate(Smi::RawValue(len)));
1239 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 1239 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
1240 __ Bind(&type_arguments_uninstantiated); 1240 __ Bind(&type_arguments_uninstantiated);
1241 } 1241 }
1242 // A runtime call to instantiate the type arguments is required. 1242 // A runtime call to instantiate the type arguments is required.
1243 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1243 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1244 __ PushObject(type_arguments()); 1244 __ PushObject(type_arguments());
1245 __ pushq(instantiator_reg); // Push instantiator type arguments. 1245 __ pushq(instantiator_reg); // Push instantiator type arguments.
1246 compiler->GenerateCallRuntime(cid(), 1246 compiler->GenerateCallRuntime(deopt_id(),
1247 token_pos(), 1247 token_pos(),
1248 try_index(), 1248 try_index(),
1249 kInstantiateTypeArgumentsRuntimeEntry); 1249 kInstantiateTypeArgumentsRuntimeEntry);
1250 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 1250 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
1251 __ popq(result_reg); // Pop instantiated type arguments. 1251 __ popq(result_reg); // Pop instantiated type arguments.
1252 __ Bind(&type_arguments_instantiated); 1252 __ Bind(&type_arguments_instantiated);
1253 ASSERT(instantiator_reg == result_reg); 1253 ASSERT(instantiator_reg == result_reg);
1254 // 'result_reg': Instantiated type arguments. 1254 // 'result_reg': Instantiated type arguments.
1255 } 1255 }
1256 1256
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1412 return locs; 1412 return locs;
1413 } 1413 }
1414 1414
1415 1415
1416 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1416 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1417 Register context_value = locs()->in(0).reg(); 1417 Register context_value = locs()->in(0).reg();
1418 Register result = locs()->out().reg(); 1418 Register result = locs()->out().reg();
1419 1419
1420 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1420 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1421 __ pushq(context_value); 1421 __ pushq(context_value);
1422 compiler->GenerateCallRuntime(cid(), 1422 compiler->GenerateCallRuntime(deopt_id(),
1423 token_pos(), 1423 token_pos(),
1424 try_index(), 1424 try_index(),
1425 kCloneContextRuntimeEntry); 1425 kCloneContextRuntimeEntry);
1426 __ popq(result); // Remove argument. 1426 __ popq(result); // Remove argument.
1427 __ popq(result); // Get result (cloned context). 1427 __ popq(result); // Get result (cloned context).
1428 } 1428 }
1429 1429
1430 1430
1431 LocationSummary* CatchEntryComp::MakeLocationSummary() const { 1431 LocationSummary* CatchEntryComp::MakeLocationSummary() const {
1432 return LocationSummary::Make(0, 1432 return LocationSummary::Make(0,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1468 } 1468 }
1469 1469
1470 1470
1471 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1471 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1472 Register temp = locs()->temp(0).reg(); 1472 Register temp = locs()->temp(0).reg();
1473 // Generate stack overflow check. 1473 // Generate stack overflow check.
1474 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); 1474 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address()));
1475 __ cmpq(RSP, Address(temp, 0)); 1475 __ cmpq(RSP, Address(temp, 0));
1476 Label no_stack_overflow; 1476 Label no_stack_overflow;
1477 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); 1477 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump);
1478 compiler->GenerateCallRuntime(cid(), 1478 compiler->GenerateCallRuntime(deopt_id(),
1479 token_pos(), 1479 token_pos(),
1480 try_index(), 1480 try_index(),
1481 kStackOverflowRuntimeEntry); 1481 kStackOverflowRuntimeEntry);
1482 __ Bind(&no_stack_overflow); 1482 __ Bind(&no_stack_overflow);
1483 } 1483 }
1484 1484
1485 1485
1486 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 1486 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
1487 const intptr_t kNumInputs = 2; 1487 const intptr_t kNumInputs = 2;
1488 1488
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1546 } 1546 }
1547 } 1547 }
1548 1548
1549 1549
1550 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1550 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1551 Register left = comp->locs()->in(0).reg(); 1551 Register left = comp->locs()->in(0).reg();
1552 Register right = comp->locs()->in(1).reg(); 1552 Register right = comp->locs()->in(1).reg();
1553 Register result = comp->locs()->out().reg(); 1553 Register result = comp->locs()->out().reg();
1554 Register temp = comp->locs()->temp(0).reg(); 1554 Register temp = comp->locs()->temp(0).reg();
1555 ASSERT(left == result); 1555 ASSERT(left == result);
1556 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1556 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1557 comp->instance_call()->token_pos(), 1557 comp->instance_call()->token_pos(),
1558 comp->instance_call()->try_index(), 1558 comp->instance_call()->try_index(),
1559 kDeoptSmiBinaryOp, 1559 kDeoptSmiBinaryOp,
1560 temp, 1560 temp,
1561 right); 1561 right);
1562 // TODO(vegorov): for many binary operations this pattern can be rearranged 1562 // TODO(vegorov): for many binary operations this pattern can be rearranged
1563 // to save one move. 1563 // to save one move.
1564 __ movq(temp, left); 1564 __ movq(temp, left);
1565 __ orq(left, right); 1565 __ orq(left, right);
1566 __ testq(left, Immediate(kSmiTagMask)); 1566 __ testq(left, Immediate(kSmiTagMask));
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 __ shlq(left, right_temp); 1657 __ shlq(left, right_temp);
1658 __ jmp(&done); 1658 __ jmp(&done);
1659 { 1659 {
1660 __ Bind(&call_method); 1660 __ Bind(&call_method);
1661 Function& target = Function::ZoneHandle( 1661 Function& target = Function::ZoneHandle(
1662 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1662 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1663 ASSERT(!target.IsNull()); 1663 ASSERT(!target.IsNull());
1664 const intptr_t kArgumentCount = 2; 1664 const intptr_t kArgumentCount = 2;
1665 __ pushq(temp); 1665 __ pushq(temp);
1666 __ pushq(right); 1666 __ pushq(right);
1667 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1667 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1668 comp->instance_call()->token_pos(), 1668 comp->instance_call()->token_pos(),
1669 comp->instance_call()->try_index(), 1669 comp->instance_call()->try_index(),
1670 target, 1670 target,
1671 kArgumentCount, 1671 kArgumentCount,
1672 Array::Handle()); // No argument names. 1672 Array::Handle()); // No argument names.
1673 ASSERT(result == RAX); 1673 ASSERT(result == RAX);
1674 } 1674 }
1675 __ Bind(&done); 1675 __ Bind(&done);
1676 break; 1676 break;
1677 } 1677 }
(...skipping 25 matching lines...) Expand all
1703 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1703 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1704 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi 1704 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi
1705 // receiver and a Mint or Smi argument. We fall back to the run time call if 1705 // receiver and a Mint or Smi argument. We fall back to the run time call if
1706 // both receiver and argument are Mint or if one of them is Mint and the other 1706 // both receiver and argument are Mint or if one of them is Mint and the other
1707 // is a negative Smi. 1707 // is a negative Smi.
1708 Register left = comp->locs()->in(0).reg(); 1708 Register left = comp->locs()->in(0).reg();
1709 Register right = comp->locs()->in(1).reg(); 1709 Register right = comp->locs()->in(1).reg();
1710 Register result = comp->locs()->out().reg(); 1710 Register result = comp->locs()->out().reg();
1711 ASSERT(left == result); 1711 ASSERT(left == result);
1712 ASSERT(comp->op_kind() == Token::kBIT_AND); 1712 ASSERT(comp->op_kind() == Token::kBIT_AND);
1713 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1713 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1714 comp->instance_call()->token_pos(), 1714 comp->instance_call()->token_pos(),
1715 comp->instance_call()->try_index(), 1715 comp->instance_call()->try_index(),
1716 kDeoptMintBinaryOp, 1716 kDeoptMintBinaryOp,
1717 left, 1717 left,
1718 right); 1718 right);
1719 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; 1719 Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
1720 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? 1720 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi?
1721 __ j(NOT_ZERO, &non_smi); 1721 __ j(NOT_ZERO, &non_smi);
1722 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? 1722 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi?
1723 __ j(ZERO, &smi_smi); 1723 __ j(ZERO, &smi_smi);
(...skipping 27 matching lines...) Expand all
1751 1751
1752 __ Bind(&smi_static_call); 1752 __ Bind(&smi_static_call);
1753 { 1753 {
1754 Function& target = Function::ZoneHandle( 1754 Function& target = Function::ZoneHandle(
1755 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1755 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1756 if (target.IsNull()) { 1756 if (target.IsNull()) {
1757 __ jmp(deopt); 1757 __ jmp(deopt);
1758 } else { 1758 } else {
1759 __ pushq(left); 1759 __ pushq(left);
1760 __ pushq(right); 1760 __ pushq(right);
1761 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1761 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1762 comp->instance_call()->token_pos(), 1762 comp->instance_call()->token_pos(),
1763 comp->instance_call()->try_index(), 1763 comp->instance_call()->try_index(),
1764 target, 1764 target,
1765 comp->instance_call()->ArgumentCount(), 1765 comp->instance_call()->ArgumentCount(),
1766 comp->instance_call()->argument_names()); 1766 comp->instance_call()->argument_names());
1767 ASSERT(result == RAX); 1767 ASSERT(result == RAX);
1768 __ jmp(&done); 1768 __ jmp(&done);
1769 } 1769 }
1770 } 1770 }
1771 1771
1772 __ Bind(&mint_static_call); 1772 __ Bind(&mint_static_call);
1773 { 1773 {
1774 Function& target = Function::ZoneHandle( 1774 Function& target = Function::ZoneHandle(
1775 comp->ic_data()->GetTargetForReceiverClassId(kMint)); 1775 comp->ic_data()->GetTargetForReceiverClassId(kMint));
1776 if (target.IsNull()) { 1776 if (target.IsNull()) {
1777 __ jmp(deopt); 1777 __ jmp(deopt);
1778 } else { 1778 } else {
1779 __ pushq(left); 1779 __ pushq(left);
1780 __ pushq(right); 1780 __ pushq(right);
1781 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1781 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1782 comp->instance_call()->token_pos(), 1782 comp->instance_call()->token_pos(),
1783 comp->instance_call()->try_index(), 1783 comp->instance_call()->try_index(),
1784 target, 1784 target,
1785 comp->instance_call()->ArgumentCount(), 1785 comp->instance_call()->ArgumentCount(),
1786 comp->instance_call()->argument_names()); 1786 comp->instance_call()->argument_names());
1787 ASSERT(result == RAX); 1787 ASSERT(result == RAX);
1788 } 1788 }
1789 } 1789 }
1790 __ Bind(&done); 1790 __ Bind(&done);
1791 } 1791 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1824 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 1824 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
1825 compiler->GenerateCall(instance_call()->token_pos(), 1825 compiler->GenerateCall(instance_call()->token_pos(),
1826 instance_call()->try_index(), 1826 instance_call()->try_index(),
1827 &label, 1827 &label,
1828 PcDescriptors::kOther); 1828 PcDescriptors::kOther);
1829 // Newly allocated object is now in the result register (RAX). 1829 // Newly allocated object is now in the result register (RAX).
1830 ASSERT(result == RAX); 1830 ASSERT(result == RAX);
1831 __ popq(right); 1831 __ popq(right);
1832 __ popq(left); 1832 __ popq(left);
1833 1833
1834 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1834 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1835 instance_call()->token_pos(), 1835 instance_call()->token_pos(),
1836 instance_call()->try_index(), 1836 instance_call()->try_index(),
1837 kDeoptDoubleBinaryOp, 1837 kDeoptDoubleBinaryOp,
1838 left, 1838 left,
1839 right); 1839 right);
1840 1840
1841 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 1841 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
1842 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 1842 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
1843 1843
1844 switch (op_kind()) { 1844 switch (op_kind()) {
(...skipping 25 matching lines...) Expand all
1870 ASSERT(ic_data.num_args_tested() == 1); 1870 ASSERT(ic_data.num_args_tested() == 1);
1871 // TODO(srdjan): Implement for more checks. 1871 // TODO(srdjan): Implement for more checks.
1872 ASSERT(ic_data.NumberOfChecks() == 1); 1872 ASSERT(ic_data.NumberOfChecks() == 1);
1873 intptr_t test_class_id; 1873 intptr_t test_class_id;
1874 Function& target = Function::Handle(); 1874 Function& target = Function::Handle();
1875 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1875 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1876 1876
1877 Register value = locs()->in(0).reg(); 1877 Register value = locs()->in(0).reg();
1878 Register result = locs()->out().reg(); 1878 Register result = locs()->out().reg();
1879 ASSERT(value == result); 1879 ASSERT(value == result);
1880 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1880 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1881 instance_call()->token_pos(), 1881 instance_call()->token_pos(),
1882 instance_call()->try_index(), 1882 instance_call()->try_index(),
1883 kDeoptUnaryOp, 1883 kDeoptUnaryOp,
1884 value); 1884 value);
1885 if (test_class_id == kSmi) { 1885 if (test_class_id == kSmi) {
1886 __ testq(value, Immediate(kSmiTagMask)); 1886 __ testq(value, Immediate(kSmiTagMask));
1887 __ j(NOT_ZERO, deopt); 1887 __ j(NOT_ZERO, deopt);
1888 switch (op_kind()) { 1888 switch (op_kind()) {
1889 case Token::kNEGATE: 1889 case Token::kNEGATE:
1890 __ negq(value); 1890 __ negq(value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1922 1922
1923 // TODO(srdjan): Implement for more checks. 1923 // TODO(srdjan): Implement for more checks.
1924 ASSERT(ic_data.NumberOfChecks() == 1); 1924 ASSERT(ic_data.NumberOfChecks() == 1);
1925 intptr_t test_class_id; 1925 intptr_t test_class_id;
1926 Function& target = Function::Handle(); 1926 Function& target = Function::Handle();
1927 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1927 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1928 1928
1929 Register value = locs()->in(0).reg(); 1929 Register value = locs()->in(0).reg();
1930 Register result = locs()->out().reg(); 1930 Register result = locs()->out().reg();
1931 ASSERT(value == result); 1931 ASSERT(value == result);
1932 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1932 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1933 instance_call()->token_pos(), 1933 instance_call()->token_pos(),
1934 instance_call()->try_index(), 1934 instance_call()->try_index(),
1935 kDeoptUnaryOp, 1935 kDeoptUnaryOp,
1936 value); 1936 value);
1937 if (test_class_id == kDouble) { 1937 if (test_class_id == kDouble) {
1938 Register temp = locs()->temp(0).reg(); 1938 Register temp = locs()->temp(0).reg();
1939 __ testq(value, Immediate(kSmiTagMask)); 1939 __ testq(value, Immediate(kSmiTagMask));
1940 __ j(ZERO, deopt); // Smi. 1940 __ j(ZERO, deopt); // Smi.
1941 __ CompareClassId(value, kDouble); 1941 __ CompareClassId(value, kDouble);
1942 __ j(NOT_EQUAL, deopt); 1942 __ j(NOT_EQUAL, deopt);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1978 } 1978 }
1979 } 1979 }
1980 1980
1981 1981
1982 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1982 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1983 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; 1983 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX;
1984 Register result = locs()->out().reg(); 1984 Register result = locs()->out().reg();
1985 1985
1986 const DeoptReasonId deopt_reason = (from() == kDouble) ? 1986 const DeoptReasonId deopt_reason = (from() == kDouble) ?
1987 kDeoptDoubleToDouble : kDeoptIntegerToDouble; 1987 kDeoptDoubleToDouble : kDeoptIntegerToDouble;
1988 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1988 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1989 instance_call()->token_pos(), 1989 instance_call()->token_pos(),
1990 instance_call()->try_index(), 1990 instance_call()->try_index(),
1991 deopt_reason, 1991 deopt_reason,
1992 value); 1992 value);
1993 1993
1994 if (from() == kDouble) { 1994 if (from() == kDouble) {
1995 __ testq(value, Immediate(kSmiTagMask)); 1995 __ testq(value, Immediate(kSmiTagMask));
1996 __ j(ZERO, deopt); // Deoptimize if Smi. 1996 __ j(ZERO, deopt); // Deoptimize if Smi.
1997 __ CompareClassId(value, kDouble); 1997 __ CompareClassId(value, kDouble);
1998 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. 1998 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double.
(...skipping 23 matching lines...) Expand all
2022 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); 2022 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
2023 } 2023 }
2024 2024
2025 2025
2026 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { 2026 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
2027 return MakeCallSummary(); 2027 return MakeCallSummary();
2028 } 2028 }
2029 2029
2030 2030
2031 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { 2031 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
2032 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 2032 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
2033 instance_call()->token_pos(), 2033 instance_call()->token_pos(),
2034 instance_call()->try_index(), 2034 instance_call()->try_index(),
2035 kDeoptPolymorphicInstanceCallTestFail); 2035 kDeoptPolymorphicInstanceCallTestFail);
2036 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 2036 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
2037 __ jmp(deopt); 2037 __ jmp(deopt);
2038 return; 2038 return;
2039 } 2039 }
2040 ASSERT(HasICData()); 2040 ASSERT(HasICData());
2041 ASSERT(ic_data()->num_args_tested() == 1); 2041 ASSERT(ic_data()->num_args_tested() == 1);
2042 Label handle_smi; 2042 Label handle_smi;
2043 Label* is_smi_label = 2043 Label* is_smi_label =
2044 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; 2044 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt;
2045 2045
2046 // Load receiver into RAX. 2046 // Load receiver into RAX.
2047 __ movq(RAX, 2047 __ movq(RAX,
2048 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); 2048 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize));
2049 __ testq(RAX, Immediate(kSmiTagMask)); 2049 __ testq(RAX, Immediate(kSmiTagMask));
2050 __ j(ZERO, is_smi_label); 2050 __ j(ZERO, is_smi_label);
2051 Label done; 2051 Label done;
2052 __ LoadClassId(RDI, RAX); 2052 __ LoadClassId(RDI, RAX);
2053 compiler->EmitTestAndCall(*ic_data(), 2053 compiler->EmitTestAndCall(*ic_data(),
2054 RDI, // Class id register. 2054 RDI, // Class id register.
2055 instance_call()->ArgumentCount(), 2055 instance_call()->ArgumentCount(),
2056 instance_call()->argument_names(), 2056 instance_call()->argument_names(),
2057 deopt, 2057 deopt,
2058 (is_smi_label == &handle_smi) ? &done : NULL, 2058 (is_smi_label == &handle_smi) ? &done : NULL,
2059 instance_call()->cid(), 2059 instance_call()->deopt_id(),
2060 instance_call()->token_pos(), 2060 instance_call()->token_pos(),
2061 instance_call()->try_index()); 2061 instance_call()->try_index());
2062 if (is_smi_label == &handle_smi) { 2062 if (is_smi_label == &handle_smi) {
2063 __ Bind(&handle_smi); 2063 __ Bind(&handle_smi);
2064 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); 2064 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi);
2065 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); 2065 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0));
2066 compiler->GenerateStaticCall(instance_call()->cid(), 2066 compiler->GenerateStaticCall(instance_call()->deopt_id(),
2067 instance_call()->token_pos(), 2067 instance_call()->token_pos(),
2068 instance_call()->try_index(), 2068 instance_call()->try_index(),
2069 target, 2069 target,
2070 instance_call()->ArgumentCount(), 2070 instance_call()->ArgumentCount(),
2071 instance_call()->argument_names()); 2071 instance_call()->argument_names());
2072 } 2072 }
2073 __ Bind(&done); 2073 __ Bind(&done);
2074 } 2074 }
2075 2075
2076 2076
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2130 Register right = locs()->in(1).reg(); 2130 Register right = locs()->in(1).reg();
2131 __ cmpq(left, right); 2131 __ cmpq(left, right);
2132 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 2132 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2133 EmitBranchOnCondition(compiler, cond); 2133 EmitBranchOnCondition(compiler, cond);
2134 return; 2134 return;
2135 } 2135 }
2136 // Relational or equality. 2136 // Relational or equality.
2137 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2137 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2138 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { 2138 if (ICDataWithBothClassIds(*ic_data(), kSmi)) {
2139 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2139 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2140 cid(), token_pos(), try_index()); 2140 deopt_id(), token_pos(), try_index());
2141 return; 2141 return;
2142 } 2142 }
2143 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { 2143 if (ICDataWithBothClassIds(*ic_data(), kDouble)) {
2144 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2144 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2145 cid(), token_pos(), try_index()); 2145 deopt_id(), token_pos(), try_index());
2146 return; 2146 return;
2147 } 2147 }
2148 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2148 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2149 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2149 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2150 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), 2150 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(),
2151 cid(), token_pos(), try_index()); 2151 deopt_id(), token_pos(), try_index());
2152 return; 2152 return;
2153 } 2153 }
2154 // Otherwise polymorphic dispatch? 2154 // Otherwise polymorphic dispatch?
2155 } 2155 }
2156 // Not equal is always split into '==' and negate, 2156 // Not equal is always split into '==' and negate,
2157 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 2157 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2158 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); 2158 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind();
2159 const String& function_name = 2159 const String& function_name =
2160 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); 2160 String::ZoneHandle(Symbols::New(Token::Str(call_kind)));
2161 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 2161 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
2162 cid(), 2162 deopt_id(),
2163 token_pos(), 2163 token_pos(),
2164 try_index()); 2164 try_index());
2165 const intptr_t kNumArguments = 2; 2165 const intptr_t kNumArguments = 2;
2166 const intptr_t kNumArgsChecked = 2; // Type-feedback. 2166 const intptr_t kNumArgsChecked = 2; // Type-feedback.
2167 compiler->GenerateInstanceCall(cid(), 2167 compiler->GenerateInstanceCall(deopt_id(),
2168 token_pos(), 2168 token_pos(),
2169 try_index(), 2169 try_index(),
2170 function_name, 2170 function_name,
2171 kNumArguments, 2171 kNumArguments,
2172 Array::ZoneHandle(), // No optional arguments. 2172 Array::ZoneHandle(), // No optional arguments.
2173 kNumArgsChecked); 2173 kNumArgsChecked);
2174 ASSERT(locs()->out().reg() == RAX); 2174 ASSERT(locs()->out().reg() == RAX);
2175 __ CompareObject(locs()->out().reg(), compiler->bool_true()); 2175 __ CompareObject(locs()->out().reg(), compiler->bool_true());
2176 EmitBranchOnCondition(compiler, branch_condition); 2176 EmitBranchOnCondition(compiler, branch_condition);
2177 } 2177 }
2178 2178
2179 } // namespace dart 2179 } // namespace dart
2180 2180
2181 #undef __ 2181 #undef __
2182 2182
2183 #endif // defined TARGET_ARCH_X64 2183 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698