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

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
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/isolate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 LocationSummary::kNoCall); 973 LocationSummary::kNoCall);
974 } 974 }
975 975
976 976
977 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 977 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
978 Register instance_reg = locs()->in(0).reg(); 978 Register instance_reg = locs()->in(0).reg();
979 Register result_reg = locs()->out().reg(); 979 Register result_reg = locs()->out().reg();
980 980
981 if (HasICData()) { 981 if (HasICData()) {
982 ASSERT(original() != NULL); 982 ASSERT(original() != NULL);
983 Label* deopt = compiler->AddDeoptStub(original()->cid(), 983 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
984 original()->token_pos(), 984 original()->token_pos(),
985 original()->try_index(), 985 original()->try_index(),
986 kDeoptInstanceGetterSameTarget, 986 kDeoptInstanceGetterSameTarget,
987 instance_reg); 987 instance_reg);
988 // Smis do not have instance fields (Smi class is always first). 988 // Smis do not have instance fields (Smi class is always first).
989 // Use 'result' as temporary register. 989 // Use 'result' as temporary register.
990 ASSERT(result_reg != instance_reg); 990 ASSERT(result_reg != instance_reg);
991 ASSERT(ic_data() != NULL); 991 ASSERT(ic_data() != NULL);
992 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 992 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
993 } 993 }
(...skipping 26 matching lines...) Expand all
1020 summary->set_out(Location::RegisterLocation(RAX)); 1020 summary->set_out(Location::RegisterLocation(RAX));
1021 return summary; 1021 return summary;
1022 } 1022 }
1023 1023
1024 1024
1025 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1025 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1026 ASSERT(locs()->in(0).reg() == RAX); // Value. 1026 ASSERT(locs()->in(0).reg() == RAX); // Value.
1027 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. 1027 ASSERT(locs()->in(1).reg() == RCX); // Instantiator.
1028 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. 1028 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments.
1029 1029
1030 compiler->GenerateInstanceOf(cid(), 1030 compiler->GenerateInstanceOf(deopt_id(),
1031 token_pos(), 1031 token_pos(),
1032 try_index(), 1032 try_index(),
1033 type(), 1033 type(),
1034 negate_result()); 1034 negate_result());
1035 ASSERT(locs()->out().reg() == RAX); 1035 ASSERT(locs()->out().reg() == RAX);
1036 } 1036 }
1037 1037
1038 1038
1039 LocationSummary* CreateArrayComp::MakeLocationSummary() const { 1039 LocationSummary* CreateArrayComp::MakeLocationSummary() const {
1040 return MakeCallSummary(); 1040 return MakeCallSummary();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 const Class& cls = Class::ZoneHandle(constructor().owner()); 1079 const Class& cls = Class::ZoneHandle(constructor().owner());
1080 Register type_arguments = locs()->in(0).reg(); 1080 Register type_arguments = locs()->in(0).reg();
1081 Register instantiator_type_arguments = locs()->in(1).reg(); 1081 Register instantiator_type_arguments = locs()->in(1).reg();
1082 Register result = locs()->out().reg(); 1082 Register result = locs()->out().reg();
1083 1083
1084 // Push the result place holder initialized to NULL. 1084 // Push the result place holder initialized to NULL.
1085 __ PushObject(Object::ZoneHandle()); 1085 __ PushObject(Object::ZoneHandle());
1086 __ PushObject(cls); 1086 __ PushObject(cls);
1087 __ pushq(type_arguments); 1087 __ pushq(type_arguments);
1088 __ pushq(instantiator_type_arguments); 1088 __ pushq(instantiator_type_arguments);
1089 compiler->GenerateCallRuntime(cid(), 1089 compiler->GenerateCallRuntime(deopt_id(),
1090 token_pos(), 1090 token_pos(),
1091 try_index(), 1091 try_index(),
1092 kAllocateObjectWithBoundsCheckRuntimeEntry); 1092 kAllocateObjectWithBoundsCheckRuntimeEntry);
1093 // Pop instantiator type arguments, type arguments, and class. 1093 // Pop instantiator type arguments, type arguments, and class.
1094 __ Drop(3); 1094 __ Drop(3);
1095 __ popq(result); // Pop new instance. 1095 __ popq(result); // Pop new instance.
1096 } 1096 }
1097 1097
1098 1098
1099 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { 1099 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const {
1100 return LocationSummary::Make(1, 1100 return LocationSummary::Make(1,
1101 Location::RequiresRegister(), 1101 Location::RequiresRegister(),
1102 LocationSummary::kNoCall); 1102 LocationSummary::kNoCall);
1103 } 1103 }
1104 1104
1105 1105
1106 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1106 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1107 Register instance_reg = locs()->in(0).reg(); 1107 Register instance_reg = locs()->in(0).reg();
1108 Register result_reg = locs()->out().reg(); 1108 Register result_reg = locs()->out().reg();
1109 if (HasICData()) { 1109 if (HasICData()) {
1110 ASSERT(original() != NULL); 1110 ASSERT(original() != NULL);
1111 Label* deopt = compiler->AddDeoptStub(original()->cid(), 1111 Label* deopt = compiler->AddDeoptStub(original()->deopt_id(),
1112 original()->token_pos(), 1112 original()->token_pos(),
1113 original()->try_index(), 1113 original()->try_index(),
1114 kDeoptInstanceGetterSameTarget, 1114 kDeoptInstanceGetterSameTarget,
1115 instance_reg); 1115 instance_reg);
1116 // Smis do not have instance fields (Smi class is always first). 1116 // Smis do not have instance fields (Smi class is always first).
1117 // Use 'result' as temporary register. 1117 // Use 'result' as temporary register.
1118 ASSERT(result_reg != instance_reg); 1118 ASSERT(result_reg != instance_reg);
1119 ASSERT(ic_data() != NULL); 1119 ASSERT(ic_data() != NULL);
1120 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); 1120 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt);
1121 } 1121 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); 1165 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump);
1166 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), 1166 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()),
1167 Immediate(Smi::RawValue(len))); 1167 Immediate(Smi::RawValue(len)));
1168 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 1168 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
1169 __ Bind(&type_arguments_uninstantiated); 1169 __ Bind(&type_arguments_uninstantiated);
1170 } 1170 }
1171 // A runtime call to instantiate the type arguments is required. 1171 // A runtime call to instantiate the type arguments is required.
1172 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1172 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1173 __ PushObject(type_arguments()); 1173 __ PushObject(type_arguments());
1174 __ pushq(instantiator_reg); // Push instantiator type arguments. 1174 __ pushq(instantiator_reg); // Push instantiator type arguments.
1175 compiler->GenerateCallRuntime(cid(), 1175 compiler->GenerateCallRuntime(deopt_id(),
1176 token_pos(), 1176 token_pos(),
1177 try_index(), 1177 try_index(),
1178 kInstantiateTypeArgumentsRuntimeEntry); 1178 kInstantiateTypeArgumentsRuntimeEntry);
1179 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 1179 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
1180 __ popq(result_reg); // Pop instantiated type arguments. 1180 __ popq(result_reg); // Pop instantiated type arguments.
1181 __ Bind(&type_arguments_instantiated); 1181 __ Bind(&type_arguments_instantiated);
1182 ASSERT(instantiator_reg == result_reg); 1182 ASSERT(instantiator_reg == result_reg);
1183 // 'result_reg': Instantiated type arguments. 1183 // 'result_reg': Instantiated type arguments.
1184 } 1184 }
1185 1185
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 return locs; 1341 return locs;
1342 } 1342 }
1343 1343
1344 1344
1345 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1345 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1346 Register context_value = locs()->in(0).reg(); 1346 Register context_value = locs()->in(0).reg();
1347 Register result = locs()->out().reg(); 1347 Register result = locs()->out().reg();
1348 1348
1349 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1349 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1350 __ pushq(context_value); 1350 __ pushq(context_value);
1351 compiler->GenerateCallRuntime(cid(), 1351 compiler->GenerateCallRuntime(deopt_id(),
1352 token_pos(), 1352 token_pos(),
1353 try_index(), 1353 try_index(),
1354 kCloneContextRuntimeEntry); 1354 kCloneContextRuntimeEntry);
1355 __ popq(result); // Remove argument. 1355 __ popq(result); // Remove argument.
1356 __ popq(result); // Get result (cloned context). 1356 __ popq(result); // Get result (cloned context).
1357 } 1357 }
1358 1358
1359 1359
1360 LocationSummary* CatchEntryComp::MakeLocationSummary() const { 1360 LocationSummary* CatchEntryComp::MakeLocationSummary() const {
1361 return LocationSummary::Make(0, 1361 return LocationSummary::Make(0,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1397 } 1397 }
1398 1398
1399 1399
1400 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1400 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1401 Register temp = locs()->temp(0).reg(); 1401 Register temp = locs()->temp(0).reg();
1402 // Generate stack overflow check. 1402 // Generate stack overflow check.
1403 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); 1403 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address()));
1404 __ cmpq(RSP, Address(temp, 0)); 1404 __ cmpq(RSP, Address(temp, 0));
1405 Label no_stack_overflow; 1405 Label no_stack_overflow;
1406 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); 1406 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump);
1407 compiler->GenerateCallRuntime(cid(), 1407 compiler->GenerateCallRuntime(deopt_id(),
1408 token_pos(), 1408 token_pos(),
1409 try_index(), 1409 try_index(),
1410 kStackOverflowRuntimeEntry); 1410 kStackOverflowRuntimeEntry);
1411 __ Bind(&no_stack_overflow); 1411 __ Bind(&no_stack_overflow);
1412 } 1412 }
1413 1413
1414 1414
1415 LocationSummary* BinaryOpComp::MakeLocationSummary() const { 1415 LocationSummary* BinaryOpComp::MakeLocationSummary() const {
1416 const intptr_t kNumInputs = 2; 1416 const intptr_t kNumInputs = 2;
1417 1417
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 } 1475 }
1476 } 1476 }
1477 1477
1478 1478
1479 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1479 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1480 Register left = comp->locs()->in(0).reg(); 1480 Register left = comp->locs()->in(0).reg();
1481 Register right = comp->locs()->in(1).reg(); 1481 Register right = comp->locs()->in(1).reg();
1482 Register result = comp->locs()->out().reg(); 1482 Register result = comp->locs()->out().reg();
1483 Register temp = comp->locs()->temp(0).reg(); 1483 Register temp = comp->locs()->temp(0).reg();
1484 ASSERT(left == result); 1484 ASSERT(left == result);
1485 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1485 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1486 comp->instance_call()->token_pos(), 1486 comp->instance_call()->token_pos(),
1487 comp->instance_call()->try_index(), 1487 comp->instance_call()->try_index(),
1488 kDeoptSmiBinaryOp, 1488 kDeoptSmiBinaryOp,
1489 temp, 1489 temp,
1490 right); 1490 right);
1491 // TODO(vegorov): for many binary operations this pattern can be rearranged 1491 // TODO(vegorov): for many binary operations this pattern can be rearranged
1492 // to save one move. 1492 // to save one move.
1493 __ movq(temp, left); 1493 __ movq(temp, left);
1494 __ orq(left, right); 1494 __ orq(left, right);
1495 __ testq(left, Immediate(kSmiTagMask)); 1495 __ testq(left, Immediate(kSmiTagMask));
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 __ shlq(left, right_temp); 1586 __ shlq(left, right_temp);
1587 __ jmp(&done); 1587 __ jmp(&done);
1588 { 1588 {
1589 __ Bind(&call_method); 1589 __ Bind(&call_method);
1590 Function& target = Function::ZoneHandle( 1590 Function& target = Function::ZoneHandle(
1591 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1591 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1592 ASSERT(!target.IsNull()); 1592 ASSERT(!target.IsNull());
1593 const intptr_t kArgumentCount = 2; 1593 const intptr_t kArgumentCount = 2;
1594 __ pushq(temp); 1594 __ pushq(temp);
1595 __ pushq(right); 1595 __ pushq(right);
1596 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1596 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1597 comp->instance_call()->token_pos(), 1597 comp->instance_call()->token_pos(),
1598 comp->instance_call()->try_index(), 1598 comp->instance_call()->try_index(),
1599 target, 1599 target,
1600 kArgumentCount, 1600 kArgumentCount,
1601 Array::Handle()); // No argument names. 1601 Array::Handle()); // No argument names.
1602 ASSERT(result == RAX); 1602 ASSERT(result == RAX);
1603 } 1603 }
1604 __ Bind(&done); 1604 __ Bind(&done);
1605 break; 1605 break;
1606 } 1606 }
(...skipping 25 matching lines...) Expand all
1632 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { 1632 static void EmitMintBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) {
1633 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi 1633 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi
1634 // receiver and a Mint or Smi argument. We fall back to the run time call if 1634 // receiver and a Mint or Smi argument. We fall back to the run time call if
1635 // both receiver and argument are Mint or if one of them is Mint and the other 1635 // both receiver and argument are Mint or if one of them is Mint and the other
1636 // is a negative Smi. 1636 // is a negative Smi.
1637 Register left = comp->locs()->in(0).reg(); 1637 Register left = comp->locs()->in(0).reg();
1638 Register right = comp->locs()->in(1).reg(); 1638 Register right = comp->locs()->in(1).reg();
1639 Register result = comp->locs()->out().reg(); 1639 Register result = comp->locs()->out().reg();
1640 ASSERT(left == result); 1640 ASSERT(left == result);
1641 ASSERT(comp->op_kind() == Token::kBIT_AND); 1641 ASSERT(comp->op_kind() == Token::kBIT_AND);
1642 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), 1642 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->deopt_id(),
1643 comp->instance_call()->token_pos(), 1643 comp->instance_call()->token_pos(),
1644 comp->instance_call()->try_index(), 1644 comp->instance_call()->try_index(),
1645 kDeoptMintBinaryOp, 1645 kDeoptMintBinaryOp,
1646 left, 1646 left,
1647 right); 1647 right);
1648 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; 1648 Label mint_static_call, smi_static_call, non_smi, smi_smi, done;
1649 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? 1649 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi?
1650 __ j(NOT_ZERO, &non_smi); 1650 __ j(NOT_ZERO, &non_smi);
1651 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? 1651 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi?
1652 __ j(ZERO, &smi_smi); 1652 __ j(ZERO, &smi_smi);
(...skipping 27 matching lines...) Expand all
1680 1680
1681 __ Bind(&smi_static_call); 1681 __ Bind(&smi_static_call);
1682 { 1682 {
1683 Function& target = Function::ZoneHandle( 1683 Function& target = Function::ZoneHandle(
1684 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); 1684 comp->ic_data()->GetTargetForReceiverClassId(kSmi));
1685 if (target.IsNull()) { 1685 if (target.IsNull()) {
1686 __ jmp(deopt); 1686 __ jmp(deopt);
1687 } else { 1687 } else {
1688 __ pushq(left); 1688 __ pushq(left);
1689 __ pushq(right); 1689 __ pushq(right);
1690 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1690 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1691 comp->instance_call()->token_pos(), 1691 comp->instance_call()->token_pos(),
1692 comp->instance_call()->try_index(), 1692 comp->instance_call()->try_index(),
1693 target, 1693 target,
1694 comp->instance_call()->ArgumentCount(), 1694 comp->instance_call()->ArgumentCount(),
1695 comp->instance_call()->argument_names()); 1695 comp->instance_call()->argument_names());
1696 ASSERT(result == RAX); 1696 ASSERT(result == RAX);
1697 __ jmp(&done); 1697 __ jmp(&done);
1698 } 1698 }
1699 } 1699 }
1700 1700
1701 __ Bind(&mint_static_call); 1701 __ Bind(&mint_static_call);
1702 { 1702 {
1703 Function& target = Function::ZoneHandle( 1703 Function& target = Function::ZoneHandle(
1704 comp->ic_data()->GetTargetForReceiverClassId(kMint)); 1704 comp->ic_data()->GetTargetForReceiverClassId(kMint));
1705 if (target.IsNull()) { 1705 if (target.IsNull()) {
1706 __ jmp(deopt); 1706 __ jmp(deopt);
1707 } else { 1707 } else {
1708 __ pushq(left); 1708 __ pushq(left);
1709 __ pushq(right); 1709 __ pushq(right);
1710 compiler->GenerateStaticCall(comp->instance_call()->cid(), 1710 compiler->GenerateStaticCall(comp->instance_call()->deopt_id(),
1711 comp->instance_call()->token_pos(), 1711 comp->instance_call()->token_pos(),
1712 comp->instance_call()->try_index(), 1712 comp->instance_call()->try_index(),
1713 target, 1713 target,
1714 comp->instance_call()->ArgumentCount(), 1714 comp->instance_call()->ArgumentCount(),
1715 comp->instance_call()->argument_names()); 1715 comp->instance_call()->argument_names());
1716 ASSERT(result == RAX); 1716 ASSERT(result == RAX);
1717 } 1717 }
1718 } 1718 }
1719 __ Bind(&done); 1719 __ Bind(&done);
1720 } 1720 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); 1753 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint());
1754 compiler->GenerateCall(instance_call()->token_pos(), 1754 compiler->GenerateCall(instance_call()->token_pos(),
1755 instance_call()->try_index(), 1755 instance_call()->try_index(),
1756 &label, 1756 &label,
1757 PcDescriptors::kOther); 1757 PcDescriptors::kOther);
1758 // Newly allocated object is now in the result register (RAX). 1758 // Newly allocated object is now in the result register (RAX).
1759 ASSERT(result == RAX); 1759 ASSERT(result == RAX);
1760 __ popq(right); 1760 __ popq(right);
1761 __ popq(left); 1761 __ popq(left);
1762 1762
1763 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1763 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1764 instance_call()->token_pos(), 1764 instance_call()->token_pos(),
1765 instance_call()->try_index(), 1765 instance_call()->try_index(),
1766 kDeoptDoubleBinaryOp, 1766 kDeoptDoubleBinaryOp,
1767 left, 1767 left,
1768 right); 1768 right);
1769 1769
1770 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); 1770 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt);
1771 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); 1771 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt);
1772 1772
1773 switch (op_kind()) { 1773 switch (op_kind()) {
(...skipping 25 matching lines...) Expand all
1799 ASSERT(ic_data.num_args_tested() == 1); 1799 ASSERT(ic_data.num_args_tested() == 1);
1800 // TODO(srdjan): Implement for more checks. 1800 // TODO(srdjan): Implement for more checks.
1801 ASSERT(ic_data.NumberOfChecks() == 1); 1801 ASSERT(ic_data.NumberOfChecks() == 1);
1802 intptr_t test_class_id; 1802 intptr_t test_class_id;
1803 Function& target = Function::Handle(); 1803 Function& target = Function::Handle();
1804 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1804 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1805 1805
1806 Register value = locs()->in(0).reg(); 1806 Register value = locs()->in(0).reg();
1807 Register result = locs()->out().reg(); 1807 Register result = locs()->out().reg();
1808 ASSERT(value == result); 1808 ASSERT(value == result);
1809 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1809 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1810 instance_call()->token_pos(), 1810 instance_call()->token_pos(),
1811 instance_call()->try_index(), 1811 instance_call()->try_index(),
1812 kDeoptUnaryOp, 1812 kDeoptUnaryOp,
1813 value); 1813 value);
1814 if (test_class_id == kSmi) { 1814 if (test_class_id == kSmi) {
1815 __ testq(value, Immediate(kSmiTagMask)); 1815 __ testq(value, Immediate(kSmiTagMask));
1816 __ j(NOT_ZERO, deopt); 1816 __ j(NOT_ZERO, deopt);
1817 switch (op_kind()) { 1817 switch (op_kind()) {
1818 case Token::kNEGATE: 1818 case Token::kNEGATE:
1819 __ negq(value); 1819 __ negq(value);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 1851
1852 // TODO(srdjan): Implement for more checks. 1852 // TODO(srdjan): Implement for more checks.
1853 ASSERT(ic_data.NumberOfChecks() == 1); 1853 ASSERT(ic_data.NumberOfChecks() == 1);
1854 intptr_t test_class_id; 1854 intptr_t test_class_id;
1855 Function& target = Function::Handle(); 1855 Function& target = Function::Handle();
1856 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); 1856 ic_data.GetOneClassCheckAt(0, &test_class_id, &target);
1857 1857
1858 Register value = locs()->in(0).reg(); 1858 Register value = locs()->in(0).reg();
1859 Register result = locs()->out().reg(); 1859 Register result = locs()->out().reg();
1860 ASSERT(value == result); 1860 ASSERT(value == result);
1861 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1861 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1862 instance_call()->token_pos(), 1862 instance_call()->token_pos(),
1863 instance_call()->try_index(), 1863 instance_call()->try_index(),
1864 kDeoptUnaryOp, 1864 kDeoptUnaryOp,
1865 value); 1865 value);
1866 if (test_class_id == kDouble) { 1866 if (test_class_id == kDouble) {
1867 Register temp = locs()->temp(0).reg(); 1867 Register temp = locs()->temp(0).reg();
1868 __ testq(value, Immediate(kSmiTagMask)); 1868 __ testq(value, Immediate(kSmiTagMask));
1869 __ j(ZERO, deopt); // Smi. 1869 __ j(ZERO, deopt); // Smi.
1870 __ CompareClassId(value, kDouble); 1870 __ CompareClassId(value, kDouble);
1871 __ j(NOT_EQUAL, deopt); 1871 __ j(NOT_EQUAL, deopt);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 } 1907 }
1908 } 1908 }
1909 1909
1910 1910
1911 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1911 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1912 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; 1912 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX;
1913 Register result = locs()->out().reg(); 1913 Register result = locs()->out().reg();
1914 1914
1915 const DeoptReasonId deopt_reason = (from() == kDouble) ? 1915 const DeoptReasonId deopt_reason = (from() == kDouble) ?
1916 kDeoptDoubleToDouble : kDeoptIntegerToDouble; 1916 kDeoptDoubleToDouble : kDeoptIntegerToDouble;
1917 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1917 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1918 instance_call()->token_pos(), 1918 instance_call()->token_pos(),
1919 instance_call()->try_index(), 1919 instance_call()->try_index(),
1920 deopt_reason, 1920 deopt_reason,
1921 value); 1921 value);
1922 1922
1923 if (from() == kDouble) { 1923 if (from() == kDouble) {
1924 __ testq(value, Immediate(kSmiTagMask)); 1924 __ testq(value, Immediate(kSmiTagMask));
1925 __ j(ZERO, deopt); // Deoptimize if Smi. 1925 __ j(ZERO, deopt); // Deoptimize if Smi.
1926 __ CompareClassId(value, kDouble); 1926 __ CompareClassId(value, kDouble);
1927 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. 1927 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double.
(...skipping 23 matching lines...) Expand all
1951 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); 1951 __ movsd(FieldAddress(result, Double::value_offset()), XMM0);
1952 } 1952 }
1953 1953
1954 1954
1955 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { 1955 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const {
1956 return MakeCallSummary(); 1956 return MakeCallSummary();
1957 } 1957 }
1958 1958
1959 1959
1960 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { 1960 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) {
1961 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), 1961 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(),
1962 instance_call()->token_pos(), 1962 instance_call()->token_pos(),
1963 instance_call()->try_index(), 1963 instance_call()->try_index(),
1964 kDeoptPolymorphicInstanceCallTestFail); 1964 kDeoptPolymorphicInstanceCallTestFail);
1965 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { 1965 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) {
1966 __ jmp(deopt); 1966 __ jmp(deopt);
1967 return; 1967 return;
1968 } 1968 }
1969 ASSERT(HasICData()); 1969 ASSERT(HasICData());
1970 ASSERT(ic_data()->num_args_tested() == 1); 1970 ASSERT(ic_data()->num_args_tested() == 1);
1971 Label handle_smi; 1971 Label handle_smi;
1972 Label* is_smi_label = 1972 Label* is_smi_label =
1973 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; 1973 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt;
1974 1974
1975 // Load receiver into RAX. 1975 // Load receiver into RAX.
1976 __ movq(RAX, 1976 __ movq(RAX,
1977 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); 1977 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize));
1978 __ testq(RAX, Immediate(kSmiTagMask)); 1978 __ testq(RAX, Immediate(kSmiTagMask));
1979 __ j(ZERO, is_smi_label); 1979 __ j(ZERO, is_smi_label);
1980 Label done; 1980 Label done;
1981 __ LoadClassId(RDI, RAX); 1981 __ LoadClassId(RDI, RAX);
1982 compiler->EmitTestAndCall(*ic_data(), 1982 compiler->EmitTestAndCall(*ic_data(),
1983 RDI, // Class id register. 1983 RDI, // Class id register.
1984 instance_call()->ArgumentCount(), 1984 instance_call()->ArgumentCount(),
1985 instance_call()->argument_names(), 1985 instance_call()->argument_names(),
1986 deopt, 1986 deopt,
1987 (is_smi_label == &handle_smi) ? &done : NULL, 1987 (is_smi_label == &handle_smi) ? &done : NULL,
1988 instance_call()->cid(), 1988 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 if (is_smi_label == &handle_smi) { 1991 if (is_smi_label == &handle_smi) {
1992 __ Bind(&handle_smi); 1992 __ Bind(&handle_smi);
1993 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); 1993 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi);
1994 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); 1994 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0));
1995 compiler->GenerateStaticCall(instance_call()->cid(), 1995 compiler->GenerateStaticCall(instance_call()->deopt_id(),
1996 instance_call()->token_pos(), 1996 instance_call()->token_pos(),
1997 instance_call()->try_index(), 1997 instance_call()->try_index(),
1998 target, 1998 target,
1999 instance_call()->ArgumentCount(), 1999 instance_call()->ArgumentCount(),
2000 instance_call()->argument_names()); 2000 instance_call()->argument_names());
2001 } 2001 }
2002 __ Bind(&done); 2002 __ Bind(&done);
2003 } 2003 }
2004 2004
2005 2005
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2059 Register right = locs()->in(1).reg(); 2059 Register right = locs()->in(1).reg();
2060 __ cmpq(left, right); 2060 __ cmpq(left, right);
2061 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; 2061 Condition cond = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL;
2062 EmitBranchOnCondition(compiler, cond); 2062 EmitBranchOnCondition(compiler, cond);
2063 return; 2063 return;
2064 } 2064 }
2065 // Relational or equality. 2065 // Relational or equality.
2066 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { 2066 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) {
2067 if (ICDataWithBothClassIds(*ic_data(), kSmi)) { 2067 if (ICDataWithBothClassIds(*ic_data(), kSmi)) {
2068 EmitSmiComparisonOp(compiler, *locs(), kind(), this, 2068 EmitSmiComparisonOp(compiler, *locs(), kind(), this,
2069 cid(), token_pos(), try_index()); 2069 deopt_id(), token_pos(), try_index());
2070 return; 2070 return;
2071 } 2071 }
2072 if (ICDataWithBothClassIds(*ic_data(), kDouble)) { 2072 if (ICDataWithBothClassIds(*ic_data(), kDouble)) {
2073 EmitDoubleComparisonOp(compiler, *locs(), kind(), this, 2073 EmitDoubleComparisonOp(compiler, *locs(), kind(), this,
2074 cid(), token_pos(), try_index()); 2074 deopt_id(), token_pos(), try_index());
2075 return; 2075 return;
2076 } 2076 }
2077 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. 2077 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons.
2078 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { 2078 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) {
2079 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), 2079 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(),
2080 cid(), token_pos(), try_index()); 2080 deopt_id(), token_pos(), try_index());
2081 return; 2081 return;
2082 } 2082 }
2083 // Otherwise polymorphic dispatch? 2083 // Otherwise polymorphic dispatch?
2084 } 2084 }
2085 // Not equal is always split into '==' and negate, 2085 // Not equal is always split into '==' and negate,
2086 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 2086 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
2087 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind(); 2087 Token::Kind call_kind = (kind() == Token::kNE) ? Token::kEQ : kind();
2088 const String& function_name = 2088 const String& function_name =
2089 String::ZoneHandle(Symbols::New(Token::Str(call_kind))); 2089 String::ZoneHandle(Symbols::New(Token::Str(call_kind)));
2090 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 2090 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
2091 cid(), 2091 deopt_id(),
2092 token_pos(), 2092 token_pos(),
2093 try_index()); 2093 try_index());
2094 const intptr_t kNumArguments = 2; 2094 const intptr_t kNumArguments = 2;
2095 const intptr_t kNumArgsChecked = 2; // Type-feedback. 2095 const intptr_t kNumArgsChecked = 2; // Type-feedback.
2096 compiler->GenerateInstanceCall(cid(), 2096 compiler->GenerateInstanceCall(deopt_id(),
2097 token_pos(), 2097 token_pos(),
2098 try_index(), 2098 try_index(),
2099 function_name, 2099 function_name,
2100 kNumArguments, 2100 kNumArguments,
2101 Array::ZoneHandle(), // No optional arguments. 2101 Array::ZoneHandle(), // No optional arguments.
2102 kNumArgsChecked); 2102 kNumArgsChecked);
2103 ASSERT(locs()->out().reg() == RAX); 2103 ASSERT(locs()->out().reg() == RAX);
2104 __ CompareObject(locs()->out().reg(), compiler->bool_true()); 2104 __ CompareObject(locs()->out().reg(), compiler->bool_true());
2105 EmitBranchOnCondition(compiler, branch_condition); 2105 EmitBranchOnCondition(compiler, branch_condition);
2106 } 2106 }
2107 2107
2108 } // namespace dart 2108 } // namespace dart
2109 2109
2110 #undef __ 2110 #undef __
2111 2111
2112 #endif // defined TARGET_ARCH_X64 2112 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | runtime/vm/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698