| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 __ popl(result); // Restore result. | 92 __ popl(result); // Restore result. |
| 93 } | 93 } |
| 94 __ LeaveFrame(); | 94 __ LeaveFrame(); |
| 95 __ ret(); | 95 __ ret(); |
| 96 | 96 |
| 97 // Generate 1 byte NOP so that the debugger can patch the | 97 // Generate 1 byte NOP so that the debugger can patch the |
| 98 // return pattern with a call to the debug stub. | 98 // return pattern with a call to the debug stub. |
| 99 __ nop(1); | 99 __ nop(1); |
| 100 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, | 100 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, |
| 101 cid(), | 101 cid(), |
| 102 token_index(), | 102 token_pos(), |
| 103 CatchClauseNode::kInvalidTryIndex); | 103 CatchClauseNode::kInvalidTryIndex); |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 LocationSummary* ClosureCallComp::MakeLocationSummary() const { | 107 LocationSummary* ClosureCallComp::MakeLocationSummary() const { |
| 108 const intptr_t kNumInputs = 0; | 108 const intptr_t kNumInputs = 0; |
| 109 const intptr_t kNumTemps = 1; | 109 const intptr_t kNumTemps = 1; |
| 110 LocationSummary* result = new LocationSummary(kNumInputs, | 110 LocationSummary* result = new LocationSummary(kNumInputs, |
| 111 kNumTemps, | 111 kNumTemps, |
| 112 LocationSummary::kCall); | 112 LocationSummary::kCall); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 Register result = locs()->out().reg(); | 171 Register result = locs()->out().reg(); |
| 172 | 172 |
| 173 // Check that the type of the value is allowed in conditional context. | 173 // Check that the type of the value is allowed in conditional context. |
| 174 // Call the runtime if the object is not bool::true or bool::false. | 174 // Call the runtime if the object is not bool::true or bool::false. |
| 175 Label done; | 175 Label done; |
| 176 __ CompareObject(obj, compiler->bool_true()); | 176 __ CompareObject(obj, compiler->bool_true()); |
| 177 __ j(EQUAL, &done, Assembler::kNearJump); | 177 __ j(EQUAL, &done, Assembler::kNearJump); |
| 178 __ CompareObject(obj, compiler->bool_false()); | 178 __ CompareObject(obj, compiler->bool_false()); |
| 179 __ j(EQUAL, &done, Assembler::kNearJump); | 179 __ j(EQUAL, &done, Assembler::kNearJump); |
| 180 | 180 |
| 181 __ pushl(Immediate(Smi::RawValue(token_index()))); // Source location. | 181 __ pushl(Immediate(Smi::RawValue(token_pos()))); // Source location. |
| 182 __ pushl(obj); // Push the source object. | 182 __ pushl(obj); // Push the source object. |
| 183 compiler->GenerateCallRuntime(cid(), | 183 compiler->GenerateCallRuntime(cid(), |
| 184 token_index(), | 184 token_pos(), |
| 185 try_index(), | 185 try_index(), |
| 186 kConditionTypeErrorRuntimeEntry); | 186 kConditionTypeErrorRuntimeEntry); |
| 187 // We should never return here. | 187 // We should never return here. |
| 188 __ int3(); | 188 __ int3(); |
| 189 | 189 |
| 190 __ Bind(&done); | 190 __ Bind(&done); |
| 191 ASSERT(obj == result); | 191 ASSERT(obj == result); |
| 192 } | 192 } |
| 193 | 193 |
| 194 | 194 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 return locs; | 241 return locs; |
| 242 } | 242 } |
| 243 | 243 |
| 244 | 244 |
| 245 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, | 245 static void EmitSmiEqualityCompare(FlowGraphCompiler* compiler, |
| 246 EqualityCompareComp* comp) { | 246 EqualityCompareComp* comp) { |
| 247 Register left = comp->locs()->in(0).reg(); | 247 Register left = comp->locs()->in(0).reg(); |
| 248 Register right = comp->locs()->in(1).reg(); | 248 Register right = comp->locs()->in(1).reg(); |
| 249 Register temp = comp->locs()->temp(0).reg(); | 249 Register temp = comp->locs()->temp(0).reg(); |
| 250 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 250 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 251 comp->token_index(), | 251 comp->token_pos(), |
| 252 comp->try_index(), | 252 comp->try_index(), |
| 253 kDeoptSmiCompareSmis, | 253 kDeoptSmiCompareSmis, |
| 254 left, | 254 left, |
| 255 right); | 255 right); |
| 256 // TODO(srdjan): Should we always include NULL test (common case)? | 256 // TODO(srdjan): Should we always include NULL test (common case)? |
| 257 __ movl(temp, left); | 257 __ movl(temp, left); |
| 258 __ orl(temp, right); | 258 __ orl(temp, right); |
| 259 __ testl(temp, Immediate(kSmiTagMask)); | 259 __ testl(temp, Immediate(kSmiTagMask)); |
| 260 __ j(NOT_ZERO, deopt); | 260 __ j(NOT_ZERO, deopt); |
| 261 __ cmpl(left, right); | 261 __ cmpl(left, right); |
| 262 if (comp->is_fused_with_branch()) { | 262 if (comp->is_fused_with_branch()) { |
| 263 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 263 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 264 } else { | 264 } else { |
| 265 Register result = comp->locs()->out().reg(); | 265 Register result = comp->locs()->out().reg(); |
| 266 Label load_true, done; | 266 Label load_true, done; |
| 267 __ j(EQUAL, &load_true, Assembler::kNearJump); | 267 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 268 __ LoadObject(result, compiler->bool_false()); | 268 __ LoadObject(result, compiler->bool_false()); |
| 269 __ jmp(&done, Assembler::kNearJump); | 269 __ jmp(&done, Assembler::kNearJump); |
| 270 __ Bind(&load_true); | 270 __ Bind(&load_true); |
| 271 __ LoadObject(result, compiler->bool_true()); | 271 __ LoadObject(result, compiler->bool_true()); |
| 272 __ Bind(&done); | 272 __ Bind(&done); |
| 273 } | 273 } |
| 274 } | 274 } |
| 275 | 275 |
| 276 | 276 |
| 277 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 277 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 278 EqualityCompareComp* comp) { | 278 EqualityCompareComp* comp) { |
| 279 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 279 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 280 comp->cid(), | 280 comp->cid(), |
| 281 comp->token_index(), | 281 comp->token_pos(), |
| 282 comp->try_index()); | 282 comp->try_index()); |
| 283 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); | 283 const String& operator_name = String::ZoneHandle(String::NewSymbol("==")); |
| 284 const int kNumberOfArguments = 2; | 284 const int kNumberOfArguments = 2; |
| 285 const Array& kNoArgumentNames = Array::Handle(); | 285 const Array& kNoArgumentNames = Array::Handle(); |
| 286 const int kNumArgumentsChecked = 2; | 286 const int kNumArgumentsChecked = 2; |
| 287 | 287 |
| 288 compiler->GenerateInstanceCall(comp->cid(), | 288 compiler->GenerateInstanceCall(comp->cid(), |
| 289 comp->token_index(), | 289 comp->token_pos(), |
| 290 comp->try_index(), | 290 comp->try_index(), |
| 291 operator_name, | 291 operator_name, |
| 292 kNumberOfArguments, | 292 kNumberOfArguments, |
| 293 kNoArgumentNames, | 293 kNoArgumentNames, |
| 294 kNumArgumentsChecked); | 294 kNumArgumentsChecked); |
| 295 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX)); | 295 ASSERT(comp->is_fused_with_branch() || (comp->locs()->out().reg() == EAX)); |
| 296 | 296 |
| 297 if (comp->is_fused_with_branch()) { | 297 if (comp->is_fused_with_branch()) { |
| 298 __ CompareObject(EAX, compiler->bool_true()); | 298 __ CompareObject(EAX, compiler->bool_true()); |
| 299 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 299 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 300 } | 300 } |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 304 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 305 EqualityCompareComp* comp, | 305 EqualityCompareComp* comp, |
| 306 Register left, | 306 Register left, |
| 307 Register right) { | 307 Register right) { |
| 308 ASSERT(comp->HasICData()); | 308 ASSERT(comp->HasICData()); |
| 309 const ICData& ic_data = *comp->ic_data(); | 309 const ICData& ic_data = *comp->ic_data(); |
| 310 ASSERT(ic_data.NumberOfChecks() > 0); | 310 ASSERT(ic_data.NumberOfChecks() > 0); |
| 311 ASSERT(ic_data.num_args_tested() == 1); | 311 ASSERT(ic_data.num_args_tested() == 1); |
| 312 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 312 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 313 comp->token_index(), | 313 comp->token_pos(), |
| 314 comp->try_index(), | 314 comp->try_index(), |
| 315 kDeoptEquality); | 315 kDeoptEquality); |
| 316 __ testl(left, Immediate(kSmiTagMask)); | 316 __ testl(left, Immediate(kSmiTagMask)); |
| 317 Register temp = comp->locs()->temp(0).reg(); | 317 Register temp = comp->locs()->temp(0).reg(); |
| 318 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { | 318 if (ic_data.GetReceiverClassIdAt(0) == kSmi) { |
| 319 Label done, load_class_id; | 319 Label done, load_class_id; |
| 320 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 320 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 321 __ movl(temp, Immediate(kSmi)); | 321 __ movl(temp, Immediate(kSmi)); |
| 322 __ jmp(&done, Assembler::kNearJump); | 322 __ jmp(&done, Assembler::kNearJump); |
| 323 __ Bind(&load_class_id); | 323 __ Bind(&load_class_id); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 348 __ j(EQUAL, &load_true, Assembler::kNearJump); | 348 __ j(EQUAL, &load_true, Assembler::kNearJump); |
| 349 __ LoadObject(result, compiler->bool_false()); | 349 __ LoadObject(result, compiler->bool_false()); |
| 350 __ jmp(&done); | 350 __ jmp(&done); |
| 351 __ Bind(&load_true); | 351 __ Bind(&load_true); |
| 352 __ LoadObject(result, compiler->bool_true()); | 352 __ LoadObject(result, compiler->bool_true()); |
| 353 } | 353 } |
| 354 } else { | 354 } else { |
| 355 const int kNumberOfArguments = 2; | 355 const int kNumberOfArguments = 2; |
| 356 const Array& kNoArgumentNames = Array::Handle(); | 356 const Array& kNoArgumentNames = Array::Handle(); |
| 357 compiler->GenerateStaticCall(comp->cid(), | 357 compiler->GenerateStaticCall(comp->cid(), |
| 358 comp->token_index(), | 358 comp->token_pos(), |
| 359 comp->try_index(), | 359 comp->try_index(), |
| 360 target, | 360 target, |
| 361 kNumberOfArguments, | 361 kNumberOfArguments, |
| 362 kNoArgumentNames); | 362 kNoArgumentNames); |
| 363 ASSERT(comp->is_fused_with_branch() || | 363 ASSERT(comp->is_fused_with_branch() || |
| 364 (comp->locs()->out().reg() == EAX)); | 364 (comp->locs()->out().reg() == EAX)); |
| 365 if (comp->is_fused_with_branch()) { | 365 if (comp->is_fused_with_branch()) { |
| 366 __ CompareObject(EAX, compiler->bool_true()); | 366 __ CompareObject(EAX, compiler->bool_true()); |
| 367 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); | 367 comp->fused_with_branch()->EmitBranchOnCondition(compiler, EQUAL); |
| 368 } | 368 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 } | 466 } |
| 467 } | 467 } |
| 468 | 468 |
| 469 | 469 |
| 470 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, | 470 static void EmitSmiRelationalOp(FlowGraphCompiler* compiler, |
| 471 RelationalOpComp* comp) { | 471 RelationalOpComp* comp) { |
| 472 Register left = comp->locs()->in(0).reg(); | 472 Register left = comp->locs()->in(0).reg(); |
| 473 Register right = comp->locs()->in(1).reg(); | 473 Register right = comp->locs()->in(1).reg(); |
| 474 Register temp = comp->locs()->temp(0).reg(); | 474 Register temp = comp->locs()->temp(0).reg(); |
| 475 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 475 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 476 comp->token_index(), | 476 comp->token_pos(), |
| 477 comp->try_index(), | 477 comp->try_index(), |
| 478 kDeoptSmiCompareSmis, | 478 kDeoptSmiCompareSmis, |
| 479 left, | 479 left, |
| 480 right); | 480 right); |
| 481 __ movl(temp, left); | 481 __ movl(temp, left); |
| 482 __ orl(temp, right); | 482 __ orl(temp, right); |
| 483 __ testl(temp, Immediate(kSmiTagMask)); | 483 __ testl(temp, Immediate(kSmiTagMask)); |
| 484 __ j(NOT_ZERO, deopt); | 484 __ j(NOT_ZERO, deopt); |
| 485 | 485 |
| 486 Condition true_condition = TokenKindToSmiCondition(comp->kind()); | 486 Condition true_condition = TokenKindToSmiCondition(comp->kind()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 515 } | 515 } |
| 516 | 516 |
| 517 | 517 |
| 518 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, | 518 static void EmitDoubleRelationalOp(FlowGraphCompiler* compiler, |
| 519 RelationalOpComp* comp) { | 519 RelationalOpComp* comp) { |
| 520 Register left = comp->locs()->in(0).reg(); | 520 Register left = comp->locs()->in(0).reg(); |
| 521 Register right = comp->locs()->in(1).reg(); | 521 Register right = comp->locs()->in(1).reg(); |
| 522 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. | 522 // TODO(srdjan): temp is only needed if a conversion Smi->Double occurs. |
| 523 Register temp = comp->locs()->temp(0).reg(); | 523 Register temp = comp->locs()->temp(0).reg(); |
| 524 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 524 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 525 comp->token_index(), | 525 comp->token_pos(), |
| 526 comp->try_index(), | 526 comp->try_index(), |
| 527 kDeoptDoubleComparison, | 527 kDeoptDoubleComparison, |
| 528 left, | 528 left, |
| 529 right); | 529 right); |
| 530 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 530 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 531 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 531 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 532 | 532 |
| 533 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); | 533 Condition true_condition = TokenKindToDoubleCondition(comp->kind()); |
| 534 __ comisd(XMM0, XMM1); | 534 __ comisd(XMM0, XMM1); |
| 535 | 535 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 560 return; | 560 return; |
| 561 } | 561 } |
| 562 if (operands_class_id() == kDouble) { | 562 if (operands_class_id() == kDouble) { |
| 563 EmitDoubleRelationalOp(compiler, this); | 563 EmitDoubleRelationalOp(compiler, this); |
| 564 return; | 564 return; |
| 565 } | 565 } |
| 566 const String& function_name = | 566 const String& function_name = |
| 567 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); | 567 String::ZoneHandle(String::NewSymbol(Token::Str(kind()))); |
| 568 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 568 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 569 cid(), | 569 cid(), |
| 570 token_index(), | 570 token_pos(), |
| 571 try_index()); | 571 try_index()); |
| 572 const intptr_t kNumArguments = 2; | 572 const intptr_t kNumArguments = 2; |
| 573 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 573 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 574 compiler->GenerateInstanceCall(cid(), | 574 compiler->GenerateInstanceCall(cid(), |
| 575 token_index(), | 575 token_pos(), |
| 576 try_index(), | 576 try_index(), |
| 577 function_name, | 577 function_name, |
| 578 kNumArguments, | 578 kNumArguments, |
| 579 Array::ZoneHandle(), // No optional arguments. | 579 Array::ZoneHandle(), // No optional arguments. |
| 580 kNumArgsChecked); | 580 kNumArgsChecked); |
| 581 ASSERT(locs()->out().reg() == EAX); | 581 ASSERT(locs()->out().reg() == EAX); |
| 582 } | 582 } |
| 583 | 583 |
| 584 | 584 |
| 585 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 585 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 610 arg_count += 1; | 610 arg_count += 1; |
| 611 } | 611 } |
| 612 if (!has_optional_parameters() && !is_native_instance_closure()) { | 612 if (!has_optional_parameters() && !is_native_instance_closure()) { |
| 613 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); | 613 __ leal(EAX, Address(EBP, (1 + arg_count) * kWordSize)); |
| 614 } else { | 614 } else { |
| 615 __ leal(EAX, | 615 __ leal(EAX, |
| 616 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 616 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 617 } | 617 } |
| 618 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 618 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 619 __ movl(EDX, Immediate(arg_count)); | 619 __ movl(EDX, Immediate(arg_count)); |
| 620 compiler->GenerateCall(token_index(), | 620 compiler->GenerateCall(token_pos(), |
| 621 try_index(), | 621 try_index(), |
| 622 &StubCode::CallNativeCFunctionLabel(), | 622 &StubCode::CallNativeCFunctionLabel(), |
| 623 PcDescriptors::kOther); | 623 PcDescriptors::kOther); |
| 624 __ popl(result); | 624 __ popl(result); |
| 625 } | 625 } |
| 626 | 626 |
| 627 | 627 |
| 628 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 628 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 629 const intptr_t kNumInputs = 2; | 629 const intptr_t kNumInputs = 2; |
| 630 if ((receiver_type() == kGrowableObjectArray) || | 630 if ((receiver_type() == kGrowableObjectArray) || |
| 631 (receiver_type() == kArray) || | 631 (receiver_type() == kArray) || |
| 632 (receiver_type() == kImmutableArray)) { | 632 (receiver_type() == kImmutableArray)) { |
| 633 const intptr_t kNumTemps = 1; | 633 const intptr_t kNumTemps = 1; |
| 634 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); | 634 LocationSummary* locs = new LocationSummary(kNumInputs, kNumTemps); |
| 635 locs->set_in(0, Location::RequiresRegister()); | 635 locs->set_in(0, Location::RequiresRegister()); |
| 636 locs->set_in(1, Location::RequiresRegister()); | 636 locs->set_in(1, Location::RequiresRegister()); |
| 637 locs->set_temp(0, Location::RequiresRegister()); | 637 locs->set_temp(0, Location::RequiresRegister()); |
| 638 locs->set_out(Location::RequiresRegister()); | 638 locs->set_out(Location::RequiresRegister()); |
| 639 return locs; | 639 return locs; |
| 640 } else { | 640 } else { |
| 641 ASSERT(receiver_type() == kIllegalObjectKind); | 641 ASSERT(receiver_type() == kIllegalObjectKind); |
| 642 return MakeCallSummary(); | 642 return MakeCallSummary(); |
| 643 } | 643 } |
| 644 } | 644 } |
| 645 | 645 |
| 646 | 646 |
| 647 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, | 647 static void EmitLoadIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 648 LoadIndexedComp* comp) { | 648 LoadIndexedComp* comp) { |
| 649 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 649 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 650 comp->token_index(), | 650 comp->token_pos(), |
| 651 comp->try_index(), | 651 comp->try_index(), |
| 652 kDeoptLoadIndexedPolymorphic); | 652 kDeoptLoadIndexedPolymorphic); |
| 653 if (comp->ic_data()->NumberOfChecks() == 0) { | 653 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 654 __ jmp(deopt); | 654 __ jmp(deopt); |
| 655 return; | 655 return; |
| 656 } | 656 } |
| 657 ASSERT(comp->HasICData()); | 657 ASSERT(comp->HasICData()); |
| 658 const ICData& ic_data = *comp->ic_data(); | 658 const ICData& ic_data = *comp->ic_data(); |
| 659 ASSERT(ic_data.num_args_tested() == 1); | 659 ASSERT(ic_data.num_args_tested() == 1); |
| 660 // No indexed access on Smi. | 660 // No indexed access on Smi. |
| 661 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 661 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 662 // Load receiver into EAX. | 662 // Load receiver into EAX. |
| 663 const intptr_t kNumArguments = 2; | 663 const intptr_t kNumArguments = 2; |
| 664 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 664 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 665 __ testl(EAX, Immediate(kSmiTagMask)); | 665 __ testl(EAX, Immediate(kSmiTagMask)); |
| 666 __ j(ZERO, deopt); | 666 __ j(ZERO, deopt); |
| 667 Label done; | 667 Label done; |
| 668 __ LoadClassId(EDI, EAX); | 668 __ LoadClassId(EDI, EAX); |
| 669 compiler->EmitTestAndCall(ic_data, | 669 compiler->EmitTestAndCall(ic_data, |
| 670 EDI, // Class id register. | 670 EDI, // Class id register. |
| 671 kNumArguments, | 671 kNumArguments, |
| 672 Array::Handle(), // No named arguments. | 672 Array::Handle(), // No named arguments. |
| 673 deopt, &done, // Labels. | 673 deopt, &done, // Labels. |
| 674 comp->cid(), | 674 comp->cid(), |
| 675 comp->token_index(), | 675 comp->token_pos(), |
| 676 comp->try_index()); | 676 comp->try_index()); |
| 677 __ Bind(&done); | 677 __ Bind(&done); |
| 678 } | 678 } |
| 679 | 679 |
| 680 | 680 |
| 681 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 681 void LoadIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 682 if (receiver_type() == kIllegalObjectKind) { | 682 if (receiver_type() == kIllegalObjectKind) { |
| 683 if (HasICData()) { | 683 if (HasICData()) { |
| 684 EmitLoadIndexedPolymorphic(compiler, this); | 684 EmitLoadIndexedPolymorphic(compiler, this); |
| 685 } else { | 685 } else { |
| 686 compiler->EmitLoadIndexedGeneric(this); | 686 compiler->EmitLoadIndexedGeneric(this); |
| 687 } | 687 } |
| 688 ASSERT(locs()->out().reg() == EAX); | 688 ASSERT(locs()->out().reg() == EAX); |
| 689 return; | 689 return; |
| 690 } | 690 } |
| 691 | 691 |
| 692 Register receiver = locs()->in(0).reg(); | 692 Register receiver = locs()->in(0).reg(); |
| 693 Register index = locs()->in(1).reg(); | 693 Register index = locs()->in(1).reg(); |
| 694 Register result = locs()->out().reg(); | 694 Register result = locs()->out().reg(); |
| 695 Register temp = locs()->temp(0).reg(); | 695 Register temp = locs()->temp(0).reg(); |
| 696 | 696 |
| 697 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? | 697 const DeoptReasonId deopt_reason = (receiver_type() == kGrowableObjectArray) ? |
| 698 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; | 698 kDeoptLoadIndexedGrowableArray : kDeoptLoadIndexedFixedArray; |
| 699 | 699 |
| 700 Label* deopt = compiler->AddDeoptStub(cid(), | 700 Label* deopt = compiler->AddDeoptStub(cid(), |
| 701 token_index(), | 701 token_pos(), |
| 702 try_index(), | 702 try_index(), |
| 703 deopt_reason, | 703 deopt_reason, |
| 704 receiver, | 704 receiver, |
| 705 index); | 705 index); |
| 706 | 706 |
| 707 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 707 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 708 __ j(ZERO, deopt); | 708 __ j(ZERO, deopt); |
| 709 __ CompareClassId(receiver, receiver_type(), temp); | 709 __ CompareClassId(receiver, receiver_type(), temp); |
| 710 __ j(NOT_EQUAL, deopt); | 710 __ j(NOT_EQUAL, deopt); |
| 711 | 711 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 761 } | 761 } |
| 762 | 762 |
| 763 | 763 |
| 764 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, | 764 static void EmitStoreIndexedGeneric(FlowGraphCompiler* compiler, |
| 765 StoreIndexedComp* comp) { | 765 StoreIndexedComp* comp) { |
| 766 const String& function_name = | 766 const String& function_name = |
| 767 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); | 767 String::ZoneHandle(String::NewSymbol(Token::Str(Token::kASSIGN_INDEX))); |
| 768 | 768 |
| 769 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 769 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 770 comp->cid(), | 770 comp->cid(), |
| 771 comp->token_index(), | 771 comp->token_pos(), |
| 772 comp->try_index()); | 772 comp->try_index()); |
| 773 | 773 |
| 774 const intptr_t kNumArguments = 3; | 774 const intptr_t kNumArguments = 3; |
| 775 const intptr_t kNumArgsChecked = 1; // Type-feedback. | 775 const intptr_t kNumArgsChecked = 1; // Type-feedback. |
| 776 compiler->GenerateInstanceCall(comp->cid(), | 776 compiler->GenerateInstanceCall(comp->cid(), |
| 777 comp->token_index(), | 777 comp->token_pos(), |
| 778 comp->try_index(), | 778 comp->try_index(), |
| 779 function_name, | 779 function_name, |
| 780 kNumArguments, | 780 kNumArguments, |
| 781 Array::ZoneHandle(), // No named arguments. | 781 Array::ZoneHandle(), // No named arguments. |
| 782 kNumArgsChecked); | 782 kNumArgsChecked); |
| 783 } | 783 } |
| 784 | 784 |
| 785 | 785 |
| 786 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, | 786 static void EmitStoreIndexedPolymorphic(FlowGraphCompiler* compiler, |
| 787 StoreIndexedComp* comp) { | 787 StoreIndexedComp* comp) { |
| 788 Label* deopt = compiler->AddDeoptStub(comp->cid(), | 788 Label* deopt = compiler->AddDeoptStub(comp->cid(), |
| 789 comp->token_index(), | 789 comp->token_pos(), |
| 790 comp->try_index(), | 790 comp->try_index(), |
| 791 kDeoptStoreIndexedPolymorphic); | 791 kDeoptStoreIndexedPolymorphic); |
| 792 if (comp->ic_data()->NumberOfChecks() == 0) { | 792 if (comp->ic_data()->NumberOfChecks() == 0) { |
| 793 __ jmp(deopt); | 793 __ jmp(deopt); |
| 794 return; | 794 return; |
| 795 } | 795 } |
| 796 ASSERT(comp->HasICData()); | 796 ASSERT(comp->HasICData()); |
| 797 const ICData& ic_data = *comp->ic_data(); | 797 const ICData& ic_data = *comp->ic_data(); |
| 798 ASSERT(ic_data.num_args_tested() == 1); | 798 ASSERT(ic_data.num_args_tested() == 1); |
| 799 // No indexed access on Smi. | 799 // No indexed access on Smi. |
| 800 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); | 800 ASSERT(ic_data.GetReceiverClassIdAt(0) != kSmi); |
| 801 // Load receiver into EAX. | 801 // Load receiver into EAX. |
| 802 const intptr_t kNumArguments = 3; | 802 const intptr_t kNumArguments = 3; |
| 803 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); | 803 __ movl(EAX, Address(ESP, (kNumArguments - 1) * kWordSize)); |
| 804 __ testl(EAX, Immediate(kSmiTagMask)); | 804 __ testl(EAX, Immediate(kSmiTagMask)); |
| 805 __ j(ZERO, deopt); | 805 __ j(ZERO, deopt); |
| 806 Label done; | 806 Label done; |
| 807 __ LoadClassId(EDI, EAX); | 807 __ LoadClassId(EDI, EAX); |
| 808 compiler->EmitTestAndCall(ic_data, | 808 compiler->EmitTestAndCall(ic_data, |
| 809 EDI, // Class id register. | 809 EDI, // Class id register. |
| 810 kNumArguments, | 810 kNumArguments, |
| 811 Array::Handle(), // No named arguments. | 811 Array::Handle(), // No named arguments. |
| 812 deopt, &done, // Labels. | 812 deopt, &done, // Labels. |
| 813 comp->cid(), | 813 comp->cid(), |
| 814 comp->token_index(), | 814 comp->token_pos(), |
| 815 comp->try_index()); | 815 comp->try_index()); |
| 816 __ Bind(&done); | 816 __ Bind(&done); |
| 817 } | 817 } |
| 818 | 818 |
| 819 | 819 |
| 820 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 820 void StoreIndexedComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 821 if (receiver_type() == kIllegalObjectKind) { | 821 if (receiver_type() == kIllegalObjectKind) { |
| 822 if (HasICData()) { | 822 if (HasICData()) { |
| 823 EmitStoreIndexedPolymorphic(compiler, this); | 823 EmitStoreIndexedPolymorphic(compiler, this); |
| 824 } else { | 824 } else { |
| 825 EmitStoreIndexedGeneric(compiler, this); | 825 EmitStoreIndexedGeneric(compiler, this); |
| 826 } | 826 } |
| 827 return; | 827 return; |
| 828 } | 828 } |
| 829 | 829 |
| 830 Register receiver = locs()->in(0).reg(); | 830 Register receiver = locs()->in(0).reg(); |
| 831 Register index = locs()->in(1).reg(); | 831 Register index = locs()->in(1).reg(); |
| 832 Register value = locs()->in(2).reg(); | 832 Register value = locs()->in(2).reg(); |
| 833 Register temp = locs()->temp(0).reg(); | 833 Register temp = locs()->temp(0).reg(); |
| 834 | 834 |
| 835 Label* deopt = compiler->AddDeoptStub(cid(), | 835 Label* deopt = compiler->AddDeoptStub(cid(), |
| 836 token_index(), | 836 token_pos(), |
| 837 try_index(), | 837 try_index(), |
| 838 kDeoptStoreIndexed, | 838 kDeoptStoreIndexed, |
| 839 receiver, | 839 receiver, |
| 840 index, | 840 index, |
| 841 value); | 841 value); |
| 842 | 842 |
| 843 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. | 843 __ testl(receiver, Immediate(kSmiTagMask)); // Deoptimize if Smi. |
| 844 __ j(ZERO, deopt); | 844 __ j(ZERO, deopt); |
| 845 __ CompareClassId(receiver, receiver_type(), temp); | 845 __ CompareClassId(receiver, receiver_type(), temp); |
| 846 __ j(NOT_EQUAL, deopt); | 846 __ j(NOT_EQUAL, deopt); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 return MakeCallSummary(); | 884 return MakeCallSummary(); |
| 885 } | 885 } |
| 886 | 886 |
| 887 | 887 |
| 888 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 888 void InstanceSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 889 const String& function_name = | 889 const String& function_name = |
| 890 String::ZoneHandle(Field::SetterSymbol(field_name())); | 890 String::ZoneHandle(Field::SetterSymbol(field_name())); |
| 891 | 891 |
| 892 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 892 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 893 cid(), | 893 cid(), |
| 894 token_index(), | 894 token_pos(), |
| 895 try_index()); | 895 try_index()); |
| 896 const intptr_t kArgumentCount = 2; | 896 const intptr_t kArgumentCount = 2; |
| 897 const intptr_t kCheckedArgumentCount = 1; | 897 const intptr_t kCheckedArgumentCount = 1; |
| 898 compiler->GenerateInstanceCall(cid(), | 898 compiler->GenerateInstanceCall(cid(), |
| 899 token_index(), | 899 token_pos(), |
| 900 try_index(), | 900 try_index(), |
| 901 function_name, | 901 function_name, |
| 902 kArgumentCount, | 902 kArgumentCount, |
| 903 Array::ZoneHandle(), | 903 Array::ZoneHandle(), |
| 904 kCheckedArgumentCount); | 904 kCheckedArgumentCount); |
| 905 } | 905 } |
| 906 | 906 |
| 907 | 907 |
| 908 LocationSummary* StaticSetterComp::MakeLocationSummary() const { | 908 LocationSummary* StaticSetterComp::MakeLocationSummary() const { |
| 909 const intptr_t kNumInputs = 1; | 909 const intptr_t kNumInputs = 1; |
| 910 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); | 910 return LocationSummary::Make(kNumInputs, Location::RequiresRegister()); |
| 911 } | 911 } |
| 912 | 912 |
| 913 | 913 |
| 914 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 914 void StaticSetterComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 915 Register value = locs()->in(0).reg(); | 915 Register value = locs()->in(0).reg(); |
| 916 Register result = locs()->out().reg(); | 916 Register result = locs()->out().reg(); |
| 917 | 917 |
| 918 // Preserve the argument as the result of the computation, | 918 // Preserve the argument as the result of the computation, |
| 919 // then call the setter. | 919 // then call the setter. |
| 920 | 920 |
| 921 // Duplicate the argument. | 921 // Duplicate the argument. |
| 922 // TODO(fschneider): Avoid preserving the value if the result is not used. | 922 // TODO(fschneider): Avoid preserving the value if the result is not used. |
| 923 __ pushl(value); | 923 __ pushl(value); |
| 924 __ pushl(value); | 924 __ pushl(value); |
| 925 compiler->GenerateStaticCall(cid(), | 925 compiler->GenerateStaticCall(cid(), |
| 926 token_index(), | 926 token_pos(), |
| 927 try_index(), | 927 try_index(), |
| 928 setter_function(), | 928 setter_function(), |
| 929 1, | 929 1, |
| 930 Array::ZoneHandle()); | 930 Array::ZoneHandle()); |
| 931 __ popl(result); | 931 __ popl(result); |
| 932 } | 932 } |
| 933 | 933 |
| 934 | 934 |
| 935 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { | 935 LocationSummary* LoadInstanceFieldComp::MakeLocationSummary() const { |
| 936 // TODO(fschneider): For this instruction the input register may be | 936 // TODO(fschneider): For this instruction the input register may be |
| 937 // reused for the result (but is not required to) because the input | 937 // reused for the result (but is not required to) because the input |
| 938 // is not used after the result is defined. We should consider adding | 938 // is not used after the result is defined. We should consider adding |
| 939 // this information to the input policy. | 939 // this information to the input policy. |
| 940 return LocationSummary::Make(1, Location::RequiresRegister()); | 940 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 941 } | 941 } |
| 942 | 942 |
| 943 | 943 |
| 944 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 944 void LoadInstanceFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 945 Register instance_reg = locs()->in(0).reg(); | 945 Register instance_reg = locs()->in(0).reg(); |
| 946 Register result_reg = locs()->out().reg(); | 946 Register result_reg = locs()->out().reg(); |
| 947 | 947 |
| 948 if (HasICData()) { | 948 if (HasICData()) { |
| 949 ASSERT(original() != NULL); | 949 ASSERT(original() != NULL); |
| 950 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 950 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
| 951 original()->token_index(), | 951 original()->token_pos(), |
| 952 original()->try_index(), | 952 original()->try_index(), |
| 953 kDeoptInstanceGetterSameTarget, | 953 kDeoptInstanceGetterSameTarget, |
| 954 instance_reg); | 954 instance_reg); |
| 955 // Smis do not have instance fields (Smi class is always first). | 955 // Smis do not have instance fields (Smi class is always first). |
| 956 // Use 'result' as temporary register. | 956 // Use 'result' as temporary register. |
| 957 ASSERT(result_reg != instance_reg); | 957 ASSERT(result_reg != instance_reg); |
| 958 ASSERT(ic_data() != NULL); | 958 ASSERT(ic_data() != NULL); |
| 959 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 959 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 960 } | 960 } |
| 961 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); | 961 __ movl(result_reg, FieldAddress(instance_reg, field().Offset())); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 983 return summary; | 983 return summary; |
| 984 } | 984 } |
| 985 | 985 |
| 986 | 986 |
| 987 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 987 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 988 ASSERT(locs()->in(0).reg() == EAX); // Value. | 988 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 989 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 989 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 990 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 990 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 991 | 991 |
| 992 compiler->GenerateInstanceOf(cid(), | 992 compiler->GenerateInstanceOf(cid(), |
| 993 token_index(), | 993 token_pos(), |
| 994 try_index(), | 994 try_index(), |
| 995 type(), | 995 type(), |
| 996 negate_result()); | 996 negate_result()); |
| 997 ASSERT(locs()->out().reg() == EAX); | 997 ASSERT(locs()->out().reg() == EAX); |
| 998 } | 998 } |
| 999 | 999 |
| 1000 | 1000 |
| 1001 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1001 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1002 // TODO(regis): The elements of the array could be considered as arguments to | 1002 // TODO(regis): The elements of the array could be considered as arguments to |
| 1003 // CreateArrayComp, thereby making CreateArrayComp a call. | 1003 // CreateArrayComp, thereby making CreateArrayComp a call. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1016 | 1016 |
| 1017 | 1017 |
| 1018 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1018 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1019 Register temp_reg = locs()->temp(0).reg(); | 1019 Register temp_reg = locs()->temp(0).reg(); |
| 1020 Register result_reg = locs()->out().reg(); | 1020 Register result_reg = locs()->out().reg(); |
| 1021 | 1021 |
| 1022 // Allocate the array. EDX = length, ECX = element type. | 1022 // Allocate the array. EDX = length, ECX = element type. |
| 1023 ASSERT(temp_reg == EDX); | 1023 ASSERT(temp_reg == EDX); |
| 1024 ASSERT(locs()->in(0).reg() == ECX); | 1024 ASSERT(locs()->in(0).reg() == ECX); |
| 1025 __ movl(temp_reg, Immediate(Smi::RawValue(ElementCount()))); | 1025 __ movl(temp_reg, Immediate(Smi::RawValue(ElementCount()))); |
| 1026 compiler->GenerateCall(token_index(), | 1026 compiler->GenerateCall(token_pos(), |
| 1027 try_index(), | 1027 try_index(), |
| 1028 &StubCode::AllocateArrayLabel(), | 1028 &StubCode::AllocateArrayLabel(), |
| 1029 PcDescriptors::kOther); | 1029 PcDescriptors::kOther); |
| 1030 ASSERT(result_reg == EAX); | 1030 ASSERT(result_reg == EAX); |
| 1031 | 1031 |
| 1032 // Pop the element values from the stack into the array. | 1032 // Pop the element values from the stack into the array. |
| 1033 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); | 1033 __ leal(temp_reg, FieldAddress(result_reg, Array::data_offset())); |
| 1034 for (int i = ElementCount() - 1; i >= 0; --i) { | 1034 for (int i = ElementCount() - 1; i >= 0; --i) { |
| 1035 ASSERT(ElementAt(i)->IsUse()); | 1035 ASSERT(ElementAt(i)->IsUse()); |
| 1036 __ popl(Address(temp_reg, i * kWordSize)); | 1036 __ popl(Address(temp_reg, i * kWordSize)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1048 | 1048 |
| 1049 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( | 1049 void AllocateObjectWithBoundsCheckComp::EmitNativeCode( |
| 1050 FlowGraphCompiler* compiler) { | 1050 FlowGraphCompiler* compiler) { |
| 1051 const Class& cls = Class::ZoneHandle(constructor().owner()); | 1051 const Class& cls = Class::ZoneHandle(constructor().owner()); |
| 1052 Register type_arguments = locs()->in(0).reg(); | 1052 Register type_arguments = locs()->in(0).reg(); |
| 1053 Register instantiator_type_arguments = locs()->in(1).reg(); | 1053 Register instantiator_type_arguments = locs()->in(1).reg(); |
| 1054 Register result = locs()->out().reg(); | 1054 Register result = locs()->out().reg(); |
| 1055 | 1055 |
| 1056 // Push the result place holder initialized to NULL. | 1056 // Push the result place holder initialized to NULL. |
| 1057 __ PushObject(Object::ZoneHandle()); | 1057 __ PushObject(Object::ZoneHandle()); |
| 1058 __ pushl(Immediate(Smi::RawValue(token_index()))); | 1058 __ pushl(Immediate(Smi::RawValue(token_pos()))); |
| 1059 __ PushObject(cls); | 1059 __ PushObject(cls); |
| 1060 __ pushl(type_arguments); | 1060 __ pushl(type_arguments); |
| 1061 __ pushl(instantiator_type_arguments); | 1061 __ pushl(instantiator_type_arguments); |
| 1062 compiler->GenerateCallRuntime(cid(), | 1062 compiler->GenerateCallRuntime(cid(), |
| 1063 token_index(), | 1063 token_pos(), |
| 1064 try_index(), | 1064 try_index(), |
| 1065 kAllocateObjectWithBoundsCheckRuntimeEntry); | 1065 kAllocateObjectWithBoundsCheckRuntimeEntry); |
| 1066 // Pop instantiator type arguments, type arguments, class, and | 1066 // Pop instantiator type arguments, type arguments, class, and |
| 1067 // source location. | 1067 // source location. |
| 1068 __ Drop(4); | 1068 __ Drop(4); |
| 1069 __ popl(result); // Pop new instance. | 1069 __ popl(result); // Pop new instance. |
| 1070 } | 1070 } |
| 1071 | 1071 |
| 1072 | 1072 |
| 1073 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1073 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1074 return LocationSummary::Make(1, Location::RequiresRegister()); | 1074 return LocationSummary::Make(1, Location::RequiresRegister()); |
| 1075 } | 1075 } |
| 1076 | 1076 |
| 1077 | 1077 |
| 1078 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1078 void LoadVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1079 Register instance_reg = locs()->in(0).reg(); | 1079 Register instance_reg = locs()->in(0).reg(); |
| 1080 Register result_reg = locs()->out().reg(); | 1080 Register result_reg = locs()->out().reg(); |
| 1081 if (HasICData()) { | 1081 if (HasICData()) { |
| 1082 ASSERT(original() != NULL); | 1082 ASSERT(original() != NULL); |
| 1083 Label* deopt = compiler->AddDeoptStub(original()->cid(), | 1083 Label* deopt = compiler->AddDeoptStub(original()->cid(), |
| 1084 original()->token_index(), | 1084 original()->token_pos(), |
| 1085 original()->try_index(), | 1085 original()->try_index(), |
| 1086 kDeoptInstanceGetterSameTarget, | 1086 kDeoptInstanceGetterSameTarget, |
| 1087 instance_reg); | 1087 instance_reg); |
| 1088 // Smis do not have instance fields (Smi class is always first). | 1088 // Smis do not have instance fields (Smi class is always first). |
| 1089 // Use 'result' as temporary register. | 1089 // Use 'result' as temporary register. |
| 1090 ASSERT(result_reg != instance_reg); | 1090 ASSERT(result_reg != instance_reg); |
| 1091 ASSERT(ic_data() != NULL); | 1091 ASSERT(ic_data() != NULL); |
| 1092 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); | 1092 compiler->EmitClassChecksNoSmi(*ic_data(), instance_reg, result_reg, deopt); |
| 1093 } | 1093 } |
| 1094 | 1094 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), | 1141 __ cmpl(FieldAddress(instantiator_reg, TypeArguments::length_offset()), |
| 1142 Immediate(Smi::RawValue(len))); | 1142 Immediate(Smi::RawValue(len))); |
| 1143 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1143 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1144 __ Bind(&type_arguments_uninstantiated); | 1144 __ Bind(&type_arguments_uninstantiated); |
| 1145 } | 1145 } |
| 1146 // A runtime call to instantiate the type arguments is required. | 1146 // A runtime call to instantiate the type arguments is required. |
| 1147 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1147 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1148 __ PushObject(type_arguments()); | 1148 __ PushObject(type_arguments()); |
| 1149 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1149 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1150 compiler->GenerateCallRuntime(cid(), | 1150 compiler->GenerateCallRuntime(cid(), |
| 1151 token_index(), | 1151 token_pos(), |
| 1152 try_index(), | 1152 try_index(), |
| 1153 kInstantiateTypeArgumentsRuntimeEntry); | 1153 kInstantiateTypeArgumentsRuntimeEntry); |
| 1154 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1154 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1155 __ popl(result_reg); // Pop instantiated type arguments. | 1155 __ popl(result_reg); // Pop instantiated type arguments. |
| 1156 __ Bind(&type_arguments_instantiated); | 1156 __ Bind(&type_arguments_instantiated); |
| 1157 ASSERT(instantiator_reg == result_reg); | 1157 ASSERT(instantiator_reg == result_reg); |
| 1158 // 'result_reg': Instantiated type arguments. | 1158 // 'result_reg': Instantiated type arguments. |
| 1159 } | 1159 } |
| 1160 | 1160 |
| 1161 | 1161 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 } | 1295 } |
| 1296 | 1296 |
| 1297 | 1297 |
| 1298 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1298 void AllocateContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1299 ASSERT(locs()->temp(0).reg() == EDX); | 1299 ASSERT(locs()->temp(0).reg() == EDX); |
| 1300 ASSERT(locs()->out().reg() == EAX); | 1300 ASSERT(locs()->out().reg() == EAX); |
| 1301 | 1301 |
| 1302 __ movl(EDX, Immediate(num_context_variables())); | 1302 __ movl(EDX, Immediate(num_context_variables())); |
| 1303 const ExternalLabel label("alloc_context", | 1303 const ExternalLabel label("alloc_context", |
| 1304 StubCode::AllocateContextEntryPoint()); | 1304 StubCode::AllocateContextEntryPoint()); |
| 1305 compiler->GenerateCall(token_index(), | 1305 compiler->GenerateCall(token_pos(), |
| 1306 try_index(), | 1306 try_index(), |
| 1307 &label, | 1307 &label, |
| 1308 PcDescriptors::kOther); | 1308 PcDescriptors::kOther); |
| 1309 } | 1309 } |
| 1310 | 1310 |
| 1311 | 1311 |
| 1312 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1312 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1313 return LocationSummary::Make(1, | 1313 return LocationSummary::Make(1, |
| 1314 Location::RequiresRegister(), | 1314 Location::RequiresRegister(), |
| 1315 LocationSummary::kCall); | 1315 LocationSummary::kCall); |
| 1316 } | 1316 } |
| 1317 | 1317 |
| 1318 | 1318 |
| 1319 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1319 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1320 Register context_value = locs()->in(0).reg(); | 1320 Register context_value = locs()->in(0).reg(); |
| 1321 Register result = locs()->out().reg(); | 1321 Register result = locs()->out().reg(); |
| 1322 | 1322 |
| 1323 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1323 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1324 __ pushl(context_value); | 1324 __ pushl(context_value); |
| 1325 compiler->GenerateCallRuntime(cid(), | 1325 compiler->GenerateCallRuntime(cid(), |
| 1326 token_index(), | 1326 token_pos(), |
| 1327 try_index(), | 1327 try_index(), |
| 1328 kCloneContextRuntimeEntry); | 1328 kCloneContextRuntimeEntry); |
| 1329 __ popl(result); // Remove argument. | 1329 __ popl(result); // Remove argument. |
| 1330 __ popl(result); // Get result (cloned context). | 1330 __ popl(result); // Get result (cloned context). |
| 1331 } | 1331 } |
| 1332 | 1332 |
| 1333 | 1333 |
| 1334 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1334 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1335 return LocationSummary::Make(0, Location::NoLocation()); | 1335 return LocationSummary::Make(0, Location::NoLocation()); |
| 1336 } | 1336 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1362 LocationSummary::kCall); | 1362 LocationSummary::kCall); |
| 1363 } | 1363 } |
| 1364 | 1364 |
| 1365 | 1365 |
| 1366 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1366 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1367 __ cmpl(ESP, | 1367 __ cmpl(ESP, |
| 1368 Address::Absolute(Isolate::Current()->stack_limit_address())); | 1368 Address::Absolute(Isolate::Current()->stack_limit_address())); |
| 1369 Label no_stack_overflow; | 1369 Label no_stack_overflow; |
| 1370 __ j(ABOVE, &no_stack_overflow); | 1370 __ j(ABOVE, &no_stack_overflow); |
| 1371 compiler->GenerateCallRuntime(cid(), | 1371 compiler->GenerateCallRuntime(cid(), |
| 1372 token_index(), | 1372 token_pos(), |
| 1373 try_index(), | 1373 try_index(), |
| 1374 kStackOverflowRuntimeEntry); | 1374 kStackOverflowRuntimeEntry); |
| 1375 __ Bind(&no_stack_overflow); | 1375 __ Bind(&no_stack_overflow); |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 | 1378 |
| 1379 LocationSummary* BinaryOpComp::MakeLocationSummary() const { | 1379 LocationSummary* BinaryOpComp::MakeLocationSummary() const { |
| 1380 const intptr_t kNumInputs = 2; | 1380 const intptr_t kNumInputs = 2; |
| 1381 | 1381 |
| 1382 if (operands_type() == kDoubleOperands) { | 1382 if (operands_type() == kDoubleOperands) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 } | 1439 } |
| 1440 | 1440 |
| 1441 | 1441 |
| 1442 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { | 1442 static void EmitSmiBinaryOp(FlowGraphCompiler* compiler, BinaryOpComp* comp) { |
| 1443 Register left = comp->locs()->in(0).reg(); | 1443 Register left = comp->locs()->in(0).reg(); |
| 1444 Register right = comp->locs()->in(1).reg(); | 1444 Register right = comp->locs()->in(1).reg(); |
| 1445 Register result = comp->locs()->out().reg(); | 1445 Register result = comp->locs()->out().reg(); |
| 1446 Register temp = comp->locs()->temp(0).reg(); | 1446 Register temp = comp->locs()->temp(0).reg(); |
| 1447 ASSERT(left == result); | 1447 ASSERT(left == result); |
| 1448 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1448 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1449 comp->instance_call()->token_index(), | 1449 comp->instance_call()->token_pos(), |
| 1450 comp->instance_call()->try_index(), | 1450 comp->instance_call()->try_index(), |
| 1451 kDeoptSmiBinaryOp, | 1451 kDeoptSmiBinaryOp, |
| 1452 temp, | 1452 temp, |
| 1453 right); | 1453 right); |
| 1454 // TODO(vegorov): for many binary operations this pattern can be rearranged | 1454 // TODO(vegorov): for many binary operations this pattern can be rearranged |
| 1455 // to save one move. | 1455 // to save one move. |
| 1456 __ movl(temp, left); | 1456 __ movl(temp, left); |
| 1457 __ orl(left, right); | 1457 __ orl(left, right); |
| 1458 __ testl(left, Immediate(kSmiTagMask)); | 1458 __ testl(left, Immediate(kSmiTagMask)); |
| 1459 __ j(NOT_ZERO, deopt); | 1459 __ j(NOT_ZERO, deopt); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 __ jmp(&done); | 1550 __ jmp(&done); |
| 1551 { | 1551 { |
| 1552 __ Bind(&call_method); | 1552 __ Bind(&call_method); |
| 1553 Function& target = Function::ZoneHandle( | 1553 Function& target = Function::ZoneHandle( |
| 1554 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1554 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1555 ASSERT(!target.IsNull()); | 1555 ASSERT(!target.IsNull()); |
| 1556 const intptr_t kArgumentCount = 2; | 1556 const intptr_t kArgumentCount = 2; |
| 1557 __ pushl(temp); | 1557 __ pushl(temp); |
| 1558 __ pushl(right); | 1558 __ pushl(right); |
| 1559 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1559 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1560 comp->instance_call()->token_index(), | 1560 comp->instance_call()->token_pos(), |
| 1561 comp->instance_call()->try_index(), | 1561 comp->instance_call()->try_index(), |
| 1562 target, | 1562 target, |
| 1563 kArgumentCount, | 1563 kArgumentCount, |
| 1564 Array::Handle()); // No argument names. | 1564 Array::Handle()); // No argument names. |
| 1565 ASSERT(result == EAX); | 1565 ASSERT(result == EAX); |
| 1566 } | 1566 } |
| 1567 __ Bind(&done); | 1567 __ Bind(&done); |
| 1568 break; | 1568 break; |
| 1569 } | 1569 } |
| 1570 case Token::kDIV: { | 1570 case Token::kDIV: { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1597 // receiver and a Mint or Smi argument. We fall back to the run time call if | 1597 // receiver and a Mint or Smi argument. We fall back to the run time call if |
| 1598 // both receiver and argument are Mint or if one of them is Mint and the other | 1598 // both receiver and argument are Mint or if one of them is Mint and the other |
| 1599 // is a negative Smi. | 1599 // is a negative Smi. |
| 1600 Register left = comp->locs()->in(0).reg(); | 1600 Register left = comp->locs()->in(0).reg(); |
| 1601 Register right = comp->locs()->in(1).reg(); | 1601 Register right = comp->locs()->in(1).reg(); |
| 1602 Register result = comp->locs()->out().reg(); | 1602 Register result = comp->locs()->out().reg(); |
| 1603 Register temp = comp->locs()->temp(0).reg(); | 1603 Register temp = comp->locs()->temp(0).reg(); |
| 1604 ASSERT(left == result); | 1604 ASSERT(left == result); |
| 1605 ASSERT(comp->op_kind() == Token::kBIT_AND); | 1605 ASSERT(comp->op_kind() == Token::kBIT_AND); |
| 1606 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1606 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1607 comp->instance_call()->token_index(), | 1607 comp->instance_call()->token_pos(), |
| 1608 comp->instance_call()->try_index(), | 1608 comp->instance_call()->try_index(), |
| 1609 kDeoptMintBinaryOp, | 1609 kDeoptMintBinaryOp, |
| 1610 left, | 1610 left, |
| 1611 right); | 1611 right); |
| 1612 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; | 1612 Label mint_static_call, smi_static_call, non_smi, smi_smi, done; |
| 1613 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? | 1613 __ testl(left, Immediate(kSmiTagMask)); // Is receiver Smi? |
| 1614 __ j(NOT_ZERO, &non_smi); | 1614 __ j(NOT_ZERO, &non_smi); |
| 1615 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? | 1615 __ testl(right, Immediate(kSmiTagMask)); // Is argument Smi? |
| 1616 __ j(ZERO, &smi_smi); | 1616 __ j(ZERO, &smi_smi); |
| 1617 __ CompareClassId(right, kMint, temp); // Is argument Mint? | 1617 __ CompareClassId(right, kMint, temp); // Is argument Mint? |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1645 __ Bind(&smi_static_call); | 1645 __ Bind(&smi_static_call); |
| 1646 { | 1646 { |
| 1647 Function& target = Function::ZoneHandle( | 1647 Function& target = Function::ZoneHandle( |
| 1648 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); | 1648 comp->ic_data()->GetTargetForReceiverClassId(kSmi)); |
| 1649 if (target.IsNull()) { | 1649 if (target.IsNull()) { |
| 1650 __ jmp(deopt); | 1650 __ jmp(deopt); |
| 1651 } else { | 1651 } else { |
| 1652 __ pushl(left); | 1652 __ pushl(left); |
| 1653 __ pushl(right); | 1653 __ pushl(right); |
| 1654 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1654 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1655 comp->instance_call()->token_index(), | 1655 comp->instance_call()->token_pos(), |
| 1656 comp->instance_call()->try_index(), | 1656 comp->instance_call()->try_index(), |
| 1657 target, | 1657 target, |
| 1658 comp->instance_call()->ArgumentCount(), | 1658 comp->instance_call()->ArgumentCount(), |
| 1659 comp->instance_call()->argument_names()); | 1659 comp->instance_call()->argument_names()); |
| 1660 ASSERT(result == EAX); | 1660 ASSERT(result == EAX); |
| 1661 __ jmp(&done); | 1661 __ jmp(&done); |
| 1662 } | 1662 } |
| 1663 } | 1663 } |
| 1664 | 1664 |
| 1665 __ Bind(&mint_static_call); | 1665 __ Bind(&mint_static_call); |
| 1666 { | 1666 { |
| 1667 Function& target = Function::ZoneHandle( | 1667 Function& target = Function::ZoneHandle( |
| 1668 comp->ic_data()->GetTargetForReceiverClassId(kMint)); | 1668 comp->ic_data()->GetTargetForReceiverClassId(kMint)); |
| 1669 if (target.IsNull()) { | 1669 if (target.IsNull()) { |
| 1670 __ jmp(deopt); | 1670 __ jmp(deopt); |
| 1671 } else { | 1671 } else { |
| 1672 __ pushl(left); | 1672 __ pushl(left); |
| 1673 __ pushl(right); | 1673 __ pushl(right); |
| 1674 compiler->GenerateStaticCall(comp->instance_call()->cid(), | 1674 compiler->GenerateStaticCall(comp->instance_call()->cid(), |
| 1675 comp->instance_call()->token_index(), | 1675 comp->instance_call()->token_pos(), |
| 1676 comp->instance_call()->try_index(), | 1676 comp->instance_call()->try_index(), |
| 1677 target, | 1677 target, |
| 1678 comp->instance_call()->ArgumentCount(), | 1678 comp->instance_call()->ArgumentCount(), |
| 1679 comp->instance_call()->argument_names()); | 1679 comp->instance_call()->argument_names()); |
| 1680 ASSERT(result == EAX); | 1680 ASSERT(result == EAX); |
| 1681 } | 1681 } |
| 1682 } | 1682 } |
| 1683 __ Bind(&done); | 1683 __ Bind(&done); |
| 1684 } | 1684 } |
| 1685 | 1685 |
| 1686 | 1686 |
| 1687 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, | 1687 static void EmitDoubleBinaryOp(FlowGraphCompiler* compiler, |
| 1688 BinaryOpComp* comp) { | 1688 BinaryOpComp* comp) { |
| 1689 Register left = EBX; | 1689 Register left = EBX; |
| 1690 Register right = ECX; | 1690 Register right = ECX; |
| 1691 Register temp = EDX; | 1691 Register temp = EDX; |
| 1692 Register result = comp->locs()->out().reg(); | 1692 Register result = comp->locs()->out().reg(); |
| 1693 | 1693 |
| 1694 const Class& double_class = compiler->double_class(); | 1694 const Class& double_class = compiler->double_class(); |
| 1695 const Code& stub = | 1695 const Code& stub = |
| 1696 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1696 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1697 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1697 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1698 compiler->GenerateCall(comp->instance_call()->token_index(), | 1698 compiler->GenerateCall(comp->instance_call()->token_pos(), |
| 1699 comp->instance_call()->try_index(), | 1699 comp->instance_call()->try_index(), |
| 1700 &label, | 1700 &label, |
| 1701 PcDescriptors::kOther); | 1701 PcDescriptors::kOther); |
| 1702 // Newly allocated object is now in the result register (RAX). | 1702 // Newly allocated object is now in the result register (RAX). |
| 1703 ASSERT(result == EAX); | 1703 ASSERT(result == EAX); |
| 1704 __ popl(right); | 1704 __ popl(right); |
| 1705 __ popl(left); | 1705 __ popl(left); |
| 1706 | 1706 |
| 1707 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), | 1707 Label* deopt = compiler->AddDeoptStub(comp->instance_call()->cid(), |
| 1708 comp->instance_call()->token_index(), | 1708 comp->instance_call()->token_pos(), |
| 1709 comp->instance_call()->try_index(), | 1709 comp->instance_call()->try_index(), |
| 1710 kDeoptDoubleBinaryOp, | 1710 kDeoptDoubleBinaryOp, |
| 1711 left, | 1711 left, |
| 1712 right); | 1712 right); |
| 1713 | 1713 |
| 1714 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); | 1714 compiler->LoadDoubleOrSmiToXmm(XMM0, left, temp, deopt); |
| 1715 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); | 1715 compiler->LoadDoubleOrSmiToXmm(XMM1, right, temp, deopt); |
| 1716 | 1716 |
| 1717 switch (comp->op_kind()) { | 1717 switch (comp->op_kind()) { |
| 1718 case Token::kADD: __ addsd(XMM0, XMM1); break; | 1718 case Token::kADD: __ addsd(XMM0, XMM1); break; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1763 // TODO(srdjan): Implement for more checks. | 1763 // TODO(srdjan): Implement for more checks. |
| 1764 ASSERT(ic_data.NumberOfChecks() == 1); | 1764 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1765 intptr_t test_class_id; | 1765 intptr_t test_class_id; |
| 1766 Function& target = Function::Handle(); | 1766 Function& target = Function::Handle(); |
| 1767 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1767 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1768 | 1768 |
| 1769 Register value = locs()->in(0).reg(); | 1769 Register value = locs()->in(0).reg(); |
| 1770 Register result = locs()->out().reg(); | 1770 Register result = locs()->out().reg(); |
| 1771 ASSERT(value == result); | 1771 ASSERT(value == result); |
| 1772 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1772 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1773 instance_call()->token_index(), | 1773 instance_call()->token_pos(), |
| 1774 instance_call()->try_index(), | 1774 instance_call()->try_index(), |
| 1775 kDeoptUnaryOp, | 1775 kDeoptUnaryOp, |
| 1776 value); | 1776 value); |
| 1777 if (test_class_id == kSmi) { | 1777 if (test_class_id == kSmi) { |
| 1778 __ testl(value, Immediate(kSmiTagMask)); | 1778 __ testl(value, Immediate(kSmiTagMask)); |
| 1779 __ j(NOT_ZERO, deopt); | 1779 __ j(NOT_ZERO, deopt); |
| 1780 switch (op_kind()) { | 1780 switch (op_kind()) { |
| 1781 case Token::kNEGATE: | 1781 case Token::kNEGATE: |
| 1782 __ negl(value); | 1782 __ negl(value); |
| 1783 __ j(OVERFLOW, deopt); | 1783 __ j(OVERFLOW, deopt); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1816 // TODO(srdjan): Implement for more checks. | 1816 // TODO(srdjan): Implement for more checks. |
| 1817 ASSERT(ic_data.NumberOfChecks() == 1); | 1817 ASSERT(ic_data.NumberOfChecks() == 1); |
| 1818 intptr_t test_class_id; | 1818 intptr_t test_class_id; |
| 1819 Function& target = Function::Handle(); | 1819 Function& target = Function::Handle(); |
| 1820 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); | 1820 ic_data.GetOneClassCheckAt(0, &test_class_id, &target); |
| 1821 | 1821 |
| 1822 Register value = locs()->in(0).reg(); | 1822 Register value = locs()->in(0).reg(); |
| 1823 Register result = locs()->out().reg(); | 1823 Register result = locs()->out().reg(); |
| 1824 ASSERT(value == result); | 1824 ASSERT(value == result); |
| 1825 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1825 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1826 instance_call()->token_index(), | 1826 instance_call()->token_pos(), |
| 1827 instance_call()->try_index(), | 1827 instance_call()->try_index(), |
| 1828 kDeoptUnaryOp, | 1828 kDeoptUnaryOp, |
| 1829 value); | 1829 value); |
| 1830 if (test_class_id == kDouble) { | 1830 if (test_class_id == kDouble) { |
| 1831 Register temp = locs()->temp(0).reg(); | 1831 Register temp = locs()->temp(0).reg(); |
| 1832 __ testl(value, Immediate(kSmiTagMask)); | 1832 __ testl(value, Immediate(kSmiTagMask)); |
| 1833 __ j(ZERO, deopt); // Smi. | 1833 __ j(ZERO, deopt); // Smi. |
| 1834 __ CompareClassId(value, kDouble, temp); | 1834 __ CompareClassId(value, kDouble, temp); |
| 1835 __ j(NOT_EQUAL, deopt); | 1835 __ j(NOT_EQUAL, deopt); |
| 1836 // Allocate result object. | 1836 // Allocate result object. |
| 1837 const Class& double_class = compiler->double_class(); | 1837 const Class& double_class = compiler->double_class(); |
| 1838 const Code& stub = | 1838 const Code& stub = |
| 1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1839 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1840 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1841 __ pushl(value); | 1841 __ pushl(value); |
| 1842 compiler->GenerateCall(instance_call()->token_index(), | 1842 compiler->GenerateCall(instance_call()->token_pos(), |
| 1843 instance_call()->try_index(), | 1843 instance_call()->try_index(), |
| 1844 &label, | 1844 &label, |
| 1845 PcDescriptors::kOther); | 1845 PcDescriptors::kOther); |
| 1846 // Result is in EAX. | 1846 // Result is in EAX. |
| 1847 ASSERT(result != temp); | 1847 ASSERT(result != temp); |
| 1848 __ movl(result, EAX); | 1848 __ movl(result, EAX); |
| 1849 __ popl(temp); | 1849 __ popl(temp); |
| 1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1850 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1851 __ DoubleNegate(XMM0); | 1851 __ DoubleNegate(XMM0); |
| 1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1852 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1873 } | 1873 } |
| 1874 | 1874 |
| 1875 | 1875 |
| 1876 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1876 void ToDoubleComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1877 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; | 1877 Register value = (from() == kDouble) ? locs()->in(0).reg() : EBX; |
| 1878 Register result = locs()->out().reg(); | 1878 Register result = locs()->out().reg(); |
| 1879 | 1879 |
| 1880 const DeoptReasonId deopt_reason = (from() == kDouble) ? | 1880 const DeoptReasonId deopt_reason = (from() == kDouble) ? |
| 1881 kDeoptDoubleToDouble : kDeoptIntegerToDouble; | 1881 kDeoptDoubleToDouble : kDeoptIntegerToDouble; |
| 1882 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1882 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1883 instance_call()->token_index(), | 1883 instance_call()->token_pos(), |
| 1884 instance_call()->try_index(), | 1884 instance_call()->try_index(), |
| 1885 deopt_reason, | 1885 deopt_reason, |
| 1886 value); | 1886 value); |
| 1887 | 1887 |
| 1888 if (from() == kDouble) { | 1888 if (from() == kDouble) { |
| 1889 Register temp = locs()->temp(0).reg(); | 1889 Register temp = locs()->temp(0).reg(); |
| 1890 __ testl(value, Immediate(kSmiTagMask)); | 1890 __ testl(value, Immediate(kSmiTagMask)); |
| 1891 __ j(ZERO, deopt); // Deoptimize if Smi. | 1891 __ j(ZERO, deopt); // Deoptimize if Smi. |
| 1892 __ CompareClassId(value, kDouble, temp); | 1892 __ CompareClassId(value, kDouble, temp); |
| 1893 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. | 1893 __ j(NOT_EQUAL, deopt); // Deoptimize if not Double. |
| 1894 ASSERT(value == result); | 1894 ASSERT(value == result); |
| 1895 return; | 1895 return; |
| 1896 } | 1896 } |
| 1897 | 1897 |
| 1898 ASSERT(from() == kSmi); | 1898 ASSERT(from() == kSmi); |
| 1899 | 1899 |
| 1900 const Class& double_class = compiler->double_class(); | 1900 const Class& double_class = compiler->double_class(); |
| 1901 const Code& stub = | 1901 const Code& stub = |
| 1902 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1902 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1903 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1903 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1904 | 1904 |
| 1905 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1905 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 1906 compiler->GenerateCall(instance_call()->token_index(), | 1906 compiler->GenerateCall(instance_call()->token_pos(), |
| 1907 instance_call()->try_index(), | 1907 instance_call()->try_index(), |
| 1908 &label, | 1908 &label, |
| 1909 PcDescriptors::kOther); | 1909 PcDescriptors::kOther); |
| 1910 ASSERT(result == EAX); | 1910 ASSERT(result == EAX); |
| 1911 __ popl(value); | 1911 __ popl(value); |
| 1912 | 1912 |
| 1913 __ testl(value, Immediate(kSmiTagMask)); | 1913 __ testl(value, Immediate(kSmiTagMask)); |
| 1914 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1914 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1915 __ SmiUntag(value); | 1915 __ SmiUntag(value); |
| 1916 __ cvtsi2sd(XMM0, value); | 1916 __ cvtsi2sd(XMM0, value); |
| 1917 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1917 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1918 } | 1918 } |
| 1919 | 1919 |
| 1920 | 1920 |
| 1921 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { | 1921 LocationSummary* PolymorphicInstanceCallComp::MakeLocationSummary() const { |
| 1922 return MakeCallSummary(); | 1922 return MakeCallSummary(); |
| 1923 } | 1923 } |
| 1924 | 1924 |
| 1925 | 1925 |
| 1926 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1926 void PolymorphicInstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1927 ASSERT(instance_call()->VerifyComputation()); | 1927 ASSERT(instance_call()->VerifyComputation()); |
| 1928 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), | 1928 Label* deopt = compiler->AddDeoptStub(instance_call()->cid(), |
| 1929 instance_call()->token_index(), | 1929 instance_call()->token_pos(), |
| 1930 instance_call()->try_index(), | 1930 instance_call()->try_index(), |
| 1931 kDeoptPolymorphicInstanceCallTestFail); | 1931 kDeoptPolymorphicInstanceCallTestFail); |
| 1932 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { | 1932 if (!HasICData() || (ic_data()->NumberOfChecks() == 0)) { |
| 1933 __ jmp(deopt); | 1933 __ jmp(deopt); |
| 1934 return; | 1934 return; |
| 1935 } | 1935 } |
| 1936 ASSERT(HasICData()); | 1936 ASSERT(HasICData()); |
| 1937 ASSERT(ic_data()->num_args_tested() == 1); | 1937 ASSERT(ic_data()->num_args_tested() == 1); |
| 1938 Label handle_smi; | 1938 Label handle_smi; |
| 1939 Label* is_smi_label = | 1939 Label* is_smi_label = |
| 1940 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; | 1940 ic_data()->GetReceiverClassIdAt(0) == kSmi ? &handle_smi : deopt; |
| 1941 | 1941 |
| 1942 // Load receiver into EAX. | 1942 // Load receiver into EAX. |
| 1943 __ movl(EAX, | 1943 __ movl(EAX, |
| 1944 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); | 1944 Address(ESP, (instance_call()->ArgumentCount() - 1) * kWordSize)); |
| 1945 __ testl(EAX, Immediate(kSmiTagMask)); | 1945 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1946 __ j(ZERO, is_smi_label); | 1946 __ j(ZERO, is_smi_label); |
| 1947 Label done; | 1947 Label done; |
| 1948 __ LoadClassId(EDI, EAX); | 1948 __ LoadClassId(EDI, EAX); |
| 1949 compiler->EmitTestAndCall(*ic_data(), | 1949 compiler->EmitTestAndCall(*ic_data(), |
| 1950 EDI, // Class id register. | 1950 EDI, // Class id register. |
| 1951 instance_call()->ArgumentCount(), | 1951 instance_call()->ArgumentCount(), |
| 1952 instance_call()->argument_names(), | 1952 instance_call()->argument_names(), |
| 1953 deopt, &done, // Labels. | 1953 deopt, &done, // Labels. |
| 1954 instance_call()->cid(), | 1954 instance_call()->cid(), |
| 1955 instance_call()->token_index(), | 1955 instance_call()->token_pos(), |
| 1956 instance_call()->try_index()); | 1956 instance_call()->try_index()); |
| 1957 if (is_smi_label == &handle_smi) { | 1957 if (is_smi_label == &handle_smi) { |
| 1958 __ Bind(&handle_smi); | 1958 __ Bind(&handle_smi); |
| 1959 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); | 1959 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmi); |
| 1960 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1960 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1961 compiler->GenerateStaticCall(instance_call()->cid(), | 1961 compiler->GenerateStaticCall(instance_call()->cid(), |
| 1962 instance_call()->token_index(), | 1962 instance_call()->token_pos(), |
| 1963 instance_call()->try_index(), | 1963 instance_call()->try_index(), |
| 1964 target, | 1964 target, |
| 1965 instance_call()->ArgumentCount(), | 1965 instance_call()->ArgumentCount(), |
| 1966 instance_call()->argument_names()); | 1966 instance_call()->argument_names()); |
| 1967 } | 1967 } |
| 1968 __ Bind(&done); | 1968 __ Bind(&done); |
| 1969 } | 1969 } |
| 1970 | 1970 |
| 1971 } // namespace dart | 1971 } // namespace dart |
| 1972 | 1972 |
| 1973 #undef __ | 1973 #undef __ |
| 1974 | 1974 |
| 1975 #endif // defined TARGET_ARCH_X64 | 1975 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |