| 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 __ nop(1); | 100 __ nop(1); |
| 101 __ nop(1); | 101 __ nop(1); |
| 102 __ nop(1); | 102 __ nop(1); |
| 103 __ nop(1); | 103 __ nop(1); |
| 104 __ nop(1); | 104 __ nop(1); |
| 105 __ nop(1); | 105 __ nop(1); |
| 106 __ nop(1); | 106 __ nop(1); |
| 107 __ nop(1); | 107 __ nop(1); |
| 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 108 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 109 cid(), | 109 cid(), |
| 110 token_index(), | 110 token_pos(), |
| 111 CatchClauseNode::kInvalidTryIndex); | 111 CatchClauseNode::kInvalidTryIndex); |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 115 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 116 const intptr_t kNumInputs = 0; | 116 const intptr_t kNumInputs = 0; |
| 117 const intptr_t kNumTemps = 1; | 117 const intptr_t kNumTemps = 1; |
| 118 LocationSummary* result = new LocationSummary(kNumInputs, | 118 LocationSummary* result = new LocationSummary(kNumInputs, |
| 119 kNumTemps, | 119 kNumTemps, |
| 120 LocationSummary::kCall); | 120 LocationSummary::kCall); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 Register result = locs()->out().reg(); | 179 Register result = locs()->out().reg(); |
| 180 | 180 |
| 181 // Check that the type of the value is allowed in conditional context. | 181 // Check that the type of the value is allowed in conditional context. |
| 182 // Call the runtime if the object is not bool::true or bool::false. | 182 // Call the runtime if the object is not bool::true or bool::false. |
| 183 Label done; | 183 Label done; |
| 184 __ CompareObject(obj, compiler->bool_true()); | 184 __ CompareObject(obj, compiler->bool_true()); |
| 185 __ j(EQUAL, &done, Assembler::kNearJump); | 185 __ j(EQUAL, &done, Assembler::kNearJump); |
| 186 __ CompareObject(obj, compiler->bool_false()); | 186 __ CompareObject(obj, compiler->bool_false()); |
| 187 __ j(EQUAL, &done, Assembler::kNearJump); | 187 __ j(EQUAL, &done, Assembler::kNearJump); |
| 188 | 188 |
| 189 __ pushq(Immediate(Smi::RawValue(token_index()))); // Source location. | 189 __ pushq(Immediate(Smi::RawValue(token_pos()))); // Source location. |
| 190 __ pushq(obj); // Push the source object. | 190 __ pushq(obj); // Push the source object. |
| 191 compiler->GenerateCallRuntime(cid(), | 191 compiler->GenerateCallRuntime(cid(), |
| 192 token_index(), | 192 token_pos(), |
| 193 try_index(), | 193 try_index(), |
| 194 kConditionTypeErrorRuntimeEntry); | 194 kConditionTypeErrorRuntimeEntry); |
| 195 // We should never return here. | 195 // We should never return here. |
| 196 __ int3(); | 196 __ int3(); |
| 197 | 197 |
| 198 __ Bind(&done); | 198 __ Bind(&done); |
| 199 ASSERT(obj == result); | 199 ASSERT(obj == result); |
| 200 } | 200 } |
| 201 | 201 |
| 202 | 202 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 return locs; | 249 return locs; |
| 250 } | 250 } |
| 251 | 251 |
| 252 | 252 |
| 253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 253 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 254 EqualityCompareComp* comp) { | 254 EqualityCompareComp* comp) { |
| 255 Register left = comp->locs()->in(0).reg(); | 255 Register left = comp->locs()->in(0).reg(); |
| 256 Register right = comp->locs()->in(1).reg(); | 256 Register right = comp->locs()->in(1).reg(); |
| 257 Register temp = comp->locs()->temp(0).reg(); | 257 Register temp = comp->locs()->temp(0).reg(); |
| 258 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 258 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 259 comp->token_index(), | 259 comp->token_pos(), |
| 260 comp->try_index(), | 260 comp->try_index(), |
| 261 kDeoptSmiCompareSmis, | 261 kDeoptSmiCompareSmis, |
| 262 left, | 262 left, |
| 263 right); | 263 right); |
| 264 // TODO(srdjan): Should we always include NULL test (common case)? | 264 // TODO(srdjan): Should we always include NULL test (common case)? |
| 265 __ movq(temp, left); | 265 __ movq(temp, left); |
| 266 __ orq(temp, right); | 266 __ orq(temp, right); |
| 267 __ testq(temp, Immediate(kSmiTagMask)); | 267 __ testq(temp, Immediate(kSmiTagMask)); |
| 268 __ j(NOT_ZERO, deopt); | 268 __ j(NOT_ZERO, deopt); |
| 269 __ cmpq(left, right); | 269 __ cmpq(left, right); |
| 270 if (comp->is_fused_with_branch()) { | 270 if (comp->is_fused_with_branch()) { |
| 271 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 271 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 272 } else { | 272 } else { |
| 273 Register result = comp->locs()->out().reg(); | 273 Register result = comp->locs()->out().reg(); |
| 274 Label load_true, done; | 274 Label load_true, done; |
| 275 __ j(EQUAL, &load_true, Assembler::kNearJump); | 275 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 276 __ LoadObject(result, compiler->bool_false()); | 276 __ LoadObject(result, compiler->bool_false()); |
| 277 __ jmp(&done, Assembler::kNearJump); | 277 __ jmp(&done, Assembler::kNearJump); |
| 278 __ Bind(&load_true); | 278 __ Bind(&load_true); |
| 279 __ LoadObject(result, compiler->bool_true()); | 279 __ LoadObject(result, compiler->bool_true()); |
| 280 __ Bind(&done); | 280 __ Bind(&done); |
| 281 } | 281 } |
| 282 } | 282 } |
| 283 | 283 |
| 284 | 284 |
| 285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 285 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 286 EqualityCompareComp* comp) { | 286 EqualityCompareComp* comp) { |
| 287 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 287 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 288 comp->cid(), | 288 comp->cid(), |
| 289 comp->token_index(), | 289 comp->token_pos(), |
| 290 comp->try_index()); | 290 comp->try_index()); |
| 291 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 291 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 292 const int kNumberOfArguments = 2; | 292 const int kNumberOfArguments = 2; |
| 293 const Array& kNoArgumentNames = Array::Handle(); | 293 const Array& kNoArgumentNames = Array::Handle(); |
| 294 const int kNumArgumentsChecked = 2; | 294 const int kNumArgumentsChecked = 2; |
| 295 | 295 |
| 296 compiler->GenerateInstanceCall(comp->cid(), | 296 compiler->GenerateInstanceCall(comp->cid(), |
| 297 comp->token_index(), | 297 comp->token_pos(), |
| 298 comp->try_index(), | 298 comp->try_index(), |
| 299 operator_name, | 299 operator_name, |
| 300 kNumberOfArguments, | 300 kNumberOfArguments, |
| 301 kNoArgumentNames, | 301 kNoArgumentNames, |
| 302 kNumArgumentsChecked); | 302 kNumArgumentsChecked); |
| 303 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); | 303 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == RAX)); |
| 304 | 304 |
| 305 if (comp->is_fused_with_branch()) { | 305 if (comp->is_fused_with_branch()) { |
| 306 __ CompareObject(RAX, compiler->bool_true()); | 306 __ CompareObject(RAX, compiler->bool_true()); |
| 307 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 307 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 308 } | 308 } |
| 309 } | 309 } |
| 310 | 310 |
| 311 | 311 |
| 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 312 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 313 EqualityCompareComp* comp, | 313 EqualityCompareComp* comp, |
| 314 Register left, | 314 Register left, |
| 315 Register right) { | 315 Register right) { |
| 316 ASSERT(comp->HasICData()); | 316 ASSERT(comp->HasICData()); |
| 317 const ICData& ic_data = *comp->ic_data(); | 317 const ICData& ic_data = *comp->ic_data(); |
| 318 ASSERT(ic_data.NumberOfChecks() > 0); | 318 ASSERT(ic_data.NumberOfChecks() > 0); |
| 319 ASSERT(ic_data.num_args_tested() == 1); | 319 ASSERT(ic_data.num_args_tested() == 1); |
| 320 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 320 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 321 comp->token_index(), | 321 comp->token_pos(), |
| 322 comp->try_index(), | 322 comp->try_index(), |
| 323 kDeoptEquality); | 323 kDeoptEquality); |
| 324 __ testq(left, Immediate(kSmiTagMask)); | 324 __ testq(left, Immediate(kSmiTagMask)); |
| 325 Register temp = comp->locs()->temp(0).reg(); | 325 Register temp = comp->locs()->temp(0).reg(); |
| 326 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 326 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
| 327 Label done, load_class_id; | 327 Label done, load_class_id; |
| 328 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 328 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 329 __ movq(temp, Immediate(kSmi)); | 329 __ movq(temp, Immediate(kSmi)); |
| 330 __ jmp(&done, Assembler::kNearJump); | 330 __ jmp(&done, Assembler::kNearJump); |
| 331 __ Bind(&load_class_id); | 331 __ Bind(&load_class_id); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 356 __ j(EQUAL, &load_true, Assembler::kNearJump); | 356 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 357 __ LoadObject(result, compiler->bool_false()); | 357 __ LoadObject(result, compiler->bool_false()); |
| 358 __ jmp(&done); | 358 __ jmp(&done); |
| 359 __ Bind(&load_true); | 359 __ Bind(&load_true); |
| 360 __ LoadObject(result, compiler->bool_true()); | 360 __ LoadObject(result, compiler->bool_true()); |
| 361 } | 361 } |
| 362 } else { | 362 } else { |
| 363 const int kNumberOfArguments = 2; | 363 const int kNumberOfArguments = 2; |
| 364 const Array& kNoArgumentNames = Array::Handle(); | 364 const Array& kNoArgumentNames = Array::Handle(); |
| 365 compiler->GenerateStaticCall(comp->cid(), | 365 compiler->GenerateStaticCall(comp->cid(), |
| 366 comp->token_index(), | 366 comp->token_pos(), |
| 367 comp->try_index(), | 367 comp->try_index(), |
| 368 target, | 368 target, |
| 369 kNumberOfArguments, | 369 kNumberOfArguments, |
| 370 kNoArgumentNames); | 370 kNoArgumentNames); |
| 371 ASSERT(comp->is_fused_with_branch() || | 371 ASSERT(comp->is_fused_with_branch() || |
| 372 (comp->locs()->out().reg() == RAX)); | 372 (comp->locs()->out().reg() == RAX)); |
| 373 if (comp->is_fused_with_branch()) { | 373 if (comp->is_fused_with_branch()) { |
| 374 __ CompareObject(RAX, compiler->bool_true()); | 374 __ CompareObject(RAX, compiler->bool_true()); |
| 375 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 375 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 376 } | 376 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 474 } |
| 475 } | 475 } |
| 476 | 476 |
| 477 | 477 |
| 478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 478 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
| 479 RelationalOpComp* comp) { | 479 RelationalOpComp* comp) { |
| 480 Register left = comp->locs()->in(0).reg(); | 480 Register left = comp->locs()->in(0).reg(); |
| 481 Register right = comp->locs()->in(1).reg(); | 481 Register right = comp->locs()->in(1).reg(); |
| 482 Register temp = comp->locs()->temp(0).reg(); | 482 Register temp = comp->locs()->temp(0).reg(); |
| 483 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 483 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 484 comp->token_index(), | 484 comp->token_pos(), |
| 485 comp->try_index(), | 485 comp->try_index(), |
| 486 kDeoptSmiCompareSmis, | 486 kDeoptSmiCompareSmis, |
| 487 left, | 487 left, |
| 488 right); | 488 right); |
| 489 __ movq(temp, left); | 489 __ movq(temp, left); |
| 490 __ orq(temp, right); | 490 __ orq(temp, right); |
| 491 __ testq(temp, Immediate(kSmiTagMask)); | 491 __ testq(temp, Immediate(kSmiTagMask)); |
| 492 __ j(NOT_ZERO, deopt); | 492 __ j(NOT_ZERO, deopt); |
| 493 | 493 |
| 494 Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 494 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 523 } | 523 } |
| 524 | 524 |
| 525 | 525 |
| 526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 526 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
| 527 RelationalOpComp* comp) { | 527 RelationalOpComp* comp) { |
| 528 Register left = comp->locs()->in(0).reg(); | 528 Register left = comp->locs()->in(0).reg(); |
| 529 Register right = comp->locs()->in(1).reg(); | 529 Register right = comp->locs()->in(1).reg(); |
| 530 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 530 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 531 Register temp = comp->locs()->temp(0).reg(); | 531 Register temp = comp->locs()->temp(0).reg(); |
| 532 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 532 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 533 comp->token_index(), | 533 comp->token_pos(), |
| 534 comp->try_index(), | 534 comp->try_index(), |
| 535 kDeoptDoubleComparison, | 535 kDeoptDoubleComparison, |
| 536 left, | 536 left, |
| 537 right); | 537 right); |
| 538 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 538 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 539 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 539 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 540 | 540 |
| 541 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 541 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
| 542 __ comisd(XMM0, XMM1); | 542 __ comisd(XMM0, XMM1); |
| 543 | 543 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 568 return; | 568 return; |
| 569 } | 569 } |
| 570 if (operands_class_id() == kDouble) { | 570 if (operands_class_id() == kDouble) { |
| 571 EmitDoubleRelationalOp(compiler, this); | 571 EmitDoubleRelationalOp(compiler, this); |
| 572 return; | 572 return; |
| 573 } | 573 } |
| 574 const String& function_name = | 574 const String& function_name = |
| 575 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 575 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
| 576 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 576 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 577 cid(), | 577 cid(), |
| 578 token_index(), | 578 token_pos(), |
| 579 try_index()); | 579 try_index()); |
| 580 const intptr_t kNumArguments = 2; | 580 const intptr_t kNumArguments = 2; |
| 581 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 581 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 582 compiler->GenerateInstanceCall(cid(), | 582 compiler->GenerateInstanceCall(cid(), |
| 583 token_index(), | 583 token_pos(), |
| 584 try_index(), | 584 try_index(), |
| 585 function_name, | 585 function_name, |
| 586 kNumArguments, | 586 kNumArguments, |
| 587 Array::ZoneHandle(), // No optional arguments. | 587 Array::ZoneHandle(), // No optional arguments. |
| 588 kNumArgsChecked); | 588 kNumArgsChecked); |
| 589 ASSERT(locs()->out().reg() == RAX); | 589 ASSERT(locs()->out().reg() == RAX); |
| 590 } | 590 } |
| 591 | 591 |
| 592 | 592 |
| 593 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 593 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 618 arg_count += 1; | 618 arg_count += 1; |
| 619 } | 619 } |
| 620 if (!has_optional_parameters() && !is_native_instance_closure()) { | 620 if (!has_optional_parameters() && !is_native_instance_closure()) { |
| 621 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); | 621 __ leaq(RAX, Address(RBP, (1 + arg_count) * kWordSize)); |
| 622 } else { | 622 } else { |
| 623 __ leaq(RAX, | 623 __ leaq(RAX, |
| 624 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 624 Address(RBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 625 } | 625 } |
| 626 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 626 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 627 __ movq(R10, Immediate(arg_count)); | 627 __ movq(R10, Immediate(arg_count)); |
| 628 compiler->GenerateCall(token_index(), | 628 compiler->GenerateCall(token_pos(), |
| 629 try_index(), | 629 try_index(), |
| 630 &StubCode::CallNativeCFunctionLabel(), | 630 &StubCode::CallNativeCFunctionLabel(), |
| 631 PcDescriptors::kOther); | 631 PcDescriptors::kOther); |
| 632 __ popq(result); | 632 __ popq(result); |
| 633 } | 633 } |
| 634 | 634 |
| 635 | 635 |
| 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 636 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 637 const intptr_t kNumInputs = 2; | 637 const intptr_t kNumInputs = 2; |
| 638 if (receiver_type() == kGrowableObjectArray) { | 638 if (receiver_type() == kGrowableObjectArray) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 649 } else { | 649 } else { |
| 650 ASSERT(receiver_type() == kIllegalObjectKind); | 650 ASSERT(receiver_type() == kIllegalObjectKind); |
| 651 return MakeCallSummary(); | 651 return MakeCallSummary(); |
| 652 } | 652 } |
| 653 } | 653 } |
| 654 | 654 |
| 655 | 655 |
| 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 656 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 657 LoadIndexedComp* comp) { | 657 LoadIndexedComp* comp) { |
| 658 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 658 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 659 comp->token_index(), | 659 comp->token_pos(), |
| 660 comp->try_index(), | 660 comp->try_index(), |
| 661 kDeoptLoadIndexedPolymorphic); | 661 kDeoptLoadIndexedPolymorphic); |
| 662 if (comp->ic_data()->NumberOfChecks() == 0) { | 662 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 663 __ jmp(deopt); | 663 __ jmp(deopt); |
| 664 return; | 664 return; |
| 665 } | 665 } |
| 666 ASSERT(comp->HasICData()); | 666 ASSERT(comp->HasICData()); |
| 667 const ICData& ic_data = *comp->ic_data(); | 667 const ICData& ic_data = *comp->ic_data(); |
| 668 ASSERT(ic_data.num_args_tested() == 1); | 668 ASSERT(ic_data.num_args_tested() == 1); |
| 669 // No indexed access on Smi. | 669 // No indexed access on Smi. |
| 670 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 670 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 671 // Load receiver into RAX. | 671 // Load receiver into RAX. |
| 672 const intptr_t kNumArguments = 2; | 672 const intptr_t kNumArguments = 2; |
| 673 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 673 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 674 __ testq(RAX, Immediate(kSmiTagMask)); | 674 __ testq(RAX, Immediate(kSmiTagMask)); |
| 675 __ j(ZERO, deopt); | 675 __ j(ZERO, deopt); |
| 676 Label done; | 676 Label done; |
| 677 __ LoadClassId(RDI, RAX); | 677 __ LoadClassId(RDI, RAX); |
| 678 compiler->EmitTestAndCall(ic_data, | 678 compiler->EmitTestAndCall(ic_data, |
| 679 RDI, // Class id register. | 679 RDI, // Class id register. |
| 680 kNumArguments, | 680 kNumArguments, |
| 681 Array::Handle(), // No named arguments. | 681 Array::Handle(), // No named arguments. |
| 682 deopt, &done, // Labels. | 682 deopt, &done, // Labels. |
| 683 comp->cid(), | 683 comp->cid(), |
| 684 comp->token_index(), | 684 comp->token_pos(), |
| 685 comp->try_index()); | 685 comp->try_index()); |
| 686 __ Bind(&done); | 686 __ Bind(&done); |
| 687 } | 687 } |
| 688 | 688 |
| 689 | 689 |
| 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 690 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 691 if (receiver_type() == kIllegalObjectKind) { | 691 if (receiver_type() == kIllegalObjectKind) { |
| 692 if (HasICData()) { | 692 if (HasICData()) { |
| 693 EmitLoadIndexedPolymorphic(compiler, this); | 693 EmitLoadIndexedPolymorphic(compiler, this); |
| 694 } else { | 694 } else { |
| 695 compiler->EmitLoadIndexedGeneric(this); | 695 compiler->EmitLoadIndexedGeneric(this); |
| 696 } | 696 } |
| 697 ASSERT(locs()->out().reg() == RAX); | 697 ASSERT(locs()->out().reg() == RAX); |
| 698 return; | 698 return; |
| 699 } | 699 } |
| 700 | 700 |
| 701 Register receiver = locs()->in(0).reg(); | 701 Register receiver = locs()->in(0).reg(); |
| 702 Register index = locs()->in(1).reg(); | 702 Register index = locs()->in(1).reg(); |
| 703 Register result = locs()->out().reg(); | 703 Register result = locs()->out().reg(); |
| 704 | 704 |
| 705 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 705 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
| 706 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 706 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 707 | 707 |
| 708 Label* deopt = compiler->AddDeoptStub(cid(), | 708 Label* deopt = compiler->AddDeoptStub(cid(), |
| 709 token_index(), | 709 token_pos(), |
| 710 try_index(), | 710 try_index(), |
| 711 deopt_reason, | 711 deopt_reason, |
| 712 receiver, | 712 receiver, |
| 713 index); | 713 index); |
| 714 | 714 |
| 715 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 715 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 716 __ j(ZERO, deopt); | 716 __ j(ZERO, deopt); |
| 717 __ CompareClassId(receiver, receiver_type()); | 717 __ CompareClassId(receiver, receiver_type()); |
| 718 __ j(NOT_EQUAL, deopt); | 718 __ j(NOT_EQUAL, deopt); |
| 719 | 719 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 } | 770 } |
| 771 | 771 |
| 772 | 772 |
| 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 773 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
| 774 StoreIndexedComp* comp) { | 774 StoreIndexedComp* comp) { |
| 775 const String& function_name = | 775 const String& function_name = |
| 776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 776 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 777 | 777 |
| 778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 778 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 779 comp->cid(), | 779 comp->cid(), |
| 780 comp->token_index(), | 780 comp->token_pos(), |
| 781 comp->try_index()); | 781 comp->try_index()); |
| 782 | 782 |
| 783 const intptr_t kNumArguments = 3; | 783 const intptr_t kNumArguments = 3; |
| 784 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 784 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 785 compiler->GenerateInstanceCall(comp->cid(), | 785 compiler->GenerateInstanceCall(comp->cid(), |
| 786 comp->token_index(), | 786 comp->token_pos(), |
| 787 comp->try_index(), | 787 comp->try_index(), |
| 788 function_name, | 788 function_name, |
| 789 kNumArguments, | 789 kNumArguments, |
| 790 Array::ZoneHandle(), // No named arguments. | 790 Array::ZoneHandle(), // No named arguments. |
| 791 kNumArgsChecked); | 791 kNumArgsChecked); |
| 792 } | 792 } |
| 793 | 793 |
| 794 | 794 |
| 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 795 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 796 StoreIndexedComp* comp) { | 796 StoreIndexedComp* comp) { |
| 797 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 797 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 798 comp->token_index(), | 798 comp->token_pos(), |
| 799 comp->try_index(), | 799 comp->try_index(), |
| 800 kDeoptStoreIndexedPolymorphic); | 800 kDeoptStoreIndexedPolymorphic); |
| 801 if (comp->ic_data()->NumberOfChecks() == 0) { | 801 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 802 __ jmp(deopt); | 802 __ jmp(deopt); |
| 803 return; | 803 return; |
| 804 } | 804 } |
| 805 ASSERT(comp->HasICData()); | 805 ASSERT(comp->HasICData()); |
| 806 const ICData& ic_data = *comp->ic_data(); | 806 const ICData& ic_data = *comp->ic_data(); |
| 807 ASSERT(ic_data.num_args_tested() == 1); | 807 ASSERT(ic_data.num_args_tested() == 1); |
| 808 // No indexed access on Smi. | 808 // No indexed access on Smi. |
| 809 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 809 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 810 // Load receiver into RAX. | 810 // Load receiver into RAX. |
| 811 const intptr_t kNumArguments = 3; | 811 const intptr_t kNumArguments = 3; |
| 812 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); | 812 __ movq(RAX, Address(RSP, (kNumArguments - 1) * kWordSize)); |
| 813 __ testq(RAX, Immediate(kSmiTagMask)); | 813 __ testq(RAX, Immediate(kSmiTagMask)); |
| 814 __ j(ZERO, deopt); | 814 __ j(ZERO, deopt); |
| 815 Label done; | 815 Label done; |
| 816 __ LoadClassId(RDI, RAX); | 816 __ LoadClassId(RDI, RAX); |
| 817 compiler->EmitTestAndCall(ic_data, | 817 compiler->EmitTestAndCall(ic_data, |
| 818 RDI, // Class id register. | 818 RDI, // Class id register. |
| 819 kNumArguments, | 819 kNumArguments, |
| 820 Array::Handle(), // No named arguments. | 820 Array::Handle(), // No named arguments. |
| 821 deopt, &done, // Labels. | 821 deopt, &done, // Labels. |
| 822 comp->cid(), | 822 comp->cid(), |
| 823 comp->token_index(), | 823 comp->token_pos(), |
| 824 comp->try_index()); | 824 comp->try_index()); |
| 825 __ Bind(&done); | 825 __ Bind(&done); |
| 826 } | 826 } |
| 827 | 827 |
| 828 | 828 |
| 829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 829 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 830 if (receiver_type() == kIllegalObjectKind) { | 830 if (receiver_type() == kIllegalObjectKind) { |
| 831 if (HasICData()) { | 831 if (HasICData()) { |
| 832 EmitStoreIndexedPolymorphic(compiler, this); | 832 EmitStoreIndexedPolymorphic(compiler, this); |
| 833 } else { | 833 } else { |
| 834 EmitStoreIndexedGeneric(compiler, this); | 834 EmitStoreIndexedGeneric(compiler, this); |
| 835 } | 835 } |
| 836 return; | 836 return; |
| 837 } | 837 } |
| 838 | 838 |
| 839 Register receiver = locs()->in(0).reg(); | 839 Register receiver = locs()->in(0).reg(); |
| 840 Register index = locs()->in(1).reg(); | 840 Register index = locs()->in(1).reg(); |
| 841 Register value = locs()->in(2).reg(); | 841 Register value = locs()->in(2).reg(); |
| 842 | 842 |
| 843 Label* deopt = compiler->AddDeoptStub(cid(), | 843 Label* deopt = compiler->AddDeoptStub(cid(), |
| 844 token_index(), | 844 token_pos(), |
| 845 try_index(), | 845 try_index(), |
| 846 kDeoptStoreIndexed, | 846 kDeoptStoreIndexed, |
| 847 receiver, | 847 receiver, |
| 848 index, | 848 index, |
| 849 value); | 849 value); |
| 850 | 850 |
| 851 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 851 __ testq(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 852 __ j(ZERO, deopt); | 852 __ j(ZERO, deopt); |
| 853 __ CompareClassId(receiver, receiver_type()); | 853 __ CompareClassId(receiver, receiver_type()); |
| 854 __ j(NOT_EQUAL, deopt); | 854 __ j(NOT_EQUAL, deopt); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 return MakeCallSummary(); | 893 return MakeCallSummary(); |
| 894 } | 894 } |
| 895 | 895 |
| 896 | 896 |
| 897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 897 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 898 const String& function_name = | 898 const String& function_name = |
| 899 String::ZoneHandle(Field::SetterSymbol(field_name())); | 899 String::ZoneHandle(Field::SetterSymbol(field_name())); |
| 900 | 900 |
| 901 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 901 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 902 cid(), | 902 cid(), |
| 903 token_index(), | 903 token_pos(), |
| 904 try_index()); | 904 try_index()); |
| 905 const intptr_t kArgumentCount = 2; | 905 const intptr_t kArgumentCount = 2; |
| 906 const intptr_t kCheckedArgumentCount = 1; | 906 const intptr_t kCheckedArgumentCount = 1; |
| 907 compiler->GenerateInstanceCall(cid(), | 907 compiler->GenerateInstanceCall(cid(), |
| 908 token_index(), | 908 token_pos(), |
| 909 try_index(), | 909 try_index(), |
| 910 function_name, | 910 function_name, |
| 911 kArgumentCount, | 911 kArgumentCount, |
| 912 Array::ZoneHandle(), | 912 Array::ZoneHandle(), |
| 913 kCheckedArgumentCount); | 913 kCheckedArgumentCount); |
| 914 } | 914 } |
| 915 | 915 |
| 916 | 916 |
| 917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 917 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
| 918 const intptr_t kNumInputs = 1; | 918 const intptr_t kNumInputs = 1; |
| 919 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 919 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
| 920 } | 920 } |
| 921 | 921 |
| 922 | 922 |
| 923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 923 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 924 Register value = locs()->in(0).reg(); | 924 Register value = locs()->in(0).reg(); |
| 925 Register result = locs()->out().reg(); | 925 Register result = locs()->out().reg(); |
| 926 | 926 |
| 927 // Preserve the argument as the result of the computation, | 927 // Preserve the argument as the result of the computation, |
| 928 // then call the setter. | 928 // then call the setter. |
| 929 | 929 |
| 930 // Duplicate the argument. | 930 // Duplicate the argument. |
| 931 // TODO(fschneider): Avoid preserving the value if the result is not used. | 931 // TODO(fschneider): Avoid preserving the value if the result is not used. |
| 932 __ pushq(value); | 932 __ pushq(value); |
| 933 __ pushq(value); | 933 __ pushq(value); |
| 934 compiler->GenerateStaticCall(cid(), | 934 compiler->GenerateStaticCall(cid(), |
| 935 token_index(), | 935 token_pos(), |
| 936 try_index(), | 936 try_index(), |
| 937 setter_function(), | 937 setter_function(), |
| 938 1, | 938 1, |
| 939 Array::ZoneHandle()); | 939 Array::ZoneHandle()); |
| 940 __ popq(result); | 940 __ popq(result); |
| 941 } | 941 } |
| 942 | 942 |
| 943 | 943 |
| 944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 944 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
| 945 // TODO(fschneider): For this instruction the input register may be | 945 // TODO(fschneider): For this instruction the input register may be |
| 946 // reused for the result (but is not required to) because the input | 946 // reused for the result (but is not required to) because the input |
| 947 // is not used after the result is defined. We should consider adding | 947 // is not used after the result is defined. We should consider adding |
| 948 // this information to the input policy. | 948 // this information to the input policy. |
| 949 return LocationSummary::Make(1, Location::RequiresRegister()); | 949 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 950 } | 950 } |
| 951 | 951 |
| 952 | 952 |
| 953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 953 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 954 Register instance_reg = locs()->in(0).reg(); | 954 Register instance_reg = locs()->in(0).reg(); |
| 955 Register result_reg = locs()->out().reg(); | 955 Register result_reg = locs()->out().reg(); |
| 956 | 956 |
| 957 if (HasICData()) { | 957 if (HasICData()) { |
| 958 ASSERT(original() != NULL); | 958 ASSERT(original() != NULL); |
| 959 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 959 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
| 960 original()->token_index(), | 960 original()->token_pos(), |
| 961 original()->try_index(), | 961 original()->try_index(), |
| 962 kDeoptInstanceGetterSameTarget, | 962 kDeoptInstanceGetterSameTarget, |
| 963 instance_reg); | 963 instance_reg); |
| 964 // Smis do not have instance fields (Smi class is always first). | 964 // Smis do not have instance fields (Smi class is always first). |
| 965 // Use 'result' as temporary register. | 965 // Use 'result' as temporary register. |
| 966 ASSERT(result_reg != instance_reg); | 966 ASSERT(result_reg != instance_reg); |
| 967 ASSERT(ic_data() != NULL); | 967 ASSERT(ic_data() != NULL); |
| 968 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 968 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 969 } | 969 } |
| 970 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); | 970 __ movq(result_reg, FieldAddress(instance_reg, field().Offset())); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 992 return summary; | 992 return summary; |
| 993 } | 993 } |
| 994 | 994 |
| 995 | 995 |
| 996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 996 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 997 ASSERT(locs()->in(0).reg() == RAX); // Value. | 997 ASSERT(locs()->in(0).reg() == RAX); // Value. |
| 998 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. | 998 ASSERT(locs()->in(1).reg() == RCX); // Instantiator. |
| 999 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. | 999 ASSERT(locs()->in(2).reg() == RDX); // Instantiator type arguments. |
| 1000 | 1000 |
| 1001 compiler->GenerateInstanceOf(cid(), | 1001 compiler->GenerateInstanceOf(cid(), |
| 1002 token_index(), | 1002 token_pos(), |
| 1003 try_index(), | 1003 try_index(), |
| 1004 type(), | 1004 type(), |
| 1005 negate_result()); | 1005 negate_result()); |
| 1006 ASSERT(locs()->out().reg() == RAX); | 1006 ASSERT(locs()->out().reg() == RAX); |
| 1007 } | 1007 } |
| 1008 | 1008 |
| 1009 | 1009 |
| 1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1010 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1011 // TODO(regis): The elements of the array could be considered as arguments to | 1011 // TODO(regis): The elements of the array could be considered as arguments to |
| 1012 // CreateArrayComp, thereby making CreateArrayComp a call. | 1012 // CreateArrayComp, thereby making CreateArrayComp a call. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1025 | 1025 |
| 1026 | 1026 |
| 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1027 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1028 Register temp_reg = locs()->temp(0).reg(); | 1028 Register temp_reg = locs()->temp(0).reg(); |
| 1029 Register result_reg = locs()->out().reg(); | 1029 Register result_reg = locs()->out().reg(); |
| 1030 | 1030 |
| 1031 // Allocate the array. R10 = length, RBX = element type. | 1031 // Allocate the array. R10 = length, RBX = element type. |
| 1032 ASSERT(temp_reg == R10); | 1032 ASSERT(temp_reg == R10); |
| 1033 ASSERT(locs()->in(0).reg() == RBX); | 1033 ASSERT(locs()->in(0).reg() == RBX); |
| 1034 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 1034 __ movq(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
| 1035 compiler->GenerateCall(token_index(), | 1035 compiler->GenerateCall(token_pos(), |
| 1036 try_index(), | 1036 try_index(), |
| 1037 &StubCode::AllocateArrayLabel(), | 1037 &StubCode::AllocateArrayLabel(), |
| 1038 PcDescriptors::kOther); | 1038 PcDescriptors::kOther); |
| 1039 ASSERT(result_reg == RAX); | 1039 ASSERT(result_reg == RAX); |
| 1040 | 1040 |
| 1041 // Pop the element values from the stack into the array. | 1041 // Pop the element values from the stack into the array. |
| 1042 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1042 __ leaq(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 1043 for (int i = ElementCount() - 1; i >= 0; --i) { | 1043 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 1044 ASSERT(ElementAt(i)->IsUse()); | 1044 ASSERT(ElementAt(i)->IsUse()); |
| 1045 __ popq(Address(temp_reg, i * kWordSize)); | 1045 __ popq(Address(temp_reg, i * kWordSize)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1057 | 1057 |
| 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1058 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 1059 FlowGraphCompiler* compiler) { | 1059 FlowGraphCompiler* compiler) { |
| 1060 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1060 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 1061 Register type_arguments = locs()->in(0).reg(); | 1061 Register type_arguments = locs()->in(0).reg(); |
| 1062 Register instantiator_type_arguments = locs()->in(1).reg(); | 1062 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1063 Register result = locs()->out().reg(); | 1063 Register result = locs()->out().reg(); |
| 1064 | 1064 |
| 1065 // Push the result place holder initialized to NULL. | 1065 // Push the result place holder initialized to NULL. |
| 1066 __ PushObject(Object::ZoneHandle()); | 1066 __ PushObject(Object::ZoneHandle()); |
| 1067 __ pushq(Immediate(Smi::RawValue(token_index()))); | 1067 __ pushq(Immediate(Smi::RawValue(token_pos()))); |
| 1068 __ PushObject(cls); | 1068 __ PushObject(cls); |
| 1069 __ pushq(type_arguments); | 1069 __ pushq(type_arguments); |
| 1070 __ pushq(instantiator_type_arguments); | 1070 __ pushq(instantiator_type_arguments); |
| 1071 compiler->GenerateCallRuntime(cid(), | 1071 compiler->GenerateCallRuntime(cid(), |
| 1072 token_index(), | 1072 token_pos(), |
| 1073 try_index(), | 1073 try_index(), |
| 1074 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1074 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 1075 // Pop instantiator type arguments, type arguments, class, and | 1075 // Pop instantiator type arguments, type arguments, class, and |
| 1076 // source location. | 1076 // source location. |
| 1077 __ Drop(4); | 1077 __ Drop(4); |
| 1078 __ popq(result); // Pop new instance. | 1078 __ popq(result); // Pop new instance. |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 | 1081 |
| 1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1082 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1083 return LocationSummary::Make(1, Location::RequiresRegister()); | 1083 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 1084 } | 1084 } |
| 1085 | 1085 |
| 1086 | 1086 |
| 1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1087 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1088 Register instance_reg = locs()->in(0).reg(); | 1088 Register instance_reg = locs()->in(0).reg(); |
| 1089 Register result_reg = locs()->out().reg(); | 1089 Register result_reg = locs()->out().reg(); |
| 1090 if (HasICData()) { | 1090 if (HasICData()) { |
| 1091 ASSERT(original() != NULL); | 1091 ASSERT(original() != NULL); |
| 1092 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1092 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
| 1093 original()->token_index(), | 1093 original()->token_pos(), |
| 1094 original()->try_index(), | 1094 original()->try_index(), |
| 1095 kDeoptInstanceGetterSameTarget, | 1095 kDeoptInstanceGetterSameTarget, |
| 1096 instance_reg); | 1096 instance_reg); |
| 1097 // Smis do not have instance fields (Smi class is always first). | 1097 // Smis do not have instance fields (Smi class is always first). |
| 1098 // Use 'result' as temporary register. | 1098 // Use 'result' as temporary register. |
| 1099 ASSERT(result_reg != instance_reg); | 1099 ASSERT(result_reg != instance_reg); |
| 1100 ASSERT(ic_data() != NULL); | 1100 ASSERT(ic_data() != NULL); |
| 1101 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1101 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1102 } | 1102 } |
| 1103 | 1103 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1148 __ cmpq(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1149 Immediate(Smi::RawValue(len))); | 1149 Immediate(Smi::RawValue(len))); |
| 1150 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1150 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1151 __ Bind(&type_arguments_uninstantiated); | 1151 __ Bind(&type_arguments_uninstantiated); |
| 1152 } | 1152 } |
| 1153 // A runtime call to instantiate the type arguments is required. | 1153 // A runtime call to instantiate the type arguments is required. |
| 1154 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1154 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1155 __ PushObject(type_arguments()); | 1155 __ PushObject(type_arguments()); |
| 1156 __ pushq(instantiator_reg); // Push instantiator type arguments. | 1156 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 1157 compiler->GenerateCallRuntime(cid(), | 1157 compiler->GenerateCallRuntime(cid(), |
| 1158 token_index(), | 1158 token_pos(), |
| 1159 try_index(), | 1159 try_index(), |
| 1160 kInstantiateTypeArgumentsRuntimeEntry); | 1160 kInstantiateTypeArgumentsRuntimeEntry); |
| 1161 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1161 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1162 __ popq(result_reg); // Pop instantiated type arguments. | 1162 __ popq(result_reg); // Pop instantiated type arguments. |
| 1163 __ Bind(&type_arguments_instantiated); | 1163 __ Bind(&type_arguments_instantiated); |
| 1164 ASSERT(instantiator_reg == result_reg); | 1164 ASSERT(instantiator_reg == result_reg); |
| 1165 // 'result_reg': Instantiated type arguments. | 1165 // 'result_reg': Instantiated type arguments. |
| 1166 } | 1166 } |
| 1167 | 1167 |
| 1168 | 1168 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 } | 1298 } |
| 1299 | 1299 |
| 1300 | 1300 |
| 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1301 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1302 ASSERT(locs()->temp(0).reg() == R10); | 1302 ASSERT(locs()->temp(0).reg() == R10); |
| 1303 ASSERT(locs()->out().reg() == RAX); | 1303 ASSERT(locs()->out().reg() == RAX); |
| 1304 | 1304 |
| 1305 __ movq(R10, Immediate(num_context_variables())); | 1305 __ movq(R10, Immediate(num_context_variables())); |
| 1306 const ExternalLabel label("alloc_context", | 1306 const ExternalLabel label("alloc_context", |
| 1307 StubCode::AllocateContextEntryPoint()); | 1307 StubCode::AllocateContextEntryPoint()); |
| 1308 compiler->GenerateCall(token_index(), | 1308 compiler->GenerateCall(token_pos(), |
| 1309 try_index(), | 1309 try_index(), |
| 1310 &label, | 1310 &label, |
| 1311 PcDescriptors::kOther); | 1311 PcDescriptors::kOther); |
| 1312 } | 1312 } |
| 1313 | 1313 |
| 1314 | 1314 |
| 1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1315 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1316 return LocationSummary::Make(1, | 1316 return LocationSummary::Make(1, |
| 1317 Location::RequiresRegister(), | 1317 Location::RequiresRegister(), |
| 1318 LocationSummary::kCall); | 1318 LocationSummary::kCall); |
| 1319 } | 1319 } |
| 1320 | 1320 |
| 1321 | 1321 |
| 1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1322 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1323 Register context_value = locs()->in(0).reg(); | 1323 Register context_value = locs()->in(0).reg(); |
| 1324 Register result = locs()->out().reg(); | 1324 Register result = locs()->out().reg(); |
| 1325 | 1325 |
| 1326 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1326 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1327 __ pushq(context_value); | 1327 __ pushq(context_value); |
| 1328 compiler->GenerateCallRuntime(cid(), | 1328 compiler->GenerateCallRuntime(cid(), |
| 1329 token_index(), | 1329 token_pos(), |
| 1330 try_index(), | 1330 try_index(), |
| 1331 kCloneContextRuntimeEntry); | 1331 kCloneContextRuntimeEntry); |
| 1332 __ popq(result); // Remove argument. | 1332 __ popq(result); // Remove argument. |
| 1333 __ popq(result); // Get result (cloned context). | 1333 __ popq(result); // Get result (cloned context). |
| 1334 } | 1334 } |
| 1335 | 1335 |
| 1336 | 1336 |
| 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1338 return LocationSummary::Make(0, Location::NoLocation()); | 1338 return LocationSummary::Make(0, Location::NoLocation()); |
| 1339 } | 1339 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1372 | 1372 |
| 1373 | 1373 |
| 1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1374 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1375 Register temp = locs()->temp(0).reg(); | 1375 Register temp = locs()->temp(0).reg(); |
| 1376 // Generate stack overflow check. | 1376 // Generate stack overflow check. |
| 1377 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); | 1377 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); |
| 1378 __ cmpq(RSP, Address(temp, 0)); | 1378 __ cmpq(RSP, Address(temp, 0)); |
| 1379 Label no_stack_overflow; | 1379 Label no_stack_overflow; |
| 1380 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); | 1380 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); |
| 1381 compiler->GenerateCallRuntime(cid(), | 1381 compiler->GenerateCallRuntime(cid(), |
| 1382 token_index(), | 1382 token_pos(), |
| 1383 try_index(), | 1383 try_index(), |
| 1384 kStackOverflowRuntimeEntry); | 1384 kStackOverflowRuntimeEntry); |
| 1385 __ Bind(&no_stack_overflow); | 1385 __ Bind(&no_stack_overflow); |
| 1386 } | 1386 } |
| 1387 | 1387 |
| 1388 | 1388 |
| 1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1389 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1390 const intptr_t kNumInputs = 2; | 1390 const intptr_t kNumInputs = 2; |
| 1391 | 1391 |
| 1392 if (operands_type() == kDoubleOperands) { | 1392 if (operands_type() == kDoubleOperands) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 | 1450 |
| 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1451 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1452 Register left = comp->locs()->in(0).reg(); | 1452 Register left = comp->locs()->in(0).reg(); |
| 1453 Register right = comp->locs()->in(1).reg(); | 1453 Register right = comp->locs()->in(1).reg(); |
| 1454 Register result = comp->locs()->out().reg(); | 1454 Register result = comp->locs()->out().reg(); |
| 1455 Register temp = comp->locs()->temp(0).reg(); | 1455 Register temp = comp->locs()->temp(0).reg(); |
| 1456 ASSERT(left == result); | 1456 ASSERT(left == result); |
| 1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1457 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1458 comp->instance_call()->token_index(), | 1458 comp->instance_call()->token_pos(), |
| 1459 comp->instance_call()->try_index(), | 1459 comp->instance_call()->try_index(), |
| 1460 kDeoptSmiBinaryOp, | 1460 kDeoptSmiBinaryOp, |
| 1461 temp, | 1461 temp, |
| 1462 right); | 1462 right); |
| 1463 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1463 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1464 // to save one move. | 1464 // to save one move. |
| 1465 __ movq(temp, left); | 1465 __ movq(temp, left); |
| 1466 __ orq(left, right); | 1466 __ orq(left, right); |
| 1467 __ testq(left, Immediate(kSmiTagMask)); | 1467 __ testq(left, Immediate(kSmiTagMask)); |
| 1468 __ j(NOT_ZERO, deopt); | 1468 __ j(NOT_ZERO, deopt); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1559 __ jmp(&done); | 1559 __ jmp(&done); |
| 1560 { | 1560 { |
| 1561 __ Bind(&call_method); | 1561 __ Bind(&call_method); |
| 1562 Function& target = Function::ZoneHandle( | 1562 Function& target = Function::ZoneHandle( |
| 1563 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1563 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1564 ASSERT(!target.IsNull()); | 1564 ASSERT(!target.IsNull()); |
| 1565 const intptr_t kArgumentCount = 2; | 1565 const intptr_t kArgumentCount = 2; |
| 1566 __ pushq(temp); | 1566 __ pushq(temp); |
| 1567 __ pushq(right); | 1567 __ pushq(right); |
| 1568 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1568 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1569 comp->instance_call()->token_index(), | 1569 comp->instance_call()->token_pos(), |
| 1570 comp->instance_call()->try_index(), | 1570 comp->instance_call()->try_index(), |
| 1571 target, | 1571 target, |
| 1572 kArgumentCount, | 1572 kArgumentCount, |
| 1573 Array::Handle()); // No argument names. | 1573 Array::Handle()); // No argument names. |
| 1574 ASSERT(result == RAX); | 1574 ASSERT(result == RAX); |
| 1575 } | 1575 } |
| 1576 __ Bind(&done); | 1576 __ Bind(&done); |
| 1577 break; | 1577 break; |
| 1578 } | 1578 } |
| 1579 case Token::kDIV: { | 1579 case Token::kDIV: { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1605 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi | 1605 // TODO(regis): For now, we only support Token::kBIT_AND for a Mint or Smi |
| 1606 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1606 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1607 // both receiver and argument are Mint or if one of them is Mint and the other | 1607 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1608 // is a negative Smi. | 1608 // is a negative Smi. |
| 1609 Register left = comp->locs()->in(0).reg(); | 1609 Register left = comp->locs()->in(0).reg(); |
| 1610 Register right = comp->locs()->in(1).reg(); | 1610 Register right = comp->locs()->in(1).reg(); |
| 1611 Register result = comp->locs()->out().reg(); | 1611 Register result = comp->locs()->out().reg(); |
| 1612 ASSERT(left == result); | 1612 ASSERT(left == result); |
| 1613 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1613 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1614 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1614 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1615 comp->instance_call()->token_index(), | 1615 comp->instance_call()->token_pos(), |
| 1616 comp->instance_call()->try_index(), | 1616 comp->instance_call()->try_index(), |
| 1617 kDeoptMintBinaryOp, | 1617 kDeoptMintBinaryOp, |
| 1618 left, | 1618 left, |
| 1619 right); | 1619 right); |
| 1620 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1620 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1621 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1621 __ testq(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1622 __ j(NOT_ZERO, &non_smi); | 1622 __ j(NOT_ZERO, &non_smi); |
| 1623 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1623 __ testq(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1624 __ j(ZERO, &smi_smi); | 1624 __ j(ZERO, &smi_smi); |
| 1625 __ CompareClassId(right, kMint); // Is argument Mint? | 1625 __ CompareClassId(right, kMint); // Is argument Mint? |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1653 __ Bind(&smi_static_call); | 1653 __ Bind(&smi_static_call); |
| 1654 { | 1654 { |
| 1655 Function& target = Function::ZoneHandle( | 1655 Function& target = Function::ZoneHandle( |
| 1656 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1656 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1657 if (target.IsNull()) { | 1657 if (target.IsNull()) { |
| 1658 __ jmp(deopt); | 1658 __ jmp(deopt); |
| 1659 } else { | 1659 } else { |
| 1660 __ pushq(left); | 1660 __ pushq(left); |
| 1661 __ pushq(right); | 1661 __ pushq(right); |
| 1662 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1662 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1663 comp->instance_call()->token_index(), | 1663 comp->instance_call()->token_pos(), |
| 1664 comp->instance_call()->try_index(), | 1664 comp->instance_call()->try_index(), |
| 1665 target, | 1665 target, |
| 1666 comp->instance_call()->ArgumentCount(), | 1666 comp->instance_call()->ArgumentCount(), |
| 1667 comp->instance_call()->argument_names()); | 1667 comp->instance_call()->argument_names()); |
| 1668 ASSERT(result == RAX); | 1668 ASSERT(result == RAX); |
| 1669 __ jmp(&done); | 1669 __ jmp(&done); |
| 1670 } | 1670 } |
| 1671 } | 1671 } |
| 1672 | 1672 |
| 1673 __ Bind(&mint_static_call); | 1673 __ Bind(&mint_static_call); |
| 1674 { | 1674 { |
| 1675 Function& target = Function::ZoneHandle( | 1675 Function& target = Function::ZoneHandle( |
| 1676 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1676 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
| 1677 if (target.IsNull()) { | 1677 if (target.IsNull()) { |
| 1678 __ jmp(deopt); | 1678 __ jmp(deopt); |
| 1679 } else { | 1679 } else { |
| 1680 __ pushq(left); | 1680 __ pushq(left); |
| 1681 __ pushq(right); | 1681 __ pushq(right); |
| 1682 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1682 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1683 comp->instance_call()->token_index(), | 1683 comp->instance_call()->token_pos(), |
| 1684 comp->instance_call()->try_index(), | 1684 comp->instance_call()->try_index(), |
| 1685 target, | 1685 target, |
| 1686 comp->instance_call()->ArgumentCount(), | 1686 comp->instance_call()->ArgumentCount(), |
| 1687 comp->instance_call()->argument_names()); | 1687 comp->instance_call()->argument_names()); |
| 1688 ASSERT(result == RAX); | 1688 ASSERT(result == RAX); |
| 1689 } | 1689 } |
| 1690 } | 1690 } |
| 1691 __ Bind(&done); | 1691 __ Bind(&done); |
| 1692 } | 1692 } |
| 1693 | 1693 |
| 1694 | 1694 |
| 1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1695 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1696 BinaryOpComp* comp) { | 1696 BinaryOpComp* comp) { |
| 1697 Register left = RBX; | 1697 Register left = RBX; |
| 1698 Register right = RCX; | 1698 Register right = RCX; |
| 1699 Register temp = RDX; | 1699 Register temp = RDX; |
| 1700 Register result = comp->locs()->out().reg(); | 1700 Register result = comp->locs()->out().reg(); |
| 1701 | 1701 |
| 1702 const Class& double_class = compiler->double_class(); | 1702 const Class& double_class = compiler->double_class(); |
| 1703 const Code& stub = | 1703 const Code& stub = |
| 1704 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1704 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1705 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1705 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1706 compiler->GenerateCall(comp->instance_call()->token_index(), | 1706 compiler->GenerateCall(comp->instance_call()->token_pos(), |
| 1707 comp->instance_call()->try_index(), | 1707 comp->instance_call()->try_index(), |
| 1708 &label, | 1708 &label, |
| 1709 PcDescriptors::kOther); | 1709 PcDescriptors::kOther); |
| 1710 // Newly allocated object is now in the result register (RAX). | 1710 // Newly allocated object is now in the result register (RAX). |
| 1711 ASSERT(result == RAX); | 1711 ASSERT(result == RAX); |
| 1712 __ popq(right); | 1712 __ popq(right); |
| 1713 __ popq(left); | 1713 __ popq(left); |
| 1714 | 1714 |
| 1715 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1715 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1716 comp->instance_call()->token_index(), | 1716 comp->instance_call()->token_pos(), |
| 1717 comp->instance_call()->try_index(), | 1717 comp->instance_call()->try_index(), |
| 1718 kDeoptDoubleBinaryOp, | 1718 kDeoptDoubleBinaryOp, |
| 1719 left, | 1719 left, |
| 1720 right); | 1720 right); |
| 1721 | 1721 |
| 1722 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1722 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1723 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1723 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 1724 | 1724 |
| 1725 switch (comp->op_kind()) { | 1725 switch (comp->op_kind()) { |
| 1726 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1726 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1771 // TODO(srdjan): Implement for more checks. | 1771 // TODO(srdjan): Implement for more checks. |
| 1772 ASSERT(ic_data.NumberOfChecks() == 1); | 1772 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1773 intptr_t test_class_id; | 1773 intptr_t test_class_id; |
| 1774 Function& target = Function::Handle(); | 1774 Function& target = Function::Handle(); |
| 1775 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1775 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1776 | 1776 |
| 1777 Register value = locs()->in(0).reg(); | 1777 Register value = locs()->in(0).reg(); |
| 1778 Register result = locs()->out().reg(); | 1778 Register result = locs()->out().reg(); |
| 1779 ASSERT(value == result); | 1779 ASSERT(value == result); |
| 1780 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1780 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1781 instance_call()->token_index(), | 1781 instance_call()->token_pos(), |
| 1782 instance_call()->try_index(), | 1782 instance_call()->try_index(), |
| 1783 kDeoptUnaryOp, | 1783 kDeoptUnaryOp, |
| 1784 value); | 1784 value); |
| 1785 if (test_class_id == kSmi) { | 1785 if (test_class_id == kSmi) { |
| 1786 __ testq(value, Immediate(kSmiTagMask)); | 1786 __ testq(value, Immediate(kSmiTagMask)); |
| 1787 __ j(NOT_ZERO, deopt); | 1787 __ j(NOT_ZERO, deopt); |
| 1788 switch (op_kind()) { | 1788 switch (op_kind()) { |
| 1789 case Token::kNEGATE: | 1789 case Token::kNEGATE: |
| 1790 __ negq(value); | 1790 __ negq(value); |
| 1791 __ j(OVERFLOW, deopt); | 1791 __ j(OVERFLOW, deopt); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 // TODO(srdjan): Implement for more checks. | 1824 // TODO(srdjan): Implement for more checks. |
| 1825 ASSERT(ic_data.NumberOfChecks() == 1); | 1825 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1826 intptr_t test_class_id; | 1826 intptr_t test_class_id; |
| 1827 Function& target = Function::Handle(); | 1827 Function& target = Function::Handle(); |
| 1828 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1828 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1829 | 1829 |
| 1830 Register value = locs()->in(0).reg(); | 1830 Register value = locs()->in(0).reg(); |
| 1831 Register result = locs()->out().reg(); | 1831 Register result = locs()->out().reg(); |
| 1832 ASSERT(value == result); | 1832 ASSERT(value == result); |
| 1833 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1833 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1834 instance_call()->token_index(), | 1834 instance_call()->token_pos(), |
| 1835 instance_call()->try_index(), | 1835 instance_call()->try_index(), |
| 1836 kDeoptUnaryOp, | 1836 kDeoptUnaryOp, |
| 1837 value); | 1837 value); |
| 1838 if (test_class_id == kDouble) { | 1838 if (test_class_id == kDouble) { |
| 1839 Register temp = locs()->temp(0).reg(); | 1839 Register temp = locs()->temp(0).reg(); |
| 1840 __ testq(value, Immediate(kSmiTagMask)); | 1840 __ testq(value, Immediate(kSmiTagMask)); |
| 1841 __ j(ZERO, deopt); // Smi. | 1841 __ j(ZERO, deopt); // Smi. |
| 1842 __ CompareClassId(value, kDouble); | 1842 __ CompareClassId(value, kDouble); |
| 1843 __ j(NOT_EQUAL, deopt); | 1843 __ j(NOT_EQUAL, deopt); |
| 1844 // Allocate result object. | 1844 // Allocate result object. |
| 1845 const Class& double_class = compiler->double_class(); | 1845 const Class& double_class = compiler->double_class(); |
| 1846 const Code& stub = | 1846 const Code& stub = |
| 1847 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1847 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1848 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1848 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1849 __ pushq(value); | 1849 __ pushq(value); |
| 1850 compiler->GenerateCall(instance_call()->token_index(), | 1850 compiler->GenerateCall(instance_call()->token_pos(), |
| 1851 instance_call()->try_index(), | 1851 instance_call()->try_index(), |
| 1852 &label, | 1852 &label, |
| 1853 PcDescriptors::kOther); | 1853 PcDescriptors::kOther); |
| 1854 // Result is in RAX. | 1854 // Result is in RAX. |
| 1855 ASSERT(result != temp); | 1855 ASSERT(result != temp); |
| 1856 __ movq(result, RAX); | 1856 __ movq(result, RAX); |
| 1857 __ popq(temp); | 1857 __ popq(temp); |
| 1858 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1858 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1859 __ DoubleNegate(XMM0); | 1859 __ DoubleNegate(XMM0); |
| 1860 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1860 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1879 } | 1879 } |
| 1880 | 1880 |
| 1881 | 1881 |
| 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1882 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1883 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; | 1883 Register value = (from() == kDouble) ? locs()->in(0).reg() : RBX; |
| 1884 Register result = locs()->out().reg(); | 1884 Register result = locs()->out().reg(); |
| 1885 | 1885 |
| 1886 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1886 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
| 1887 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1887 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1888 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1888 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1889 instance_call()->token_index(), | 1889 instance_call()->token_pos(), |
| 1890 instance_call()->try_index(), | 1890 instance_call()->try_index(), |
| 1891 deopt_reason, | 1891 deopt_reason, |
| 1892 value); | 1892 value); |
| 1893 | 1893 |
| 1894 if (from() == kDouble) { | 1894 if (from() == kDouble) { |
| 1895 __ testq(value, Immediate(kSmiTagMask)); | 1895 __ testq(value, Immediate(kSmiTagMask)); |
| 1896 __ j(ZERO, deopt); // Deoptimize if Smi. | 1896 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1897 __ CompareClassId(value, kDouble); | 1897 __ CompareClassId(value, kDouble); |
| 1898 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1898 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1899 ASSERT(value == result); | 1899 ASSERT(value == result); |
| 1900 return; | 1900 return; |
| 1901 } | 1901 } |
| 1902 | 1902 |
| 1903 ASSERT(from() == kSmi); | 1903 ASSERT(from() == kSmi); |
| 1904 | 1904 |
| 1905 const Class& double_class = compiler->double_class(); | 1905 const Class& double_class = compiler->double_class(); |
| 1906 const Code& stub = | 1906 const Code& stub = |
| 1907 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1907 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1908 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1908 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1909 | 1909 |
| 1910 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1910 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 1911 compiler->GenerateCall(instance_call()->token_index(), | 1911 compiler->GenerateCall(instance_call()->token_pos(), |
| 1912 instance_call()->try_index(), | 1912 instance_call()->try_index(), |
| 1913 &label, | 1913 &label, |
| 1914 PcDescriptors::kOther); | 1914 PcDescriptors::kOther); |
| 1915 ASSERT(result == RAX); | 1915 ASSERT(result == RAX); |
| 1916 __ popq(value); | 1916 __ popq(value); |
| 1917 | 1917 |
| 1918 __ testq(value, Immediate(kSmiTagMask)); | 1918 __ testq(value, Immediate(kSmiTagMask)); |
| 1919 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1919 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1920 __ SmiUntag(value); | 1920 __ SmiUntag(value); |
| 1921 __ cvtsi2sd(XMM0, value); | 1921 __ cvtsi2sd(XMM0, value); |
| 1922 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1922 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1923 } | 1923 } |
| 1924 | 1924 |
| 1925 | 1925 |
| 1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1926 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 1927 return MakeCallSummary(); | 1927 return MakeCallSummary(); |
| 1928 } | 1928 } |
| 1929 | 1929 |
| 1930 | 1930 |
| 1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1931 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1932 ASSERT(instance_call()->VerifyComputation()); | 1932 ASSERT(instance_call()->VerifyComputation()); |
| 1933 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1933 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1934 instance_call()->token_index(), | 1934 instance_call()->token_pos(), |
| 1935 instance_call()->try_index(), | 1935 instance_call()->try_index(), |
| 1936 kDeoptPolymorphicInstanceCallTestFail); | 1936 kDeoptPolymorphicInstanceCallTestFail); |
| 1937 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1937 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1938 __ jmp(deopt); | 1938 __ jmp(deopt); |
| 1939 return; | 1939 return; |
| 1940 } | 1940 } |
| 1941 ASSERT(HasICData()); | 1941 ASSERT(HasICData()); |
| 1942 ASSERT(ic_data()->num_args_tested() == 1); | 1942 ASSERT(ic_data()->num_args_tested() == 1); |
| 1943 Label handle_smi; | 1943 Label handle_smi; |
| 1944 Label* is_smi_label = | 1944 Label* is_smi_label = |
| 1945 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1945 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
| 1946 | 1946 |
| 1947 // Load receiver into RAX. | 1947 // Load receiver into RAX. |
| 1948 __ movq(RAX, | 1948 __ movq(RAX, |
| 1949 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1949 Address(RSP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1950 __ testq(RAX, Immediate(kSmiTagMask)); | 1950 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1951 __ j(ZERO, is_smi_label); | 1951 __ j(ZERO, is_smi_label); |
| 1952 Label done; | 1952 Label done; |
| 1953 __ LoadClassId(RDI, RAX); | 1953 __ LoadClassId(RDI, RAX); |
| 1954 compiler->EmitTestAndCall(*ic_data(), | 1954 compiler->EmitTestAndCall(*ic_data(), |
| 1955 RDI, // Class id register. | 1955 RDI, // Class id register. |
| 1956 instance_call()->ArgumentCount(), | 1956 instance_call()->ArgumentCount(), |
| 1957 instance_call()->argument_names(), | 1957 instance_call()->argument_names(), |
| 1958 deopt, &done, // Labels. | 1958 deopt, &done, // Labels. |
| 1959 instance_call()->cid(), | 1959 instance_call()->cid(), |
| 1960 instance_call()->token_index(), | 1960 instance_call()->token_pos(), |
| 1961 instance_call()->try_index()); | 1961 instance_call()->try_index()); |
| 1962 if (is_smi_label == &handle_smi) { | 1962 if (is_smi_label == &handle_smi) { |
| 1963 __ Bind(&handle_smi); | 1963 __ Bind(&handle_smi); |
| 1964 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1964 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
| 1965 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1965 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1966 compiler->GenerateStaticCall(instance_call()->cid(), | 1966 compiler->GenerateStaticCall(instance_call()->cid(), |
| 1967 instance_call()->token_index(), | 1967 instance_call()->token_pos(), |
| 1968 instance_call()->try_index(), | 1968 instance_call()->try_index(), |
| 1969 target, | 1969 target, |
| 1970 instance_call()->ArgumentCount(), | 1970 instance_call()->ArgumentCount(), |
| 1971 instance_call()->argument_names()); | 1971 instance_call()->argument_names()); |
| 1972 } | 1972 } |
| 1973 __ Bind(&done); | 1973 __ Bind(&done); |
| 1974 } | 1974 } |
| 1975 | 1975 |
| 1976 } // namespace dart | 1976 } // namespace dart |
| 1977 | 1977 |
| 1978 #undef __ | 1978 #undef __ |
| 1979 | 1979 |
| 1980 #endif // defined TARGET_ARCH_X64 | 1980 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |