| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 __ CompareObject(obj, compiler->bool_true()); | 217 __ CompareObject(obj, compiler->bool_true()); |
| 218 __ j(EQUAL, &done, Assembler::kNearJump); | 218 __ j(EQUAL, &done, Assembler::kNearJump); |
| 219 __ CompareObject(obj, compiler->bool_false()); | 219 __ CompareObject(obj, compiler->bool_false()); |
| 220 __ j(EQUAL, &done, Assembler::kNearJump); | 220 __ j(EQUAL, &done, Assembler::kNearJump); |
| 221 | 221 |
| 222 __ pushq(obj); // Push the source object. | 222 __ pushq(obj); // Push the source object. |
| 223 compiler->GenerateCallRuntime(deopt_id(), | 223 compiler->GenerateCallRuntime(deopt_id(), |
| 224 token_pos(), | 224 token_pos(), |
| 225 try_index(), | 225 try_index(), |
| 226 kConditionTypeErrorRuntimeEntry, | 226 kConditionTypeErrorRuntimeEntry, |
| 227 locs()->stack_bitmap()); | 227 locs()); |
| 228 // We should never return here. | 228 // We should never return here. |
| 229 __ int3(); | 229 __ int3(); |
| 230 __ Bind(&done); | 230 __ Bind(&done); |
| 231 } | 231 } |
| 232 ASSERT(obj == result); | 232 ASSERT(obj == result); |
| 233 } | 233 } |
| 234 | 234 |
| 235 | 235 |
| 236 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 236 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 237 switch (kind) { | 237 switch (kind) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 locs->set_out(Location::RegisterLocation(RAX)); | 282 locs->set_out(Location::RegisterLocation(RAX)); |
| 283 return locs; | 283 return locs; |
| 284 } | 284 } |
| 285 | 285 |
| 286 | 286 |
| 287 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 287 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 288 intptr_t deopt_id, | 288 intptr_t deopt_id, |
| 289 intptr_t token_pos, | 289 intptr_t token_pos, |
| 290 intptr_t try_index, | 290 intptr_t try_index, |
| 291 Token::Kind kind, | 291 Token::Kind kind, |
| 292 const LocationSummary& locs) { | 292 LocationSummary* locs) { |
| 293 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 293 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 294 deopt_id, | 294 deopt_id, |
| 295 token_pos, | 295 token_pos, |
| 296 try_index); | 296 try_index); |
| 297 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 297 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 298 const int kNumberOfArguments = 2; | 298 const int kNumberOfArguments = 2; |
| 299 const Array& kNoArgumentNames = Array::Handle(); | 299 const Array& kNoArgumentNames = Array::Handle(); |
| 300 const int kNumArgumentsChecked = 2; | 300 const int kNumArgumentsChecked = 2; |
| 301 | 301 |
| 302 Label done, false_label, true_label; | 302 Label done, false_label, true_label; |
| 303 Register left = locs.in(0).reg(); | 303 Register left = locs->in(0).reg(); |
| 304 Register right = locs.in(1).reg(); | 304 Register right = locs->in(1).reg(); |
| 305 __ popq(right); | 305 __ popq(right); |
| 306 __ popq(left); | 306 __ popq(left); |
| 307 const Immediate raw_null = | 307 const Immediate raw_null = |
| 308 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 308 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 309 Label check_identity, instance_call; | 309 Label check_identity, instance_call; |
| 310 __ cmpq(right, raw_null); | 310 __ cmpq(right, raw_null); |
| 311 __ j(EQUAL, &check_identity, Assembler::kNearJump); | 311 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 312 __ cmpq(left, raw_null); | 312 __ cmpq(left, raw_null); |
| 313 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); | 313 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); |
| 314 | 314 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 329 __ Bind(&instance_call); | 329 __ Bind(&instance_call); |
| 330 __ pushq(left); | 330 __ pushq(left); |
| 331 __ pushq(right); | 331 __ pushq(right); |
| 332 compiler->GenerateInstanceCall(deopt_id, | 332 compiler->GenerateInstanceCall(deopt_id, |
| 333 token_pos, | 333 token_pos, |
| 334 try_index, | 334 try_index, |
| 335 operator_name, | 335 operator_name, |
| 336 kNumberOfArguments, | 336 kNumberOfArguments, |
| 337 kNoArgumentNames, | 337 kNoArgumentNames, |
| 338 kNumArgumentsChecked, | 338 kNumArgumentsChecked, |
| 339 locs.stack_bitmap()); | 339 locs); |
| 340 if (kind == Token::kNE) { | 340 if (kind == Token::kNE) { |
| 341 // Negate the condition: true label returns false and vice versa. | 341 // Negate the condition: true label returns false and vice versa. |
| 342 __ CompareObject(RAX, compiler->bool_true()); | 342 __ CompareObject(RAX, compiler->bool_true()); |
| 343 __ j(EQUAL, &true_label, Assembler::kNearJump); | 343 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 344 __ Bind(&false_label); | 344 __ Bind(&false_label); |
| 345 __ LoadObject(RAX, compiler->bool_true()); | 345 __ LoadObject(RAX, compiler->bool_true()); |
| 346 __ jmp(&done, Assembler::kNearJump); | 346 __ jmp(&done, Assembler::kNearJump); |
| 347 __ Bind(&true_label); | 347 __ Bind(&true_label); |
| 348 __ LoadObject(RAX, compiler->bool_false()); | 348 __ LoadObject(RAX, compiler->bool_false()); |
| 349 } | 349 } |
| 350 __ Bind(&done); | 350 __ Bind(&done); |
| 351 } | 351 } |
| 352 | 352 |
| 353 | 353 |
| 354 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 354 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 355 const ICData& orig_ic_data, | 355 const ICData& orig_ic_data, |
| 356 const LocationSummary& locs, | 356 LocationSummary* locs, |
| 357 BranchInstr* branch, | 357 BranchInstr* branch, |
| 358 Token::Kind kind, | 358 Token::Kind kind, |
| 359 intptr_t deopt_id, | 359 intptr_t deopt_id, |
| 360 intptr_t token_pos, | 360 intptr_t token_pos, |
| 361 intptr_t try_index, | 361 intptr_t try_index) { |
| 362 BitmapBuilder* stack_bitmap) { | |
| 363 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 362 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 364 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 363 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 365 ASSERT(ic_data.NumberOfChecks() > 0); | 364 ASSERT(ic_data.NumberOfChecks() > 0); |
| 366 ASSERT(ic_data.num_args_tested() == 1); | 365 ASSERT(ic_data.num_args_tested() == 1); |
| 367 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); | 366 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); |
| 368 Register left = locs.in(0).reg(); | 367 Register left = locs->in(0).reg(); |
| 369 Register right = locs.in(1).reg(); | 368 Register right = locs->in(1).reg(); |
| 370 __ testq(left, Immediate(kSmiTagMask)); | 369 __ testq(left, Immediate(kSmiTagMask)); |
| 371 Register temp = locs.temp(0).reg(); | 370 Register temp = locs->temp(0).reg(); |
| 372 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 371 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 373 Label done, load_class_id; | 372 Label done, load_class_id; |
| 374 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 373 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 375 __ movq(temp, Immediate(kSmiCid)); | 374 __ movq(temp, Immediate(kSmiCid)); |
| 376 __ jmp(&done, Assembler::kNearJump); | 375 __ jmp(&done, Assembler::kNearJump); |
| 377 __ Bind(&load_class_id); | 376 __ Bind(&load_class_id); |
| 378 __ LoadClassId(temp, left); | 377 __ LoadClassId(temp, left); |
| 379 __ Bind(&done); | 378 __ Bind(&done); |
| 380 } else { | 379 } else { |
| 381 __ j(ZERO, deopt); // Smi deopts. | 380 __ j(ZERO, deopt); // Smi deopts. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 393 __ j(NOT_EQUAL, &next_test); | 392 __ j(NOT_EQUAL, &next_test); |
| 394 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 393 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 395 if (target.Owner() == object_store->object_class()) { | 394 if (target.Owner() == object_store->object_class()) { |
| 396 // Object.== is same as ===. | 395 // Object.== is same as ===. |
| 397 __ Drop(2); | 396 __ Drop(2); |
| 398 __ cmpq(left, right); | 397 __ cmpq(left, right); |
| 399 if (branch != NULL) { | 398 if (branch != NULL) { |
| 400 branch->EmitBranchOnCondition(compiler, cond); | 399 branch->EmitBranchOnCondition(compiler, cond); |
| 401 } else { | 400 } else { |
| 402 // This case should be rare. | 401 // This case should be rare. |
| 403 Register result = locs.out().reg(); | 402 Register result = locs->out().reg(); |
| 404 Label load_true; | 403 Label load_true; |
| 405 __ j(cond, &load_true, Assembler::kNearJump); | 404 __ j(cond, &load_true, Assembler::kNearJump); |
| 406 __ LoadObject(result, compiler->bool_false()); | 405 __ LoadObject(result, compiler->bool_false()); |
| 407 __ jmp(&done); | 406 __ jmp(&done); |
| 408 __ Bind(&load_true); | 407 __ Bind(&load_true); |
| 409 __ LoadObject(result, compiler->bool_true()); | 408 __ LoadObject(result, compiler->bool_true()); |
| 410 } | 409 } |
| 411 } else { | 410 } else { |
| 412 const int kNumberOfArguments = 2; | 411 const int kNumberOfArguments = 2; |
| 413 const Array& kNoArgumentNames = Array::Handle(); | 412 const Array& kNoArgumentNames = Array::Handle(); |
| 414 compiler->GenerateStaticCall(deopt_id, | 413 compiler->GenerateStaticCall(deopt_id, |
| 415 token_pos, | 414 token_pos, |
| 416 try_index, | 415 try_index, |
| 417 target, | 416 target, |
| 418 kNumberOfArguments, | 417 kNumberOfArguments, |
| 419 kNoArgumentNames, | 418 kNoArgumentNames, |
| 420 stack_bitmap); | 419 locs); |
| 421 if (branch == NULL) { | 420 if (branch == NULL) { |
| 422 if (kind == Token::kNE) { | 421 if (kind == Token::kNE) { |
| 423 Label false_label; | 422 Label false_label; |
| 424 __ CompareObject(RAX, compiler->bool_true()); | 423 __ CompareObject(RAX, compiler->bool_true()); |
| 425 __ j(EQUAL, &false_label, Assembler::kNearJump); | 424 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 426 __ LoadObject(RAX, compiler->bool_true()); | 425 __ LoadObject(RAX, compiler->bool_true()); |
| 427 __ jmp(&done); | 426 __ jmp(&done); |
| 428 __ Bind(&false_label); | 427 __ Bind(&false_label); |
| 429 __ LoadObject(RAX, compiler->bool_false()); | 428 __ LoadObject(RAX, compiler->bool_false()); |
| 430 __ jmp(&done); | 429 __ jmp(&done); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 Condition cond = TokenKindToSmiCondition(kind); | 496 Condition cond = TokenKindToSmiCondition(kind); |
| 498 branch->EmitBranchOnCondition(compiler, cond); | 497 branch->EmitBranchOnCondition(compiler, cond); |
| 499 } | 498 } |
| 500 } | 499 } |
| 501 | 500 |
| 502 | 501 |
| 503 // First test if receiver is NULL, in which case === is applied. | 502 // First test if receiver is NULL, in which case === is applied. |
| 504 // If type feedback was provided (lists of <class-id, target>), do a | 503 // If type feedback was provided (lists of <class-id, target>), do a |
| 505 // type by type check (either === or static call to the operator. | 504 // type by type check (either === or static call to the operator. |
| 506 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 505 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 507 const LocationSummary& locs, | 506 LocationSummary* locs, |
| 508 Token::Kind kind, | 507 Token::Kind kind, |
| 509 BranchInstr* branch, | 508 BranchInstr* branch, |
| 510 const ICData& ic_data, | 509 const ICData& ic_data, |
| 511 intptr_t deopt_id, | 510 intptr_t deopt_id, |
| 512 intptr_t token_pos, | 511 intptr_t token_pos, |
| 513 intptr_t try_index) { | 512 intptr_t try_index) { |
| 514 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 513 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 515 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 514 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 516 Register left = locs.in(0).reg(); | 515 Register left = locs->in(0).reg(); |
| 517 Register right = locs.in(1).reg(); | 516 Register right = locs->in(1).reg(); |
| 518 const Immediate raw_null = | 517 const Immediate raw_null = |
| 519 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 518 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 520 Label done, identity_compare, non_null_compare; | 519 Label done, identity_compare, non_null_compare; |
| 521 __ cmpq(right, raw_null); | 520 __ cmpq(right, raw_null); |
| 522 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 521 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
| 523 __ cmpq(left, raw_null); | 522 __ cmpq(left, raw_null); |
| 524 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 523 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 525 // Comparison with NULL is "===". | 524 // Comparison with NULL is "===". |
| 526 __ Bind(&identity_compare); | 525 __ Bind(&identity_compare); |
| 527 __ cmpq(left, right); | 526 __ cmpq(left, right); |
| 528 Condition cond = TokenKindToSmiCondition(kind); | 527 Condition cond = TokenKindToSmiCondition(kind); |
| 529 if (branch != NULL) { | 528 if (branch != NULL) { |
| 530 branch->EmitBranchOnCondition(compiler, cond); | 529 branch->EmitBranchOnCondition(compiler, cond); |
| 531 } else { | 530 } else { |
| 532 Register result = locs.out().reg(); | 531 Register result = locs->out().reg(); |
| 533 Label load_true; | 532 Label load_true; |
| 534 __ j(cond, &load_true, Assembler::kNearJump); | 533 __ j(cond, &load_true, Assembler::kNearJump); |
| 535 __ LoadObject(result, compiler->bool_false()); | 534 __ LoadObject(result, compiler->bool_false()); |
| 536 __ jmp(&done); | 535 __ jmp(&done); |
| 537 __ Bind(&load_true); | 536 __ Bind(&load_true); |
| 538 __ LoadObject(result, compiler->bool_true()); | 537 __ LoadObject(result, compiler->bool_true()); |
| 539 } | 538 } |
| 540 __ jmp(&done); | 539 __ jmp(&done); |
| 541 __ Bind(&non_null_compare); // Receiver is not null. | 540 __ Bind(&non_null_compare); // Receiver is not null. |
| 542 __ pushq(left); | 541 __ pushq(left); |
| 543 __ pushq(right); | 542 __ pushq(right); |
| 544 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 543 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 545 deopt_id, token_pos, try_index, | 544 deopt_id, token_pos, try_index); |
| 546 locs.stack_bitmap()); | |
| 547 __ Bind(&done); | 545 __ Bind(&done); |
| 548 } | 546 } |
| 549 | 547 |
| 550 | 548 |
| 551 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 549 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 552 const LocationSummary& locs, | 550 const LocationSummary& locs, |
| 553 Token::Kind kind, | 551 Token::Kind kind, |
| 554 BranchInstr* branch, | 552 BranchInstr* branch, |
| 555 intptr_t deopt_id, | 553 intptr_t deopt_id, |
| 556 intptr_t token_pos, | 554 intptr_t token_pos, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 return; | 645 return; |
| 648 } | 646 } |
| 649 const bool is_checked_strict_equal = | 647 const bool is_checked_strict_equal = |
| 650 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 648 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 651 if (is_checked_strict_equal) { | 649 if (is_checked_strict_equal) { |
| 652 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 650 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, |
| 653 deopt_id(), token_pos(), try_index()); | 651 deopt_id(), token_pos(), try_index()); |
| 654 return; | 652 return; |
| 655 } | 653 } |
| 656 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 654 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 657 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), | 655 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), |
| 658 deopt_id(), token_pos(), try_index()); | 656 deopt_id(), token_pos(), try_index()); |
| 659 } else { | 657 } else { |
| 660 Register left = locs()->in(0).reg(); | 658 Register left = locs()->in(0).reg(); |
| 661 Register right = locs()->in(1).reg(); | 659 Register right = locs()->in(1).reg(); |
| 662 __ pushq(left); | 660 __ pushq(left); |
| 663 __ pushq(right); | 661 __ pushq(right); |
| 664 EmitEqualityAsInstanceCall(compiler, | 662 EmitEqualityAsInstanceCall(compiler, |
| 665 deopt_id(), | 663 deopt_id(), |
| 666 token_pos(), | 664 token_pos(), |
| 667 try_index(), | 665 try_index(), |
| 668 kind(), | 666 kind(), |
| 669 *locs()); | 667 locs()); |
| 670 ASSERT(locs()->out().reg() == RAX); | 668 ASSERT(locs()->out().reg() == RAX); |
| 671 } | 669 } |
| 672 } | 670 } |
| 673 | 671 |
| 674 | 672 |
| 675 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 673 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 676 const intptr_t kNumInputs = 2; | 674 const intptr_t kNumInputs = 2; |
| 677 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { | 675 if (operands_class_id() == kSmiCid || operands_class_id() == kDoubleCid) { |
| 678 const intptr_t kNumTemps = 1; | 676 const intptr_t kNumTemps = 1; |
| 679 LocationSummary* summary = | 677 LocationSummary* summary = |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 const intptr_t kNumArguments = 2; | 729 const intptr_t kNumArguments = 2; |
| 732 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 730 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 733 RDI, // Class id register. | 731 RDI, // Class id register. |
| 734 kNumArguments, | 732 kNumArguments, |
| 735 Array::Handle(), // No named arguments. | 733 Array::Handle(), // No named arguments. |
| 736 deopt, // Deoptimize target. | 734 deopt, // Deoptimize target. |
| 737 NULL, // Fallthrough when done. | 735 NULL, // Fallthrough when done. |
| 738 deopt_id(), | 736 deopt_id(), |
| 739 token_pos(), | 737 token_pos(), |
| 740 try_index(), | 738 try_index(), |
| 741 locs()->stack_bitmap()); | 739 locs()); |
| 742 ASSERT(locs()->out().reg() == RAX); | 740 ASSERT(locs()->out().reg() == RAX); |
| 743 return; | 741 return; |
| 744 } | 742 } |
| 745 const String& function_name = | 743 const String& function_name = |
| 746 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 744 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 747 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 745 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 748 deopt_id(), | 746 deopt_id(), |
| 749 token_pos(), | 747 token_pos(), |
| 750 try_index()); | 748 try_index()); |
| 751 const intptr_t kNumArguments = 2; | 749 const intptr_t kNumArguments = 2; |
| 752 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 750 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 753 compiler->GenerateInstanceCall(deopt_id(), | 751 compiler->GenerateInstanceCall(deopt_id(), |
| 754 token_pos(), | 752 token_pos(), |
| 755 try_index(), | 753 try_index(), |
| 756 function_name, | 754 function_name, |
| 757 kNumArguments, | 755 kNumArguments, |
| 758 Array::ZoneHandle(), // No optional arguments. | 756 Array::ZoneHandle(), // No optional arguments. |
| 759 kNumArgsChecked, | 757 kNumArgsChecked, |
| 760 locs()->stack_bitmap()); | 758 locs()); |
| 761 ASSERT(locs()->out().reg() == RAX); | 759 ASSERT(locs()->out().reg() == RAX); |
| 762 } | 760 } |
| 763 | 761 |
| 764 | 762 |
| 765 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 763 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 766 const intptr_t kNumInputs = 0; | 764 const intptr_t kNumInputs = 0; |
| 767 const intptr_t kNumTemps = 3; | 765 const intptr_t kNumTemps = 3; |
| 768 LocationSummary* locs = | 766 LocationSummary* locs = |
| 769 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 767 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 770 locs->set_temp(0, Location::RegisterLocation(RAX)); | 768 locs->set_temp(0, Location::RegisterLocation(RAX)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 793 } else { | 791 } else { |
| 794 __ leaq(RAX, | 792 __ leaq(RAX, |
| 795 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 793 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 796 } | 794 } |
| 797 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 795 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 798 __ movq(R10, Immediate(arg_count)); | 796 __ movq(R10, Immediate(arg_count)); |
| 799 compiler->GenerateCall(token_pos(), | 797 compiler->GenerateCall(token_pos(), |
| 800 try_index(), | 798 try_index(), |
| 801 &StubCode::CallNativeCFunctionLabel(), | 799 &StubCode::CallNativeCFunctionLabel(), |
| 802 PcDescriptors::kOther, | 800 PcDescriptors::kOther, |
| 803 locs()->stack_bitmap()); | 801 locs()); |
| 804 __ popq(result); | 802 __ popq(result); |
| 805 } | 803 } |
| 806 | 804 |
| 807 | 805 |
| 808 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 806 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 809 const intptr_t kNumInputs = 2; | 807 const intptr_t kNumInputs = 2; |
| 810 if (receiver_type() == kGrowableObjectArrayCid) { | 808 if (receiver_type() == kGrowableObjectArrayCid) { |
| 811 const intptr_t kNumTemps = 1; | 809 const intptr_t kNumTemps = 1; |
| 812 LocationSummary* locs = | 810 LocationSummary* locs = |
| 813 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 811 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1006 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1009 ASSERT(locs()->in(0).reg() == RAX); // Value. | 1007 ASSERT(locs()->in(0).reg() == RAX); // Value. |
| 1010 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 1008 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
| 1011 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 1009 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
| 1012 | 1010 |
| 1013 compiler->GenerateInstanceOf(deopt_id(), | 1011 compiler->GenerateInstanceOf(deopt_id(), |
| 1014 token_pos(), | 1012 token_pos(), |
| 1015 try_index(), | 1013 try_index(), |
| 1016 type(), | 1014 type(), |
| 1017 negate_result(), | 1015 negate_result(), |
| 1018 locs()->stack_bitmap()); | 1016 locs()); |
| 1019 ASSERT(locs()->out().reg() == RAX); | 1017 ASSERT(locs()->out().reg() == RAX); |
| 1020 } | 1018 } |
| 1021 | 1019 |
| 1022 | 1020 |
| 1023 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1021 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1024 const intptr_t kNumInputs = 1; | 1022 const intptr_t kNumInputs = 1; |
| 1025 const intptr_t kNumTemps = 0; | 1023 const intptr_t kNumTemps = 0; |
| 1026 LocationSummary* locs = | 1024 LocationSummary* locs = |
| 1027 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1025 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1028 locs->set_in(0, Location::RegisterLocation(RBX)); | 1026 locs->set_in(0, Location::RegisterLocation(RBX)); |
| 1029 locs->set_out(Location::RegisterLocation(RAX)); | 1027 locs->set_out(Location::RegisterLocation(RAX)); |
| 1030 return locs; | 1028 return locs; |
| 1031 } | 1029 } |
| 1032 | 1030 |
| 1033 | 1031 |
| 1034 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1032 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1035 // Allocate the array. R10 = length, RBX = element type. | 1033 // Allocate the array. R10 = length, RBX = element type. |
| 1036 ASSERT(locs()->in(0).reg() == RBX); | 1034 ASSERT(locs()->in(0).reg() == RBX); |
| 1037 __ movq(R10, Immediate(Smi::RawValue(ArgumentCount()))); | 1035 __ movq(R10, Immediate(Smi::RawValue(ArgumentCount()))); |
| 1038 compiler->GenerateCall(token_pos(), | 1036 compiler->GenerateCall(token_pos(), |
| 1039 try_index(), | 1037 try_index(), |
| 1040 &StubCode::AllocateArrayLabel(), | 1038 &StubCode::AllocateArrayLabel(), |
| 1041 PcDescriptors::kOther, | 1039 PcDescriptors::kOther, |
| 1042 locs()->stack_bitmap()); | 1040 locs()); |
| 1043 ASSERT(locs()->out().reg() == RAX); | 1041 ASSERT(locs()->out().reg() == RAX); |
| 1044 | 1042 |
| 1045 // Pop the element values from the stack into the array. | 1043 // Pop the element values from the stack into the array. |
| 1046 __ leaq(R10, FieldAddress(RAX, Array::data_offset())); | 1044 __ leaq(R10, FieldAddress(RAX, Array::data_offset())); |
| 1047 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1045 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
| 1048 ASSERT(ArgumentAt(i)->value()->IsUse()); | 1046 ASSERT(ArgumentAt(i)->value()->IsUse()); |
| 1049 __ popq(Address(R10, i * kWordSize)); | 1047 __ popq(Address(R10, i * kWordSize)); |
| 1050 } | 1048 } |
| 1051 } | 1049 } |
| 1052 | 1050 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1073 | 1071 |
| 1074 // Push the result place holder initialized to NULL. | 1072 // Push the result place holder initialized to NULL. |
| 1075 __ PushObject(Object::ZoneHandle()); | 1073 __ PushObject(Object::ZoneHandle()); |
| 1076 __ PushObject(cls); | 1074 __ PushObject(cls); |
| 1077 __ pushq(type_arguments); | 1075 __ pushq(type_arguments); |
| 1078 __ pushq(instantiator_type_arguments); | 1076 __ pushq(instantiator_type_arguments); |
| 1079 compiler->GenerateCallRuntime(deopt_id(), | 1077 compiler->GenerateCallRuntime(deopt_id(), |
| 1080 token_pos(), | 1078 token_pos(), |
| 1081 try_index(), | 1079 try_index(), |
| 1082 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1080 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1083 locs()->stack_bitmap()); | 1081 locs()); |
| 1084 // Pop instantiator type arguments, type arguments, and class. | 1082 // Pop instantiator type arguments, type arguments, and class. |
| 1085 __ Drop(3); | 1083 __ Drop(3); |
| 1086 __ popq(result); // Pop new instance. | 1084 __ popq(result); // Pop new instance. |
| 1087 } | 1085 } |
| 1088 | 1086 |
| 1089 | 1087 |
| 1090 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1088 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1091 return LocationSummary::Make(1, | 1089 return LocationSummary::Make(1, |
| 1092 Location::RequiresRegister(), | 1090 Location::RequiresRegister(), |
| 1093 LocationSummary::kNoCall); | 1091 LocationSummary::kNoCall); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 __ Bind(&type_arguments_uninstantiated); | 1156 __ Bind(&type_arguments_uninstantiated); |
| 1159 } | 1157 } |
| 1160 // A runtime call to instantiate the type arguments is required. | 1158 // A runtime call to instantiate the type arguments is required. |
| 1161 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1159 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1162 __ PushObject(type_arguments()); | 1160 __ PushObject(type_arguments()); |
| 1163 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1161 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 1164 compiler->GenerateCallRuntime(deopt_id(), | 1162 compiler->GenerateCallRuntime(deopt_id(), |
| 1165 token_pos(), | 1163 token_pos(), |
| 1166 try_index(), | 1164 try_index(), |
| 1167 kInstantiateTypeArgumentsRuntimeEntry, | 1165 kInstantiateTypeArgumentsRuntimeEntry, |
| 1168 locs()->stack_bitmap()); | 1166 locs()); |
| 1169 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1167 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1170 __ popq(result_reg); // Pop instantiated type arguments. | 1168 __ popq(result_reg); // Pop instantiated type arguments. |
| 1171 __ Bind(&type_arguments_instantiated); | 1169 __ Bind(&type_arguments_instantiated); |
| 1172 ASSERT(instantiator_reg == result_reg); | 1170 ASSERT(instantiator_reg == result_reg); |
| 1173 // 'result_reg': Instantiated type arguments. | 1171 // 'result_reg': Instantiated type arguments. |
| 1174 } | 1172 } |
| 1175 | 1173 |
| 1176 | 1174 |
| 1177 LocationSummary* | 1175 LocationSummary* |
| 1178 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 1176 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 ASSERT(locs()->temp(0).reg() == R10); | 1309 ASSERT(locs()->temp(0).reg() == R10); |
| 1312 ASSERT(locs()->out().reg() == RAX); | 1310 ASSERT(locs()->out().reg() == RAX); |
| 1313 | 1311 |
| 1314 __ movq(R10, Immediate(num_context_variables())); | 1312 __ movq(R10, Immediate(num_context_variables())); |
| 1315 const ExternalLabel label("alloc_context", | 1313 const ExternalLabel label("alloc_context", |
| 1316 StubCode::AllocateContextEntryPoint()); | 1314 StubCode::AllocateContextEntryPoint()); |
| 1317 compiler->GenerateCall(token_pos(), | 1315 compiler->GenerateCall(token_pos(), |
| 1318 try_index(), | 1316 try_index(), |
| 1319 &label, | 1317 &label, |
| 1320 PcDescriptors::kOther, | 1318 PcDescriptors::kOther, |
| 1321 locs()->stack_bitmap()); | 1319 locs()); |
| 1322 } | 1320 } |
| 1323 | 1321 |
| 1324 | 1322 |
| 1325 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1323 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1326 const intptr_t kNumInputs = 1; | 1324 const intptr_t kNumInputs = 1; |
| 1327 const intptr_t kNumTemps = 0; | 1325 const intptr_t kNumTemps = 0; |
| 1328 LocationSummary* locs = | 1326 LocationSummary* locs = |
| 1329 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1327 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1330 locs->set_in(0, Location::RegisterLocation(RAX)); | 1328 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 1331 locs->set_out(Location::RegisterLocation(RAX)); | 1329 locs->set_out(Location::RegisterLocation(RAX)); |
| 1332 return locs; | 1330 return locs; |
| 1333 } | 1331 } |
| 1334 | 1332 |
| 1335 | 1333 |
| 1336 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1334 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1337 Register context_value = locs()->in(0).reg(); | 1335 Register context_value = locs()->in(0).reg(); |
| 1338 Register result = locs()->out().reg(); | 1336 Register result = locs()->out().reg(); |
| 1339 | 1337 |
| 1340 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1338 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1341 __ pushq(context_value); | 1339 __ pushq(context_value); |
| 1342 compiler->GenerateCallRuntime(deopt_id(), | 1340 compiler->GenerateCallRuntime(deopt_id(), |
| 1343 token_pos(), | 1341 token_pos(), |
| 1344 try_index(), | 1342 try_index(), |
| 1345 kCloneContextRuntimeEntry, | 1343 kCloneContextRuntimeEntry, |
| 1346 locs()->stack_bitmap()); | 1344 locs()); |
| 1347 __ popq(result); // Remove argument. | 1345 __ popq(result); // Remove argument. |
| 1348 __ popq(result); // Get result (cloned context). | 1346 __ popq(result); // Get result (cloned context). |
| 1349 } | 1347 } |
| 1350 | 1348 |
| 1351 | 1349 |
| 1352 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1350 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1353 return LocationSummary::Make(0, | 1351 return LocationSummary::Make(0, |
| 1354 Location::NoLocation(), | 1352 Location::NoLocation(), |
| 1355 LocationSummary::kNoCall); | 1353 LocationSummary::kNoCall); |
| 1356 } | 1354 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1393 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1391 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) |
| 1394 : computation_(computation) { } | 1392 : computation_(computation) { } |
| 1395 | 1393 |
| 1396 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1394 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1397 __ Bind(entry_label()); | 1395 __ Bind(entry_label()); |
| 1398 compiler->SaveLiveRegisters(computation_->locs()); | 1396 compiler->SaveLiveRegisters(computation_->locs()); |
| 1399 compiler->GenerateCallRuntime(computation_->deopt_id(), | 1397 compiler->GenerateCallRuntime(computation_->deopt_id(), |
| 1400 computation_->token_pos(), | 1398 computation_->token_pos(), |
| 1401 computation_->try_index(), | 1399 computation_->try_index(), |
| 1402 kStackOverflowRuntimeEntry, | 1400 kStackOverflowRuntimeEntry, |
| 1403 computation_->locs()->stack_bitmap()); | 1401 computation_->locs()); |
| 1404 compiler->RestoreLiveRegisters(computation_->locs()); | 1402 compiler->RestoreLiveRegisters(computation_->locs()); |
| 1405 __ jmp(exit_label()); | 1403 __ jmp(exit_label()); |
| 1406 } | 1404 } |
| 1407 | 1405 |
| 1408 private: | 1406 private: |
| 1409 CheckStackOverflowComp* computation_; | 1407 CheckStackOverflowComp* computation_; |
| 1410 }; | 1408 }; |
| 1411 | 1409 |
| 1412 | 1410 |
| 1413 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1411 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1586 const intptr_t kArgumentCount = 2; | 1584 const intptr_t kArgumentCount = 2; |
| 1587 __ pushq(temp); | 1585 __ pushq(temp); |
| 1588 __ pushq(right); | 1586 __ pushq(right); |
| 1589 compiler->GenerateStaticCall( | 1587 compiler->GenerateStaticCall( |
| 1590 instance_call()->deopt_id(), | 1588 instance_call()->deopt_id(), |
| 1591 instance_call()->token_pos(), | 1589 instance_call()->token_pos(), |
| 1592 instance_call()->try_index(), | 1590 instance_call()->try_index(), |
| 1593 target, | 1591 target, |
| 1594 kArgumentCount, | 1592 kArgumentCount, |
| 1595 Array::Handle(), // No argument names. | 1593 Array::Handle(), // No argument names. |
| 1596 locs()->stack_bitmap()); | 1594 locs()); |
| 1597 ASSERT(result == RAX); | 1595 ASSERT(result == RAX); |
| 1598 } | 1596 } |
| 1599 __ Bind(&done); | 1597 __ Bind(&done); |
| 1600 break; | 1598 break; |
| 1601 } | 1599 } |
| 1602 case Token::kDIV: { | 1600 case Token::kDIV: { |
| 1603 // Dispatches to 'Double./'. | 1601 // Dispatches to 'Double./'. |
| 1604 // TODO(srdjan): Implement as conversion to double and double division. | 1602 // TODO(srdjan): Implement as conversion to double and double division. |
| 1605 UNREACHABLE(); | 1603 UNREACHABLE(); |
| 1606 break; | 1604 break; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1692 } else { | 1690 } else { |
| 1693 __ pushq(left); | 1691 __ pushq(left); |
| 1694 __ pushq(right); | 1692 __ pushq(right); |
| 1695 compiler->GenerateStaticCall( | 1693 compiler->GenerateStaticCall( |
| 1696 instance_call()->deopt_id(), | 1694 instance_call()->deopt_id(), |
| 1697 instance_call()->token_pos(), | 1695 instance_call()->token_pos(), |
| 1698 instance_call()->try_index(), | 1696 instance_call()->try_index(), |
| 1699 target, | 1697 target, |
| 1700 instance_call()->ArgumentCount(), | 1698 instance_call()->ArgumentCount(), |
| 1701 instance_call()->argument_names(), | 1699 instance_call()->argument_names(), |
| 1702 locs()->stack_bitmap()); | 1700 locs()); |
| 1703 ASSERT(result == RAX); | 1701 ASSERT(result == RAX); |
| 1704 __ jmp(&done); | 1702 __ jmp(&done); |
| 1705 } | 1703 } |
| 1706 } | 1704 } |
| 1707 | 1705 |
| 1708 __ Bind(&mint_static_call); | 1706 __ Bind(&mint_static_call); |
| 1709 { | 1707 { |
| 1710 Function& target = Function::ZoneHandle( | 1708 Function& target = Function::ZoneHandle( |
| 1711 ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1709 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1712 if (target.IsNull()) { | 1710 if (target.IsNull()) { |
| 1713 __ jmp(deopt); | 1711 __ jmp(deopt); |
| 1714 } else { | 1712 } else { |
| 1715 __ pushq(left); | 1713 __ pushq(left); |
| 1716 __ pushq(right); | 1714 __ pushq(right); |
| 1717 compiler->GenerateStaticCall( | 1715 compiler->GenerateStaticCall( |
| 1718 instance_call()->deopt_id(), | 1716 instance_call()->deopt_id(), |
| 1719 instance_call()->token_pos(), | 1717 instance_call()->token_pos(), |
| 1720 instance_call()->try_index(), | 1718 instance_call()->try_index(), |
| 1721 target, | 1719 target, |
| 1722 instance_call()->ArgumentCount(), | 1720 instance_call()->ArgumentCount(), |
| 1723 instance_call()->argument_names(), | 1721 instance_call()->argument_names(), |
| 1724 locs()->stack_bitmap()); | 1722 locs()); |
| 1725 ASSERT(result == RAX); | 1723 ASSERT(result == RAX); |
| 1726 } | 1724 } |
| 1727 } | 1725 } |
| 1728 __ Bind(&done); | 1726 __ Bind(&done); |
| 1729 } | 1727 } |
| 1730 | 1728 |
| 1731 | 1729 |
| 1732 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { | 1730 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
| 1733 return MakeCallSummary(); // Calls into a stub for allocation. | 1731 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1734 } | 1732 } |
| 1735 | 1733 |
| 1736 | 1734 |
| 1737 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1735 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1738 Register left = RBX; | 1736 Register left = RBX; |
| 1739 Register right = RCX; | 1737 Register right = RCX; |
| 1740 Register temp = RDX; | 1738 Register temp = RDX; |
| 1741 Register result = locs()->out().reg(); | 1739 Register result = locs()->out().reg(); |
| 1742 | 1740 |
| 1743 const Class& double_class = compiler->double_class(); | 1741 const Class& double_class = compiler->double_class(); |
| 1744 const Code& stub = | 1742 const Code& stub = |
| 1745 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1743 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1746 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1744 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1747 compiler->GenerateCall(instance_call()->token_pos(), | 1745 compiler->GenerateCall(instance_call()->token_pos(), |
| 1748 instance_call()->try_index(), | 1746 instance_call()->try_index(), |
| 1749 &label, | 1747 &label, |
| 1750 PcDescriptors::kOther, | 1748 PcDescriptors::kOther, |
| 1751 locs()->stack_bitmap()); | 1749 locs()); |
| 1752 // Newly allocated object is now in the result register (RAX). | 1750 // Newly allocated object is now in the result register (RAX). |
| 1753 ASSERT(result == RAX); | 1751 ASSERT(result == RAX); |
| 1754 __ movq(right, Address(RSP, 0)); | 1752 __ movq(right, Address(RSP, 0)); |
| 1755 __ movq(left, Address(RSP, kWordSize)); | 1753 __ movq(left, Address(RSP, kWordSize)); |
| 1756 | 1754 |
| 1757 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1755 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1758 instance_call()->try_index(), | 1756 instance_call()->try_index(), |
| 1759 kDeoptBinaryDoubleOp); | 1757 kDeoptBinaryDoubleOp); |
| 1760 | 1758 |
| 1761 // Binary operation of two Smi's produces a Smi not a double. | 1759 // Binary operation of two Smi's produces a Smi not a double. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 // Allocate result object. | 1865 // Allocate result object. |
| 1868 const Class& double_class = compiler->double_class(); | 1866 const Class& double_class = compiler->double_class(); |
| 1869 const Code& stub = | 1867 const Code& stub = |
| 1870 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1868 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1871 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1869 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1872 __ pushq(value); | 1870 __ pushq(value); |
| 1873 compiler->GenerateCall(instance_call()->token_pos(), | 1871 compiler->GenerateCall(instance_call()->token_pos(), |
| 1874 instance_call()->try_index(), | 1872 instance_call()->try_index(), |
| 1875 &label, | 1873 &label, |
| 1876 PcDescriptors::kOther, | 1874 PcDescriptors::kOther, |
| 1877 instance_call()->locs()->stack_bitmap()); | 1875 instance_call()->locs()); |
| 1878 // Result is in RAX. | 1876 // Result is in RAX. |
| 1879 ASSERT(result != temp); | 1877 ASSERT(result != temp); |
| 1880 __ movq(result, RAX); | 1878 __ movq(result, RAX); |
| 1881 __ popq(temp); | 1879 __ popq(temp); |
| 1882 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1880 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1883 __ DoubleNegate(XMM0); | 1881 __ DoubleNegate(XMM0); |
| 1884 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1882 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1885 } else { | 1883 } else { |
| 1886 UNREACHABLE(); | 1884 UNREACHABLE(); |
| 1887 } | 1885 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1932 const Code& stub = | 1930 const Code& stub = |
| 1933 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1931 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1934 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1932 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1935 | 1933 |
| 1936 // TODO(fschneider): Inline new-space allocation and move the call into | 1934 // TODO(fschneider): Inline new-space allocation and move the call into |
| 1937 // deferred code. | 1935 // deferred code. |
| 1938 compiler->GenerateCall(instance_call()->token_pos(), | 1936 compiler->GenerateCall(instance_call()->token_pos(), |
| 1939 instance_call()->try_index(), | 1937 instance_call()->try_index(), |
| 1940 &label, | 1938 &label, |
| 1941 PcDescriptors::kOther, | 1939 PcDescriptors::kOther, |
| 1942 locs()->stack_bitmap()); | 1940 locs()); |
| 1943 ASSERT(result == RAX); | 1941 ASSERT(result == RAX); |
| 1944 Register value = RBX; | 1942 Register value = RBX; |
| 1945 // Preserve argument on the stack until after the deoptimization point. | 1943 // Preserve argument on the stack until after the deoptimization point. |
| 1946 __ movq(value, Address(RSP, 0)); | 1944 __ movq(value, Address(RSP, 0)); |
| 1947 | 1945 |
| 1948 __ testq(value, Immediate(kSmiTagMask)); | 1946 __ testq(value, Immediate(kSmiTagMask)); |
| 1949 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1947 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1950 __ SmiUntag(value); | 1948 __ SmiUntag(value); |
| 1951 __ cvtsi2sd(XMM0, value); | 1949 __ cvtsi2sd(XMM0, value); |
| 1952 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1950 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1982 __ LoadClassId(RDI, RAX); | 1980 __ LoadClassId(RDI, RAX); |
| 1983 compiler->EmitTestAndCall(*ic_data(), | 1981 compiler->EmitTestAndCall(*ic_data(), |
| 1984 RDI, // Class id register. | 1982 RDI, // Class id register. |
| 1985 instance_call()->ArgumentCount(), | 1983 instance_call()->ArgumentCount(), |
| 1986 instance_call()->argument_names(), | 1984 instance_call()->argument_names(), |
| 1987 deopt, | 1985 deopt, |
| 1988 (is_smi_label == &handle_smi) ? &done : NULL, | 1986 (is_smi_label == &handle_smi) ? &done : NULL, |
| 1989 instance_call()->deopt_id(), | 1987 instance_call()->deopt_id(), |
| 1990 instance_call()->token_pos(), | 1988 instance_call()->token_pos(), |
| 1991 instance_call()->try_index(), | 1989 instance_call()->try_index(), |
| 1992 locs()->stack_bitmap()); | 1990 locs()); |
| 1993 if (is_smi_label == &handle_smi) { | 1991 if (is_smi_label == &handle_smi) { |
| 1994 __ Bind(&handle_smi); | 1992 __ Bind(&handle_smi); |
| 1995 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); | 1993 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
| 1996 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1994 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1997 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1995 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1998 instance_call()->token_pos(), | 1996 instance_call()->token_pos(), |
| 1999 instance_call()->try_index(), | 1997 instance_call()->try_index(), |
| 2000 target, | 1998 target, |
| 2001 instance_call()->ArgumentCount(), | 1999 instance_call()->ArgumentCount(), |
| 2002 instance_call()->argument_names(), | 2000 instance_call()->argument_names(), |
| 2003 locs()->stack_bitmap()); | 2001 locs()); |
| 2004 } | 2002 } |
| 2005 __ Bind(&done); | 2003 __ Bind(&done); |
| 2006 } | 2004 } |
| 2007 | 2005 |
| 2008 | 2006 |
| 2009 // TODO(srdjan): Move to shared. | 2007 // TODO(srdjan): Move to shared. |
| 2010 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { | 2008 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { |
| 2011 if (ic_data.num_args_tested() != 2) return false; | 2009 if (ic_data.num_args_tested() != 2) return false; |
| 2012 if (ic_data.NumberOfChecks() != 1) return false; | 2010 if (ic_data.NumberOfChecks() != 1) return false; |
| 2013 Function& target = Function::Handle(); | 2011 Function& target = Function::Handle(); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 deopt_id(), token_pos(), try_index()); | 2090 deopt_id(), token_pos(), try_index()); |
| 2093 return; | 2091 return; |
| 2094 } | 2092 } |
| 2095 if (IsCheckedStrictEquals(*ic_data(), kind())) { | 2093 if (IsCheckedStrictEquals(*ic_data(), kind())) { |
| 2096 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, | 2094 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, |
| 2097 deopt_id(), token_pos(), try_index()); | 2095 deopt_id(), token_pos(), try_index()); |
| 2098 return; | 2096 return; |
| 2099 } | 2097 } |
| 2100 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2098 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2101 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2099 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2102 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2100 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), |
| 2103 deopt_id(), token_pos(), try_index()); | 2101 deopt_id(), token_pos(), try_index()); |
| 2104 return; | 2102 return; |
| 2105 } | 2103 } |
| 2106 // Otherwise polymorphic dispatch? | 2104 // Otherwise polymorphic dispatch? |
| 2107 } | 2105 } |
| 2108 Register left = locs()->in(0).reg(); | 2106 Register left = locs()->in(0).reg(); |
| 2109 Register right = locs()->in(1).reg(); | 2107 Register right = locs()->in(1).reg(); |
| 2110 __ pushq(left); | 2108 __ pushq(left); |
| 2111 __ pushq(right); | 2109 __ pushq(right); |
| 2112 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) { | 2110 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) { |
| 2113 EmitEqualityAsInstanceCall(compiler, | 2111 EmitEqualityAsInstanceCall(compiler, |
| 2114 deopt_id(), | 2112 deopt_id(), |
| 2115 token_pos(), | 2113 token_pos(), |
| 2116 try_index(), | 2114 try_index(), |
| 2117 Token::kEQ, // kNE reverse occurs at branch. | 2115 Token::kEQ, // kNE reverse occurs at branch. |
| 2118 *locs()); | 2116 locs()); |
| 2119 } else { | 2117 } else { |
| 2120 const String& function_name = | 2118 const String& function_name = |
| 2121 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 2119 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 2122 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2120 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 2123 deopt_id(), | 2121 deopt_id(), |
| 2124 token_pos(), | 2122 token_pos(), |
| 2125 try_index()); | 2123 try_index()); |
| 2126 const intptr_t kNumArguments = 2; | 2124 const intptr_t kNumArguments = 2; |
| 2127 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2125 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 2128 compiler->GenerateInstanceCall(deopt_id(), | 2126 compiler->GenerateInstanceCall(deopt_id(), |
| 2129 token_pos(), | 2127 token_pos(), |
| 2130 try_index(), | 2128 try_index(), |
| 2131 function_name, | 2129 function_name, |
| 2132 kNumArguments, | 2130 kNumArguments, |
| 2133 Array::ZoneHandle(), // No optional args. | 2131 Array::ZoneHandle(), // No optional args. |
| 2134 kNumArgsChecked, | 2132 kNumArgsChecked, |
| 2135 locs()->stack_bitmap()); | 2133 locs()); |
| 2136 } | 2134 } |
| 2137 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2135 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 2138 __ CompareObject(RAX, compiler->bool_true()); | 2136 __ CompareObject(RAX, compiler->bool_true()); |
| 2139 EmitBranchOnCondition(compiler, branch_condition); | 2137 EmitBranchOnCondition(compiler, branch_condition); |
| 2140 } | 2138 } |
| 2141 | 2139 |
| 2142 | 2140 |
| 2143 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2141 LocationSummary* CheckClassComp::MakeLocationSummary() const { |
| 2144 const intptr_t kNumInputs = 1; | 2142 const intptr_t kNumInputs = 1; |
| 2145 const intptr_t kNumTemps = 1; | 2143 const intptr_t kNumTemps = 1; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2205 __ testq(value, Immediate(kSmiTagMask)); | 2203 __ testq(value, Immediate(kSmiTagMask)); |
| 2206 __ j(NOT_ZERO, deopt); | 2204 __ j(NOT_ZERO, deopt); |
| 2207 } | 2205 } |
| 2208 | 2206 |
| 2209 | 2207 |
| 2210 } // namespace dart | 2208 } // namespace dart |
| 2211 | 2209 |
| 2212 #undef __ | 2210 #undef __ |
| 2213 | 2211 |
| 2214 #endif // defined TARGET_ARCH_X64 | 2212 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |