| 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/intrinsifier.h" |
| 6 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 7 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 8 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 9 #include "vm/flags.h" | 10 #include "vm/flags.h" |
| 10 #include "vm/flow_graph.h" | 11 #include "vm/flow_graph.h" |
| 11 #include "vm/flow_graph_compiler.h" | |
| 12 #include "vm/flow_graph_allocator.h" | 12 #include "vm/flow_graph_allocator.h" |
| 13 #include "vm/flow_graph_builder.h" | 13 #include "vm/flow_graph_builder.h" |
| 14 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/il_printer.h" | 15 #include "vm/il_printer.h" |
| 15 #include "vm/intermediate_language.h" | 16 #include "vm/intermediate_language.h" |
| 16 #include "vm/intrinsifier.h" | |
| 17 #include "vm/object.h" | 17 #include "vm/object.h" |
| 18 #include "vm/parser.h" | 18 #include "vm/parser.h" |
| 19 #include "vm/symbols.h" | 19 #include "vm/symbols.h" |
| 20 | 20 |
| 21 | |
| 22 namespace dart { | 21 namespace dart { |
| 23 | 22 |
| 24 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); | 23 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible"); |
| 25 DEFINE_FLAG(bool, trace_intrinsifier, false, "Trace intrinsifier"); | 24 DEFINE_FLAG(bool, trace_intrinsifier, false, "Trace intrinsifier"); |
| 26 DECLARE_FLAG(bool, code_comments); | 25 DECLARE_FLAG(bool, code_comments); |
| 27 DECLARE_FLAG(bool, print_flow_graph); | 26 DECLARE_FLAG(bool, print_flow_graph); |
| 28 DECLARE_FLAG(bool, print_flow_graph_optimized); | 27 DECLARE_FLAG(bool, print_flow_graph_optimized); |
| 29 | 28 |
| 30 bool Intrinsifier::CanIntrinsify(const Function& function) { | 29 bool Intrinsifier::CanIntrinsify(const Function& function) { |
| 31 if (FLAG_trace_intrinsifier) { | 30 if (FLAG_trace_intrinsifier) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 52 THR_Print("No, not intrinsic function.\n"); | 51 THR_Print("No, not intrinsic function.\n"); |
| 53 } | 52 } |
| 54 return false; | 53 return false; |
| 55 } | 54 } |
| 56 if (FLAG_trace_intrinsifier) { | 55 if (FLAG_trace_intrinsifier) { |
| 57 THR_Print("Yes.\n"); | 56 THR_Print("Yes.\n"); |
| 58 } | 57 } |
| 59 return true; | 58 return true; |
| 60 } | 59 } |
| 61 | 60 |
| 62 | |
| 63 #if !defined(DART_PRECOMPILED_RUNTIME) | 61 #if !defined(DART_PRECOMPILED_RUNTIME) |
| 64 void Intrinsifier::InitializeState() { | 62 void Intrinsifier::InitializeState() { |
| 65 Thread* thread = Thread::Current(); | 63 Thread* thread = Thread::Current(); |
| 66 Zone* zone = thread->zone(); | 64 Zone* zone = thread->zone(); |
| 67 Library& lib = Library::Handle(zone); | 65 Library& lib = Library::Handle(zone); |
| 68 Class& cls = Class::Handle(zone); | 66 Class& cls = Class::Handle(zone); |
| 69 Function& func = Function::Handle(zone); | 67 Function& func = Function::Handle(zone); |
| 70 String& str = String::Handle(zone); | 68 String& str = String::Handle(zone); |
| 71 Error& error = Error::Handle(zone); | 69 Error& error = Error::Handle(zone); |
| 72 | 70 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 | 112 |
| 115 // Setup all dart:developer lib functions that can be intrinsified. | 113 // Setup all dart:developer lib functions that can be intrinsified. |
| 116 lib = Library::DeveloperLibrary(); | 114 lib = Library::DeveloperLibrary(); |
| 117 ASSERT(!lib.IsNull()); | 115 ASSERT(!lib.IsNull()); |
| 118 DEVELOPER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 116 DEVELOPER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
| 119 | 117 |
| 120 #undef SETUP_FUNCTION | 118 #undef SETUP_FUNCTION |
| 121 } | 119 } |
| 122 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 120 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| 123 | 121 |
| 124 | |
| 125 // DBC does not use graph intrinsics. | 122 // DBC does not use graph intrinsics. |
| 126 #if !defined(TARGET_ARCH_DBC) | 123 #if !defined(TARGET_ARCH_DBC) |
| 127 static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) { | 124 static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) { |
| 128 // The FlowGraph here is constructed by the intrinsics builder methods, and | 125 // The FlowGraph here is constructed by the intrinsics builder methods, and |
| 129 // is different from compiler->flow_graph(), the original method's flow graph. | 126 // is different from compiler->flow_graph(), the original method's flow graph. |
| 130 compiler->assembler()->Comment("Graph intrinsic begin"); | 127 compiler->assembler()->Comment("Graph intrinsic begin"); |
| 131 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) { | 128 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) { |
| 132 BlockEntryInstr* block = graph->reverse_postorder()[i]; | 129 BlockEntryInstr* block = graph->reverse_postorder()[i]; |
| 133 if (block->IsGraphEntry()) continue; // No code for graph entry needed. | 130 if (block->IsGraphEntry()) continue; // No code for graph entry needed. |
| 134 | 131 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 153 // Calls are not supported in intrinsics code. | 150 // Calls are not supported in intrinsics code. |
| 154 ASSERT(!instr->locs()->always_calls()); | 151 ASSERT(!instr->locs()->always_calls()); |
| 155 instr->EmitNativeCode(compiler); | 152 instr->EmitNativeCode(compiler); |
| 156 } | 153 } |
| 157 } | 154 } |
| 158 } | 155 } |
| 159 compiler->assembler()->Comment("Graph intrinsic end"); | 156 compiler->assembler()->Comment("Graph intrinsic end"); |
| 160 } | 157 } |
| 161 #endif | 158 #endif |
| 162 | 159 |
| 163 | |
| 164 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, | 160 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, |
| 165 FlowGraphCompiler* compiler) { | 161 FlowGraphCompiler* compiler) { |
| 166 #if !defined(TARGET_ARCH_DBC) | 162 #if !defined(TARGET_ARCH_DBC) |
| 167 ZoneGrowableArray<const ICData*>* ic_data_array = | 163 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 168 new ZoneGrowableArray<const ICData*>(); | 164 new ZoneGrowableArray<const ICData*>(); |
| 169 FlowGraphBuilder builder(parsed_function, *ic_data_array, | 165 FlowGraphBuilder builder(parsed_function, *ic_data_array, |
| 170 /* not building var desc */ NULL, | 166 /* not building var desc */ NULL, |
| 171 /* not inlining */ NULL, Compiler::kNoOSRDeoptId); | 167 /* not inlining */ NULL, Compiler::kNoOSRDeoptId); |
| 172 | 168 |
| 173 intptr_t block_id = builder.AllocateBlockId(); | 169 intptr_t block_id = builder.AllocateBlockId(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 FlowGraphPrinter printer(*graph); | 203 FlowGraphPrinter printer(*graph); |
| 208 printer.PrintBlocks(); | 204 printer.PrintBlocks(); |
| 209 } | 205 } |
| 210 EmitCodeFor(compiler, graph); | 206 EmitCodeFor(compiler, graph); |
| 211 return true; | 207 return true; |
| 212 #else | 208 #else |
| 213 return false; | 209 return false; |
| 214 #endif // !defined(TARGET_ARCH_DBC) | 210 #endif // !defined(TARGET_ARCH_DBC) |
| 215 } | 211 } |
| 216 | 212 |
| 217 | |
| 218 // Returns true if fall-through code can be omitted. | 213 // Returns true if fall-through code can be omitted. |
| 219 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, | 214 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, |
| 220 FlowGraphCompiler* compiler) { | 215 FlowGraphCompiler* compiler) { |
| 221 const Function& function = parsed_function.function(); | 216 const Function& function = parsed_function.function(); |
| 222 if (!CanIntrinsify(function)) { | 217 if (!CanIntrinsify(function)) { |
| 223 return false; | 218 return false; |
| 224 } | 219 } |
| 225 | 220 |
| 226 ASSERT(!compiler->flow_graph().IsCompiledForOsr()); | 221 ASSERT(!compiler->flow_graph().IsCompiledForOsr()); |
| 227 if (GraphIntrinsify(parsed_function, compiler)) { | 222 if (GraphIntrinsify(parsed_function, compiler)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 GRAPH_INTRINSICS_LIST(EMIT_CASE) | 258 GRAPH_INTRINSICS_LIST(EMIT_CASE) |
| 264 default: | 259 default: |
| 265 break; | 260 break; |
| 266 } | 261 } |
| 267 #endif | 262 #endif |
| 268 | 263 |
| 269 #undef EMIT_INTRINSIC | 264 #undef EMIT_INTRINSIC |
| 270 return false; | 265 return false; |
| 271 } | 266 } |
| 272 | 267 |
| 273 | |
| 274 #if !defined(TARGET_ARCH_DBC) | 268 #if !defined(TARGET_ARCH_DBC) |
| 275 static intptr_t CidForRepresentation(Representation rep) { | 269 static intptr_t CidForRepresentation(Representation rep) { |
| 276 switch (rep) { | 270 switch (rep) { |
| 277 case kUnboxedDouble: | 271 case kUnboxedDouble: |
| 278 return kDoubleCid; | 272 return kDoubleCid; |
| 279 case kUnboxedFloat32x4: | 273 case kUnboxedFloat32x4: |
| 280 return kFloat32x4Cid; | 274 return kFloat32x4Cid; |
| 281 case kUnboxedInt32x4: | 275 case kUnboxedInt32x4: |
| 282 return kInt32x4Cid; | 276 return kInt32x4Cid; |
| 283 case kUnboxedFloat64x2: | 277 case kUnboxedFloat64x2: |
| 284 return kFloat64x2Cid; | 278 return kFloat64x2Cid; |
| 285 case kUnboxedUint32: | 279 case kUnboxedUint32: |
| 286 return kDynamicCid; // smi or mint. | 280 return kDynamicCid; // smi or mint. |
| 287 default: | 281 default: |
| 288 UNREACHABLE(); | 282 UNREACHABLE(); |
| 289 return kIllegalCid; | 283 return kIllegalCid; |
| 290 } | 284 } |
| 291 } | 285 } |
| 292 | 286 |
| 293 | |
| 294 // Notes about the graph intrinsics: | 287 // Notes about the graph intrinsics: |
| 295 // | 288 // |
| 296 // IR instructions which would jump to a deoptimization sequence on failure | 289 // IR instructions which would jump to a deoptimization sequence on failure |
| 297 // instead branch to the intrinsic slow path. | 290 // instead branch to the intrinsic slow path. |
| 298 // | 291 // |
| 299 class BlockBuilder : public ValueObject { | 292 class BlockBuilder : public ValueObject { |
| 300 public: | 293 public: |
| 301 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) | 294 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) |
| 302 : flow_graph_(flow_graph), | 295 : flow_graph_(flow_graph), |
| 303 entry_(entry), | 296 entry_(entry), |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 private: | 370 private: |
| 378 Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind, | 371 Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind, |
| 379 ZoneGrowableArray<Value*>* args) { | 372 ZoneGrowableArray<Value*>* args) { |
| 380 InvokeMathCFunctionInstr* invoke_math_c_function = | 373 InvokeMathCFunctionInstr* invoke_math_c_function = |
| 381 new InvokeMathCFunctionInstr(args, Thread::kNoDeoptId, recognized_kind, | 374 new InvokeMathCFunctionInstr(args, Thread::kNoDeoptId, recognized_kind, |
| 382 TokenPos()); | 375 TokenPos()); |
| 383 AddDefinition(invoke_math_c_function); | 376 AddDefinition(invoke_math_c_function); |
| 384 return invoke_math_c_function; | 377 return invoke_math_c_function; |
| 385 } | 378 } |
| 386 | 379 |
| 387 | |
| 388 FlowGraph* flow_graph_; | 380 FlowGraph* flow_graph_; |
| 389 BlockEntryInstr* entry_; | 381 BlockEntryInstr* entry_; |
| 390 Instruction* current_; | 382 Instruction* current_; |
| 391 Environment* fall_through_env_; | 383 Environment* fall_through_env_; |
| 392 }; | 384 }; |
| 393 | 385 |
| 394 | |
| 395 static void PrepareIndexedOp(BlockBuilder* builder, | 386 static void PrepareIndexedOp(BlockBuilder* builder, |
| 396 Definition* array, | 387 Definition* array, |
| 397 Definition* index, | 388 Definition* index, |
| 398 intptr_t length_offset) { | 389 intptr_t length_offset) { |
| 399 Definition* length = builder->AddDefinition(new LoadFieldInstr( | 390 Definition* length = builder->AddDefinition(new LoadFieldInstr( |
| 400 new Value(array), length_offset, Type::ZoneHandle(Type::SmiType()), | 391 new Value(array), length_offset, Type::ZoneHandle(Type::SmiType()), |
| 401 TokenPosition::kNoSource)); | 392 TokenPosition::kNoSource)); |
| 402 builder->AddInstruction(new CheckArrayBoundInstr( | 393 builder->AddInstruction(new CheckArrayBoundInstr( |
| 403 new Value(length), new Value(index), Thread::kNoDeoptId)); | 394 new Value(length), new Value(index), Thread::kNoDeoptId)); |
| 404 } | 395 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 // Nothing to do. | 465 // Nothing to do. |
| 475 break; | 466 break; |
| 476 default: | 467 default: |
| 477 UNREACHABLE(); | 468 UNREACHABLE(); |
| 478 break; | 469 break; |
| 479 } | 470 } |
| 480 builder.AddIntrinsicReturn(new Value(result)); | 471 builder.AddIntrinsicReturn(new Value(result)); |
| 481 return true; | 472 return true; |
| 482 } | 473 } |
| 483 | 474 |
| 484 | |
| 485 static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph, | 475 static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph, |
| 486 intptr_t array_cid) { | 476 intptr_t array_cid) { |
| 487 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 477 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 488 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 478 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 489 BlockBuilder builder(flow_graph, normal_entry); | 479 BlockBuilder builder(flow_graph, normal_entry); |
| 490 | 480 |
| 491 Definition* value = builder.AddParameter(1); | 481 Definition* value = builder.AddParameter(1); |
| 492 Definition* index = builder.AddParameter(2); | 482 Definition* index = builder.AddParameter(2); |
| 493 Definition* array = builder.AddParameter(3); | 483 Definition* array = builder.AddParameter(3); |
| 494 | 484 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 builder.AddInstruction(new StoreIndexedInstr( | 564 builder.AddInstruction(new StoreIndexedInstr( |
| 575 new Value(array), new Value(index), new Value(value), kNoStoreBarrier, | 565 new Value(array), new Value(index), new Value(value), kNoStoreBarrier, |
| 576 Instance::ElementSizeFor(array_cid), // index scale | 566 Instance::ElementSizeFor(array_cid), // index scale |
| 577 array_cid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); | 567 array_cid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
| 578 // Return null. | 568 // Return null. |
| 579 Definition* null_def = builder.AddNullDefinition(); | 569 Definition* null_def = builder.AddNullDefinition(); |
| 580 builder.AddIntrinsicReturn(new Value(null_def)); | 570 builder.AddIntrinsicReturn(new Value(null_def)); |
| 581 return true; | 571 return true; |
| 582 } | 572 } |
| 583 | 573 |
| 584 | |
| 585 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ | 574 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 586 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 575 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 587 return IntrinsifyArrayGetIndexed( \ | 576 return IntrinsifyArrayGetIndexed( \ |
| 588 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 577 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 589 MethodRecognizer::k##enum_name##GetIndexed)); \ | 578 MethodRecognizer::k##enum_name##GetIndexed)); \ |
| 590 } | 579 } |
| 591 | 580 |
| 592 | |
| 593 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ | 581 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ |
| 594 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 582 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
| 595 return IntrinsifyArraySetIndexed( \ | 583 return IntrinsifyArraySetIndexed( \ |
| 596 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 584 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 597 MethodRecognizer::k##enum_name##SetIndexed)); \ | 585 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 598 } | 586 } |
| 599 | 587 |
| 600 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. | 588 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. |
| 601 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) | 589 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) |
| 602 | 590 |
| 603 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 591 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 604 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ | 592 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 605 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) | 593 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) |
| 606 | 594 |
| 607 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array) | 595 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array) |
| 608 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) | 596 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) |
| 609 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) | 597 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) |
| 610 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray) | 598 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray) |
| 611 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray) | 599 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray) |
| 612 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array) | 600 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array) |
| 613 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array) | 601 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array) |
| 614 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) | 602 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) |
| 615 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) | 603 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) |
| 616 | 604 |
| 617 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS | 605 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS |
| 618 #undef DEFINE_ARRAY_GETTER_INTRINSIC | 606 #undef DEFINE_ARRAY_GETTER_INTRINSIC |
| 619 #undef DEFINE_ARRAY_SETTER_INTRINSIC | 607 #undef DEFINE_ARRAY_SETTER_INTRINSIC |
| 620 | 608 |
| 621 | |
| 622 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ | 609 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 623 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 610 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 624 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ | 611 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
| 625 return false; \ | 612 return false; \ |
| 626 } \ | 613 } \ |
| 627 return IntrinsifyArrayGetIndexed( \ | 614 return IntrinsifyArrayGetIndexed( \ |
| 628 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 615 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 629 MethodRecognizer::k##enum_name##GetIndexed)); \ | 616 MethodRecognizer::k##enum_name##GetIndexed)); \ |
| 630 } | 617 } |
| 631 | 618 |
| 632 | |
| 633 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ | 619 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ |
| 634 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 620 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
| 635 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ | 621 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
| 636 return false; \ | 622 return false; \ |
| 637 } \ | 623 } \ |
| 638 return IntrinsifyArraySetIndexed( \ | 624 return IntrinsifyArraySetIndexed( \ |
| 639 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 625 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 640 MethodRecognizer::k##enum_name##SetIndexed)); \ | 626 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 641 } | 627 } |
| 642 | 628 |
| 643 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 629 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 644 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ | 630 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 645 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) | 631 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) |
| 646 | 632 |
| 647 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) | 633 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) |
| 648 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) | 634 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) |
| 649 | 635 |
| 650 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS | 636 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS |
| 651 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC | 637 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC |
| 652 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC | 638 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC |
| 653 | 639 |
| 654 | |
| 655 #define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ | 640 #define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 656 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 641 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
| 657 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ | 642 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ |
| 658 return false; \ | 643 return false; \ |
| 659 } \ | 644 } \ |
| 660 return IntrinsifyArrayGetIndexed( \ | 645 return IntrinsifyArrayGetIndexed( \ |
| 661 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 646 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 662 MethodRecognizer::k##enum_name##GetIndexed)); \ | 647 MethodRecognizer::k##enum_name##GetIndexed)); \ |
| 663 } | 648 } |
| 664 | 649 |
| 665 | |
| 666 #define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \ | 650 #define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \ |
| 667 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 651 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
| 668 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ | 652 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ |
| 669 return false; \ | 653 return false; \ |
| 670 } \ | 654 } \ |
| 671 return IntrinsifyArraySetIndexed( \ | 655 return IntrinsifyArraySetIndexed( \ |
| 672 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ | 656 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
| 673 MethodRecognizer::k##enum_name##SetIndexed)); \ | 657 MethodRecognizer::k##enum_name##SetIndexed)); \ |
| 674 } | 658 } |
| 675 | 659 |
| 676 #define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 660 #define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
| 677 DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ | 661 DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ |
| 678 DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) | 662 DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) |
| 679 | 663 |
| 680 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array) | 664 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array) |
| 681 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array) | 665 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array) |
| 682 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array) | 666 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array) |
| 683 | 667 |
| 684 #undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS | 668 #undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS |
| 685 #undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC | 669 #undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC |
| 686 #undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC | 670 #undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC |
| 687 | 671 |
| 688 | |
| 689 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { | 672 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { |
| 690 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 673 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 691 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 674 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 692 BlockBuilder builder(flow_graph, normal_entry); | 675 BlockBuilder builder(flow_graph, normal_entry); |
| 693 | 676 |
| 694 Definition* index = builder.AddParameter(1); | 677 Definition* index = builder.AddParameter(1); |
| 695 Definition* str = builder.AddParameter(2); | 678 Definition* str = builder.AddParameter(2); |
| 696 PrepareIndexedOp(&builder, str, index, String::length_offset()); | 679 PrepareIndexedOp(&builder, str, index, String::length_offset()); |
| 697 | 680 |
| 698 // For external strings: Load external data. | 681 // For external strings: Load external data. |
| 699 if (cid == kExternalOneByteStringCid) { | 682 if (cid == kExternalOneByteStringCid) { |
| 700 str = builder.AddDefinition(new LoadUntaggedInstr( | 683 str = builder.AddDefinition(new LoadUntaggedInstr( |
| 701 new Value(str), ExternalOneByteString::external_data_offset())); | 684 new Value(str), ExternalOneByteString::external_data_offset())); |
| 702 str = builder.AddDefinition(new LoadUntaggedInstr( | 685 str = builder.AddDefinition(new LoadUntaggedInstr( |
| 703 new Value(str), RawExternalOneByteString::ExternalData::data_offset())); | 686 new Value(str), RawExternalOneByteString::ExternalData::data_offset())); |
| 704 } else if (cid == kExternalTwoByteStringCid) { | 687 } else if (cid == kExternalTwoByteStringCid) { |
| 705 str = builder.AddDefinition(new LoadUntaggedInstr( | 688 str = builder.AddDefinition(new LoadUntaggedInstr( |
| 706 new Value(str), ExternalTwoByteString::external_data_offset())); | 689 new Value(str), ExternalTwoByteString::external_data_offset())); |
| 707 str = builder.AddDefinition(new LoadUntaggedInstr( | 690 str = builder.AddDefinition(new LoadUntaggedInstr( |
| 708 new Value(str), RawExternalTwoByteString::ExternalData::data_offset())); | 691 new Value(str), RawExternalTwoByteString::ExternalData::data_offset())); |
| 709 } | 692 } |
| 710 | 693 |
| 711 Definition* result = builder.AddDefinition(new LoadIndexedInstr( | 694 Definition* result = builder.AddDefinition(new LoadIndexedInstr( |
| 712 new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid, | 695 new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid, |
| 713 kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); | 696 kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
| 714 builder.AddIntrinsicReturn(new Value(result)); | 697 builder.AddIntrinsicReturn(new Value(result)); |
| 715 return true; | 698 return true; |
| 716 } | 699 } |
| 717 | 700 |
| 718 | |
| 719 bool Intrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) { | 701 bool Intrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) { |
| 720 return BuildCodeUnitAt(flow_graph, kOneByteStringCid); | 702 return BuildCodeUnitAt(flow_graph, kOneByteStringCid); |
| 721 } | 703 } |
| 722 | 704 |
| 723 | |
| 724 bool Intrinsifier::Build_TwoByteStringCodeUnitAt(FlowGraph* flow_graph) { | 705 bool Intrinsifier::Build_TwoByteStringCodeUnitAt(FlowGraph* flow_graph) { |
| 725 return BuildCodeUnitAt(flow_graph, kTwoByteStringCid); | 706 return BuildCodeUnitAt(flow_graph, kTwoByteStringCid); |
| 726 } | 707 } |
| 727 | 708 |
| 728 | |
| 729 bool Intrinsifier::Build_ExternalOneByteStringCodeUnitAt( | 709 bool Intrinsifier::Build_ExternalOneByteStringCodeUnitAt( |
| 730 FlowGraph* flow_graph) { | 710 FlowGraph* flow_graph) { |
| 731 return BuildCodeUnitAt(flow_graph, kExternalOneByteStringCid); | 711 return BuildCodeUnitAt(flow_graph, kExternalOneByteStringCid); |
| 732 } | 712 } |
| 733 | 713 |
| 734 | |
| 735 bool Intrinsifier::Build_ExternalTwoByteStringCodeUnitAt( | 714 bool Intrinsifier::Build_ExternalTwoByteStringCodeUnitAt( |
| 736 FlowGraph* flow_graph) { | 715 FlowGraph* flow_graph) { |
| 737 return BuildCodeUnitAt(flow_graph, kExternalTwoByteStringCid); | 716 return BuildCodeUnitAt(flow_graph, kExternalTwoByteStringCid); |
| 738 } | 717 } |
| 739 | 718 |
| 740 | |
| 741 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { | 719 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { |
| 742 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; | 720 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |
| 743 | 721 |
| 744 Zone* zone = flow_graph->zone(); | 722 Zone* zone = flow_graph->zone(); |
| 745 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 723 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 746 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 724 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 747 BlockBuilder builder(flow_graph, normal_entry); | 725 BlockBuilder builder(flow_graph, normal_entry); |
| 748 | 726 |
| 749 Definition* right = builder.AddParameter(1); | 727 Definition* right = builder.AddParameter(1); |
| 750 Definition* left = builder.AddParameter(2); | 728 Definition* left = builder.AddParameter(2); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 762 /* is_checked = */ true); | 740 /* is_checked = */ true); |
| 763 | 741 |
| 764 Definition* unboxed_result = builder.AddDefinition(new BinaryFloat32x4OpInstr( | 742 Definition* unboxed_result = builder.AddDefinition(new BinaryFloat32x4OpInstr( |
| 765 kind, new Value(left_simd), new Value(right_simd), Thread::kNoDeoptId)); | 743 kind, new Value(left_simd), new Value(right_simd), Thread::kNoDeoptId)); |
| 766 Definition* result = builder.AddDefinition( | 744 Definition* result = builder.AddDefinition( |
| 767 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); | 745 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); |
| 768 builder.AddIntrinsicReturn(new Value(result)); | 746 builder.AddIntrinsicReturn(new Value(result)); |
| 769 return true; | 747 return true; |
| 770 } | 748 } |
| 771 | 749 |
| 772 | |
| 773 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { | 750 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { |
| 774 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); | 751 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); |
| 775 } | 752 } |
| 776 | 753 |
| 777 | |
| 778 bool Intrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) { | 754 bool Intrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) { |
| 779 return BuildBinaryFloat32x4Op(flow_graph, Token::kSUB); | 755 return BuildBinaryFloat32x4Op(flow_graph, Token::kSUB); |
| 780 } | 756 } |
| 781 | 757 |
| 782 | |
| 783 bool Intrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) { | 758 bool Intrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) { |
| 784 return BuildBinaryFloat32x4Op(flow_graph, Token::kADD); | 759 return BuildBinaryFloat32x4Op(flow_graph, Token::kADD); |
| 785 } | 760 } |
| 786 | 761 |
| 787 | |
| 788 static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph, | 762 static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph, |
| 789 MethodRecognizer::Kind kind) { | 763 MethodRecognizer::Kind kind) { |
| 790 if (!FlowGraphCompiler::SupportsUnboxedDoubles() || | 764 if (!FlowGraphCompiler::SupportsUnboxedDoubles() || |
| 791 !FlowGraphCompiler::SupportsUnboxedSimd128()) { | 765 !FlowGraphCompiler::SupportsUnboxedSimd128()) { |
| 792 return false; | 766 return false; |
| 793 } | 767 } |
| 794 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 768 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 795 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 769 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 796 BlockBuilder builder(flow_graph, normal_entry); | 770 BlockBuilder builder(flow_graph, normal_entry); |
| 797 | 771 |
| 798 Definition* receiver = builder.AddParameter(1); | 772 Definition* receiver = builder.AddParameter(1); |
| 799 | 773 |
| 800 Definition* unboxed_receiver = | 774 Definition* unboxed_receiver = |
| 801 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver), | 775 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver), |
| 802 /* is_checked = */ true); | 776 /* is_checked = */ true); |
| 803 | 777 |
| 804 Definition* unboxed_result = builder.AddDefinition(new Simd32x4ShuffleInstr( | 778 Definition* unboxed_result = builder.AddDefinition(new Simd32x4ShuffleInstr( |
| 805 kind, new Value(unboxed_receiver), 0, Thread::kNoDeoptId)); | 779 kind, new Value(unboxed_receiver), 0, Thread::kNoDeoptId)); |
| 806 | 780 |
| 807 Definition* result = builder.AddDefinition( | 781 Definition* result = builder.AddDefinition( |
| 808 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 782 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
| 809 builder.AddIntrinsicReturn(new Value(result)); | 783 builder.AddIntrinsicReturn(new Value(result)); |
| 810 return true; | 784 return true; |
| 811 } | 785 } |
| 812 | 786 |
| 813 | |
| 814 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { | 787 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { |
| 815 return BuildFloat32x4Shuffle(flow_graph, | 788 return BuildFloat32x4Shuffle(flow_graph, |
| 816 MethodRecognizer::kFloat32x4ShuffleX); | 789 MethodRecognizer::kFloat32x4ShuffleX); |
| 817 } | 790 } |
| 818 | 791 |
| 819 | |
| 820 bool Intrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) { | 792 bool Intrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) { |
| 821 return BuildFloat32x4Shuffle(flow_graph, | 793 return BuildFloat32x4Shuffle(flow_graph, |
| 822 MethodRecognizer::kFloat32x4ShuffleY); | 794 MethodRecognizer::kFloat32x4ShuffleY); |
| 823 } | 795 } |
| 824 | 796 |
| 825 | |
| 826 bool Intrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) { | 797 bool Intrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) { |
| 827 return BuildFloat32x4Shuffle(flow_graph, | 798 return BuildFloat32x4Shuffle(flow_graph, |
| 828 MethodRecognizer::kFloat32x4ShuffleZ); | 799 MethodRecognizer::kFloat32x4ShuffleZ); |
| 829 } | 800 } |
| 830 | 801 |
| 831 | |
| 832 bool Intrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) { | 802 bool Intrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) { |
| 833 return BuildFloat32x4Shuffle(flow_graph, | 803 return BuildFloat32x4Shuffle(flow_graph, |
| 834 MethodRecognizer::kFloat32x4ShuffleW); | 804 MethodRecognizer::kFloat32x4ShuffleW); |
| 835 } | 805 } |
| 836 | 806 |
| 837 | |
| 838 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { | 807 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { |
| 839 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 808 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 840 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 809 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 841 BlockBuilder builder(flow_graph, normal_entry); | 810 BlockBuilder builder(flow_graph, normal_entry); |
| 842 | 811 |
| 843 Definition* array = builder.AddParameter(1); | 812 Definition* array = builder.AddParameter(1); |
| 844 | 813 |
| 845 Definition* length = builder.AddDefinition(new LoadFieldInstr( | 814 Definition* length = builder.AddDefinition(new LoadFieldInstr( |
| 846 new Value(array), offset, Type::ZoneHandle(), builder.TokenPos())); | 815 new Value(array), offset, Type::ZoneHandle(), builder.TokenPos())); |
| 847 builder.AddIntrinsicReturn(new Value(length)); | 816 builder.AddIntrinsicReturn(new Value(length)); |
| 848 return true; | 817 return true; |
| 849 } | 818 } |
| 850 | 819 |
| 851 | |
| 852 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) { | 820 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) { |
| 853 return BuildLoadField(flow_graph, Array::length_offset()); | 821 return BuildLoadField(flow_graph, Array::length_offset()); |
| 854 } | 822 } |
| 855 | 823 |
| 856 | |
| 857 bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) { | 824 bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) { |
| 858 return BuildLoadField(flow_graph, Array::length_offset()); | 825 return BuildLoadField(flow_graph, Array::length_offset()); |
| 859 } | 826 } |
| 860 | 827 |
| 861 | |
| 862 bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) { | 828 bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) { |
| 863 return BuildLoadField(flow_graph, GrowableObjectArray::length_offset()); | 829 return BuildLoadField(flow_graph, GrowableObjectArray::length_offset()); |
| 864 } | 830 } |
| 865 | 831 |
| 866 | |
| 867 bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) { | 832 bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) { |
| 868 return BuildLoadField(flow_graph, String::length_offset()); | 833 return BuildLoadField(flow_graph, String::length_offset()); |
| 869 } | 834 } |
| 870 | 835 |
| 871 | |
| 872 bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) { | 836 bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) { |
| 873 return BuildLoadField(flow_graph, TypedData::length_offset()); | 837 return BuildLoadField(flow_graph, TypedData::length_offset()); |
| 874 } | 838 } |
| 875 | 839 |
| 876 | |
| 877 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) { | 840 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) { |
| 878 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 841 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 879 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 842 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 880 BlockBuilder builder(flow_graph, normal_entry); | 843 BlockBuilder builder(flow_graph, normal_entry); |
| 881 | 844 |
| 882 Definition* array = builder.AddParameter(1); | 845 Definition* array = builder.AddParameter(1); |
| 883 | 846 |
| 884 Definition* backing_store = builder.AddDefinition( | 847 Definition* backing_store = builder.AddDefinition( |
| 885 new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(), | 848 new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(), |
| 886 Type::ZoneHandle(), builder.TokenPos())); | 849 Type::ZoneHandle(), builder.TokenPos())); |
| 887 Definition* capacity = builder.AddDefinition( | 850 Definition* capacity = builder.AddDefinition( |
| 888 new LoadFieldInstr(new Value(backing_store), Array::length_offset(), | 851 new LoadFieldInstr(new Value(backing_store), Array::length_offset(), |
| 889 Type::ZoneHandle(), builder.TokenPos())); | 852 Type::ZoneHandle(), builder.TokenPos())); |
| 890 builder.AddIntrinsicReturn(new Value(capacity)); | 853 builder.AddIntrinsicReturn(new Value(capacity)); |
| 891 return true; | 854 return true; |
| 892 } | 855 } |
| 893 | 856 |
| 894 | |
| 895 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { | 857 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { |
| 896 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 858 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 897 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 859 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 898 BlockBuilder builder(flow_graph, normal_entry); | 860 BlockBuilder builder(flow_graph, normal_entry); |
| 899 | 861 |
| 900 Definition* index = builder.AddParameter(1); | 862 Definition* index = builder.AddParameter(1); |
| 901 Definition* growable_array = builder.AddParameter(2); | 863 Definition* growable_array = builder.AddParameter(2); |
| 902 | 864 |
| 903 PrepareIndexedOp(&builder, growable_array, index, | 865 PrepareIndexedOp(&builder, growable_array, index, |
| 904 GrowableObjectArray::length_offset()); | 866 GrowableObjectArray::length_offset()); |
| 905 | 867 |
| 906 Definition* backing_store = builder.AddDefinition(new LoadFieldInstr( | 868 Definition* backing_store = builder.AddDefinition(new LoadFieldInstr( |
| 907 new Value(growable_array), GrowableObjectArray::data_offset(), | 869 new Value(growable_array), GrowableObjectArray::data_offset(), |
| 908 Type::ZoneHandle(), builder.TokenPos())); | 870 Type::ZoneHandle(), builder.TokenPos())); |
| 909 Definition* result = builder.AddDefinition(new LoadIndexedInstr( | 871 Definition* result = builder.AddDefinition(new LoadIndexedInstr( |
| 910 new Value(backing_store), new Value(index), | 872 new Value(backing_store), new Value(index), |
| 911 Instance::ElementSizeFor(kArrayCid), // index scale | 873 Instance::ElementSizeFor(kArrayCid), // index scale |
| 912 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); | 874 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
| 913 builder.AddIntrinsicReturn(new Value(result)); | 875 builder.AddIntrinsicReturn(new Value(result)); |
| 914 return true; | 876 return true; |
| 915 } | 877 } |
| 916 | 878 |
| 917 | |
| 918 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { | 879 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { |
| 919 if (Isolate::Current()->type_checks()) { | 880 if (Isolate::Current()->type_checks()) { |
| 920 return false; | 881 return false; |
| 921 } | 882 } |
| 922 | 883 |
| 923 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 884 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 924 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 885 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 925 BlockBuilder builder(flow_graph, normal_entry); | 886 BlockBuilder builder(flow_graph, normal_entry); |
| 926 | 887 |
| 927 Definition* value = builder.AddParameter(1); | 888 Definition* value = builder.AddParameter(1); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 939 new Value(backing_store), new Value(index), new Value(value), | 900 new Value(backing_store), new Value(index), new Value(value), |
| 940 kEmitStoreBarrier, | 901 kEmitStoreBarrier, |
| 941 Instance::ElementSizeFor(kArrayCid), // index scale | 902 Instance::ElementSizeFor(kArrayCid), // index scale |
| 942 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); | 903 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
| 943 // Return null. | 904 // Return null. |
| 944 Definition* null_def = builder.AddNullDefinition(); | 905 Definition* null_def = builder.AddNullDefinition(); |
| 945 builder.AddIntrinsicReturn(new Value(null_def)); | 906 builder.AddIntrinsicReturn(new Value(null_def)); |
| 946 return true; | 907 return true; |
| 947 } | 908 } |
| 948 | 909 |
| 949 | |
| 950 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { | 910 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { |
| 951 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 911 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 952 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 912 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 953 BlockBuilder builder(flow_graph, normal_entry); | 913 BlockBuilder builder(flow_graph, normal_entry); |
| 954 | 914 |
| 955 Definition* data = builder.AddParameter(1); | 915 Definition* data = builder.AddParameter(1); |
| 956 Definition* growable_array = builder.AddParameter(2); | 916 Definition* growable_array = builder.AddParameter(2); |
| 957 Zone* zone = flow_graph->zone(); | 917 Zone* zone = flow_graph->zone(); |
| 958 | 918 |
| 959 Cids* value_check = Cids::CreateMonomorphic(zone, kArrayCid); | 919 Cids* value_check = Cids::CreateMonomorphic(zone, kArrayCid); |
| 960 builder.AddInstruction(new CheckClassInstr( | 920 builder.AddInstruction(new CheckClassInstr( |
| 961 new Value(data), Thread::kNoDeoptId, *value_check, builder.TokenPos())); | 921 new Value(data), Thread::kNoDeoptId, *value_check, builder.TokenPos())); |
| 962 | 922 |
| 963 builder.AddInstruction(new StoreInstanceFieldInstr( | 923 builder.AddInstruction(new StoreInstanceFieldInstr( |
| 964 GrowableObjectArray::data_offset(), new Value(growable_array), | 924 GrowableObjectArray::data_offset(), new Value(growable_array), |
| 965 new Value(data), kEmitStoreBarrier, builder.TokenPos())); | 925 new Value(data), kEmitStoreBarrier, builder.TokenPos())); |
| 966 // Return null. | 926 // Return null. |
| 967 Definition* null_def = builder.AddNullDefinition(); | 927 Definition* null_def = builder.AddNullDefinition(); |
| 968 builder.AddIntrinsicReturn(new Value(null_def)); | 928 builder.AddIntrinsicReturn(new Value(null_def)); |
| 969 return true; | 929 return true; |
| 970 } | 930 } |
| 971 | 931 |
| 972 | |
| 973 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { | 932 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { |
| 974 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 933 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 975 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 934 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 976 BlockBuilder builder(flow_graph, normal_entry); | 935 BlockBuilder builder(flow_graph, normal_entry); |
| 977 | 936 |
| 978 Definition* length = builder.AddParameter(1); | 937 Definition* length = builder.AddParameter(1); |
| 979 Definition* growable_array = builder.AddParameter(2); | 938 Definition* growable_array = builder.AddParameter(2); |
| 980 | 939 |
| 981 builder.AddInstruction(new CheckSmiInstr( | 940 builder.AddInstruction(new CheckSmiInstr( |
| 982 new Value(length), Thread::kNoDeoptId, builder.TokenPos())); | 941 new Value(length), Thread::kNoDeoptId, builder.TokenPos())); |
| 983 builder.AddInstruction(new StoreInstanceFieldInstr( | 942 builder.AddInstruction(new StoreInstanceFieldInstr( |
| 984 GrowableObjectArray::length_offset(), new Value(growable_array), | 943 GrowableObjectArray::length_offset(), new Value(growable_array), |
| 985 new Value(length), kNoStoreBarrier, builder.TokenPos())); | 944 new Value(length), kNoStoreBarrier, builder.TokenPos())); |
| 986 Definition* null_def = builder.AddNullDefinition(); | 945 Definition* null_def = builder.AddNullDefinition(); |
| 987 builder.AddIntrinsicReturn(new Value(null_def)); | 946 builder.AddIntrinsicReturn(new Value(null_def)); |
| 988 return true; | 947 return true; |
| 989 } | 948 } |
| 990 | 949 |
| 991 | |
| 992 bool Intrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) { | 950 bool Intrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) { |
| 993 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 951 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { |
| 994 return false; | 952 return false; |
| 995 } | 953 } |
| 996 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 954 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 997 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 955 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 998 BlockBuilder builder(flow_graph, normal_entry); | 956 BlockBuilder builder(flow_graph, normal_entry); |
| 999 | 957 |
| 1000 Definition* receiver = builder.AddParameter(1); | 958 Definition* receiver = builder.AddParameter(1); |
| 1001 Definition* unboxed_value = | 959 Definition* unboxed_value = |
| 1002 builder.AddUnboxInstr(kUnboxedDouble, new Value(receiver), | 960 builder.AddUnboxInstr(kUnboxedDouble, new Value(receiver), |
| 1003 /* is_checked = */ true); | 961 /* is_checked = */ true); |
| 1004 Definition* unboxed_result = builder.AddDefinition(new UnaryDoubleOpInstr( | 962 Definition* unboxed_result = builder.AddDefinition(new UnaryDoubleOpInstr( |
| 1005 Token::kNEGATE, new Value(unboxed_value), Thread::kNoDeoptId)); | 963 Token::kNEGATE, new Value(unboxed_value), Thread::kNoDeoptId)); |
| 1006 Definition* result = builder.AddDefinition( | 964 Definition* result = builder.AddDefinition( |
| 1007 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 965 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
| 1008 builder.AddIntrinsicReturn(new Value(result)); | 966 builder.AddIntrinsicReturn(new Value(result)); |
| 1009 return true; | 967 return true; |
| 1010 } | 968 } |
| 1011 | 969 |
| 1012 | |
| 1013 static bool BuildInvokeMathCFunction(BlockBuilder* builder, | 970 static bool BuildInvokeMathCFunction(BlockBuilder* builder, |
| 1014 MethodRecognizer::Kind kind, | 971 MethodRecognizer::Kind kind, |
| 1015 intptr_t num_parameters = 1) { | 972 intptr_t num_parameters = 1) { |
| 1016 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 973 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { |
| 1017 return false; | 974 return false; |
| 1018 } | 975 } |
| 1019 ZoneGrowableArray<Value*>* args = | 976 ZoneGrowableArray<Value*>* args = |
| 1020 new ZoneGrowableArray<Value*>(num_parameters); | 977 new ZoneGrowableArray<Value*>(num_parameters); |
| 1021 | 978 |
| 1022 for (intptr_t i = 0; i < num_parameters; i++) { | 979 for (intptr_t i = 0; i < num_parameters; i++) { |
| 1023 const intptr_t parameter_index = (num_parameters - i); | 980 const intptr_t parameter_index = (num_parameters - i); |
| 1024 Definition* value = builder->AddParameter(parameter_index); | 981 Definition* value = builder->AddParameter(parameter_index); |
| 1025 Definition* unboxed_value = | 982 Definition* unboxed_value = |
| 1026 builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false); | 983 builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false); |
| 1027 args->Add(new Value(unboxed_value)); | 984 args->Add(new Value(unboxed_value)); |
| 1028 } | 985 } |
| 1029 | 986 |
| 1030 Definition* unboxed_result = builder->InvokeMathCFunction(kind, args); | 987 Definition* unboxed_result = builder->InvokeMathCFunction(kind, args); |
| 1031 | 988 |
| 1032 Definition* result = builder->AddDefinition( | 989 Definition* result = builder->AddDefinition( |
| 1033 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 990 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
| 1034 | 991 |
| 1035 builder->AddIntrinsicReturn(new Value(result)); | 992 builder->AddIntrinsicReturn(new Value(result)); |
| 1036 | 993 |
| 1037 return true; | 994 return true; |
| 1038 } | 995 } |
| 1039 | 996 |
| 1040 | |
| 1041 bool Intrinsifier::Build_MathSin(FlowGraph* flow_graph) { | 997 bool Intrinsifier::Build_MathSin(FlowGraph* flow_graph) { |
| 1042 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 998 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1043 | 999 |
| 1044 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1000 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1045 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1001 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1046 BlockBuilder builder(flow_graph, normal_entry); | 1002 BlockBuilder builder(flow_graph, normal_entry); |
| 1047 | 1003 |
| 1048 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathSin); | 1004 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathSin); |
| 1049 } | 1005 } |
| 1050 | 1006 |
| 1051 | |
| 1052 bool Intrinsifier::Build_MathCos(FlowGraph* flow_graph) { | 1007 bool Intrinsifier::Build_MathCos(FlowGraph* flow_graph) { |
| 1053 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1008 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1054 | 1009 |
| 1055 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1010 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1056 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1011 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1057 BlockBuilder builder(flow_graph, normal_entry); | 1012 BlockBuilder builder(flow_graph, normal_entry); |
| 1058 | 1013 |
| 1059 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathCos); | 1014 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathCos); |
| 1060 } | 1015 } |
| 1061 | 1016 |
| 1062 | |
| 1063 bool Intrinsifier::Build_MathTan(FlowGraph* flow_graph) { | 1017 bool Intrinsifier::Build_MathTan(FlowGraph* flow_graph) { |
| 1064 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1018 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1065 | 1019 |
| 1066 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1020 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1067 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1021 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1068 BlockBuilder builder(flow_graph, normal_entry); | 1022 BlockBuilder builder(flow_graph, normal_entry); |
| 1069 | 1023 |
| 1070 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathTan); | 1024 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathTan); |
| 1071 } | 1025 } |
| 1072 | 1026 |
| 1073 | |
| 1074 bool Intrinsifier::Build_MathAsin(FlowGraph* flow_graph) { | 1027 bool Intrinsifier::Build_MathAsin(FlowGraph* flow_graph) { |
| 1075 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1028 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1076 | 1029 |
| 1077 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1030 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1078 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1031 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1079 BlockBuilder builder(flow_graph, normal_entry); | 1032 BlockBuilder builder(flow_graph, normal_entry); |
| 1080 | 1033 |
| 1081 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAsin); | 1034 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAsin); |
| 1082 } | 1035 } |
| 1083 | 1036 |
| 1084 | |
| 1085 bool Intrinsifier::Build_MathAcos(FlowGraph* flow_graph) { | 1037 bool Intrinsifier::Build_MathAcos(FlowGraph* flow_graph) { |
| 1086 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1038 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1087 | 1039 |
| 1088 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1040 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1089 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1041 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1090 BlockBuilder builder(flow_graph, normal_entry); | 1042 BlockBuilder builder(flow_graph, normal_entry); |
| 1091 | 1043 |
| 1092 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAcos); | 1044 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAcos); |
| 1093 } | 1045 } |
| 1094 | 1046 |
| 1095 | |
| 1096 bool Intrinsifier::Build_MathAtan(FlowGraph* flow_graph) { | 1047 bool Intrinsifier::Build_MathAtan(FlowGraph* flow_graph) { |
| 1097 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1048 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1098 | 1049 |
| 1099 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1050 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1100 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1051 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1101 BlockBuilder builder(flow_graph, normal_entry); | 1052 BlockBuilder builder(flow_graph, normal_entry); |
| 1102 | 1053 |
| 1103 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan); | 1054 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan); |
| 1104 } | 1055 } |
| 1105 | 1056 |
| 1106 | |
| 1107 bool Intrinsifier::Build_MathAtan2(FlowGraph* flow_graph) { | 1057 bool Intrinsifier::Build_MathAtan2(FlowGraph* flow_graph) { |
| 1108 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1058 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1109 | 1059 |
| 1110 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1060 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1111 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1061 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1112 BlockBuilder builder(flow_graph, normal_entry); | 1062 BlockBuilder builder(flow_graph, normal_entry); |
| 1113 | 1063 |
| 1114 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan2, | 1064 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan2, |
| 1115 /* num_parameters = */ 2); | 1065 /* num_parameters = */ 2); |
| 1116 } | 1066 } |
| 1117 | 1067 |
| 1118 | |
| 1119 bool Intrinsifier::Build_DoubleMod(FlowGraph* flow_graph) { | 1068 bool Intrinsifier::Build_DoubleMod(FlowGraph* flow_graph) { |
| 1120 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1069 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1121 | 1070 |
| 1122 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1071 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1123 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1072 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1124 BlockBuilder builder(flow_graph, normal_entry); | 1073 BlockBuilder builder(flow_graph, normal_entry); |
| 1125 | 1074 |
| 1126 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleMod, | 1075 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleMod, |
| 1127 /* num_parameters = */ 2); | 1076 /* num_parameters = */ 2); |
| 1128 } | 1077 } |
| 1129 | 1078 |
| 1130 | |
| 1131 bool Intrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) { | 1079 bool Intrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) { |
| 1132 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1080 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1133 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1081 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
| 1134 // way. | 1082 // way. |
| 1135 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1083 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
| 1136 | 1084 |
| 1137 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1085 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1138 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1086 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1139 BlockBuilder builder(flow_graph, normal_entry); | 1087 BlockBuilder builder(flow_graph, normal_entry); |
| 1140 | 1088 |
| 1141 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleCeil); | 1089 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleCeil); |
| 1142 } | 1090 } |
| 1143 | 1091 |
| 1144 | |
| 1145 bool Intrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) { | 1092 bool Intrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) { |
| 1146 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1093 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1147 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1094 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
| 1148 // way. | 1095 // way. |
| 1149 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1096 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
| 1150 | 1097 |
| 1151 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1098 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1152 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1099 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1153 BlockBuilder builder(flow_graph, normal_entry); | 1100 BlockBuilder builder(flow_graph, normal_entry); |
| 1154 | 1101 |
| 1155 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleFloor); | 1102 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleFloor); |
| 1156 } | 1103 } |
| 1157 | 1104 |
| 1158 | |
| 1159 bool Intrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) { | 1105 bool Intrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) { |
| 1160 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1106 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1161 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1107 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
| 1162 // way. | 1108 // way. |
| 1163 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1109 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
| 1164 | 1110 |
| 1165 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1111 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1166 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1112 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1167 BlockBuilder builder(flow_graph, normal_entry); | 1113 BlockBuilder builder(flow_graph, normal_entry); |
| 1168 | 1114 |
| 1169 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleTruncate); | 1115 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleTruncate); |
| 1170 } | 1116 } |
| 1171 | 1117 |
| 1172 | |
| 1173 bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) { | 1118 bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) { |
| 1174 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1119 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 1175 | 1120 |
| 1176 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1121 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 1177 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1122 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 1178 BlockBuilder builder(flow_graph, normal_entry); | 1123 BlockBuilder builder(flow_graph, normal_entry); |
| 1179 | 1124 |
| 1180 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound); | 1125 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound); |
| 1181 } | 1126 } |
| 1182 | 1127 |
| 1183 | |
| 1184 void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) { | 1128 void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) { |
| 1185 IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/false); | 1129 IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/false); |
| 1186 } | 1130 } |
| 1187 | 1131 |
| 1188 | |
| 1189 void Intrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler) { | 1132 void Intrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler) { |
| 1190 IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/true); | 1133 IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/true); |
| 1191 } | 1134 } |
| 1192 #endif // !defined(TARGET_ARCH_DBC) | 1135 #endif // !defined(TARGET_ARCH_DBC) |
| 1193 | 1136 |
| 1194 | |
| 1195 } // namespace dart | 1137 } // namespace dart |
| OLD | NEW |