| 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 // Class for intrinsifying functions. | 4 // Class for intrinsifying functions. |
| 5 | 5 |
| 6 #include "vm/assembler.h" | 6 #include "vm/assembler.h" |
| 7 #include "vm/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 new LoadFieldInstr(new Value(array), | 377 new LoadFieldInstr(new Value(array), |
| 378 length_offset, | 378 length_offset, |
| 379 Type::ZoneHandle(Type::SmiType()), | 379 Type::ZoneHandle(Type::SmiType()), |
| 380 TokenPosition::kNoSource)); | 380 TokenPosition::kNoSource)); |
| 381 builder->AddInstruction( | 381 builder->AddInstruction( |
| 382 new CheckArrayBoundInstr(new Value(length), | 382 new CheckArrayBoundInstr(new Value(length), |
| 383 new Value(index), | 383 new Value(index), |
| 384 Thread::kNoDeoptId)); | 384 Thread::kNoDeoptId)); |
| 385 } | 385 } |
| 386 | 386 |
| 387 | 387 static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph, |
| 388 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { | 388 intptr_t array_cid) { |
| 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 391 BlockBuilder builder(flow_graph, normal_entry); | 391 BlockBuilder builder(flow_graph, normal_entry); |
| 392 | |
| 393 Definition* index = builder.AddParameter(1); | |
| 394 Definition* array = builder.AddParameter(2); | |
| 395 | |
| 396 PrepareIndexedOp(&builder, array, index, Array::length_offset()); | |
| 397 | |
| 398 Definition* result = builder.AddDefinition( | |
| 399 new LoadIndexedInstr(new Value(array), | |
| 400 new Value(index), | |
| 401 Instance::ElementSizeFor(kArrayCid), // index scale | |
| 402 kArrayCid, | |
| 403 Thread::kNoDeoptId, | |
| 404 builder.TokenPos())); | |
| 405 builder.AddIntrinsicReturn(new Value(result)); | |
| 406 return true; | |
| 407 } | |
| 408 | |
| 409 | |
| 410 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { | |
| 411 return Build_ObjectArrayGetIndexed(flow_graph); | |
| 412 } | |
| 413 | |
| 414 | |
| 415 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { | |
| 416 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 417 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 418 BlockBuilder builder(flow_graph, normal_entry); | |
| 419 | 392 |
| 420 Definition* index = builder.AddParameter(1); | 393 Definition* index = builder.AddParameter(1); |
| 421 Definition* array = builder.AddParameter(2); | 394 Definition* array = builder.AddParameter(2); |
| 422 | 395 |
| 423 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 396 intptr_t length_offset = Array::length_offset(); |
| 397 if (RawObject::IsTypedDataClassId(array_cid)) { |
| 398 length_offset = TypedData::length_offset(); |
| 399 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 400 length_offset = ExternalTypedData::length_offset(); |
| 401 } |
| 402 |
| 403 PrepareIndexedOp(&builder, array, index, length_offset); |
| 404 |
| 405 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 406 array = builder.AddDefinition( |
| 407 new LoadUntaggedInstr(new Value(array), |
| 408 ExternalTypedData::data_offset())); |
| 409 } |
| 424 | 410 |
| 425 Definition* result = builder.AddDefinition( | 411 Definition* result = builder.AddDefinition( |
| 426 new LoadIndexedInstr(new Value(array), | 412 new LoadIndexedInstr(new Value(array), |
| 427 new Value(index), | 413 new Value(index), |
| 428 1, // index scale | 414 Instance::ElementSizeFor(array_cid), // index scale |
| 429 kTypedDataUint8ArrayCid, | 415 array_cid, |
| 430 Thread::kNoDeoptId, | 416 Thread::kNoDeoptId, |
| 431 builder.TokenPos())); | 417 builder.TokenPos())); |
| 418 // Box and/or convert result if necessary. |
| 419 switch (array_cid) { |
| 420 case kTypedDataInt32ArrayCid: |
| 421 case kExternalTypedDataInt32ArrayCid: |
| 422 result = builder.AddDefinition( |
| 423 BoxInstr::Create(kUnboxedInt32, new Value(result))); |
| 424 break; |
| 425 case kTypedDataUint32ArrayCid: |
| 426 case kExternalTypedDataUint32ArrayCid: |
| 427 result = builder.AddDefinition( |
| 428 BoxInstr::Create(kUnboxedUint32, new Value(result))); |
| 429 break; |
| 430 case kTypedDataFloat32ArrayCid: |
| 431 result = builder.AddDefinition( |
| 432 new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId)); |
| 433 // Fall through. |
| 434 case kTypedDataFloat64ArrayCid: |
| 435 result = builder.AddDefinition( |
| 436 BoxInstr::Create(kUnboxedDouble, new Value(result))); |
| 437 break; |
| 438 case kArrayCid: |
| 439 case kImmutableArrayCid: |
| 440 case kTypedDataInt8ArrayCid: |
| 441 case kTypedDataUint8ArrayCid: |
| 442 case kExternalTypedDataUint8ArrayCid: |
| 443 case kTypedDataUint8ClampedArrayCid: |
| 444 case kExternalTypedDataUint8ClampedArrayCid: |
| 445 case kTypedDataInt16ArrayCid: |
| 446 case kTypedDataUint16ArrayCid: |
| 447 // Nothing to do. |
| 448 break; |
| 449 default: |
| 450 UNREACHABLE(); |
| 451 break; |
| 452 } |
| 432 builder.AddIntrinsicReturn(new Value(result)); | 453 builder.AddIntrinsicReturn(new Value(result)); |
| 433 return true; | 454 return true; |
| 434 } | 455 } |
| 435 | 456 |
| 436 | 457 |
| 437 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { | 458 static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph, |
| 459 intptr_t array_cid) { |
| 438 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 460 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 439 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 461 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 440 BlockBuilder builder(flow_graph, normal_entry); | 462 BlockBuilder builder(flow_graph, normal_entry); |
| 441 | |
| 442 Definition* index = builder.AddParameter(1); | |
| 443 Definition* array = builder.AddParameter(2); | |
| 444 | |
| 445 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | |
| 446 | |
| 447 Definition* elements = builder.AddDefinition( | |
| 448 new LoadUntaggedInstr(new Value(array), | |
| 449 ExternalTypedData::data_offset())); | |
| 450 Definition* result = builder.AddDefinition( | |
| 451 new LoadIndexedInstr(new Value(elements), | |
| 452 new Value(index), | |
| 453 1, // index scale | |
| 454 kExternalTypedDataUint8ArrayCid, | |
| 455 Thread::kNoDeoptId, | |
| 456 builder.TokenPos())); | |
| 457 builder.AddIntrinsicReturn(new Value(result)); | |
| 458 return true; | |
| 459 } | |
| 460 | |
| 461 | |
| 462 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { | |
| 463 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 464 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 465 BlockBuilder builder(flow_graph, normal_entry); | |
| 466 | 463 |
| 467 Definition* value = builder.AddParameter(1); | 464 Definition* value = builder.AddParameter(1); |
| 468 Definition* index = builder.AddParameter(2); | 465 Definition* index = builder.AddParameter(2); |
| 469 Definition* array = builder.AddParameter(3); | 466 Definition* array = builder.AddParameter(3); |
| 470 | 467 |
| 471 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 468 intptr_t length_offset = Array::length_offset(); |
| 469 if (RawObject::IsTypedDataClassId(array_cid)) { |
| 470 length_offset = TypedData::length_offset(); |
| 471 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 472 length_offset = ExternalTypedData::length_offset(); |
| 473 } |
| 472 | 474 |
| 473 builder.AddInstruction( | 475 PrepareIndexedOp(&builder, array, index, length_offset); |
| 474 new CheckSmiInstr(new Value(value), | |
| 475 Thread::kNoDeoptId, | |
| 476 builder.TokenPos())); | |
| 477 | 476 |
| 477 // Value check/conversion. |
| 478 switch (array_cid) { |
| 479 case kTypedDataInt8ArrayCid: |
| 480 case kTypedDataUint8ArrayCid: |
| 481 case kExternalTypedDataUint8ArrayCid: |
| 482 case kTypedDataUint8ClampedArrayCid: |
| 483 case kExternalTypedDataUint8ClampedArrayCid: |
| 484 case kTypedDataInt16ArrayCid: |
| 485 case kTypedDataUint16ArrayCid: |
| 486 builder.AddInstruction(new CheckSmiInstr(new Value(value), |
| 487 Thread::kNoDeoptId, |
| 488 builder.TokenPos())); |
| 489 break; |
| 490 case kTypedDataInt32ArrayCid: |
| 491 case kExternalTypedDataInt32ArrayCid: |
| 492 // Use same truncating unbox-instruction for int32 and uint32. |
| 493 // Fall-through. |
| 494 case kTypedDataUint32ArrayCid: |
| 495 case kExternalTypedDataUint32ArrayCid: |
| 496 // Supports smi and mint, slow-case for bigints. |
| 497 value = builder.AddUnboxInstr(kUnboxedUint32, |
| 498 new Value(value), |
| 499 /* is_checked = */ false); |
| 500 break; |
| 501 case kTypedDataFloat32ArrayCid: |
| 502 case kTypedDataFloat64ArrayCid: { |
| 503 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 504 flow_graph->function(), |
| 505 Symbols::Empty(), // Dummy function name. |
| 506 Object::empty_array(), // Dummy args. descr. |
| 507 Thread::kNoDeoptId, |
| 508 1, |
| 509 false)); |
| 510 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); |
| 511 builder.AddInstruction( |
| 512 new CheckClassInstr(new Value(value), |
| 513 Thread::kNoDeoptId, |
| 514 value_check, |
| 515 builder.TokenPos())); |
| 516 value = builder.AddUnboxInstr(kUnboxedDouble, |
| 517 new Value(value), |
| 518 /* is_checked = */ true); |
| 519 if (array_cid == kTypedDataFloat32ArrayCid) { |
| 520 value = builder.AddDefinition( |
| 521 new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId)); |
| 522 } |
| 523 break; |
| 524 } |
| 525 default: |
| 526 UNREACHABLE(); |
| 527 } |
| 528 |
| 529 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
| 530 array = builder.AddDefinition( |
| 531 new LoadUntaggedInstr(new Value(array), |
| 532 ExternalTypedData::data_offset())); |
| 533 } |
| 534 // No store barrier. |
| 535 ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) || |
| 536 RawObject::IsTypedDataClassId(array_cid)); |
| 478 builder.AddInstruction( | 537 builder.AddInstruction( |
| 479 new StoreIndexedInstr(new Value(array), | 538 new StoreIndexedInstr(new Value(array), |
| 480 new Value(index), | 539 new Value(index), |
| 481 new Value(value), | 540 new Value(value), |
| 482 kNoStoreBarrier, | 541 kNoStoreBarrier, |
| 483 1, // index scale | 542 Instance::ElementSizeFor(array_cid), // index scale |
| 484 kTypedDataUint8ArrayCid, | 543 array_cid, |
| 485 Thread::kNoDeoptId, | 544 Thread::kNoDeoptId, |
| 486 builder.TokenPos())); | 545 builder.TokenPos())); |
| 487 // Return null. | 546 // Return null. |
| 488 Definition* null_def = builder.AddNullDefinition(); | |
| 489 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 490 return true; | |
| 491 } | |
| 492 | |
| 493 | |
| 494 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { | |
| 495 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | |
| 496 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | |
| 497 BlockBuilder builder(flow_graph, normal_entry); | |
| 498 | |
| 499 Definition* value = builder.AddParameter(1); | |
| 500 Definition* index = builder.AddParameter(2); | |
| 501 Definition* array = builder.AddParameter(3); | |
| 502 | |
| 503 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | |
| 504 | |
| 505 builder.AddInstruction( | |
| 506 new CheckSmiInstr(new Value(value), | |
| 507 Thread::kNoDeoptId, | |
| 508 builder.TokenPos())); | |
| 509 Definition* elements = builder.AddDefinition( | |
| 510 new LoadUntaggedInstr(new Value(array), | |
| 511 ExternalTypedData::data_offset())); | |
| 512 builder.AddInstruction( | |
| 513 new StoreIndexedInstr(new Value(elements), | |
| 514 new Value(index), | |
| 515 new Value(value), | |
| 516 kNoStoreBarrier, | |
| 517 1, // index scale | |
| 518 kExternalTypedDataUint8ArrayCid, | |
| 519 Thread::kNoDeoptId, | |
| 520 builder.TokenPos())); | |
| 521 // Return null. | |
| 522 Definition* null_def = builder.AddNullDefinition(); | 547 Definition* null_def = builder.AddNullDefinition(); |
| 523 builder.AddIntrinsicReturn(new Value(null_def)); | 548 builder.AddIntrinsicReturn(new Value(null_def)); |
| 524 return true; | 549 return true; |
| 525 } | 550 } |
| 526 | 551 |
| 527 | 552 |
| 528 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { | 553 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 529 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 554 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 530 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 555 return IntrinsifyArrayGetIndexed( \ |
| 531 BlockBuilder builder(flow_graph, normal_entry); | 556 flow_graph, \ |
| 532 | 557 MethodRecognizer::MethodKindToReceiverCid( \ |
| 533 Definition* value = builder.AddParameter(1); | 558 MethodRecognizer::k##enum_name##GetIndexed)); \ |
| 534 Definition* index = builder.AddParameter(2); | |
| 535 Definition* array = builder.AddParameter(3); | |
| 536 | |
| 537 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
| 538 | |
| 539 Definition* unboxed_value = | |
| 540 builder.AddUnboxInstr(kUnboxedUint32, | |
| 541 new Value(value), | |
| 542 /* is_checked = */ true); | |
| 543 | |
| 544 builder.AddInstruction( | |
| 545 new StoreIndexedInstr(new Value(array), | |
| 546 new Value(index), | |
| 547 new Value(unboxed_value), | |
| 548 kNoStoreBarrier, | |
| 549 4, // index scale | |
| 550 kTypedDataUint32ArrayCid, | |
| 551 Thread::kNoDeoptId, | |
| 552 builder.TokenPos())); | |
| 553 // Return null. | |
| 554 Definition* null_def = builder.AddNullDefinition(); | |
| 555 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 556 return true; | |
| 557 } | 559 } |
| 558 | 560 |
| 559 | 561 |
| 560 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { | 562 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ |
| 561 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 563 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
| 562 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 564 return IntrinsifyArraySetIndexed( \ |
| 563 BlockBuilder builder(flow_graph, normal_entry); | 565 flow_graph, \ |
| 566 MethodRecognizer::MethodKindToReceiverCid( \ |
| 567 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 568 } |
| 564 | 569 |
| 565 Definition* index = builder.AddParameter(1); | 570 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. |
| 566 Definition* array = builder.AddParameter(2); | 571 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) |
| 567 | 572 |
| 568 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 573 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 574 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 575 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) |
| 569 | 576 |
| 570 Definition* unboxed_value = builder.AddDefinition( | 577 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array) |
| 571 new LoadIndexedInstr(new Value(array), | 578 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) |
| 572 new Value(index), | 579 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) |
| 573 4, // index scale | 580 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray) |
| 574 kTypedDataUint32ArrayCid, | 581 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray) |
| 575 Thread::kNoDeoptId, | 582 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array) |
| 576 builder.TokenPos())); | 583 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array) |
| 577 Definition* result = builder.AddDefinition( | 584 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) |
| 578 BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); | 585 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) |
| 579 builder.AddIntrinsicReturn(new Value(result)); | 586 |
| 580 return true; | 587 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS |
| 588 #undef DEFINE_ARRAY_GETTER_INTRINSIC |
| 589 #undef DEFINE_ARRAY_SETTER_INTRINSIC |
| 590 |
| 591 |
| 592 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 593 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 594 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
| 595 return false; \ |
| 596 } \ |
| 597 return IntrinsifyArrayGetIndexed( \ |
| 598 flow_graph, \ |
| 599 MethodRecognizer::MethodKindToReceiverCid( \ |
| 600 MethodRecognizer::k##enum_name##GetIndexed)); \ |
| 581 } | 601 } |
| 582 | 602 |
| 583 | 603 |
| 584 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { | 604 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ |
| 585 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 605 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
| 586 return false; | 606 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
| 587 } | 607 return false; \ |
| 588 | 608 } \ |
| 589 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 609 return IntrinsifyArraySetIndexed( \ |
| 590 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 610 flow_graph, \ |
| 591 BlockBuilder builder(flow_graph, normal_entry); | 611 MethodRecognizer::MethodKindToReceiverCid( \ |
| 592 | 612 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 593 Definition* value = builder.AddParameter(1); | |
| 594 Definition* index = builder.AddParameter(2); | |
| 595 Definition* array = builder.AddParameter(3); | |
| 596 | |
| 597 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
| 598 | |
| 599 const ICData& value_check = ICData::ZoneHandle(ICData::New( | |
| 600 flow_graph->function(), | |
| 601 String::Handle(flow_graph->function().name()), | |
| 602 Object::empty_array(), // Dummy args. descr. | |
| 603 Thread::kNoDeoptId, | |
| 604 1, | |
| 605 false)); | |
| 606 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); | |
| 607 builder.AddInstruction( | |
| 608 new CheckClassInstr(new Value(value), | |
| 609 Thread::kNoDeoptId, | |
| 610 value_check, | |
| 611 builder.TokenPos())); | |
| 612 Definition* double_value = | |
| 613 builder.AddUnboxInstr(kUnboxedDouble, | |
| 614 new Value(value), | |
| 615 /* is_checked = */ true); | |
| 616 | |
| 617 builder.AddInstruction( | |
| 618 new StoreIndexedInstr(new Value(array), | |
| 619 new Value(index), | |
| 620 new Value(double_value), | |
| 621 kNoStoreBarrier, | |
| 622 8, // index scale | |
| 623 kTypedDataFloat64ArrayCid, | |
| 624 Thread::kNoDeoptId, | |
| 625 builder.TokenPos())); | |
| 626 // Return null. | |
| 627 Definition* null_def = builder.AddNullDefinition(); | |
| 628 builder.AddIntrinsicReturn(new Value(null_def)); | |
| 629 return true; | |
| 630 } | 613 } |
| 631 | 614 |
| 615 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 616 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 617 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) |
| 632 | 618 |
| 633 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { | 619 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) |
| 634 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 620 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) |
| 635 return false; | |
| 636 } | |
| 637 | 621 |
| 638 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 622 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS |
| 639 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 623 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC |
| 640 BlockBuilder builder(flow_graph, normal_entry); | 624 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC |
| 641 | |
| 642 Definition* index = builder.AddParameter(1); | |
| 643 Definition* array = builder.AddParameter(2); | |
| 644 | |
| 645 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | |
| 646 | |
| 647 Definition* unboxed_value = builder.AddDefinition( | |
| 648 new LoadIndexedInstr(new Value(array), | |
| 649 new Value(index), | |
| 650 8, // index scale | |
| 651 kTypedDataFloat64ArrayCid, | |
| 652 Thread::kNoDeoptId, | |
| 653 builder.TokenPos())); | |
| 654 Definition* result = builder.AddDefinition( | |
| 655 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); | |
| 656 builder.AddIntrinsicReturn(new Value(result)); | |
| 657 return true; | |
| 658 } | |
| 659 | 625 |
| 660 | 626 |
| 661 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { | 627 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { |
| 662 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 628 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 663 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 629 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 664 BlockBuilder builder(flow_graph, normal_entry); | 630 BlockBuilder builder(flow_graph, normal_entry); |
| 665 | 631 |
| 666 Definition* index = builder.AddParameter(1); | 632 Definition* index = builder.AddParameter(1); |
| 667 Definition* str = builder.AddParameter(2); | 633 Definition* str = builder.AddParameter(2); |
| 668 PrepareIndexedOp(&builder, str, index, String::length_offset()); | 634 PrepareIndexedOp(&builder, str, index, String::length_offset()); |
| (...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1193 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1228 BlockBuilder builder(flow_graph, normal_entry); | 1194 BlockBuilder builder(flow_graph, normal_entry); |
| 1229 | 1195 |
| 1230 return BuildInvokeMathCFunction(&builder, | 1196 return BuildInvokeMathCFunction(&builder, |
| 1231 MethodRecognizer::kDoubleRound); | 1197 MethodRecognizer::kDoubleRound); |
| 1232 } | 1198 } |
| 1233 #endif // !defined(TARGET_ARCH_DBC) | 1199 #endif // !defined(TARGET_ARCH_DBC) |
| 1234 | 1200 |
| 1235 | 1201 |
| 1236 } // namespace dart | 1202 } // namespace dart |
| OLD | NEW |