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 |