| 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 if (FLAG_trace_functions) { | 81 if (FLAG_trace_functions) { |
| 82 const Function& function = | 82 const Function& function = |
| 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); | 83 Function::ZoneHandle(compiler->parsed_function().function().raw()); |
| 84 __ LoadObject(temp, function); | 84 __ LoadObject(temp, function); |
| 85 __ pushl(result); // Preserve result. | 85 __ pushl(result); // Preserve result. |
| 86 __ pushl(temp); | 86 __ pushl(temp); |
| 87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, | 87 compiler->GenerateCallRuntime(Isolate::kNoDeoptId, |
| 88 0, | 88 0, |
| 89 CatchClauseNode::kInvalidTryIndex, | 89 CatchClauseNode::kInvalidTryIndex, |
| 90 kTraceFunctionExitRuntimeEntry, | 90 kTraceFunctionExitRuntimeEntry, |
| 91 locs()->stack_bitmap()); | 91 locs()); |
| 92 __ popl(temp); // Remove argument. | 92 __ popl(temp); // Remove argument. |
| 93 __ popl(result); // Restore result. | 93 __ popl(result); // Restore result. |
| 94 } | 94 } |
| 95 #if defined(DEBUG) | 95 #if defined(DEBUG) |
| 96 // TODO(srdjan): Fix for functions with finally clause. | 96 // TODO(srdjan): Fix for functions with finally clause. |
| 97 // A finally clause may leave a previously pushed return value if it | 97 // A finally clause may leave a previously pushed return value if it |
| 98 // has its own return instruction. Method that have finally are currently | 98 // has its own return instruction. Method that have finally are currently |
| 99 // not optimized. | 99 // not optimized. |
| 100 if (!compiler->HasFinally()) { | 100 if (!compiler->HasFinally()) { |
| 101 Label done; | 101 Label done; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 __ CompareObject(obj, compiler->bool_true()); | 208 __ CompareObject(obj, compiler->bool_true()); |
| 209 __ j(EQUAL, &done, Assembler::kNearJump); | 209 __ j(EQUAL, &done, Assembler::kNearJump); |
| 210 __ CompareObject(obj, compiler->bool_false()); | 210 __ CompareObject(obj, compiler->bool_false()); |
| 211 __ j(EQUAL, &done, Assembler::kNearJump); | 211 __ j(EQUAL, &done, Assembler::kNearJump); |
| 212 | 212 |
| 213 __ pushl(obj); // Push the source object. | 213 __ pushl(obj); // Push the source object. |
| 214 compiler->GenerateCallRuntime(deopt_id(), | 214 compiler->GenerateCallRuntime(deopt_id(), |
| 215 token_pos(), | 215 token_pos(), |
| 216 try_index(), | 216 try_index(), |
| 217 kConditionTypeErrorRuntimeEntry, | 217 kConditionTypeErrorRuntimeEntry, |
| 218 locs()->stack_bitmap()); | 218 locs()); |
| 219 // We should never return here. | 219 // We should never return here. |
| 220 __ int3(); | 220 __ int3(); |
| 221 __ Bind(&done); | 221 __ Bind(&done); |
| 222 } | 222 } |
| 223 ASSERT(obj == result); | 223 ASSERT(obj == result); |
| 224 } | 224 } |
| 225 | 225 |
| 226 | 226 |
| 227 static Condition TokenKindToSmiCondition(Token::Kind kind) { | 227 static Condition TokenKindToSmiCondition(Token::Kind kind) { |
| 228 switch (kind) { | 228 switch (kind) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 locs->set_out(Location::RegisterLocation(EAX)); | 273 locs->set_out(Location::RegisterLocation(EAX)); |
| 274 return locs; | 274 return locs; |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, | 278 static void EmitEqualityAsInstanceCall(FlowGraphCompiler* compiler, |
| 279 intptr_t deopt_id, | 279 intptr_t deopt_id, |
| 280 intptr_t token_pos, | 280 intptr_t token_pos, |
| 281 intptr_t try_index, | 281 intptr_t try_index, |
| 282 Token::Kind kind, | 282 Token::Kind kind, |
| 283 const LocationSummary& locs) { | 283 LocationSummary* locs) { |
| 284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 284 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 285 deopt_id, | 285 deopt_id, |
| 286 token_pos, | 286 token_pos, |
| 287 try_index); | 287 try_index); |
| 288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); | 288 const String& operator_name = String::ZoneHandle(Symbols::New("==")); |
| 289 const int kNumberOfArguments = 2; | 289 const int kNumberOfArguments = 2; |
| 290 const Array& kNoArgumentNames = Array::Handle(); | 290 const Array& kNoArgumentNames = Array::Handle(); |
| 291 const int kNumArgumentsChecked = 2; | 291 const int kNumArgumentsChecked = 2; |
| 292 | 292 |
| 293 Label done, false_label, true_label; | 293 Label done, false_label, true_label; |
| 294 Register left = locs.in(0).reg(); | 294 Register left = locs->in(0).reg(); |
| 295 Register right = locs.in(1).reg(); | 295 Register right = locs->in(1).reg(); |
| 296 __ popl(right); | 296 __ popl(right); |
| 297 __ popl(left); | 297 __ popl(left); |
| 298 const Immediate raw_null = | 298 const Immediate raw_null = |
| 299 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 299 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 300 Label check_identity, instance_call; | 300 Label check_identity, instance_call; |
| 301 __ cmpl(right, raw_null); | 301 __ cmpl(right, raw_null); |
| 302 __ j(EQUAL, &check_identity, Assembler::kNearJump); | 302 __ j(EQUAL, &check_identity, Assembler::kNearJump); |
| 303 __ cmpl(left, raw_null); | 303 __ cmpl(left, raw_null); |
| 304 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); | 304 __ j(NOT_EQUAL, &instance_call, Assembler::kNearJump); |
| 305 | 305 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 320 __ Bind(&instance_call); | 320 __ Bind(&instance_call); |
| 321 __ pushl(left); | 321 __ pushl(left); |
| 322 __ pushl(right); | 322 __ pushl(right); |
| 323 compiler->GenerateInstanceCall(deopt_id, | 323 compiler->GenerateInstanceCall(deopt_id, |
| 324 token_pos, | 324 token_pos, |
| 325 try_index, | 325 try_index, |
| 326 operator_name, | 326 operator_name, |
| 327 kNumberOfArguments, | 327 kNumberOfArguments, |
| 328 kNoArgumentNames, | 328 kNoArgumentNames, |
| 329 kNumArgumentsChecked, | 329 kNumArgumentsChecked, |
| 330 locs.stack_bitmap()); | 330 locs); |
| 331 if (kind == Token::kNE) { | 331 if (kind == Token::kNE) { |
| 332 // Negate the condition: true label returns false and vice versa. | 332 // Negate the condition: true label returns false and vice versa. |
| 333 __ CompareObject(EAX, compiler->bool_true()); | 333 __ CompareObject(EAX, compiler->bool_true()); |
| 334 __ j(EQUAL, &true_label, Assembler::kNearJump); | 334 __ j(EQUAL, &true_label, Assembler::kNearJump); |
| 335 __ Bind(&false_label); | 335 __ Bind(&false_label); |
| 336 __ LoadObject(EAX, compiler->bool_true()); | 336 __ LoadObject(EAX, compiler->bool_true()); |
| 337 __ jmp(&done, Assembler::kNearJump); | 337 __ jmp(&done, Assembler::kNearJump); |
| 338 __ Bind(&true_label); | 338 __ Bind(&true_label); |
| 339 __ LoadObject(EAX, compiler->bool_false()); | 339 __ LoadObject(EAX, compiler->bool_false()); |
| 340 } | 340 } |
| 341 __ Bind(&done); | 341 __ Bind(&done); |
| 342 } | 342 } |
| 343 | 343 |
| 344 | 344 |
| 345 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, | 345 static void EmitEqualityAsPolymorphicCall(FlowGraphCompiler* compiler, |
| 346 const ICData& orig_ic_data, | 346 const ICData& orig_ic_data, |
| 347 const LocationSummary& locs, | 347 LocationSummary* locs, |
| 348 BranchInstr* branch, | 348 BranchInstr* branch, |
| 349 Token::Kind kind, | 349 Token::Kind kind, |
| 350 intptr_t deopt_id, | 350 intptr_t deopt_id, |
| 351 intptr_t token_pos, | 351 intptr_t token_pos, |
| 352 intptr_t try_index, | 352 intptr_t try_index) { |
| 353 BitmapBuilder* stack_bitmap) { | |
| 354 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 353 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 355 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); | 354 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); |
| 356 ASSERT(ic_data.NumberOfChecks() > 0); | 355 ASSERT(ic_data.NumberOfChecks() > 0); |
| 357 ASSERT(ic_data.num_args_tested() == 1); | 356 ASSERT(ic_data.num_args_tested() == 1); |
| 358 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); | 357 Label* deopt = compiler->AddDeoptStub(deopt_id, try_index, kDeoptEquality); |
| 359 Register left = locs.in(0).reg(); | 358 Register left = locs->in(0).reg(); |
| 360 Register right = locs.in(1).reg(); | 359 Register right = locs->in(1).reg(); |
| 361 __ testl(left, Immediate(kSmiTagMask)); | 360 __ testl(left, Immediate(kSmiTagMask)); |
| 362 Register temp = locs.temp(0).reg(); | 361 Register temp = locs->temp(0).reg(); |
| 363 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { | 362 if (ic_data.GetReceiverClassIdAt(0) == kSmiCid) { |
| 364 Label done, load_class_id; | 363 Label done, load_class_id; |
| 365 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); | 364 __ j(NOT_ZERO, &load_class_id, Assembler::kNearJump); |
| 366 __ movl(temp, Immediate(kSmiCid)); | 365 __ movl(temp, Immediate(kSmiCid)); |
| 367 __ jmp(&done, Assembler::kNearJump); | 366 __ jmp(&done, Assembler::kNearJump); |
| 368 __ Bind(&load_class_id); | 367 __ Bind(&load_class_id); |
| 369 __ LoadClassId(temp, left); | 368 __ LoadClassId(temp, left); |
| 370 __ Bind(&done); | 369 __ Bind(&done); |
| 371 } else { | 370 } else { |
| 372 __ j(ZERO, deopt); // Smi deopts. | 371 __ j(ZERO, deopt); // Smi deopts. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 383 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); | 382 __ cmpl(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); |
| 384 __ j(NOT_EQUAL, &next_test); | 383 __ j(NOT_EQUAL, &next_test); |
| 385 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); | 384 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); |
| 386 if (target.Owner() == object_store->object_class()) { | 385 if (target.Owner() == object_store->object_class()) { |
| 387 // Object.== is same as ===. | 386 // Object.== is same as ===. |
| 388 __ Drop(2); | 387 __ Drop(2); |
| 389 __ cmpl(left, right); | 388 __ cmpl(left, right); |
| 390 if (branch != NULL) { | 389 if (branch != NULL) { |
| 391 branch->EmitBranchOnCondition(compiler, cond); | 390 branch->EmitBranchOnCondition(compiler, cond); |
| 392 } else { | 391 } else { |
| 393 Register result = locs.out().reg(); | 392 Register result = locs->out().reg(); |
| 394 Label load_true; | 393 Label load_true; |
| 395 __ j(cond, &load_true, Assembler::kNearJump); | 394 __ j(cond, &load_true, Assembler::kNearJump); |
| 396 __ LoadObject(result, compiler->bool_false()); | 395 __ LoadObject(result, compiler->bool_false()); |
| 397 __ jmp(&done); | 396 __ jmp(&done); |
| 398 __ Bind(&load_true); | 397 __ Bind(&load_true); |
| 399 __ LoadObject(result, compiler->bool_true()); | 398 __ LoadObject(result, compiler->bool_true()); |
| 400 } | 399 } |
| 401 } else { | 400 } else { |
| 402 const int kNumberOfArguments = 2; | 401 const int kNumberOfArguments = 2; |
| 403 const Array& kNoArgumentNames = Array::Handle(); | 402 const Array& kNoArgumentNames = Array::Handle(); |
| 404 compiler->GenerateStaticCall(deopt_id, | 403 compiler->GenerateStaticCall(deopt_id, |
| 405 token_pos, | 404 token_pos, |
| 406 try_index, | 405 try_index, |
| 407 target, | 406 target, |
| 408 kNumberOfArguments, | 407 kNumberOfArguments, |
| 409 kNoArgumentNames, | 408 kNoArgumentNames, |
| 410 stack_bitmap); | 409 locs); |
| 411 if (branch == NULL) { | 410 if (branch == NULL) { |
| 412 if (kind == Token::kNE) { | 411 if (kind == Token::kNE) { |
| 413 Label false_label; | 412 Label false_label; |
| 414 __ CompareObject(EAX, compiler->bool_true()); | 413 __ CompareObject(EAX, compiler->bool_true()); |
| 415 __ j(EQUAL, &false_label, Assembler::kNearJump); | 414 __ j(EQUAL, &false_label, Assembler::kNearJump); |
| 416 __ LoadObject(EAX, compiler->bool_true()); | 415 __ LoadObject(EAX, compiler->bool_true()); |
| 417 __ jmp(&done); | 416 __ jmp(&done); |
| 418 __ Bind(&false_label); | 417 __ Bind(&false_label); |
| 419 __ LoadObject(EAX, compiler->bool_false()); | 418 __ LoadObject(EAX, compiler->bool_false()); |
| 420 __ jmp(&done); | 419 __ jmp(&done); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 Condition cond = TokenKindToSmiCondition(kind); | 486 Condition cond = TokenKindToSmiCondition(kind); |
| 488 branch->EmitBranchOnCondition(compiler, cond); | 487 branch->EmitBranchOnCondition(compiler, cond); |
| 489 } | 488 } |
| 490 } | 489 } |
| 491 | 490 |
| 492 | 491 |
| 493 // First test if receiver is NULL, in which case === is applied. | 492 // First test if receiver is NULL, in which case === is applied. |
| 494 // If type feedback was provided (lists of <class-id, target>), do a | 493 // If type feedback was provided (lists of <class-id, target>), do a |
| 495 // type by type check (either === or static call to the operator. | 494 // type by type check (either === or static call to the operator. |
| 496 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, | 495 static void EmitGenericEqualityCompare(FlowGraphCompiler* compiler, |
| 497 const LocationSummary& locs, | 496 LocationSummary* locs, |
| 498 Token::Kind kind, | 497 Token::Kind kind, |
| 499 BranchInstr* branch, | 498 BranchInstr* branch, |
| 500 const ICData& ic_data, | 499 const ICData& ic_data, |
| 501 intptr_t deopt_id, | 500 intptr_t deopt_id, |
| 502 intptr_t token_pos, | 501 intptr_t token_pos, |
| 503 intptr_t try_index) { | 502 intptr_t try_index) { |
| 504 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); | 503 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); |
| 505 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 504 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
| 506 Register left = locs.in(0).reg(); | 505 Register left = locs->in(0).reg(); |
| 507 Register right = locs.in(1).reg(); | 506 Register right = locs->in(1).reg(); |
| 508 const Immediate raw_null = | 507 const Immediate raw_null = |
| 509 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 508 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 510 Label done, identity_compare, non_null_compare; | 509 Label done, identity_compare, non_null_compare; |
| 511 __ cmpl(right, raw_null); | 510 __ cmpl(right, raw_null); |
| 512 __ j(EQUAL, &identity_compare, Assembler::kNearJump); | 511 __ j(EQUAL, &identity_compare, Assembler::kNearJump); |
| 513 __ cmpl(left, raw_null); | 512 __ cmpl(left, raw_null); |
| 514 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); | 513 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); |
| 515 // Comparison with NULL is "===". | 514 // Comparison with NULL is "===". |
| 516 __ Bind(&identity_compare); | 515 __ Bind(&identity_compare); |
| 517 __ cmpl(left, right); | 516 __ cmpl(left, right); |
| 518 Condition cond = TokenKindToSmiCondition(kind); | 517 Condition cond = TokenKindToSmiCondition(kind); |
| 519 if (branch != NULL) { | 518 if (branch != NULL) { |
| 520 branch->EmitBranchOnCondition(compiler, cond); | 519 branch->EmitBranchOnCondition(compiler, cond); |
| 521 } else { | 520 } else { |
| 522 Register result = locs.out().reg(); | 521 Register result = locs->out().reg(); |
| 523 Label load_true; | 522 Label load_true; |
| 524 __ j(cond, &load_true, Assembler::kNearJump); | 523 __ j(cond, &load_true, Assembler::kNearJump); |
| 525 __ LoadObject(result, compiler->bool_false()); | 524 __ LoadObject(result, compiler->bool_false()); |
| 526 __ jmp(&done); | 525 __ jmp(&done); |
| 527 __ Bind(&load_true); | 526 __ Bind(&load_true); |
| 528 __ LoadObject(result, compiler->bool_true()); | 527 __ LoadObject(result, compiler->bool_true()); |
| 529 } | 528 } |
| 530 __ jmp(&done); | 529 __ jmp(&done); |
| 531 __ Bind(&non_null_compare); // Receiver is not null. | 530 __ Bind(&non_null_compare); // Receiver is not null. |
| 532 __ pushl(left); | 531 __ pushl(left); |
| 533 __ pushl(right); | 532 __ pushl(right); |
| 534 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, | 533 EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, |
| 535 deopt_id, token_pos, try_index, | 534 deopt_id, token_pos, try_index); |
| 536 locs.stack_bitmap()); | |
| 537 __ Bind(&done); | 535 __ Bind(&done); |
| 538 } | 536 } |
| 539 | 537 |
| 540 | 538 |
| 541 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, | 539 static void EmitSmiComparisonOp(FlowGraphCompiler* compiler, |
| 542 const LocationSummary& locs, | 540 const LocationSummary& locs, |
| 543 Token::Kind kind, | 541 Token::Kind kind, |
| 544 BranchInstr* branch, | 542 BranchInstr* branch, |
| 545 intptr_t deopt_id, | 543 intptr_t deopt_id, |
| 546 intptr_t token_pos, | 544 intptr_t token_pos, |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 return; | 635 return; |
| 638 } | 636 } |
| 639 const bool is_checked_strict_equal = | 637 const bool is_checked_strict_equal = |
| 640 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); | 638 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); |
| 641 if (is_checked_strict_equal) { | 639 if (is_checked_strict_equal) { |
| 642 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, | 640 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), NULL, |
| 643 deopt_id(), token_pos(), try_index()); | 641 deopt_id(), token_pos(), try_index()); |
| 644 return; | 642 return; |
| 645 } | 643 } |
| 646 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { | 644 if (HasICData() && (ic_data()->NumberOfChecks() > 0)) { |
| 647 EmitGenericEqualityCompare(compiler, *locs(), kind(), NULL, *ic_data(), | 645 EmitGenericEqualityCompare(compiler, locs(), kind(), NULL, *ic_data(), |
| 648 deopt_id(), token_pos(), try_index()); | 646 deopt_id(), token_pos(), try_index()); |
| 649 } else { | 647 } else { |
| 650 Register left = locs()->in(0).reg(); | 648 Register left = locs()->in(0).reg(); |
| 651 Register right = locs()->in(1).reg(); | 649 Register right = locs()->in(1).reg(); |
| 652 __ pushl(left); | 650 __ pushl(left); |
| 653 __ pushl(right); | 651 __ pushl(right); |
| 654 EmitEqualityAsInstanceCall(compiler, | 652 EmitEqualityAsInstanceCall(compiler, |
| 655 deopt_id(), | 653 deopt_id(), |
| 656 token_pos(), | 654 token_pos(), |
| 657 try_index(), | 655 try_index(), |
| 658 kind(), | 656 kind(), |
| 659 *locs()); | 657 locs()); |
| 660 ASSERT(locs()->out().reg() == EAX); | 658 ASSERT(locs()->out().reg() == EAX); |
| 661 } | 659 } |
| 662 } | 660 } |
| 663 | 661 |
| 664 | 662 |
| 665 LocationSummary* RelationalOpComp::MakeLocationSummary() const { | 663 LocationSummary* RelationalOpComp::MakeLocationSummary() const { |
| 666 const intptr_t kNumInputs = 2; | 664 const intptr_t kNumInputs = 2; |
| 667 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) { | 665 if ((operands_class_id() == kSmiCid) || (operands_class_id() == kDoubleCid)) { |
| 668 const intptr_t kNumTemps = 1; | 666 const intptr_t kNumTemps = 1; |
| 669 LocationSummary* summary = | 667 LocationSummary* summary = |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 __ Bind(&done); | 718 __ Bind(&done); |
| 721 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), | 719 compiler->EmitTestAndCall(ICData::Handle(ic_data()->AsUnaryClassChecks()), |
| 722 EDI, // Class id register. | 720 EDI, // Class id register. |
| 723 kNumArguments, | 721 kNumArguments, |
| 724 Array::Handle(), // No named arguments. | 722 Array::Handle(), // No named arguments. |
| 725 deopt, // Deoptimize target. | 723 deopt, // Deoptimize target. |
| 726 NULL, // Fallthrough when done. | 724 NULL, // Fallthrough when done. |
| 727 deopt_id(), | 725 deopt_id(), |
| 728 token_pos(), | 726 token_pos(), |
| 729 try_index(), | 727 try_index(), |
| 730 locs()->stack_bitmap()); | 728 locs()); |
| 731 ASSERT(locs()->out().reg() == EAX); | 729 ASSERT(locs()->out().reg() == EAX); |
| 732 return; | 730 return; |
| 733 } | 731 } |
| 734 const String& function_name = | 732 const String& function_name = |
| 735 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 733 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 736 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 734 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 737 deopt_id(), | 735 deopt_id(), |
| 738 token_pos(), | 736 token_pos(), |
| 739 try_index()); | 737 try_index()); |
| 740 const intptr_t kNumArguments = 2; | 738 const intptr_t kNumArguments = 2; |
| 741 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 739 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 742 compiler->GenerateInstanceCall(deopt_id(), | 740 compiler->GenerateInstanceCall(deopt_id(), |
| 743 token_pos(), | 741 token_pos(), |
| 744 try_index(), | 742 try_index(), |
| 745 function_name, | 743 function_name, |
| 746 kNumArguments, | 744 kNumArguments, |
| 747 Array::ZoneHandle(), // No optional arguments. | 745 Array::ZoneHandle(), // No optional arguments. |
| 748 kNumArgsChecked, | 746 kNumArgsChecked, |
| 749 locs()->stack_bitmap()); | 747 locs()); |
| 750 ASSERT(locs()->out().reg() == EAX); | 748 ASSERT(locs()->out().reg() == EAX); |
| 751 } | 749 } |
| 752 | 750 |
| 753 | 751 |
| 754 LocationSummary* NativeCallComp::MakeLocationSummary() const { | 752 LocationSummary* NativeCallComp::MakeLocationSummary() const { |
| 755 const intptr_t kNumInputs = 0; | 753 const intptr_t kNumInputs = 0; |
| 756 const intptr_t kNumTemps = 3; | 754 const intptr_t kNumTemps = 3; |
| 757 LocationSummary* locs = | 755 LocationSummary* locs = |
| 758 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 756 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 759 locs->set_temp(0, Location::RegisterLocation(EAX)); | 757 locs->set_temp(0, Location::RegisterLocation(EAX)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 782 } else { | 780 } else { |
| 783 __ leal(EAX, | 781 __ leal(EAX, |
| 784 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); | 782 Address(EBP, ParsedFunction::kFirstLocalSlotIndex * kWordSize)); |
| 785 } | 783 } |
| 786 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); | 784 __ movl(ECX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 787 __ movl(EDX, Immediate(arg_count)); | 785 __ movl(EDX, Immediate(arg_count)); |
| 788 compiler->GenerateCall(token_pos(), | 786 compiler->GenerateCall(token_pos(), |
| 789 try_index(), | 787 try_index(), |
| 790 &StubCode::CallNativeCFunctionLabel(), | 788 &StubCode::CallNativeCFunctionLabel(), |
| 791 PcDescriptors::kOther, | 789 PcDescriptors::kOther, |
| 792 locs()->stack_bitmap()); | 790 locs()); |
| 793 __ popl(result); | 791 __ popl(result); |
| 794 } | 792 } |
| 795 | 793 |
| 796 | 794 |
| 797 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { | 795 LocationSummary* LoadIndexedComp::MakeLocationSummary() const { |
| 798 ASSERT((receiver_type() == kGrowableObjectArrayCid) || | 796 ASSERT((receiver_type() == kGrowableObjectArrayCid) || |
| 799 (receiver_type() == kArrayCid) || | 797 (receiver_type() == kArrayCid) || |
| 800 (receiver_type() == kImmutableArrayCid)); | 798 (receiver_type() == kImmutableArrayCid)); |
| 801 const intptr_t kNumInputs = 2; | 799 const intptr_t kNumInputs = 2; |
| 802 const intptr_t kNumTemps = 1; | 800 const intptr_t kNumTemps = 1; |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 986 void InstanceOfComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 989 ASSERT(locs()->in(0).reg() == EAX); // Value. | 987 ASSERT(locs()->in(0).reg() == EAX); // Value. |
| 990 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. | 988 ASSERT(locs()->in(1).reg() == ECX); // Instantiator. |
| 991 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. | 989 ASSERT(locs()->in(2).reg() == EDX); // Instantiator type arguments. |
| 992 | 990 |
| 993 compiler->GenerateInstanceOf(deopt_id(), | 991 compiler->GenerateInstanceOf(deopt_id(), |
| 994 token_pos(), | 992 token_pos(), |
| 995 try_index(), | 993 try_index(), |
| 996 type(), | 994 type(), |
| 997 negate_result(), | 995 negate_result(), |
| 998 locs()->stack_bitmap()); | 996 locs()); |
| 999 ASSERT(locs()->out().reg() == EAX); | 997 ASSERT(locs()->out().reg() == EAX); |
| 1000 } | 998 } |
| 1001 | 999 |
| 1002 | 1000 |
| 1003 LocationSummary* CreateArrayComp::MakeLocationSummary() const { | 1001 LocationSummary* CreateArrayComp::MakeLocationSummary() const { |
| 1004 const intptr_t kNumInputs = 1; | 1002 const intptr_t kNumInputs = 1; |
| 1005 const intptr_t kNumTemps = 0; | 1003 const intptr_t kNumTemps = 0; |
| 1006 LocationSummary* locs = | 1004 LocationSummary* locs = |
| 1007 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1005 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1008 locs->set_in(0, Location::RegisterLocation(ECX)); | 1006 locs->set_in(0, Location::RegisterLocation(ECX)); |
| 1009 locs->set_out(Location::RegisterLocation(EAX)); | 1007 locs->set_out(Location::RegisterLocation(EAX)); |
| 1010 return locs; | 1008 return locs; |
| 1011 } | 1009 } |
| 1012 | 1010 |
| 1013 | 1011 |
| 1014 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1012 void CreateArrayComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1015 // Allocate the array. EDX = length, ECX = element type. | 1013 // Allocate the array. EDX = length, ECX = element type. |
| 1016 ASSERT(locs()->in(0).reg() == ECX); | 1014 ASSERT(locs()->in(0).reg() == ECX); |
| 1017 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); | 1015 __ movl(EDX, Immediate(Smi::RawValue(ArgumentCount()))); |
| 1018 compiler->GenerateCall(token_pos(), | 1016 compiler->GenerateCall(token_pos(), |
| 1019 try_index(), | 1017 try_index(), |
| 1020 &StubCode::AllocateArrayLabel(), | 1018 &StubCode::AllocateArrayLabel(), |
| 1021 PcDescriptors::kOther, | 1019 PcDescriptors::kOther, |
| 1022 locs()->stack_bitmap()); | 1020 locs()); |
| 1023 ASSERT(locs()->out().reg() == EAX); | 1021 ASSERT(locs()->out().reg() == EAX); |
| 1024 | 1022 |
| 1025 // Pop the element values from the stack into the array. | 1023 // Pop the element values from the stack into the array. |
| 1026 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); | 1024 __ leal(EDX, FieldAddress(EAX, Array::data_offset())); |
| 1027 for (int i = ArgumentCount() - 1; i >= 0; --i) { | 1025 for (int i = ArgumentCount() - 1; i >= 0; --i) { |
| 1028 ASSERT(ArgumentAt(i)->value()->IsUse()); | 1026 ASSERT(ArgumentAt(i)->value()->IsUse()); |
| 1029 __ popl(Address(EDX, i * kWordSize)); | 1027 __ popl(Address(EDX, i * kWordSize)); |
| 1030 } | 1028 } |
| 1031 } | 1029 } |
| 1032 | 1030 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1053 | 1051 |
| 1054 // Push the result place holder initialized to NULL. | 1052 // Push the result place holder initialized to NULL. |
| 1055 __ PushObject(Object::ZoneHandle()); | 1053 __ PushObject(Object::ZoneHandle()); |
| 1056 __ PushObject(cls); | 1054 __ PushObject(cls); |
| 1057 __ pushl(type_arguments); | 1055 __ pushl(type_arguments); |
| 1058 __ pushl(instantiator_type_arguments); | 1056 __ pushl(instantiator_type_arguments); |
| 1059 compiler->GenerateCallRuntime(deopt_id(), | 1057 compiler->GenerateCallRuntime(deopt_id(), |
| 1060 token_pos(), | 1058 token_pos(), |
| 1061 try_index(), | 1059 try_index(), |
| 1062 kAllocateObjectWithBoundsCheckRuntimeEntry, | 1060 kAllocateObjectWithBoundsCheckRuntimeEntry, |
| 1063 locs()->stack_bitmap()); | 1061 locs()); |
| 1064 // Pop instantiator type arguments, type arguments, and class. | 1062 // Pop instantiator type arguments, type arguments, and class. |
| 1065 // source location. | 1063 // source location. |
| 1066 __ Drop(3); | 1064 __ Drop(3); |
| 1067 __ popl(result); // Pop new instance. | 1065 __ popl(result); // Pop new instance. |
| 1068 } | 1066 } |
| 1069 | 1067 |
| 1070 | 1068 |
| 1071 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { | 1069 LocationSummary* LoadVMFieldComp::MakeLocationSummary() const { |
| 1072 return LocationSummary::Make(1, | 1070 return LocationSummary::Make(1, |
| 1073 Location::RequiresRegister(), | 1071 Location::RequiresRegister(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 __ Bind(&type_arguments_uninstantiated); | 1139 __ Bind(&type_arguments_uninstantiated); |
| 1142 } | 1140 } |
| 1143 // A runtime call to instantiate the type arguments is required. | 1141 // A runtime call to instantiate the type arguments is required. |
| 1144 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1142 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1145 __ PushObject(type_arguments()); | 1143 __ PushObject(type_arguments()); |
| 1146 __ pushl(instantiator_reg); // Push instantiator type arguments. | 1144 __ pushl(instantiator_reg); // Push instantiator type arguments. |
| 1147 compiler->GenerateCallRuntime(deopt_id(), | 1145 compiler->GenerateCallRuntime(deopt_id(), |
| 1148 token_pos(), | 1146 token_pos(), |
| 1149 try_index(), | 1147 try_index(), |
| 1150 kInstantiateTypeArgumentsRuntimeEntry, | 1148 kInstantiateTypeArgumentsRuntimeEntry, |
| 1151 locs()->stack_bitmap()); | 1149 locs()); |
| 1152 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 1150 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 1153 __ popl(result_reg); // Pop instantiated type arguments. | 1151 __ popl(result_reg); // Pop instantiated type arguments. |
| 1154 __ Bind(&type_arguments_instantiated); | 1152 __ Bind(&type_arguments_instantiated); |
| 1155 ASSERT(instantiator_reg == result_reg); | 1153 ASSERT(instantiator_reg == result_reg); |
| 1156 // 'result_reg': Instantiated type arguments. | 1154 // 'result_reg': Instantiated type arguments. |
| 1157 } | 1155 } |
| 1158 | 1156 |
| 1159 | 1157 |
| 1160 LocationSummary* | 1158 LocationSummary* |
| 1161 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { | 1159 ExtractConstructorTypeArgumentsComp::MakeLocationSummary() const { |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 ASSERT(locs()->temp(0).reg() == EDX); | 1296 ASSERT(locs()->temp(0).reg() == EDX); |
| 1299 ASSERT(locs()->out().reg() == EAX); | 1297 ASSERT(locs()->out().reg() == EAX); |
| 1300 | 1298 |
| 1301 __ movl(EDX, Immediate(num_context_variables())); | 1299 __ movl(EDX, Immediate(num_context_variables())); |
| 1302 const ExternalLabel label("alloc_context", | 1300 const ExternalLabel label("alloc_context", |
| 1303 StubCode::AllocateContextEntryPoint()); | 1301 StubCode::AllocateContextEntryPoint()); |
| 1304 compiler->GenerateCall(token_pos(), | 1302 compiler->GenerateCall(token_pos(), |
| 1305 try_index(), | 1303 try_index(), |
| 1306 &label, | 1304 &label, |
| 1307 PcDescriptors::kOther, | 1305 PcDescriptors::kOther, |
| 1308 locs()->stack_bitmap()); | 1306 locs()); |
| 1309 } | 1307 } |
| 1310 | 1308 |
| 1311 | 1309 |
| 1312 LocationSummary* CloneContextComp::MakeLocationSummary() const { | 1310 LocationSummary* CloneContextComp::MakeLocationSummary() const { |
| 1313 const intptr_t kNumInputs = 1; | 1311 const intptr_t kNumInputs = 1; |
| 1314 const intptr_t kNumTemps = 0; | 1312 const intptr_t kNumTemps = 0; |
| 1315 LocationSummary* locs = | 1313 LocationSummary* locs = |
| 1316 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); | 1314 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); |
| 1317 locs->set_in(0, Location::RegisterLocation(EAX)); | 1315 locs->set_in(0, Location::RegisterLocation(EAX)); |
| 1318 locs->set_out(Location::RegisterLocation(EAX)); | 1316 locs->set_out(Location::RegisterLocation(EAX)); |
| 1319 return locs; | 1317 return locs; |
| 1320 } | 1318 } |
| 1321 | 1319 |
| 1322 | 1320 |
| 1323 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1321 void CloneContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1324 Register context_value = locs()->in(0).reg(); | 1322 Register context_value = locs()->in(0).reg(); |
| 1325 Register result = locs()->out().reg(); | 1323 Register result = locs()->out().reg(); |
| 1326 | 1324 |
| 1327 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1325 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1328 __ pushl(context_value); | 1326 __ pushl(context_value); |
| 1329 compiler->GenerateCallRuntime(deopt_id(), | 1327 compiler->GenerateCallRuntime(deopt_id(), |
| 1330 token_pos(), | 1328 token_pos(), |
| 1331 try_index(), | 1329 try_index(), |
| 1332 kCloneContextRuntimeEntry, | 1330 kCloneContextRuntimeEntry, |
| 1333 locs()->stack_bitmap()); | 1331 locs()); |
| 1334 __ popl(result); // Remove argument. | 1332 __ popl(result); // Remove argument. |
| 1335 __ popl(result); // Get result (cloned context). | 1333 __ popl(result); // Get result (cloned context). |
| 1336 } | 1334 } |
| 1337 | 1335 |
| 1338 | 1336 |
| 1339 LocationSummary* CatchEntryComp::MakeLocationSummary() const { | 1337 LocationSummary* CatchEntryComp::MakeLocationSummary() const { |
| 1340 return LocationSummary::Make(0, | 1338 return LocationSummary::Make(0, |
| 1341 Location::NoLocation(), | 1339 Location::NoLocation(), |
| 1342 LocationSummary::kNoCall); | 1340 LocationSummary::kNoCall); |
| 1343 } | 1341 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) | 1377 explicit CheckStackOverflowSlowPath(CheckStackOverflowComp* computation) |
| 1380 : computation_(computation) { } | 1378 : computation_(computation) { } |
| 1381 | 1379 |
| 1382 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 1380 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1383 __ Bind(entry_label()); | 1381 __ Bind(entry_label()); |
| 1384 compiler->SaveLiveRegisters(computation_->locs()); | 1382 compiler->SaveLiveRegisters(computation_->locs()); |
| 1385 compiler->GenerateCallRuntime(computation_->deopt_id(), | 1383 compiler->GenerateCallRuntime(computation_->deopt_id(), |
| 1386 computation_->token_pos(), | 1384 computation_->token_pos(), |
| 1387 computation_->try_index(), | 1385 computation_->try_index(), |
| 1388 kStackOverflowRuntimeEntry, | 1386 kStackOverflowRuntimeEntry, |
| 1389 computation_->locs()->stack_bitmap()); | 1387 computation_->locs()); |
| 1390 compiler->RestoreLiveRegisters(computation_->locs()); | 1388 compiler->RestoreLiveRegisters(computation_->locs()); |
| 1391 __ jmp(exit_label()); | 1389 __ jmp(exit_label()); |
| 1392 } | 1390 } |
| 1393 | 1391 |
| 1394 private: | 1392 private: |
| 1395 CheckStackOverflowComp* computation_; | 1393 CheckStackOverflowComp* computation_; |
| 1396 }; | 1394 }; |
| 1397 | 1395 |
| 1398 | 1396 |
| 1399 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1397 void CheckStackOverflowComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 const intptr_t kArgumentCount = 2; | 1569 const intptr_t kArgumentCount = 2; |
| 1572 __ pushl(temp); | 1570 __ pushl(temp); |
| 1573 __ pushl(right); | 1571 __ pushl(right); |
| 1574 compiler->GenerateStaticCall( | 1572 compiler->GenerateStaticCall( |
| 1575 instance_call()->deopt_id(), | 1573 instance_call()->deopt_id(), |
| 1576 instance_call()->token_pos(), | 1574 instance_call()->token_pos(), |
| 1577 instance_call()->try_index(), | 1575 instance_call()->try_index(), |
| 1578 target, | 1576 target, |
| 1579 kArgumentCount, | 1577 kArgumentCount, |
| 1580 Array::Handle(), // No argument names. | 1578 Array::Handle(), // No argument names. |
| 1581 locs()->stack_bitmap()); | 1579 locs()); |
| 1582 ASSERT(result == EAX); | 1580 ASSERT(result == EAX); |
| 1583 } | 1581 } |
| 1584 __ Bind(&done); | 1582 __ Bind(&done); |
| 1585 break; | 1583 break; |
| 1586 } | 1584 } |
| 1587 case Token::kDIV: { | 1585 case Token::kDIV: { |
| 1588 // Dispatches to 'Double./'. | 1586 // Dispatches to 'Double./'. |
| 1589 // TODO(srdjan): Implement as conversion to double and double division. | 1587 // TODO(srdjan): Implement as conversion to double and double division. |
| 1590 UNREACHABLE(); | 1588 UNREACHABLE(); |
| 1591 break; | 1589 break; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 } else { | 1677 } else { |
| 1680 __ pushl(left); | 1678 __ pushl(left); |
| 1681 __ pushl(right); | 1679 __ pushl(right); |
| 1682 compiler->GenerateStaticCall( | 1680 compiler->GenerateStaticCall( |
| 1683 instance_call()->deopt_id(), | 1681 instance_call()->deopt_id(), |
| 1684 instance_call()->token_pos(), | 1682 instance_call()->token_pos(), |
| 1685 instance_call()->try_index(), | 1683 instance_call()->try_index(), |
| 1686 target, | 1684 target, |
| 1687 instance_call()->ArgumentCount(), | 1685 instance_call()->ArgumentCount(), |
| 1688 instance_call()->argument_names(), | 1686 instance_call()->argument_names(), |
| 1689 locs()->stack_bitmap()); | 1687 locs()); |
| 1690 ASSERT(result == EAX); | 1688 ASSERT(result == EAX); |
| 1691 __ jmp(&done); | 1689 __ jmp(&done); |
| 1692 } | 1690 } |
| 1693 } | 1691 } |
| 1694 | 1692 |
| 1695 __ Bind(&mint_static_call); | 1693 __ Bind(&mint_static_call); |
| 1696 { | 1694 { |
| 1697 Function& target = Function::ZoneHandle( | 1695 Function& target = Function::ZoneHandle( |
| 1698 ic_data()->GetTargetForReceiverClassId(kMintCid)); | 1696 ic_data()->GetTargetForReceiverClassId(kMintCid)); |
| 1699 if (target.IsNull()) { | 1697 if (target.IsNull()) { |
| 1700 __ jmp(deopt); | 1698 __ jmp(deopt); |
| 1701 } else { | 1699 } else { |
| 1702 __ pushl(left); | 1700 __ pushl(left); |
| 1703 __ pushl(right); | 1701 __ pushl(right); |
| 1704 compiler->GenerateStaticCall( | 1702 compiler->GenerateStaticCall( |
| 1705 instance_call()->deopt_id(), | 1703 instance_call()->deopt_id(), |
| 1706 instance_call()->token_pos(), | 1704 instance_call()->token_pos(), |
| 1707 instance_call()->try_index(), | 1705 instance_call()->try_index(), |
| 1708 target, | 1706 target, |
| 1709 instance_call()->ArgumentCount(), | 1707 instance_call()->ArgumentCount(), |
| 1710 instance_call()->argument_names(), | 1708 instance_call()->argument_names(), |
| 1711 locs()->stack_bitmap()); | 1709 locs()); |
| 1712 ASSERT(result == EAX); | 1710 ASSERT(result == EAX); |
| 1713 } | 1711 } |
| 1714 } | 1712 } |
| 1715 __ Bind(&done); | 1713 __ Bind(&done); |
| 1716 } | 1714 } |
| 1717 | 1715 |
| 1718 | 1716 |
| 1719 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { | 1717 LocationSummary* BinaryDoubleOpComp::MakeLocationSummary() const { |
| 1720 return MakeCallSummary(); // Calls into a stub for allocation. | 1718 return MakeCallSummary(); // Calls into a stub for allocation. |
| 1721 } | 1719 } |
| 1722 | 1720 |
| 1723 | 1721 |
| 1724 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1722 void BinaryDoubleOpComp::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1725 Register left = EBX; | 1723 Register left = EBX; |
| 1726 Register right = ECX; | 1724 Register right = ECX; |
| 1727 Register temp = EDX; | 1725 Register temp = EDX; |
| 1728 Register result = locs()->out().reg(); | 1726 Register result = locs()->out().reg(); |
| 1729 | 1727 |
| 1730 const Class& double_class = compiler->double_class(); | 1728 const Class& double_class = compiler->double_class(); |
| 1731 const Code& stub = | 1729 const Code& stub = |
| 1732 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1730 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1733 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1731 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1734 compiler->GenerateCall(instance_call()->token_pos(), | 1732 compiler->GenerateCall(instance_call()->token_pos(), |
| 1735 instance_call()->try_index(), | 1733 instance_call()->try_index(), |
| 1736 &label, | 1734 &label, |
| 1737 PcDescriptors::kOther, | 1735 PcDescriptors::kOther, |
| 1738 locs()->stack_bitmap()); | 1736 locs()); |
| 1739 // Newly allocated object is now in the result register (RAX). | 1737 // Newly allocated object is now in the result register (RAX). |
| 1740 ASSERT(result == EAX); | 1738 ASSERT(result == EAX); |
| 1741 __ movl(right, Address(ESP, 0)); | 1739 __ movl(right, Address(ESP, 0)); |
| 1742 __ movl(left, Address(ESP, kWordSize)); | 1740 __ movl(left, Address(ESP, kWordSize)); |
| 1743 | 1741 |
| 1744 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), | 1742 Label* deopt = compiler->AddDeoptStub(instance_call()->deopt_id(), |
| 1745 instance_call()->try_index(), | 1743 instance_call()->try_index(), |
| 1746 kDeoptBinaryDoubleOp); | 1744 kDeoptBinaryDoubleOp); |
| 1747 | 1745 |
| 1748 // Binary operation of two Smi's produces a Smi not a double. | 1746 // Binary operation of two Smi's produces a Smi not a double. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 // Allocate result object. | 1852 // Allocate result object. |
| 1855 const Class& double_class = compiler->double_class(); | 1853 const Class& double_class = compiler->double_class(); |
| 1856 const Code& stub = | 1854 const Code& stub = |
| 1857 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1855 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1858 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1856 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1859 __ pushl(value); | 1857 __ pushl(value); |
| 1860 compiler->GenerateCall(instance_call()->token_pos(), | 1858 compiler->GenerateCall(instance_call()->token_pos(), |
| 1861 instance_call()->try_index(), | 1859 instance_call()->try_index(), |
| 1862 &label, | 1860 &label, |
| 1863 PcDescriptors::kOther, | 1861 PcDescriptors::kOther, |
| 1864 locs()->stack_bitmap()); | 1862 locs()); |
| 1865 // Result is in EAX. | 1863 // Result is in EAX. |
| 1866 ASSERT(result != temp); | 1864 ASSERT(result != temp); |
| 1867 __ movl(result, EAX); | 1865 __ movl(result, EAX); |
| 1868 __ popl(temp); | 1866 __ popl(temp); |
| 1869 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 1867 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 1870 __ DoubleNegate(XMM0); | 1868 __ DoubleNegate(XMM0); |
| 1871 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1869 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| 1872 } else { | 1870 } else { |
| 1873 UNREACHABLE(); | 1871 UNREACHABLE(); |
| 1874 } | 1872 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 const Class& double_class = compiler->double_class(); | 1917 const Class& double_class = compiler->double_class(); |
| 1920 const Code& stub = | 1918 const Code& stub = |
| 1921 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); | 1919 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1922 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); | 1920 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1923 | 1921 |
| 1924 // TODO(vegorov): allocate box in the driver loop to avoid spilling. | 1922 // TODO(vegorov): allocate box in the driver loop to avoid spilling. |
| 1925 compiler->GenerateCall(instance_call()->token_pos(), | 1923 compiler->GenerateCall(instance_call()->token_pos(), |
| 1926 instance_call()->try_index(), | 1924 instance_call()->try_index(), |
| 1927 &label, | 1925 &label, |
| 1928 PcDescriptors::kOther, | 1926 PcDescriptors::kOther, |
| 1929 locs()->stack_bitmap()); | 1927 locs()); |
| 1930 ASSERT(result == EAX); | 1928 ASSERT(result == EAX); |
| 1931 Register value = EBX; | 1929 Register value = EBX; |
| 1932 // Preserve argument on the stack until after the deoptimization point. | 1930 // Preserve argument on the stack until after the deoptimization point. |
| 1933 __ movl(value, Address(ESP, 0)); | 1931 __ movl(value, Address(ESP, 0)); |
| 1934 | 1932 |
| 1935 __ testl(value, Immediate(kSmiTagMask)); | 1933 __ testl(value, Immediate(kSmiTagMask)); |
| 1936 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. | 1934 __ j(NOT_ZERO, deopt); // Deoptimize if not Smi. |
| 1937 __ SmiUntag(value); | 1935 __ SmiUntag(value); |
| 1938 __ cvtsi2sd(XMM0, value); | 1936 __ cvtsi2sd(XMM0, value); |
| 1939 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); | 1937 __ movsd(FieldAddress(result, Double::value_offset()), XMM0); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1969 __ LoadClassId(EDI, EAX); | 1967 __ LoadClassId(EDI, EAX); |
| 1970 compiler->EmitTestAndCall(*ic_data(), | 1968 compiler->EmitTestAndCall(*ic_data(), |
| 1971 EDI, // Class id register. | 1969 EDI, // Class id register. |
| 1972 instance_call()->ArgumentCount(), | 1970 instance_call()->ArgumentCount(), |
| 1973 instance_call()->argument_names(), | 1971 instance_call()->argument_names(), |
| 1974 deopt, | 1972 deopt, |
| 1975 (is_smi_label == &handle_smi) ? &done : NULL, | 1973 (is_smi_label == &handle_smi) ? &done : NULL, |
| 1976 instance_call()->deopt_id(), | 1974 instance_call()->deopt_id(), |
| 1977 instance_call()->token_pos(), | 1975 instance_call()->token_pos(), |
| 1978 instance_call()->try_index(), | 1976 instance_call()->try_index(), |
| 1979 locs()->stack_bitmap()); | 1977 locs()); |
| 1980 if (is_smi_label == &handle_smi) { | 1978 if (is_smi_label == &handle_smi) { |
| 1981 __ Bind(&handle_smi); | 1979 __ Bind(&handle_smi); |
| 1982 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); | 1980 ASSERT(ic_data()->GetReceiverClassIdAt(0) == kSmiCid); |
| 1983 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); | 1981 const Function& target = Function::ZoneHandle(ic_data()->GetTargetAt(0)); |
| 1984 compiler->GenerateStaticCall(instance_call()->deopt_id(), | 1982 compiler->GenerateStaticCall(instance_call()->deopt_id(), |
| 1985 instance_call()->token_pos(), | 1983 instance_call()->token_pos(), |
| 1986 instance_call()->try_index(), | 1984 instance_call()->try_index(), |
| 1987 target, | 1985 target, |
| 1988 instance_call()->ArgumentCount(), | 1986 instance_call()->ArgumentCount(), |
| 1989 instance_call()->argument_names(), | 1987 instance_call()->argument_names(), |
| 1990 locs()->stack_bitmap()); | 1988 locs()); |
| 1991 } | 1989 } |
| 1992 __ Bind(&done); | 1990 __ Bind(&done); |
| 1993 } | 1991 } |
| 1994 | 1992 |
| 1995 | 1993 |
| 1996 // TODO(srdjan): Move to shared. | 1994 // TODO(srdjan): Move to shared. |
| 1997 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { | 1995 static bool ICDataWithBothClassIds(const ICData& ic_data, intptr_t class_id) { |
| 1998 if (ic_data.num_args_tested() != 2) return false; | 1996 if (ic_data.num_args_tested() != 2) return false; |
| 1999 if (ic_data.NumberOfChecks() != 1) return false; | 1997 if (ic_data.NumberOfChecks() != 1) return false; |
| 2000 Function& target = Function::Handle(); | 1998 Function& target = Function::Handle(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 return; | 2078 return; |
| 2081 } | 2079 } |
| 2082 if (IsCheckedStrictEquals(*ic_data(), kind())) { | 2080 if (IsCheckedStrictEquals(*ic_data(), kind())) { |
| 2083 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, | 2081 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), this, |
| 2084 deopt_id(), token_pos(), try_index()); | 2082 deopt_id(), token_pos(), try_index()); |
| 2085 return; | 2083 return; |
| 2086 } | 2084 } |
| 2087 | 2085 |
| 2088 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. | 2086 // TODO(srdjan): Add Smi/Double, Double/Smi comparisons. |
| 2089 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { | 2087 if ((kind() == Token::kEQ) || (kind() == Token::kNE)) { |
| 2090 EmitGenericEqualityCompare(compiler, *locs(), kind(), this, *ic_data(), | 2088 EmitGenericEqualityCompare(compiler, locs(), kind(), this, *ic_data(), |
| 2091 deopt_id(), token_pos(), try_index()); | 2089 deopt_id(), token_pos(), try_index()); |
| 2092 return; | 2090 return; |
| 2093 } | 2091 } |
| 2094 // Otherwise polymorphic dispatch? | 2092 // Otherwise polymorphic dispatch? |
| 2095 } | 2093 } |
| 2096 Register left = locs()->in(0).reg(); | 2094 Register left = locs()->in(0).reg(); |
| 2097 Register right = locs()->in(1).reg(); | 2095 Register right = locs()->in(1).reg(); |
| 2098 __ pushl(left); | 2096 __ pushl(left); |
| 2099 __ pushl(right); | 2097 __ pushl(right); |
| 2100 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) { | 2098 if ((kind() == Token::kNE) || (kind() == Token::kEQ)) { |
| 2101 EmitEqualityAsInstanceCall(compiler, | 2099 EmitEqualityAsInstanceCall(compiler, |
| 2102 deopt_id(), | 2100 deopt_id(), |
| 2103 token_pos(), | 2101 token_pos(), |
| 2104 try_index(), | 2102 try_index(), |
| 2105 Token::kEQ, // kNE reverse occurs at branch. | 2103 Token::kEQ, // kNE reverse occurs at branch. |
| 2106 *locs()); | 2104 locs()); |
| 2107 } else { | 2105 } else { |
| 2108 const String& function_name = | 2106 const String& function_name = |
| 2109 String::ZoneHandle(Symbols::New(Token::Str(kind()))); | 2107 String::ZoneHandle(Symbols::New(Token::Str(kind()))); |
| 2110 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, | 2108 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, |
| 2111 deopt_id(), | 2109 deopt_id(), |
| 2112 token_pos(), | 2110 token_pos(), |
| 2113 try_index()); | 2111 try_index()); |
| 2114 const intptr_t kNumArguments = 2; | 2112 const intptr_t kNumArguments = 2; |
| 2115 const intptr_t kNumArgsChecked = 2; // Type-feedback. | 2113 const intptr_t kNumArgsChecked = 2; // Type-feedback. |
| 2116 compiler->GenerateInstanceCall(deopt_id(), | 2114 compiler->GenerateInstanceCall(deopt_id(), |
| 2117 token_pos(), | 2115 token_pos(), |
| 2118 try_index(), | 2116 try_index(), |
| 2119 function_name, | 2117 function_name, |
| 2120 kNumArguments, | 2118 kNumArguments, |
| 2121 Array::ZoneHandle(), // No optional args. | 2119 Array::ZoneHandle(), // No optional args. |
| 2122 kNumArgsChecked, | 2120 kNumArgsChecked, |
| 2123 locs()->stack_bitmap()); | 2121 locs()); |
| 2124 } | 2122 } |
| 2125 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; | 2123 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; |
| 2126 __ CompareObject(EAX, compiler->bool_true()); | 2124 __ CompareObject(EAX, compiler->bool_true()); |
| 2127 EmitBranchOnCondition(compiler, branch_condition); | 2125 EmitBranchOnCondition(compiler, branch_condition); |
| 2128 } | 2126 } |
| 2129 | 2127 |
| 2130 | 2128 |
| 2131 LocationSummary* CheckClassComp::MakeLocationSummary() const { | 2129 LocationSummary* CheckClassComp::MakeLocationSummary() const { |
| 2132 const intptr_t kNumInputs = 1; | 2130 const intptr_t kNumInputs = 1; |
| 2133 const intptr_t kNumTemps = 1; | 2131 const intptr_t kNumTemps = 1; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2193 __ testl(value, Immediate(kSmiTagMask)); | 2191 __ testl(value, Immediate(kSmiTagMask)); |
| 2194 __ j(NOT_ZERO, deopt); | 2192 __ j(NOT_ZERO, deopt); |
| 2195 } | 2193 } |
| 2196 | 2194 |
| 2197 | 2195 |
| 2198 } // namespace dart | 2196 } // namespace dart |
| 2199 | 2197 |
| 2200 #undef __ | 2198 #undef __ |
| 2201 | 2199 |
| 2202 #endif // defined TARGET_ARCH_X64 | 2200 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |