| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 if (FLAG_trace_functions) { | 81 if (FLAG_trace_functions) { |
| 82 const Function& function = | 82 const Function& function = |
| 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 84 __ LoadObject(temp, function); | 84 __ LoadObject(temp, function); |
| 85 __ pushl(result); // Preserve result. | 85 __ pushl(result); // Preserve result. |
| 86 __ pushl(temp); | 86 __ pushl(temp); |
| 87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, | 87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
| 88 0, | 88 0, |
| 89 CatchClauseNode::kInvalidTryIndex, | |
| 90 kTraceFunctionExitRuntimeEntry, | 89 kTraceFunctionExitRuntimeEntry, |
| 91 locs()); | 90 locs()); |
| 92 __ popl(temp); // Remove argument. | 91 __ popl(temp); // Remove argument. |
| 93 __ popl(result); // Restore result. | 92 __ popl(result); // Restore result. |
| 94 } | 93 } |
| 95 #if defined(DEBUG) | 94 #if defined(DEBUG) |
| 96 // TODO(srdjan): Fix for functions with finally clause. | 95 // TODO(srdjan): Fix for functions with finally clause. |
| 97 // A finally clause may leave a previously pushed return value if it | 96 // A finally clause may leave a previously pushed return value if it |
| 98 // has its own return instruction. Method that have finally are currently | 97 // has its own return instruction. Method that have finally are currently |
| 99 // not optimized. | 98 // not optimized. |
| 100 if (!compiler->HasFinally()) { | 99 if (!compiler->HasFinally()) { |
| 101 Label done; | 100 Label done; |
| 102 __ movl(EDI, EBP); | 101 __ movl(EDI, EBP); |
| 103 __ subl(EDI, ESP); | 102 __ subl(EDI, ESP); |
| 104 // + 1 for Pc marker. | 103 // + 1 for Pc marker. |
| 105 __ cmpl(EDI, Immediate((compiler->StackSize() + 1) * kWordSize)); | 104 __ cmpl(EDI, Immediate((compiler->StackSize() + 1) * kWordSize)); |
| 106 __ j(EQUAL, &done, Assembler::kNearJump); | 105 __ j(EQUAL, &done, Assembler::kNearJump); |
| 107 __ int3(); | 106 __ int3(); |
| 108 __ Bind(&done); | 107 __ Bind(&done); |
| 109 } | 108 } |
| 110 #endif | 109 #endif |
| 111 __ LeaveFrame(); | 110 __ LeaveFrame(); |
| 112 __ ret(); | 111 __ ret(); |
| 113 | 112 |
| 114 // Generate 1 byte NOP so that the debugger can patch the | 113 // Generate 1 byte NOP so that the debugger can patch the |
| 115 // return pattern with a call to the debug stub. | 114 // return pattern with a call to the debug stub. |
| 116 __ nop(1); | 115 __ nop(1); |
| 117 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 116 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 118 deopt_id(), | 117 deopt_id(), |
| 119 token_pos(), | 118 token_pos()); |
| 120 CatchClauseNode::kInvalidTryIndex); | |
| 121 } | 119 } |
| 122 | 120 |
| 123 | 121 |
| 124 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 122 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 125 const intptr_t kNumInputs = 0; | 123 const intptr_t kNumInputs = 0; |
| 126 const intptr_t kNumTemps = 1; | 124 const intptr_t kNumTemps = 1; |
| 127 LocationSummary* result = | 125 LocationSummary* result = |
| 128 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 126 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 129 result->set_out(Location::RegisterLocation(EAX)); | 127 result->set_out(Location::RegisterLocation(EAX)); |
| 130 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. | 128 result->set_temp(0, Location::RegisterLocation(EDX)); // Arg. descriptor. |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 // Call the runtime if the object is not bool::true or bool::false. | 204 // Call the runtime if the object is not bool::true or bool::false. |
| 207 Label done; | 205 Label done; |
| 208 __ CompareObject(obj, compiler->bool_true()); | 206 __ CompareObject(obj, compiler->bool_true()); |
| 209 __ j(EQUAL, &done, Assembler::kNearJump); | 207 __ j(EQUAL, &done, Assembler::kNearJump); |
| 210 __ CompareObject(obj, compiler->bool_false()); | 208 __ CompareObject(obj, compiler->bool_false()); |
| 211 __ j(EQUAL, &done, Assembler::kNearJump); | 209 __ j(EQUAL, &done, Assembler::kNearJump); |
| 212 | 210 |
| 213 __ pushl(obj); // Push the source object. | 211 __ pushl(obj); // Push the source object. |
| 214 compiler->GenerateCallRuntime(deopt_id(), | 212 compiler->GenerateCallRuntime(deopt_id(), |
| 215 token_pos(), | 213 token_pos(), |
| 216 try_index(), | |
| 217 kConditionTypeErrorRuntimeEntry, | 214 kConditionTypeErrorRuntimeEntry, |
| 218 locs()); | 215 locs()); |
| 219 // We should never return here. | 216 // We should never return here. |
| 220 __ int3(); | 217 __ int3(); |
| 221 __ Bind(&done); | 218 __ Bind(&done); |
| 222 } | 219 } |
| 223 ASSERT(obj == result); | 220 ASSERT(obj == result); |
| 224 } | 221 } |
| 225 | 222 |
| 226 | 223 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 locs->set_in(0, Location::RegisterLocation(ECX)); | 268 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 272 locs->set_in(1, Location::RegisterLocation(EDX)); | 269 locs->set_in(1, Location::RegisterLocation(EDX)); |
| 273 locs->set_out(Location::RegisterLocation(EAX)); | 270 locs->set_out(Location::RegisterLocation(EAX)); |
| 274 return locs; | 271 return locs; |
| 275 } | 272 } |
| 276 | 273 |
| 277 | 274 |
| 278 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 275 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 279 intptr_t deopt_id, | 276 intptr_t deopt_id, |
| 280 intptr_t token_pos, | 277 intptr_t token_pos, |
| 281 intptr_t try_index, | |
| 282 Token::Kind kind, | 278 Token::Kind kind, |
| 283 LocationSummary* locs) { | 279 LocationSummary* locs) { |
| 284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 280 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 285 deopt_id, | 281 deopt_id, |
| 286 token_pos, | 282 token_pos); |
| 287 try_index); | |
| 288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 283 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 289 const int kNumberOfArguments = 2; | 284 const int kNumberOfArguments = 2; |
| 290 const Array& kNoArgumentNames = Array::Handle(); | 285 const Array& kNoArgumentNames = Array::Handle(); |
| 291 const int kNumArgumentsChecked = 2; | 286 const int kNumArgumentsChecked = 2; |
| 292 | 287 |
| 293 Label done, false_label, true_label; | 288 Label done, false_label, true_label; |
| 294 Register left = locs->in(0).reg(); | 289 Register left = locs->in(0).reg(); |
| 295 Register right = locs->in(1).reg(); | 290 Register right = locs->in(1).reg(); |
| 296 __ popl(right); | 291 __ popl(right); |
| 297 __ popl(left); | 292 __ popl(left); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 315 } else { | 310 } else { |
| 316 ASSERT(kind == Token::kNE); | 311 ASSERT(kind == Token::kNE); |
| 317 __ jmp(&false_label); | 312 __ jmp(&false_label); |
| 318 } | 313 } |
| 319 | 314 |
| 320 __ Bind(&instance_call); | 315 __ Bind(&instance_call); |
| 321 __ pushl(left); | 316 __ pushl(left); |
| 322 __ pushl(right); | 317 __ pushl(right); |
| 323 compiler->GenerateInstanceCall(deopt_id, | 318 compiler->GenerateInstanceCall(deopt_id, |
| 324 token_pos, | 319 token_pos, |
| 325 try_index, | |
| 326 operator_name, | 320 operator_name, |
| 327 kNumberOfArguments, | 321 kNumberOfArguments, |
| 328 kNoArgumentNames, | 322 kNoArgumentNames, |
| 329 kNumArgumentsChecked, | 323 kNumArgumentsChecked, |
| 330 locs); | 324 locs); |
| 331 if (kind == Token::kNE) { | 325 if (kind == Token::kNE) { |
| 332 // Negate the condition: true label returns false and vice versa. | 326 // Negate the condition: true label returns false and vice versa. |
| 333 __ CompareObject(EAX, compiler->bool_true()); | 327 __ CompareObject(EAX, compiler->bool_true()); |
| 334 __ j(EQUAL, &true_label, Assembler::kNearJump); | 328 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 335 __ Bind(&false_label); | 329 __ Bind(&false_label); |
| 336 __ LoadObject(EAX, compiler->bool_true()); | 330 __ LoadObject(EAX, compiler->bool_true()); |
| 337 __ jmp(&done, Assembler::kNearJump); | 331 __ jmp(&done, Assembler::kNearJump); |
| 338 __ Bind(&true_label); | 332 __ Bind(&true_label); |
| 339 __ LoadObject(EAX, compiler->bool_false()); | 333 __ LoadObject(EAX, compiler->bool_false()); |
| 340 } | 334 } |
| 341 __ Bind(&done); | 335 __ Bind(&done); |
| 342 } | 336 } |
| 343 | 337 |
| 344 | 338 |
| 345 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 339 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 346 const ICData& orig_ic_data, | 340 const ICData& orig_ic_data, |
| 347 LocationSummary* locs, | 341 LocationSummary* locs, |
| 348 BranchInstr* branch, | 342 BranchInstr* branch, |
| 349 Token::Kind kind, | 343 Token::Kind kind, |
| 350 intptr_t deopt_id, | 344 intptr_t deopt_id, |
| 351 intptr_t token_pos, | 345 intptr_t token_pos) { |
| 352 intptr_t try_index) { | |
| 353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 346 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 347 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 355 ASSERT(ic_data.NumberOfChecks() > 0); | 348 ASSERT(ic_data.NumberOfChecks() > 0); |
| 356 ASSERT(ic_data.num_args_tested() == 1); | 349 ASSERT(ic_data.num_args_tested() == 1); |
| 357 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); | 350 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); |
| 358 Register left = locs->in(0).reg(); | 351 Register left = locs->in(0).reg(); |
| 359 Register right = locs->in(1).reg(); | 352 Register right = locs->in(1).reg(); |
| 360 __ testl(left, Immediate(kSmiTagMask)); | 353 __ testl(left, Immediate(kSmiTagMask)); |
| 361 Register temp = locs->temp(0).reg(); | 354 Register temp = locs->temp(0).reg(); |
| 362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 355 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 __ LoadObject(result, compiler->bool_false()); | 388 __ LoadObject(result, compiler->bool_false()); |
| 396 __ jmp(&done); | 389 __ jmp(&done); |
| 397 __ Bind(&load_true); | 390 __ Bind(&load_true); |
| 398 __ LoadObject(result, compiler->bool_true()); | 391 __ LoadObject(result, compiler->bool_true()); |
| 399 } | 392 } |
| 400 } else { | 393 } else { |
| 401 const int kNumberOfArguments = 2; | 394 const int kNumberOfArguments = 2; |
| 402 const Array& kNoArgumentNames = Array::Handle(); | 395 const Array& kNoArgumentNames = Array::Handle(); |
| 403 compiler->GenerateStaticCall(deopt_id, | 396 compiler->GenerateStaticCall(deopt_id, |
| 404 token_pos, | 397 token_pos, |
| 405 try_index, | |
| 406 target, | 398 target, |
| 407 kNumberOfArguments, | 399 kNumberOfArguments, |
| 408 kNoArgumentNames, | 400 kNoArgumentNames, |
| 409 locs); | 401 locs); |
| 410 if (branch == NULL) { | 402 if (branch == NULL) { |
| 411 if (kind == Token::kNE) { | 403 if (kind == Token::kNE) { |
| 412 Label false_label; | 404 Label false_label; |
| 413 __ CompareObject(EAX, compiler->bool_true()); | 405 __ CompareObject(EAX, compiler->bool_true()); |
| 414 __ j(EQUAL, &false_label, Assembler::kNearJump); | 406 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 415 __ LoadObject(EAX, compiler->bool_true()); | 407 __ LoadObject(EAX, compiler->bool_true()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 | 479 |
| 488 // First test if receiver is NULL, in which case === is applied. | 480 // First test if receiver is NULL, in which case === is applied. |
| 489 // If type feedback was provided (lists of <class-id, target>), do a | 481 // If type feedback was provided (lists of <class-id, target>), do a |
| 490 // type by type check (either === or static call to the operator. | 482 // type by type check (either === or static call to the operator. |
| 491 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 483 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 492 LocationSummary* locs, | 484 LocationSummary* locs, |
| 493 Token::Kind kind, | 485 Token::Kind kind, |
| 494 BranchInstr* branch, | 486 BranchInstr* branch, |
| 495 const ICData& ic_data, | 487 const ICData& ic_data, |
| 496 intptr_t deopt_id, | 488 intptr_t deopt_id, |
| 497 intptr_t token_pos, | 489 intptr_t token_pos) { |
| 498 intptr_t try_index) { | |
| 499 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 490 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 500 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 491 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 501 Register left = locs->in(0).reg(); | 492 Register left = locs->in(0).reg(); |
| 502 Register right = locs->in(1).reg(); | 493 Register right = locs->in(1).reg(); |
| 503 const Immediate raw_null = | 494 const Immediate raw_null = |
| 504 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 495 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 505 Label done, identity_compare, non_null_compare; | 496 Label done, identity_compare, non_null_compare; |
| 506 __ cmpl(right, raw_null); | 497 __ cmpl(right, raw_null); |
| 507 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 498 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
| 508 __ cmpl(left, raw_null); | 499 __ cmpl(left, raw_null); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 520 __ LoadObject(result, compiler->bool_false()); | 511 __ LoadObject(result, compiler->bool_false()); |
| 521 __ jmp(&done); | 512 __ jmp(&done); |
| 522 __ Bind(&load_true); | 513 __ Bind(&load_true); |
| 523 __ LoadObject(result, compiler->bool_true()); | 514 __ LoadObject(result, compiler->bool_true()); |
| 524 } | 515 } |
| 525 __ jmp(&done); | 516 __ jmp(&done); |
| 526 __ Bind(&non_null_compare); // Receiver is not null. | 517 __ Bind(&non_null_compare); // Receiver is not null. |
| 527 __ pushl(left); | 518 __ pushl(left); |
| 528 __ pushl(right); | 519 __ pushl(right); |
| 529 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 520 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 530 deopt_id, token_pos, try_index); | 521 deopt_id, token_pos); |
| 531 __ Bind(&done); | 522 __ Bind(&done); |
| 532 } | 523 } |
| 533 | 524 |
| 534 | 525 |
| 535 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 526 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 536 const LocationSummary& locs, | 527 const LocationSummary& locs, |
| 537 Token::Kind kind, | 528 Token::Kind kind, |
| 538 BranchInstr* branch, | 529 BranchInstr* branch, |
| 539 intptr_t deopt_id) { | 530 intptr_t deopt_id) { |
| 540 Register left = locs.in(0).reg(); | 531 Register left = locs.in(0).reg(); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 } | 616 } |
| 626 const bool is_checked_strict_equal = | 617 const bool is_checked_strict_equal = |
| 627 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 618 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 628 if (is_checked_strict_equal) { | 619 if (is_checked_strict_equal) { |
| 629 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, | 620 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, |
| 630 deopt_id()); | 621 deopt_id()); |
| 631 return; | 622 return; |
| 632 } | 623 } |
| 633 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 624 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 634 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), | 625 EmitGenericEqualityCompare(compiler, locs(), kind(), kNoBranch, *ic_data(), |
| 635 deopt_id(), token_pos(), try_index()); | 626 deopt_id(), token_pos()); |
| 636 return; | 627 return; |
| 637 } | 628 } |
| 638 Register left = locs()->in(0).reg(); | 629 Register left = locs()->in(0).reg(); |
| 639 Register right = locs()->in(1).reg(); | 630 Register right = locs()->in(1).reg(); |
| 640 __ pushl(left); | 631 __ pushl(left); |
| 641 __ pushl(right); | 632 __ pushl(right); |
| 642 EmitEqualityAsInstanceCall(compiler, | 633 EmitEqualityAsInstanceCall(compiler, deopt_id(), token_pos(), kind(), locs()); |
| 643 deopt_id(), | |
| 644 token_pos(), | |
| 645 try_index(), | |
| 646 kind(), | |
| 647 locs()); | |
| 648 ASSERT(locs()->out().reg() == EAX); | 634 ASSERT(locs()->out().reg() == EAX); |
| 649 } | 635 } |
| 650 | 636 |
| 651 | 637 |
| 652 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 638 void EqualityCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, |
| 653 BranchInstr* branch) { | 639 BranchInstr* branch) { |
| 654 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 640 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 655 if (receiver_class_id() == kSmiCid) { | 641 if (receiver_class_id() == kSmiCid) { |
| 656 // Deoptimizes if both arguments not Smi. | 642 // Deoptimizes if both arguments not Smi. |
| 657 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 643 EmitSmiComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
| 658 return; | 644 return; |
| 659 } | 645 } |
| 660 if (receiver_class_id() == kDoubleCid) { | 646 if (receiver_class_id() == kDoubleCid) { |
| 661 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. | 647 // Deoptimizes if both arguments are Smi, or if none is Double or Smi. |
| 662 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); | 648 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch, deopt_id()); |
| 663 return; | 649 return; |
| 664 } | 650 } |
| 665 const bool is_checked_strict_equal = | 651 const bool is_checked_strict_equal = |
| 666 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 652 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 667 if (is_checked_strict_equal) { | 653 if (is_checked_strict_equal) { |
| 668 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, | 654 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, |
| 669 deopt_id()); | 655 deopt_id()); |
| 670 return; | 656 return; |
| 671 } | 657 } |
| 672 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 658 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 673 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), | 659 EmitGenericEqualityCompare(compiler, locs(), kind(), branch, *ic_data(), |
| 674 deopt_id(), token_pos(), try_index()); | 660 deopt_id(), token_pos()); |
| 675 return; | 661 return; |
| 676 } | 662 } |
| 677 Register left = locs()->in(0).reg(); | 663 Register left = locs()->in(0).reg(); |
| 678 Register right = locs()->in(1).reg(); | 664 Register right = locs()->in(1).reg(); |
| 679 __ pushl(left); | 665 __ pushl(left); |
| 680 __ pushl(right); | 666 __ pushl(right); |
| 681 EmitEqualityAsInstanceCall(compiler, | 667 EmitEqualityAsInstanceCall(compiler, |
| 682 deopt_id(), | 668 deopt_id(), |
| 683 token_pos(), | 669 token_pos(), |
| 684 try_index(), | |
| 685 Token::kEQ, // kNE reverse occurs at branch. | 670 Token::kEQ, // kNE reverse occurs at branch. |
| 686 locs()); | 671 locs()); |
| 687 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 672 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 688 __ CompareObject(EAX, compiler->bool_true()); | 673 __ CompareObject(EAX, compiler->bool_true()); |
| 689 branch->EmitBranchOnCondition(compiler, branch_condition); | 674 branch->EmitBranchOnCondition(compiler, branch_condition); |
| 690 } | 675 } |
| 691 | 676 |
| 692 | 677 |
| 693 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 678 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 694 const intptr_t kNumInputs = 2; | 679 const intptr_t kNumInputs = 2; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 __ j(ZERO, &done); | 727 __ j(ZERO, &done); |
| 743 __ LoadClassId(EDI, left); | 728 __ LoadClassId(EDI, left); |
| 744 __ Bind(&done); | 729 __ Bind(&done); |
| 745 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 730 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 746 EDI, // Class id register. | 731 EDI, // Class id register. |
| 747 kNumArguments, | 732 kNumArguments, |
| 748 Array::Handle(), // No named arguments. | 733 Array::Handle(), // No named arguments. |
| 749 deopt, // Deoptimize target. | 734 deopt, // Deoptimize target. |
| 750 deopt_id(), | 735 deopt_id(), |
| 751 token_pos(), | 736 token_pos(), |
| 752 try_index(), | |
| 753 locs()); | 737 locs()); |
| 754 return; | 738 return; |
| 755 } | 739 } |
| 756 const String& function_name = | 740 const String& function_name = |
| 757 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 741 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 758 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 742 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 759 deopt_id(), | 743 deopt_id(), |
| 760 token_pos(), | 744 token_pos()); |
| 761 try_index()); | |
| 762 const intptr_t kNumArguments = 2; | 745 const intptr_t kNumArguments = 2; |
| 763 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 746 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 764 compiler->GenerateInstanceCall(deopt_id(), | 747 compiler->GenerateInstanceCall(deopt_id(), |
| 765 token_pos(), | 748 token_pos(), |
| 766 try_index(), | |
| 767 function_name, | 749 function_name, |
| 768 kNumArguments, | 750 kNumArguments, |
| 769 Array::ZoneHandle(), // No optional arguments. | 751 Array::ZoneHandle(), // No optional arguments. |
| 770 kNumArgsChecked, | 752 kNumArgsChecked, |
| 771 locs()); | 753 locs()); |
| 772 } | 754 } |
| 773 | 755 |
| 774 | 756 |
| 775 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, | 757 void RelationalOpComp::EmitBranchCode(FlowGraphCompiler* compiler, |
| 776 BranchInstr* branch) { | 758 BranchInstr* branch) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 816 } | 798 } |
| 817 if (!has_optional_parameters() && !is_native_instance_closure()) { | 799 if (!has_optional_parameters() && !is_native_instance_closure()) { |
| 818 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 800 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
| 819 } else { | 801 } else { |
| 820 __ leal(EAX, | 802 __ leal(EAX, |
| 821 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 803 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 822 } | 804 } |
| 823 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 805 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 824 __ movl(EDX, Immediate(arg_count)); | 806 __ movl(EDX, Immediate(arg_count)); |
| 825 compiler->GenerateCall(token_pos(), | 807 compiler->GenerateCall(token_pos(), |
| 826 try_index(), | |
| 827 &StubCode::CallNativeCFunctionLabel(), | 808 &StubCode::CallNativeCFunctionLabel(), |
| 828 PcDescriptors::kOther, | 809 PcDescriptors::kOther, |
| 829 locs()); | 810 locs()); |
| 830 __ popl(result); | 811 __ popl(result); |
| 831 } | 812 } |
| 832 | 813 |
| 833 | 814 |
| 834 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 815 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 835 ASSERT((receiver_type() == kGrowableObjectArrayCid) || | 816 ASSERT((receiver_type() == kGrowableObjectArrayCid) || |
| 836 (receiver_type() == kArrayCid) || | 817 (receiver_type() == kArrayCid) || |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 } | 1014 } |
| 1034 | 1015 |
| 1035 | 1016 |
| 1036 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1017 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1037 ASSERT(locs()->in(0).reg() == EAX); // Value. | 1018 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 1038 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 1019 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 1039 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 1020 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 1040 | 1021 |
| 1041 compiler->GenerateInstanceOf(deopt_id(), | 1022 compiler->GenerateInstanceOf(deopt_id(), |
| 1042 token_pos(), | 1023 token_pos(), |
| 1043 try_index(), | |
| 1044 type(), | 1024 type(), |
| 1045 negate_result(), | 1025 negate_result(), |
| 1046 locs()); | 1026 locs()); |
| 1047 ASSERT(locs()->out().reg() == EAX); | 1027 ASSERT(locs()->out().reg() == EAX); |
| 1048 } | 1028 } |
| 1049 | 1029 |
| 1050 | 1030 |
| 1051 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1031 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1052 const intptr_t kNumInputs = 1; | 1032 const intptr_t kNumInputs = 1; |
| 1053 const intptr_t kNumTemps = 0; | 1033 const intptr_t kNumTemps = 0; |
| 1054 LocationSummary* locs = | 1034 LocationSummary* locs = |
| 1055 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1035 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1056 locs->set_in(0, Location::RegisterLocation(ECX)); | 1036 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1057 locs->set_out(Location::RegisterLocation(EAX)); | 1037 locs->set_out(Location::RegisterLocation(EAX)); |
| 1058 return locs; | 1038 return locs; |
| 1059 } | 1039 } |
| 1060 | 1040 |
| 1061 | 1041 |
| 1062 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1042 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1063 // Allocate the array. EDX = length, ECX = element type. | 1043 // Allocate the array. EDX = length, ECX = element type. |
| 1064 ASSERT(locs()->in(0).reg() == ECX); | 1044 ASSERT(locs()->in(0).reg() == ECX); |
| 1065 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); | 1045 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); |
| 1066 compiler->GenerateCall(token_pos(), | 1046 compiler->GenerateCall(token_pos(), |
| 1067 try_index(), | |
| 1068 &StubCode::AllocateArrayLabel(), | 1047 &StubCode::AllocateArrayLabel(), |
| 1069 PcDescriptors::kOther, | 1048 PcDescriptors::kOther, |
| 1070 locs()); | 1049 locs()); |
| 1071 ASSERT(locs()->out().reg() == EAX); | 1050 ASSERT(locs()->out().reg() == EAX); |
| 1072 | 1051 |
| 1073 // Pop the element values from the stack into the array. | 1052 // Pop the element values from the stack into the array. |
| 1074 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); | 1053 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); |
| 1075 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1054 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
| 1076 ASSERT(ArgumentAt(i)->value()->IsUse()); | 1055 ASSERT(ArgumentAt(i)->value()->IsUse()); |
| 1077 __ popl(Address(EDX, i * kWordSize)); | 1056 __ popl(Address(EDX, i * kWordSize)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1099 Register instantiator_type_arguments = locs()->in(1).reg(); | 1078 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1100 Register result = locs()->out().reg(); | 1079 Register result = locs()->out().reg(); |
| 1101 | 1080 |
| 1102 // Push the result place holder initialized to NULL. | 1081 // Push the result place holder initialized to NULL. |
| 1103 __ PushObject(Object::ZoneHandle()); | 1082 __ PushObject(Object::ZoneHandle()); |
| 1104 __ PushObject(cls); | 1083 __ PushObject(cls); |
| 1105 __ pushl(type_arguments); | 1084 __ pushl(type_arguments); |
| 1106 __ pushl(instantiator_type_arguments); | 1085 __ pushl(instantiator_type_arguments); |
| 1107 compiler->GenerateCallRuntime(deopt_id(), | 1086 compiler->GenerateCallRuntime(deopt_id(), |
| 1108 token_pos(), | 1087 token_pos(), |
| 1109 try_index(), | |
| 1110 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1088 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1111 locs()); | 1089 locs()); |
| 1112 // Pop instantiator type arguments, type arguments, and class. | 1090 // Pop instantiator type arguments, type arguments, and class. |
| 1113 // source location. | 1091 // source location. |
| 1114 __ Drop(3); | 1092 __ Drop(3); |
| 1115 __ popl(result); // Pop new instance. | 1093 __ popl(result); // Pop new instance. |
| 1116 } | 1094 } |
| 1117 | 1095 |
| 1118 | 1096 |
| 1119 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1097 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1186 Immediate(Smi::RawValue(len))); | 1164 Immediate(Smi::RawValue(len))); |
| 1187 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1165 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1188 __ Bind(&type_arguments_uninstantiated); | 1166 __ Bind(&type_arguments_uninstantiated); |
| 1189 } | 1167 } |
| 1190 // A runtime call to instantiate the type arguments is required. | 1168 // A runtime call to instantiate the type arguments is required. |
| 1191 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1169 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1192 __ PushObject(type_arguments()); | 1170 __ PushObject(type_arguments()); |
| 1193 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1171 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1194 compiler->GenerateCallRuntime(deopt_id(), | 1172 compiler->GenerateCallRuntime(deopt_id(), |
| 1195 token_pos(), | 1173 token_pos(), |
| 1196 try_index(), | |
| 1197 kInstantiateTypeArgumentsRuntimeEntry, | 1174 kInstantiateTypeArgumentsRuntimeEntry, |
| 1198 locs()); | 1175 locs()); |
| 1199 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1176 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1200 __ popl(result_reg); // Pop instantiated type arguments. | 1177 __ popl(result_reg); // Pop instantiated type arguments. |
| 1201 __ Bind(&type_arguments_instantiated); | 1178 __ Bind(&type_arguments_instantiated); |
| 1202 ASSERT(instantiator_reg == result_reg); | 1179 ASSERT(instantiator_reg == result_reg); |
| 1203 // 'result_reg': Instantiated type arguments. | 1180 // 'result_reg': Instantiated type arguments. |
| 1204 } | 1181 } |
| 1205 | 1182 |
| 1206 | 1183 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 | 1319 |
| 1343 | 1320 |
| 1344 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1321 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1345 ASSERT(locs()->temp(0).reg() == EDX); | 1322 ASSERT(locs()->temp(0).reg() == EDX); |
| 1346 ASSERT(locs()->out().reg() == EAX); | 1323 ASSERT(locs()->out().reg() == EAX); |
| 1347 | 1324 |
| 1348 __ movl(EDX, Immediate(num_context_variables())); | 1325 __ movl(EDX, Immediate(num_context_variables())); |
| 1349 const ExternalLabel label("alloc_context", | 1326 const ExternalLabel label("alloc_context", |
| 1350 StubCode::AllocateContextEntryPoint()); | 1327 StubCode::AllocateContextEntryPoint()); |
| 1351 compiler->GenerateCall(token_pos(), | 1328 compiler->GenerateCall(token_pos(), |
| 1352 try_index(), | |
| 1353 &label, | 1329 &label, |
| 1354 PcDescriptors::kOther, | 1330 PcDescriptors::kOther, |
| 1355 locs()); | 1331 locs()); |
| 1356 } | 1332 } |
| 1357 | 1333 |
| 1358 | 1334 |
| 1359 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1335 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1360 const intptr_t kNumInputs = 1; | 1336 const intptr_t kNumInputs = 1; |
| 1361 const intptr_t kNumTemps = 0; | 1337 const intptr_t kNumTemps = 0; |
| 1362 LocationSummary* locs = | 1338 LocationSummary* locs = |
| 1363 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1339 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1364 locs->set_in(0, Location::RegisterLocation(EAX)); | 1340 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1365 locs->set_out(Location::RegisterLocation(EAX)); | 1341 locs->set_out(Location::RegisterLocation(EAX)); |
| 1366 return locs; | 1342 return locs; |
| 1367 } | 1343 } |
| 1368 | 1344 |
| 1369 | 1345 |
| 1370 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1346 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1371 Register context_value = locs()->in(0).reg(); | 1347 Register context_value = locs()->in(0).reg(); |
| 1372 Register result = locs()->out().reg(); | 1348 Register result = locs()->out().reg(); |
| 1373 | 1349 |
| 1374 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1350 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1375 __ pushl(context_value); | 1351 __ pushl(context_value); |
| 1376 compiler->GenerateCallRuntime(deopt_id(), | 1352 compiler->GenerateCallRuntime(deopt_id(), |
| 1377 token_pos(), | 1353 token_pos(), |
| 1378 try_index(), | |
| 1379 kCloneContextRuntimeEntry, | 1354 kCloneContextRuntimeEntry, |
| 1380 locs()); | 1355 locs()); |
| 1381 __ popl(result); // Remove argument. | 1356 __ popl(result); // Remove argument. |
| 1382 __ popl(result); // Get result (cloned context). | 1357 __ popl(result); // Get result (cloned context). |
| 1383 } | 1358 } |
| 1384 | 1359 |
| 1385 | 1360 |
| 1386 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1361 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1387 return LocationSummary::Make(0, | 1362 return LocationSummary::Make(0, |
| 1388 Location::NoLocation(), | 1363 Location::NoLocation(), |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 class CheckStackOverflowSlowPath : public SlowPathCode { | 1399 class CheckStackOverflowSlowPath : public SlowPathCode { |
| 1425 public: | 1400 public: |
| 1426 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1401 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) |
| 1427 : computation_(computation) { } | 1402 : computation_(computation) { } |
| 1428 | 1403 |
| 1429 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1404 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1430 __ Bind(entry_label()); | 1405 __ Bind(entry_label()); |
| 1431 compiler->SaveLiveRegisters(computation_->locs()); | 1406 compiler->SaveLiveRegisters(computation_->locs()); |
| 1432 compiler->GenerateCallRuntime(computation_->deopt_id(), | 1407 compiler->GenerateCallRuntime(computation_->deopt_id(), |
| 1433 computation_->token_pos(), | 1408 computation_->token_pos(), |
| 1434 computation_->try_index(), | |
| 1435 kStackOverflowRuntimeEntry, | 1409 kStackOverflowRuntimeEntry, |
| 1436 computation_->locs()); | 1410 computation_->locs()); |
| 1437 compiler->RestoreLiveRegisters(computation_->locs()); | 1411 compiler->RestoreLiveRegisters(computation_->locs()); |
| 1438 __ jmp(exit_label()); | 1412 __ jmp(exit_label()); |
| 1439 } | 1413 } |
| 1440 | 1414 |
| 1441 private: | 1415 private: |
| 1442 CheckStackOverflowComp* computation_; | 1416 CheckStackOverflowComp* computation_; |
| 1443 }; | 1417 }; |
| 1444 | 1418 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 __ Bind(&call_method); | 1587 __ Bind(&call_method); |
| 1614 Function& target = Function::ZoneHandle( | 1588 Function& target = Function::ZoneHandle( |
| 1615 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1589 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1616 ASSERT(!target.IsNull()); | 1590 ASSERT(!target.IsNull()); |
| 1617 const intptr_t kArgumentCount = 2; | 1591 const intptr_t kArgumentCount = 2; |
| 1618 __ pushl(temp); | 1592 __ pushl(temp); |
| 1619 __ pushl(right); | 1593 __ pushl(right); |
| 1620 compiler->GenerateStaticCall( | 1594 compiler->GenerateStaticCall( |
| 1621 instance_call()->deopt_id(), | 1595 instance_call()->deopt_id(), |
| 1622 instance_call()->token_pos(), | 1596 instance_call()->token_pos(), |
| 1623 instance_call()->try_index(), | |
| 1624 target, | 1597 target, |
| 1625 kArgumentCount, | 1598 kArgumentCount, |
| 1626 Array::Handle(), // No argument names. | 1599 Array::Handle(), // No argument names. |
| 1627 locs()); | 1600 locs()); |
| 1628 ASSERT(result == EAX); | 1601 ASSERT(result == EAX); |
| 1629 } | 1602 } |
| 1630 __ Bind(&done); | 1603 __ Bind(&done); |
| 1631 break; | 1604 break; |
| 1632 } | 1605 } |
| 1633 case Token::kDIV: { | 1606 case Token::kDIV: { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1720 Function& target = Function::ZoneHandle( | 1693 Function& target = Function::ZoneHandle( |
| 1721 ic_data()->GetTargetForReceiverClassId(kSmiCid)); | 1694 ic_data()->GetTargetForReceiverClassId(kSmiCid)); |
| 1722 if (target.IsNull()) { | 1695 if (target.IsNull()) { |
| 1723 __ jmp(deopt); | 1696 __ jmp(deopt); |
| 1724 } else { | 1697 } else { |
| 1725 __ pushl(left); | 1698 __ pushl(left); |
| 1726 __ pushl(right); | 1699 __ pushl(right); |
| 1727 compiler->GenerateStaticCall( | 1700 compiler->GenerateStaticCall( |
| 1728 instance_call()->deopt_id(), | 1701 instance_call()->deopt_id(), |
| 1729 instance_call()->token_pos(), | 1702 instance_call()->token_pos(), |
| 1730 instance_call()->try_index(), | |
| 1731 target, | 1703 target, |
| 1732 instance_call()->ArgumentCount(), | 1704 instance_call()->ArgumentCount(), |
| 1733 instance_call()->argument_names(), | 1705 instance_call()->argument_names(), |
| 1734 locs()); | 1706 locs()); |
| 1735 ASSERT(result == EAX); | 1707 ASSERT(result == EAX); |
| 1736 __ jmp(&done); | 1708 __ jmp(&done); |
| 1737 } | 1709 } |
| 1738 } | 1710 } |
| 1739 | 1711 |
| 1740 __ Bind(&mint_static_call); | 1712 __ Bind(&mint_static_call); |
| 1741 { | 1713 { |
| 1742 Function& target = Function::ZoneHandle( | 1714 Function& target = Function::ZoneHandle( |
| 1743 ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1715 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1744 if (target.IsNull()) { | 1716 if (target.IsNull()) { |
| 1745 __ jmp(deopt); | 1717 __ jmp(deopt); |
| 1746 } else { | 1718 } else { |
| 1747 __ pushl(left); | 1719 __ pushl(left); |
| 1748 __ pushl(right); | 1720 __ pushl(right); |
| 1749 compiler->GenerateStaticCall( | 1721 compiler->GenerateStaticCall( |
| 1750 instance_call()->deopt_id(), | 1722 instance_call()->deopt_id(), |
| 1751 instance_call()->token_pos(), | 1723 instance_call()->token_pos(), |
| 1752 instance_call()->try_index(), | |
| 1753 target, | 1724 target, |
| 1754 instance_call()->ArgumentCount(), | 1725 instance_call()->ArgumentCount(), |
| 1755 instance_call()->argument_names(), | 1726 instance_call()->argument_names(), |
| 1756 locs()); | 1727 locs()); |
| 1757 ASSERT(result == EAX); | 1728 ASSERT(result == EAX); |
| 1758 } | 1729 } |
| 1759 } | 1730 } |
| 1760 __ Bind(&done); | 1731 __ Bind(&done); |
| 1761 } | 1732 } |
| 1762 | 1733 |
| 1763 | 1734 |
| 1764 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { | 1735 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
| 1765 return MakeCallSummary(); // Calls into a stub for allocation. | 1736 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1766 } | 1737 } |
| 1767 | 1738 |
| 1768 | 1739 |
| 1769 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1740 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1770 Register left = EBX; | 1741 Register left = EBX; |
| 1771 Register right = ECX; | 1742 Register right = ECX; |
| 1772 Register temp = EDX; | 1743 Register temp = EDX; |
| 1773 Register result = locs()->out().reg(); | 1744 Register result = locs()->out().reg(); |
| 1774 | 1745 |
| 1775 const Class& double_class = compiler->double_class(); | 1746 const Class& double_class = compiler->double_class(); |
| 1776 const Code& stub = | 1747 const Code& stub = |
| 1777 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1748 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1778 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1749 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1779 compiler->GenerateCall(instance_call()->token_pos(), | 1750 compiler->GenerateCall(instance_call()->token_pos(), |
| 1780 instance_call()->try_index(), | |
| 1781 &label, | 1751 &label, |
| 1782 PcDescriptors::kOther, | 1752 PcDescriptors::kOther, |
| 1783 locs()); | 1753 locs()); |
| 1784 // Newly allocated object is now in the result register (RAX). | 1754 // Newly allocated object is now in the result register (RAX). |
| 1785 ASSERT(result == EAX); | 1755 ASSERT(result == EAX); |
| 1786 __ movl(right, Address(ESP, 0)); | 1756 __ movl(right, Address(ESP, 0)); |
| 1787 __ movl(left, Address(ESP, kWordSize)); | 1757 __ movl(left, Address(ESP, kWordSize)); |
| 1788 | 1758 |
| 1789 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1759 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1790 kDeoptBinaryDoubleOp); | 1760 kDeoptBinaryDoubleOp); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1863 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1833 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1864 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1834 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1865 | 1835 |
| 1866 // TODO(vegorov): here stack map needs to be set up correctly to skip | 1836 // TODO(vegorov): here stack map needs to be set up correctly to skip |
| 1867 // double registers. | 1837 // double registers. |
| 1868 LocationSummary* locs = computation_->locs(); | 1838 LocationSummary* locs = computation_->locs(); |
| 1869 locs->live_registers()->Remove(locs->out()); | 1839 locs->live_registers()->Remove(locs->out()); |
| 1870 | 1840 |
| 1871 compiler->SaveLiveRegisters(locs); | 1841 compiler->SaveLiveRegisters(locs); |
| 1872 compiler->GenerateCall(computation_->instance_call()->token_pos(), | 1842 compiler->GenerateCall(computation_->instance_call()->token_pos(), |
| 1873 computation_->instance_call()->try_index(), | |
| 1874 &label, | 1843 &label, |
| 1875 PcDescriptors::kOther, | 1844 PcDescriptors::kOther, |
| 1876 locs); | 1845 locs); |
| 1877 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); | 1846 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX); |
| 1878 compiler->RestoreLiveRegisters(locs); | 1847 compiler->RestoreLiveRegisters(locs); |
| 1879 | 1848 |
| 1880 __ jmp(exit_label()); | 1849 __ jmp(exit_label()); |
| 1881 } | 1850 } |
| 1882 | 1851 |
| 1883 private: | 1852 private: |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 __ j(ZERO, deopt); // Smi. | 1997 __ j(ZERO, deopt); // Smi. |
| 2029 __ CompareClassId(value, kDoubleCid, temp); | 1998 __ CompareClassId(value, kDoubleCid, temp); |
| 2030 __ j(NOT_EQUAL, deopt); | 1999 __ j(NOT_EQUAL, deopt); |
| 2031 // Allocate result object. | 2000 // Allocate result object. |
| 2032 const Class& double_class = compiler->double_class(); | 2001 const Class& double_class = compiler->double_class(); |
| 2033 const Code& stub = | 2002 const Code& stub = |
| 2034 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2003 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2035 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2004 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 2036 __ pushl(value); | 2005 __ pushl(value); |
| 2037 compiler->GenerateCall(instance_call()->token_pos(), | 2006 compiler->GenerateCall(instance_call()->token_pos(), |
| 2038 instance_call()->try_index(), | |
| 2039 &label, | 2007 &label, |
| 2040 PcDescriptors::kOther, | 2008 PcDescriptors::kOther, |
| 2041 locs()); | 2009 locs()); |
| 2042 // Result is in EAX. | 2010 // Result is in EAX. |
| 2043 ASSERT(result != temp); | 2011 ASSERT(result != temp); |
| 2044 __ movl(result, EAX); | 2012 __ movl(result, EAX); |
| 2045 __ popl(temp); | 2013 __ popl(temp); |
| 2046 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 2014 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 2047 __ DoubleNegate(XMM0); | 2015 __ DoubleNegate(XMM0); |
| 2048 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 2016 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2091 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 2059 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 2092 kDeoptIntegerToDouble); | 2060 kDeoptIntegerToDouble); |
| 2093 | 2061 |
| 2094 const Class& double_class = compiler->double_class(); | 2062 const Class& double_class = compiler->double_class(); |
| 2095 const Code& stub = | 2063 const Code& stub = |
| 2096 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 2064 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 2097 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 2065 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 2098 | 2066 |
| 2099 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 2067 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 2100 compiler->GenerateCall(instance_call()->token_pos(), | 2068 compiler->GenerateCall(instance_call()->token_pos(), |
| 2101 instance_call()->try_index(), | |
| 2102 &label, | 2069 &label, |
| 2103 PcDescriptors::kOther, | 2070 PcDescriptors::kOther, |
| 2104 locs()); | 2071 locs()); |
| 2105 ASSERT(result == EAX); | 2072 ASSERT(result == EAX); |
| 2106 Register value = EBX; | 2073 Register value = EBX; |
| 2107 // Preserve argument on the stack until after the deoptimization point. | 2074 // Preserve argument on the stack until after the deoptimization point. |
| 2108 __ movl(value, Address(ESP, 0)); | 2075 __ movl(value, Address(ESP, 0)); |
| 2109 | 2076 |
| 2110 __ testl(value, Immediate(kSmiTagMask)); | 2077 __ testl(value, Immediate(kSmiTagMask)); |
| 2111 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 2078 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2127 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 2094 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 2128 __ jmp(deopt); | 2095 __ jmp(deopt); |
| 2129 return; | 2096 return; |
| 2130 } | 2097 } |
| 2131 ASSERT(HasICData()); | 2098 ASSERT(HasICData()); |
| 2132 ASSERT(ic_data()->num_args_tested() == 1); | 2099 ASSERT(ic_data()->num_args_tested() == 1); |
| 2133 if (!with_checks()) { | 2100 if (!with_checks()) { |
| 2134 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 2101 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 2135 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 2102 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 2136 instance_call()->token_pos(), | 2103 instance_call()->token_pos(), |
| 2137 instance_call()->try_index(), | |
| 2138 target, | 2104 target, |
| 2139 instance_call()->ArgumentCount(), | 2105 instance_call()->ArgumentCount(), |
| 2140 instance_call()->argument_names(), | 2106 instance_call()->argument_names(), |
| 2141 locs()); | 2107 locs()); |
| 2142 return; | 2108 return; |
| 2143 } | 2109 } |
| 2144 | 2110 |
| 2145 // Load receiver into EAX. | 2111 // Load receiver into EAX. |
| 2146 __ movl(EAX, | 2112 __ movl(EAX, |
| 2147 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 2113 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 2148 | 2114 |
| 2149 Label done; | 2115 Label done; |
| 2150 __ movl(EDI, Immediate(kSmiCid)); | 2116 __ movl(EDI, Immediate(kSmiCid)); |
| 2151 __ testl(EAX, Immediate(kSmiTagMask)); | 2117 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2152 __ j(ZERO, &done); | 2118 __ j(ZERO, &done); |
| 2153 __ LoadClassId(EDI, EAX); | 2119 __ LoadClassId(EDI, EAX); |
| 2154 __ Bind(&done); | 2120 __ Bind(&done); |
| 2155 | 2121 |
| 2156 compiler->EmitTestAndCall(*ic_data(), | 2122 compiler->EmitTestAndCall(*ic_data(), |
| 2157 EDI, // Class id register. | 2123 EDI, // Class id register. |
| 2158 instance_call()->ArgumentCount(), | 2124 instance_call()->ArgumentCount(), |
| 2159 instance_call()->argument_names(), | 2125 instance_call()->argument_names(), |
| 2160 deopt, | 2126 deopt, |
| 2161 instance_call()->deopt_id(), | 2127 instance_call()->deopt_id(), |
| 2162 instance_call()->token_pos(), | 2128 instance_call()->token_pos(), |
| 2163 instance_call()->try_index(), | |
| 2164 locs()); | 2129 locs()); |
| 2165 } | 2130 } |
| 2166 | 2131 |
| 2167 | 2132 |
| 2168 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2133 void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2169 computation()->EmitBranchCode(compiler, this); | 2134 computation()->EmitBranchCode(compiler, this); |
| 2170 } | 2135 } |
| 2171 | 2136 |
| 2172 | 2137 |
| 2173 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2138 LocationSummary* CheckClassComp::MakeLocationSummary() const { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 } | 2221 } |
| 2257 __ j(ABOVE_EQUAL, deopt); | 2222 __ j(ABOVE_EQUAL, deopt); |
| 2258 } | 2223 } |
| 2259 | 2224 |
| 2260 | 2225 |
| 2261 } // namespace dart | 2226 } // namespace dart |
| 2262 | 2227 |
| 2263 #undef __ | 2228 #undef __ |
| 2264 | 2229 |
| 2265 #endif // defined TARGET_ARCH_X64 | 2230 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |