OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // Class for intrinsifying functions. | 4 // Class for intrinsifying functions. |
5 | 5 |
6 #include "vm/assembler.h" | 6 #include "vm/assembler.h" |
7 #include "vm/compiler.h" | 7 #include "vm/compiler.h" |
8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 } else { \ | 75 } else { \ |
76 str = String::New(#class_name); \ | 76 str = String::New(#class_name); \ |
77 cls = lib.LookupClassAllowPrivate(str); \ | 77 cls = lib.LookupClassAllowPrivate(str); \ |
78 ASSERT(!cls.IsNull()); \ | 78 ASSERT(!cls.IsNull()); \ |
79 error = cls.EnsureIsFinalized(thread); \ | 79 error = cls.EnsureIsFinalized(thread); \ |
80 if (!error.IsNull()) { \ | 80 if (!error.IsNull()) { \ |
81 OS::PrintErr("%s\n", error.ToErrorCString()); \ | 81 OS::PrintErr("%s\n", error.ToErrorCString()); \ |
82 } \ | 82 } \ |
83 ASSERT(error.IsNull()); \ | 83 ASSERT(error.IsNull()); \ |
84 if (#function_name[0] == '.') { \ | 84 if (#function_name[0] == '.') { \ |
85 str = String::New(#class_name#function_name); \ | 85 str = String::New(#class_name #function_name); \ |
86 } else { \ | 86 } else { \ |
87 str = String::New(#function_name); \ | 87 str = String::New(#function_name); \ |
88 } \ | 88 } \ |
89 func = cls.LookupFunctionAllowPrivate(str); \ | 89 func = cls.LookupFunctionAllowPrivate(str); \ |
90 } \ | 90 } \ |
91 ASSERT(!func.IsNull()); \ | 91 ASSERT(!func.IsNull()); \ |
92 func.set_is_intrinsic(true); | 92 func.set_is_intrinsic(true); |
93 | 93 |
94 // Set up all core lib functions that can be intrinsified. | 94 // Set up all core lib functions that can be intrinsified. |
95 lib = Library::CoreLibrary(); | 95 lib = Library::CoreLibrary(); |
(...skipping 19 matching lines...) Expand all Loading... |
115 ASSERT(!lib.IsNull()); | 115 ASSERT(!lib.IsNull()); |
116 DEVELOPER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); | 116 DEVELOPER_LIB_INTRINSIC_LIST(SETUP_FUNCTION); |
117 | 117 |
118 #undef SETUP_FUNCTION | 118 #undef SETUP_FUNCTION |
119 } | 119 } |
120 #endif // defined(DART_NO_SNAPSHOT). | 120 #endif // defined(DART_NO_SNAPSHOT). |
121 | 121 |
122 | 122 |
123 // DBC does not use graph intrinsics. | 123 // DBC does not use graph intrinsics. |
124 #if !defined(TARGET_ARCH_DBC) | 124 #if !defined(TARGET_ARCH_DBC) |
125 static void EmitCodeFor(FlowGraphCompiler* compiler, | 125 static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) { |
126 FlowGraph* graph) { | |
127 // The FlowGraph here is constructed by the intrinsics builder methods, and | 126 // The FlowGraph here is constructed by the intrinsics builder methods, and |
128 // is different from compiler->flow_graph(), the original method's flow graph. | 127 // is different from compiler->flow_graph(), the original method's flow graph. |
129 compiler->assembler()->Comment("Graph intrinsic begin"); | 128 compiler->assembler()->Comment("Graph intrinsic begin"); |
130 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) { | 129 for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) { |
131 BlockEntryInstr* block = graph->reverse_postorder()[i]; | 130 BlockEntryInstr* block = graph->reverse_postorder()[i]; |
132 if (block->IsGraphEntry()) continue; // No code for graph entry needed. | 131 if (block->IsGraphEntry()) continue; // No code for graph entry needed. |
133 | 132 |
134 if (block->HasParallelMove()) { | 133 if (block->HasParallelMove()) { |
135 compiler->parallel_move_resolver()->EmitNativeCode( | 134 compiler->parallel_move_resolver()->EmitNativeCode( |
136 block->parallel_move()); | 135 block->parallel_move()); |
(...skipping 21 matching lines...) Expand all Loading... |
158 compiler->assembler()->Comment("Graph intrinsic end"); | 157 compiler->assembler()->Comment("Graph intrinsic end"); |
159 } | 158 } |
160 #endif | 159 #endif |
161 | 160 |
162 | 161 |
163 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, | 162 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, |
164 FlowGraphCompiler* compiler) { | 163 FlowGraphCompiler* compiler) { |
165 #if !defined(TARGET_ARCH_DBC) | 164 #if !defined(TARGET_ARCH_DBC) |
166 ZoneGrowableArray<const ICData*>* ic_data_array = | 165 ZoneGrowableArray<const ICData*>* ic_data_array = |
167 new ZoneGrowableArray<const ICData*>(); | 166 new ZoneGrowableArray<const ICData*>(); |
168 FlowGraphBuilder builder(parsed_function, | 167 FlowGraphBuilder builder(parsed_function, *ic_data_array, |
169 *ic_data_array, | |
170 NULL, // NULL = not inlining. | 168 NULL, // NULL = not inlining. |
171 Compiler::kNoOSRDeoptId); | 169 Compiler::kNoOSRDeoptId); |
172 | 170 |
173 intptr_t block_id = builder.AllocateBlockId(); | 171 intptr_t block_id = builder.AllocateBlockId(); |
174 TargetEntryInstr* normal_entry = | 172 TargetEntryInstr* normal_entry = |
175 new TargetEntryInstr(block_id, | 173 new TargetEntryInstr(block_id, CatchClauseNode::kInvalidTryIndex); |
176 CatchClauseNode::kInvalidTryIndex); | |
177 GraphEntryInstr* graph_entry = new GraphEntryInstr( | 174 GraphEntryInstr* graph_entry = new GraphEntryInstr( |
178 parsed_function, normal_entry, Compiler::kNoOSRDeoptId); | 175 parsed_function, normal_entry, Compiler::kNoOSRDeoptId); |
179 FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); | 176 FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); |
180 const Function& function = parsed_function.function(); | 177 const Function& function = parsed_function.function(); |
181 switch (function.recognized_kind()) { | 178 switch (function.recognized_kind()) { |
182 #define EMIT_CASE(class_name, function_name, enum_name, type, fp) \ | 179 #define EMIT_CASE(class_name, function_name, enum_name, type, fp) \ |
183 case MethodRecognizer::k##enum_name: \ | 180 case MethodRecognizer::k##enum_name: \ |
184 if (!Build_##enum_name(graph)) return false; \ | 181 if (!Build_##enum_name(graph)) return false; \ |
185 break; | 182 break; |
186 | 183 |
187 GRAPH_INTRINSICS_LIST(EMIT_CASE); | 184 GRAPH_INTRINSICS_LIST(EMIT_CASE); |
188 default: | 185 default: |
189 return false; | 186 return false; |
190 #undef EMIT_CASE | 187 #undef EMIT_CASE |
191 } | 188 } |
192 | 189 |
193 if (FLAG_support_il_printer && | 190 if (FLAG_support_il_printer && FLAG_print_flow_graph && |
194 FLAG_print_flow_graph && FlowGraphPrinter::ShouldPrint(function)) { | 191 FlowGraphPrinter::ShouldPrint(function)) { |
195 THR_Print("Intrinsic graph before\n"); | 192 THR_Print("Intrinsic graph before\n"); |
196 FlowGraphPrinter printer(*graph); | 193 FlowGraphPrinter printer(*graph); |
197 printer.PrintBlocks(); | 194 printer.PrintBlocks(); |
198 } | 195 } |
199 | 196 |
200 // Perform register allocation on the SSA graph. | 197 // Perform register allocation on the SSA graph. |
201 FlowGraphAllocator allocator(*graph, true); // Intrinsic mode. | 198 FlowGraphAllocator allocator(*graph, true); // Intrinsic mode. |
202 allocator.AllocateRegisters(); | 199 allocator.AllocateRegisters(); |
203 | 200 |
204 if (FLAG_support_il_printer && | 201 if (FLAG_support_il_printer && FLAG_print_flow_graph && |
205 FLAG_print_flow_graph && FlowGraphPrinter::ShouldPrint(function)) { | 202 FlowGraphPrinter::ShouldPrint(function)) { |
206 THR_Print("Intrinsic graph after\n"); | 203 THR_Print("Intrinsic graph after\n"); |
207 FlowGraphPrinter printer(*graph); | 204 FlowGraphPrinter printer(*graph); |
208 printer.PrintBlocks(); | 205 printer.PrintBlocks(); |
209 } | 206 } |
210 EmitCodeFor(compiler, graph); | 207 EmitCodeFor(compiler, graph); |
211 return true; | 208 return true; |
212 #else | 209 #else |
213 return false; | 210 return false; |
214 #endif // !defined(TARGET_ARCH_DBC) | 211 #endif // !defined(TARGET_ARCH_DBC) |
215 } | 212 } |
216 | 213 |
217 | 214 |
218 // Returns true if fall-through code can be omitted. | 215 // Returns true if fall-through code can be omitted. |
219 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, | 216 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function, |
220 FlowGraphCompiler* compiler) { | 217 FlowGraphCompiler* compiler) { |
221 const Function& function = parsed_function.function(); | 218 const Function& function = parsed_function.function(); |
222 if (!CanIntrinsify(function)) { | 219 if (!CanIntrinsify(function)) { |
223 return false; | 220 return false; |
224 } | 221 } |
225 | 222 |
226 ASSERT(!compiler->flow_graph().IsCompiledForOsr()); | 223 ASSERT(!compiler->flow_graph().IsCompiledForOsr()); |
227 if (GraphIntrinsify(parsed_function, compiler)) { | 224 if (GraphIntrinsify(parsed_function, compiler)) { |
228 return compiler->intrinsic_slow_path_label()->IsUnused(); | 225 return compiler->intrinsic_slow_path_label()->IsUnused(); |
229 } | 226 } |
230 | 227 |
231 #define EMIT_CASE(class_name, function_name, enum_name, type, fp) \ | 228 #define EMIT_CASE(class_name, function_name, enum_name, type, fp) \ |
232 case MethodRecognizer::k##enum_name: \ | 229 case MethodRecognizer::k##enum_name: \ |
233 compiler->assembler()->Comment("Intrinsic"); \ | 230 compiler->assembler()->Comment("Intrinsic"); \ |
234 enum_name(compiler->assembler()); \ | 231 enum_name(compiler->assembler()); \ |
235 break; | 232 break; |
236 | 233 |
237 switch (function.recognized_kind()) { | 234 switch (function.recognized_kind()) { |
238 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE); | 235 ALL_INTRINSICS_NO_INTEGER_LIB_LIST(EMIT_CASE); |
239 default: | 236 default: |
240 break; | 237 break; |
241 } | 238 } |
242 switch (function.recognized_kind()) { | 239 switch (function.recognized_kind()) { |
243 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE) | 240 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE) |
244 default: | 241 default: |
245 break; | 242 break; |
246 } | 243 } |
247 | 244 |
248 // On DBC all graph intrinsics are handled in the same way as non-graph | 245 // On DBC all graph intrinsics are handled in the same way as non-graph |
249 // intrinsics. | 246 // intrinsics. |
250 #if defined(TARGET_ARCH_DBC) | 247 #if defined(TARGET_ARCH_DBC) |
251 switch (function.recognized_kind()) { | 248 switch (function.recognized_kind()) { |
252 GRAPH_INTRINSICS_LIST(EMIT_CASE) | 249 GRAPH_INTRINSICS_LIST(EMIT_CASE) |
253 default: | 250 default: |
254 break; | 251 break; |
255 } | 252 } |
256 #endif | 253 #endif |
257 | 254 |
258 #undef EMIT_INTRINSIC | 255 #undef EMIT_INTRINSIC |
259 return false; | 256 return false; |
(...skipping 21 matching lines...) Expand all Loading... |
281 | 278 |
282 | 279 |
283 // Notes about the graph intrinsics: | 280 // Notes about the graph intrinsics: |
284 // | 281 // |
285 // IR instructions which would jump to a deoptimization sequence on failure | 282 // IR instructions which would jump to a deoptimization sequence on failure |
286 // instead branch to the intrinsic slow path. | 283 // instead branch to the intrinsic slow path. |
287 // | 284 // |
288 class BlockBuilder : public ValueObject { | 285 class BlockBuilder : public ValueObject { |
289 public: | 286 public: |
290 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) | 287 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) |
291 : flow_graph_(flow_graph), entry_(entry), current_(entry) { } | 288 : flow_graph_(flow_graph), entry_(entry), current_(entry) {} |
292 | 289 |
293 Definition* AddToInitialDefinitions(Definition* def) { | 290 Definition* AddToInitialDefinitions(Definition* def) { |
294 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | 291 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
295 flow_graph_->AddToInitialDefinitions(def); | 292 flow_graph_->AddToInitialDefinitions(def); |
296 return def; | 293 return def; |
297 } | 294 } |
298 | 295 |
299 Definition* AddDefinition(Definition* def) { | 296 Definition* AddDefinition(Definition* def) { |
300 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | 297 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
301 current_ = current_->AppendInstruction(def); | 298 current_ = current_->AppendInstruction(def); |
302 return def; | 299 return def; |
303 } | 300 } |
304 | 301 |
305 Instruction* AddInstruction(Instruction* instr) { | 302 Instruction* AddInstruction(Instruction* instr) { |
306 current_ = current_->AppendInstruction(instr); | 303 current_ = current_->AppendInstruction(instr); |
307 return instr; | 304 return instr; |
308 } | 305 } |
309 | 306 |
310 void AddIntrinsicReturn(Value* value) { | 307 void AddIntrinsicReturn(Value* value) { |
311 ReturnInstr* instr = new ReturnInstr(TokenPos(), value); | 308 ReturnInstr* instr = new ReturnInstr(TokenPos(), value); |
312 AddInstruction(instr); | 309 AddInstruction(instr); |
313 entry_->set_last_instruction(instr); | 310 entry_->set_last_instruction(instr); |
314 } | 311 } |
315 | 312 |
316 Definition* AddParameter(intptr_t index) { | 313 Definition* AddParameter(intptr_t index) { |
317 intptr_t adjustment = Intrinsifier::ParameterSlotFromSp(); | 314 intptr_t adjustment = Intrinsifier::ParameterSlotFromSp(); |
318 return AddToInitialDefinitions( | 315 return AddToInitialDefinitions(new ParameterInstr( |
319 new ParameterInstr(adjustment + index, | 316 adjustment + index, flow_graph_->graph_entry(), SPREG)); |
320 flow_graph_->graph_entry(), | |
321 SPREG)); | |
322 } | 317 } |
323 | 318 |
324 TokenPosition TokenPos() { | 319 TokenPosition TokenPos() { return flow_graph_->function().token_pos(); } |
325 return flow_graph_->function().token_pos(); | 320 |
| 321 Definition* AddNullDefinition() { |
| 322 return AddDefinition(new ConstantInstr(Object::ZoneHandle(Object::null()))); |
326 } | 323 } |
327 | 324 |
328 Definition* AddNullDefinition() { | 325 Definition* AddUnboxInstr(Representation rep, Value* value, bool is_checked) { |
329 return AddDefinition( | 326 Definition* unboxed_value = |
330 new ConstantInstr(Object::ZoneHandle(Object::null()))); | 327 AddDefinition(UnboxInstr::Create(rep, value, Thread::kNoDeoptId)); |
331 } | |
332 | |
333 Definition* AddUnboxInstr(Representation rep, | |
334 Value* value, | |
335 bool is_checked) { | |
336 Definition* unboxed_value = AddDefinition( | |
337 UnboxInstr::Create(rep, value, Thread::kNoDeoptId)); | |
338 if (is_checked) { | 328 if (is_checked) { |
339 // The type of |value| has already been checked and it is safe to | 329 // The type of |value| has already been checked and it is safe to |
340 // adjust reaching type. This is done manually because there is no type | 330 // adjust reaching type. This is done manually because there is no type |
341 // propagation when building intrinsics. | 331 // propagation when building intrinsics. |
342 unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( | 332 unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( |
343 CompileType::FromCid(CidForRepresentation(rep)))); | 333 CompileType::FromCid(CidForRepresentation(rep)))); |
344 } | 334 } |
345 return unboxed_value; | 335 return unboxed_value; |
346 } | 336 } |
347 | 337 |
348 Definition* AddUnboxInstr(Representation rep, | 338 Definition* AddUnboxInstr(Representation rep, |
349 Definition* boxed, | 339 Definition* boxed, |
350 bool is_checked) { | 340 bool is_checked) { |
351 return AddUnboxInstr(rep, new Value(boxed), is_checked); | 341 return AddUnboxInstr(rep, new Value(boxed), is_checked); |
352 } | 342 } |
353 | 343 |
354 Definition* InvokeMathCFunction(MethodRecognizer::Kind recognized_kind, | 344 Definition* InvokeMathCFunction(MethodRecognizer::Kind recognized_kind, |
355 ZoneGrowableArray<Value*>* args) { | 345 ZoneGrowableArray<Value*>* args) { |
356 return InvokeMathCFunctionHelper(recognized_kind, args); | 346 return InvokeMathCFunctionHelper(recognized_kind, args); |
357 } | 347 } |
358 | 348 |
359 private: | 349 private: |
360 Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind, | 350 Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind, |
361 ZoneGrowableArray<Value*>* args) { | 351 ZoneGrowableArray<Value*>* args) { |
362 InvokeMathCFunctionInstr* invoke_math_c_function = | 352 InvokeMathCFunctionInstr* invoke_math_c_function = |
363 new InvokeMathCFunctionInstr(args, | 353 new InvokeMathCFunctionInstr(args, Thread::kNoDeoptId, recognized_kind, |
364 Thread::kNoDeoptId, | |
365 recognized_kind, | |
366 TokenPos()); | 354 TokenPos()); |
367 AddDefinition(invoke_math_c_function); | 355 AddDefinition(invoke_math_c_function); |
368 return invoke_math_c_function; | 356 return invoke_math_c_function; |
369 } | 357 } |
370 | 358 |
371 | 359 |
372 FlowGraph* flow_graph_; | 360 FlowGraph* flow_graph_; |
373 BlockEntryInstr* entry_; | 361 BlockEntryInstr* entry_; |
374 Instruction* current_; | 362 Instruction* current_; |
375 }; | 363 }; |
376 | 364 |
377 | 365 |
378 static void PrepareIndexedOp(BlockBuilder* builder, | 366 static void PrepareIndexedOp(BlockBuilder* builder, |
379 Definition* array, | 367 Definition* array, |
380 Definition* index, | 368 Definition* index, |
381 intptr_t length_offset) { | 369 intptr_t length_offset) { |
382 Definition* length = builder->AddDefinition( | 370 Definition* length = builder->AddDefinition(new LoadFieldInstr( |
383 new LoadFieldInstr(new Value(array), | 371 new Value(array), length_offset, Type::ZoneHandle(Type::SmiType()), |
384 length_offset, | 372 TokenPosition::kNoSource)); |
385 Type::ZoneHandle(Type::SmiType()), | 373 builder->AddInstruction(new CheckArrayBoundInstr( |
386 TokenPosition::kNoSource)); | 374 new Value(length), new Value(index), Thread::kNoDeoptId)); |
387 builder->AddInstruction( | |
388 new CheckArrayBoundInstr(new Value(length), | |
389 new Value(index), | |
390 Thread::kNoDeoptId)); | |
391 } | 375 } |
392 | 376 |
393 static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph, | 377 static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph, |
394 intptr_t array_cid) { | 378 intptr_t array_cid) { |
395 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 379 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
396 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 380 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
397 BlockBuilder builder(flow_graph, normal_entry); | 381 BlockBuilder builder(flow_graph, normal_entry); |
398 | 382 |
399 Definition* index = builder.AddParameter(1); | 383 Definition* index = builder.AddParameter(1); |
400 Definition* array = builder.AddParameter(2); | 384 Definition* array = builder.AddParameter(2); |
401 | 385 |
402 intptr_t length_offset = Array::length_offset(); | 386 intptr_t length_offset = Array::length_offset(); |
403 if (RawObject::IsTypedDataClassId(array_cid)) { | 387 if (RawObject::IsTypedDataClassId(array_cid)) { |
404 length_offset = TypedData::length_offset(); | 388 length_offset = TypedData::length_offset(); |
405 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 389 } else if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
406 length_offset = ExternalTypedData::length_offset(); | 390 length_offset = ExternalTypedData::length_offset(); |
407 } | 391 } |
408 | 392 |
409 PrepareIndexedOp(&builder, array, index, length_offset); | 393 PrepareIndexedOp(&builder, array, index, length_offset); |
410 | 394 |
411 if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 395 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
412 array = builder.AddDefinition( | 396 array = builder.AddDefinition(new LoadUntaggedInstr( |
413 new LoadUntaggedInstr(new Value(array), | 397 new Value(array), ExternalTypedData::data_offset())); |
414 ExternalTypedData::data_offset())); | |
415 } | 398 } |
416 | 399 |
417 Definition* result = builder.AddDefinition( | 400 Definition* result = builder.AddDefinition(new LoadIndexedInstr( |
418 new LoadIndexedInstr(new Value(array), | 401 new Value(array), new Value(index), |
419 new Value(index), | 402 Instance::ElementSizeFor(array_cid), // index scale |
420 Instance::ElementSizeFor(array_cid), // index scale | 403 array_cid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
421 array_cid, | |
422 kAlignedAccess, | |
423 Thread::kNoDeoptId, | |
424 builder.TokenPos())); | |
425 // Box and/or convert result if necessary. | 404 // Box and/or convert result if necessary. |
426 switch (array_cid) { | 405 switch (array_cid) { |
427 case kTypedDataInt32ArrayCid: | 406 case kTypedDataInt32ArrayCid: |
428 case kExternalTypedDataInt32ArrayCid: | 407 case kExternalTypedDataInt32ArrayCid: |
429 result = builder.AddDefinition( | 408 result = builder.AddDefinition( |
430 BoxInstr::Create(kUnboxedInt32, new Value(result))); | 409 BoxInstr::Create(kUnboxedInt32, new Value(result))); |
431 break; | 410 break; |
432 case kTypedDataUint32ArrayCid: | 411 case kTypedDataUint32ArrayCid: |
433 case kExternalTypedDataUint32ArrayCid: | 412 case kExternalTypedDataUint32ArrayCid: |
434 result = builder.AddDefinition( | 413 result = builder.AddDefinition( |
435 BoxInstr::Create(kUnboxedUint32, new Value(result))); | 414 BoxInstr::Create(kUnboxedUint32, new Value(result))); |
436 break; | 415 break; |
437 case kTypedDataFloat32ArrayCid: | 416 case kTypedDataFloat32ArrayCid: |
438 result = builder.AddDefinition( | 417 result = builder.AddDefinition( |
439 new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId)); | 418 new FloatToDoubleInstr(new Value(result), Thread::kNoDeoptId)); |
440 // Fall through. | 419 // Fall through. |
441 case kTypedDataFloat64ArrayCid: | 420 case kTypedDataFloat64ArrayCid: |
442 result = builder.AddDefinition( | 421 result = builder.AddDefinition( |
443 BoxInstr::Create(kUnboxedDouble, new Value(result))); | 422 BoxInstr::Create(kUnboxedDouble, new Value(result))); |
444 break; | 423 break; |
445 case kTypedDataFloat32x4ArrayCid: | 424 case kTypedDataFloat32x4ArrayCid: |
446 result = builder.AddDefinition( | 425 result = builder.AddDefinition( |
447 BoxInstr::Create(kUnboxedFloat32x4, new Value(result))); | 426 BoxInstr::Create(kUnboxedFloat32x4, new Value(result))); |
448 break; | 427 break; |
449 case kTypedDataInt32x4ArrayCid: | 428 case kTypedDataInt32x4ArrayCid: |
450 result = builder.AddDefinition( | 429 result = builder.AddDefinition( |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 | 474 |
496 // Value check/conversion. | 475 // Value check/conversion. |
497 switch (array_cid) { | 476 switch (array_cid) { |
498 case kTypedDataInt8ArrayCid: | 477 case kTypedDataInt8ArrayCid: |
499 case kTypedDataUint8ArrayCid: | 478 case kTypedDataUint8ArrayCid: |
500 case kExternalTypedDataUint8ArrayCid: | 479 case kExternalTypedDataUint8ArrayCid: |
501 case kTypedDataUint8ClampedArrayCid: | 480 case kTypedDataUint8ClampedArrayCid: |
502 case kExternalTypedDataUint8ClampedArrayCid: | 481 case kExternalTypedDataUint8ClampedArrayCid: |
503 case kTypedDataInt16ArrayCid: | 482 case kTypedDataInt16ArrayCid: |
504 case kTypedDataUint16ArrayCid: | 483 case kTypedDataUint16ArrayCid: |
505 builder.AddInstruction(new CheckSmiInstr(new Value(value), | 484 builder.AddInstruction(new CheckSmiInstr( |
506 Thread::kNoDeoptId, | 485 new Value(value), Thread::kNoDeoptId, builder.TokenPos())); |
507 builder.TokenPos())); | |
508 break; | 486 break; |
509 case kTypedDataInt32ArrayCid: | 487 case kTypedDataInt32ArrayCid: |
510 case kExternalTypedDataInt32ArrayCid: | 488 case kExternalTypedDataInt32ArrayCid: |
511 // Use same truncating unbox-instruction for int32 and uint32. | 489 // Use same truncating unbox-instruction for int32 and uint32. |
512 // Fall-through. | 490 // Fall-through. |
513 case kTypedDataUint32ArrayCid: | 491 case kTypedDataUint32ArrayCid: |
514 case kExternalTypedDataUint32ArrayCid: | 492 case kExternalTypedDataUint32ArrayCid: |
515 // Supports smi and mint, slow-case for bigints. | 493 // Supports smi and mint, slow-case for bigints. |
516 value = builder.AddUnboxInstr(kUnboxedUint32, | 494 value = builder.AddUnboxInstr(kUnboxedUint32, new Value(value), |
517 new Value(value), | |
518 /* is_checked = */ false); | 495 /* is_checked = */ false); |
519 break; | 496 break; |
520 case kTypedDataFloat32ArrayCid: | 497 case kTypedDataFloat32ArrayCid: |
521 case kTypedDataFloat64ArrayCid: | 498 case kTypedDataFloat64ArrayCid: |
522 case kTypedDataFloat32x4ArrayCid: | 499 case kTypedDataFloat32x4ArrayCid: |
523 case kTypedDataInt32x4ArrayCid: | 500 case kTypedDataInt32x4ArrayCid: |
524 case kTypedDataFloat64x2ArrayCid: { | 501 case kTypedDataFloat64x2ArrayCid: { |
525 intptr_t value_check_cid = kDoubleCid; | 502 intptr_t value_check_cid = kDoubleCid; |
526 Representation rep = kUnboxedDouble; | 503 Representation rep = kUnboxedDouble; |
527 switch (array_cid) { | 504 switch (array_cid) { |
528 case kTypedDataFloat32x4ArrayCid: | 505 case kTypedDataFloat32x4ArrayCid: |
529 value_check_cid = kFloat32x4Cid; | 506 value_check_cid = kFloat32x4Cid; |
530 rep = kUnboxedFloat32x4; | 507 rep = kUnboxedFloat32x4; |
531 break; | 508 break; |
532 case kTypedDataInt32x4ArrayCid: | 509 case kTypedDataInt32x4ArrayCid: |
533 value_check_cid = kInt32x4Cid; | 510 value_check_cid = kInt32x4Cid; |
534 rep = kUnboxedInt32x4; | 511 rep = kUnboxedInt32x4; |
535 break; | 512 break; |
536 case kTypedDataFloat64x2ArrayCid: | 513 case kTypedDataFloat64x2ArrayCid: |
537 value_check_cid = kFloat64x2Cid; | 514 value_check_cid = kFloat64x2Cid; |
538 rep = kUnboxedFloat64x2; | 515 rep = kUnboxedFloat64x2; |
539 break; | 516 break; |
540 default: | 517 default: |
541 // Float32/Float64 case already handled. | 518 // Float32/Float64 case already handled. |
542 break; | 519 break; |
543 } | 520 } |
544 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 521 const ICData& value_check = ICData::ZoneHandle( |
545 flow_graph->function(), | 522 ICData::New(flow_graph->function(), |
546 Symbols::Empty(), // Dummy function name. | 523 Symbols::Empty(), // Dummy function name. |
547 Object::empty_array(), // Dummy args. descr. | 524 Object::empty_array(), // Dummy args. descr. |
548 Thread::kNoDeoptId, | 525 Thread::kNoDeoptId, 1, false)); |
549 1, | |
550 false)); | |
551 value_check.AddReceiverCheck(value_check_cid, flow_graph->function()); | 526 value_check.AddReceiverCheck(value_check_cid, flow_graph->function()); |
552 builder.AddInstruction( | 527 builder.AddInstruction( |
553 new CheckClassInstr(new Value(value), | 528 new CheckClassInstr(new Value(value), Thread::kNoDeoptId, value_check, |
554 Thread::kNoDeoptId, | |
555 value_check, | |
556 builder.TokenPos())); | 529 builder.TokenPos())); |
557 value = builder.AddUnboxInstr(rep, | 530 value = builder.AddUnboxInstr(rep, new Value(value), |
558 new Value(value), | |
559 /* is_checked = */ true); | 531 /* is_checked = */ true); |
560 if (array_cid == kTypedDataFloat32ArrayCid) { | 532 if (array_cid == kTypedDataFloat32ArrayCid) { |
561 value = builder.AddDefinition( | 533 value = builder.AddDefinition( |
562 new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId)); | 534 new DoubleToFloatInstr(new Value(value), Thread::kNoDeoptId)); |
563 } | 535 } |
564 break; | 536 break; |
565 } | 537 } |
566 default: | 538 default: |
567 UNREACHABLE(); | 539 UNREACHABLE(); |
568 } | 540 } |
569 | 541 |
570 if (RawObject::IsExternalTypedDataClassId(array_cid)) { | 542 if (RawObject::IsExternalTypedDataClassId(array_cid)) { |
571 array = builder.AddDefinition( | 543 array = builder.AddDefinition(new LoadUntaggedInstr( |
572 new LoadUntaggedInstr(new Value(array), | 544 new Value(array), ExternalTypedData::data_offset())); |
573 ExternalTypedData::data_offset())); | |
574 } | 545 } |
575 // No store barrier. | 546 // No store barrier. |
576 ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) || | 547 ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) || |
577 RawObject::IsTypedDataClassId(array_cid)); | 548 RawObject::IsTypedDataClassId(array_cid)); |
578 builder.AddInstruction( | 549 builder.AddInstruction(new StoreIndexedInstr( |
579 new StoreIndexedInstr(new Value(array), | 550 new Value(array), new Value(index), new Value(value), kNoStoreBarrier, |
580 new Value(index), | 551 Instance::ElementSizeFor(array_cid), // index scale |
581 new Value(value), | 552 array_cid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
582 kNoStoreBarrier, | |
583 Instance::ElementSizeFor(array_cid), // index scale | |
584 array_cid, | |
585 kAlignedAccess, | |
586 Thread::kNoDeoptId, | |
587 builder.TokenPos())); | |
588 // Return null. | 553 // Return null. |
589 Definition* null_def = builder.AddNullDefinition(); | 554 Definition* null_def = builder.AddNullDefinition(); |
590 builder.AddIntrinsicReturn(new Value(null_def)); | 555 builder.AddIntrinsicReturn(new Value(null_def)); |
591 return true; | 556 return true; |
592 } | 557 } |
593 | 558 |
594 | 559 |
595 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ | 560 #define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
596 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 561 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
597 return IntrinsifyArrayGetIndexed( \ | 562 return IntrinsifyArrayGetIndexed( \ |
598 flow_graph, \ | 563 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
599 MethodRecognizer::MethodKindToReceiverCid( \ | 564 MethodRecognizer::k##enum_name##GetIndexed)); \ |
600 MethodRecognizer::k##enum_name##GetIndexed)); \ | 565 } |
601 } | |
602 | 566 |
603 | 567 |
604 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ | 568 #define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \ |
605 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 569 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
606 return IntrinsifyArraySetIndexed( \ | 570 return IntrinsifyArraySetIndexed( \ |
607 flow_graph, \ | 571 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
608 MethodRecognizer::MethodKindToReceiverCid( \ | 572 MethodRecognizer::k##enum_name##SetIndexed)); \ |
609 MethodRecognizer::k##enum_name##SetIndexed)); \ | 573 } |
610 } | |
611 | 574 |
612 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. | 575 DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray) // Setter in intrinsifier_<arch>.cc. |
613 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) | 576 DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray) |
614 | 577 |
615 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 578 #define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
616 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ | 579 DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \ |
617 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) | 580 DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) |
618 | 581 |
619 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array) | 582 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array) |
620 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) | 583 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array) |
621 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) | 584 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array) |
622 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray) | 585 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray) |
623 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray) | 586 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray) |
624 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array) | 587 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array) |
625 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array) | 588 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array) |
626 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) | 589 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array) |
627 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) | 590 DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array) |
628 | 591 |
629 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS | 592 #undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS |
630 #undef DEFINE_ARRAY_GETTER_INTRINSIC | 593 #undef DEFINE_ARRAY_GETTER_INTRINSIC |
631 #undef DEFINE_ARRAY_SETTER_INTRINSIC | 594 #undef DEFINE_ARRAY_SETTER_INTRINSIC |
632 | 595 |
633 | 596 |
634 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ | 597 #define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
635 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 598 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
636 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ | 599 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
637 return false; \ | 600 return false; \ |
638 } \ | 601 } \ |
639 return IntrinsifyArrayGetIndexed( \ | 602 return IntrinsifyArrayGetIndexed( \ |
640 flow_graph, \ | 603 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
641 MethodRecognizer::MethodKindToReceiverCid( \ | 604 MethodRecognizer::k##enum_name##GetIndexed)); \ |
642 MethodRecognizer::k##enum_name##GetIndexed)); \ | 605 } |
643 } | |
644 | 606 |
645 | 607 |
646 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ | 608 #define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \ |
647 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 609 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
648 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ | 610 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \ |
649 return false; \ | 611 return false; \ |
650 } \ | 612 } \ |
651 return IntrinsifyArraySetIndexed( \ | 613 return IntrinsifyArraySetIndexed( \ |
652 flow_graph, \ | 614 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
653 MethodRecognizer::MethodKindToReceiverCid( \ | 615 MethodRecognizer::k##enum_name##SetIndexed)); \ |
654 MethodRecognizer::k##enum_name##SetIndexed)); \ | 616 } |
655 } | |
656 | 617 |
657 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 618 #define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
658 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ | 619 DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \ |
659 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) | 620 DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) |
660 | 621 |
661 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) | 622 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array) |
662 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) | 623 DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array) |
663 | 624 |
664 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS | 625 #undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS |
665 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC | 626 #undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC |
666 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC | 627 #undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC |
667 | 628 |
668 | 629 |
669 #define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ | 630 #define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ |
670 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ | 631 bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) { \ |
671 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ | 632 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ |
672 return false; \ | 633 return false; \ |
673 } \ | 634 } \ |
674 return IntrinsifyArrayGetIndexed( \ | 635 return IntrinsifyArrayGetIndexed( \ |
675 flow_graph, \ | 636 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
676 MethodRecognizer::MethodKindToReceiverCid( \ | 637 MethodRecognizer::k##enum_name##GetIndexed)); \ |
677 MethodRecognizer::k##enum_name##GetIndexed)); \ | 638 } |
678 } | |
679 | 639 |
680 | 640 |
681 #define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \ | 641 #define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \ |
682 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ | 642 bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) { \ |
683 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ | 643 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \ |
684 return false; \ | 644 return false; \ |
685 } \ | 645 } \ |
686 return IntrinsifyArraySetIndexed( \ | 646 return IntrinsifyArraySetIndexed( \ |
687 flow_graph, \ | 647 flow_graph, MethodRecognizer::MethodKindToReceiverCid( \ |
688 MethodRecognizer::MethodKindToReceiverCid( \ | 648 MethodRecognizer::k##enum_name##SetIndexed)); \ |
689 MethodRecognizer::k##enum_name##SetIndexed)); \ | 649 } |
690 } | |
691 | 650 |
692 #define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ | 651 #define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \ |
693 DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ | 652 DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \ |
694 DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) | 653 DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) |
695 | 654 |
696 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array) | 655 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array) |
697 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array) | 656 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array) |
698 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array) | 657 DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array) |
699 | 658 |
700 #undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS | 659 #undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS |
701 #undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC | 660 #undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC |
702 #undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC | 661 #undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC |
703 | 662 |
704 | 663 |
705 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { | 664 static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) { |
706 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 665 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
707 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 666 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
708 BlockBuilder builder(flow_graph, normal_entry); | 667 BlockBuilder builder(flow_graph, normal_entry); |
709 | 668 |
710 Definition* index = builder.AddParameter(1); | 669 Definition* index = builder.AddParameter(1); |
711 Definition* str = builder.AddParameter(2); | 670 Definition* str = builder.AddParameter(2); |
712 PrepareIndexedOp(&builder, str, index, String::length_offset()); | 671 PrepareIndexedOp(&builder, str, index, String::length_offset()); |
713 | 672 |
714 // For external strings: Load external data. | 673 // For external strings: Load external data. |
715 if (cid == kExternalOneByteStringCid) { | 674 if (cid == kExternalOneByteStringCid) { |
716 str = builder.AddDefinition( | 675 str = builder.AddDefinition(new LoadUntaggedInstr( |
717 new LoadUntaggedInstr(new Value(str), | 676 new Value(str), ExternalOneByteString::external_data_offset())); |
718 ExternalOneByteString::external_data_offset())); | 677 str = builder.AddDefinition(new LoadUntaggedInstr( |
719 str = builder.AddDefinition( | 678 new Value(str), RawExternalOneByteString::ExternalData::data_offset())); |
720 new LoadUntaggedInstr( | |
721 new Value(str), | |
722 RawExternalOneByteString::ExternalData::data_offset())); | |
723 } else if (cid == kExternalTwoByteStringCid) { | 679 } else if (cid == kExternalTwoByteStringCid) { |
724 str = builder.AddDefinition( | 680 str = builder.AddDefinition(new LoadUntaggedInstr( |
725 new LoadUntaggedInstr(new Value(str), | 681 new Value(str), ExternalTwoByteString::external_data_offset())); |
726 ExternalTwoByteString::external_data_offset())); | 682 str = builder.AddDefinition(new LoadUntaggedInstr( |
727 str = builder.AddDefinition( | 683 new Value(str), RawExternalTwoByteString::ExternalData::data_offset())); |
728 new LoadUntaggedInstr( | |
729 new Value(str), | |
730 RawExternalTwoByteString::ExternalData::data_offset())); | |
731 } | 684 } |
732 | 685 |
733 Definition* result = builder.AddDefinition( | 686 Definition* result = builder.AddDefinition(new LoadIndexedInstr( |
734 new LoadIndexedInstr(new Value(str), | 687 new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid, |
735 new Value(index), | 688 kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
736 Instance::ElementSizeFor(cid), | |
737 cid, | |
738 kAlignedAccess, | |
739 Thread::kNoDeoptId, | |
740 builder.TokenPos())); | |
741 builder.AddIntrinsicReturn(new Value(result)); | 689 builder.AddIntrinsicReturn(new Value(result)); |
742 return true; | 690 return true; |
743 } | 691 } |
744 | 692 |
745 | 693 |
746 bool Intrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) { | 694 bool Intrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) { |
747 return BuildCodeUnitAt(flow_graph, kOneByteStringCid); | 695 return BuildCodeUnitAt(flow_graph, kOneByteStringCid); |
748 } | 696 } |
749 | 697 |
750 | 698 |
(...skipping 18 matching lines...) Expand all Loading... |
769 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; | 717 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |
770 | 718 |
771 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 719 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
772 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 720 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
773 BlockBuilder builder(flow_graph, normal_entry); | 721 BlockBuilder builder(flow_graph, normal_entry); |
774 | 722 |
775 Definition* right = builder.AddParameter(1); | 723 Definition* right = builder.AddParameter(1); |
776 Definition* left = builder.AddParameter(2); | 724 Definition* left = builder.AddParameter(2); |
777 | 725 |
778 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 726 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
779 flow_graph->function(), | 727 flow_graph->function(), String::Handle(flow_graph->function().name()), |
780 String::Handle(flow_graph->function().name()), | |
781 Object::empty_array(), // Dummy args. descr. | 728 Object::empty_array(), // Dummy args. descr. |
782 Thread::kNoDeoptId, | 729 Thread::kNoDeoptId, 1, false)); |
783 1, | |
784 false)); | |
785 value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); | 730 value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); |
786 // Check argument. Receiver (left) is known to be a Float32x4. | 731 // Check argument. Receiver (left) is known to be a Float32x4. |
787 builder.AddInstruction( | 732 builder.AddInstruction(new CheckClassInstr( |
788 new CheckClassInstr(new Value(right), | 733 new Value(right), Thread::kNoDeoptId, value_check, builder.TokenPos())); |
789 Thread::kNoDeoptId, | |
790 value_check, | |
791 builder.TokenPos())); | |
792 Definition* left_simd = | 734 Definition* left_simd = |
793 builder.AddUnboxInstr(kUnboxedFloat32x4, | 735 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left), |
794 new Value(left), | |
795 /* is_checked = */ true); | 736 /* is_checked = */ true); |
796 | 737 |
797 Definition* right_simd = | 738 Definition* right_simd = |
798 builder.AddUnboxInstr(kUnboxedFloat32x4, | 739 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right), |
799 new Value(right), | |
800 /* is_checked = */ true); | 740 /* is_checked = */ true); |
801 | 741 |
802 Definition* unboxed_result = builder.AddDefinition( | 742 Definition* unboxed_result = builder.AddDefinition(new BinaryFloat32x4OpInstr( |
803 new BinaryFloat32x4OpInstr(kind, | 743 kind, new Value(left_simd), new Value(right_simd), Thread::kNoDeoptId)); |
804 new Value(left_simd), | |
805 new Value(right_simd), | |
806 Thread::kNoDeoptId)); | |
807 Definition* result = builder.AddDefinition( | 744 Definition* result = builder.AddDefinition( |
808 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); | 745 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); |
809 builder.AddIntrinsicReturn(new Value(result)); | 746 builder.AddIntrinsicReturn(new Value(result)); |
810 return true; | 747 return true; |
811 } | 748 } |
812 | 749 |
813 | 750 |
814 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { | 751 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { |
815 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); | 752 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); |
816 } | 753 } |
(...skipping 15 matching lines...) Expand all Loading... |
832 !FlowGraphCompiler::SupportsUnboxedSimd128()) { | 769 !FlowGraphCompiler::SupportsUnboxedSimd128()) { |
833 return false; | 770 return false; |
834 } | 771 } |
835 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 772 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
836 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 773 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
837 BlockBuilder builder(flow_graph, normal_entry); | 774 BlockBuilder builder(flow_graph, normal_entry); |
838 | 775 |
839 Definition* receiver = builder.AddParameter(1); | 776 Definition* receiver = builder.AddParameter(1); |
840 | 777 |
841 Definition* unboxed_receiver = | 778 Definition* unboxed_receiver = |
842 builder.AddUnboxInstr(kUnboxedFloat32x4, | 779 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver), |
843 new Value(receiver), | |
844 /* is_checked = */ true); | 780 /* is_checked = */ true); |
845 | 781 |
846 Definition* unboxed_result = builder.AddDefinition( | 782 Definition* unboxed_result = builder.AddDefinition(new Simd32x4ShuffleInstr( |
847 new Simd32x4ShuffleInstr(kind, | 783 kind, new Value(unboxed_receiver), 0, Thread::kNoDeoptId)); |
848 new Value(unboxed_receiver), | |
849 0, | |
850 Thread::kNoDeoptId)); | |
851 | 784 |
852 Definition* result = builder.AddDefinition( | 785 Definition* result = builder.AddDefinition( |
853 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 786 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
854 builder.AddIntrinsicReturn(new Value(result)); | 787 builder.AddIntrinsicReturn(new Value(result)); |
855 return true; | 788 return true; |
856 } | 789 } |
857 | 790 |
858 | 791 |
859 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { | 792 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { |
860 return BuildFloat32x4Shuffle(flow_graph, | 793 return BuildFloat32x4Shuffle(flow_graph, |
(...skipping 19 matching lines...) Expand all Loading... |
880 } | 813 } |
881 | 814 |
882 | 815 |
883 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { | 816 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { |
884 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 817 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
885 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 818 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
886 BlockBuilder builder(flow_graph, normal_entry); | 819 BlockBuilder builder(flow_graph, normal_entry); |
887 | 820 |
888 Definition* array = builder.AddParameter(1); | 821 Definition* array = builder.AddParameter(1); |
889 | 822 |
890 Definition* length = builder.AddDefinition( | 823 Definition* length = builder.AddDefinition(new LoadFieldInstr( |
891 new LoadFieldInstr(new Value(array), | 824 new Value(array), offset, Type::ZoneHandle(), builder.TokenPos())); |
892 offset, | |
893 Type::ZoneHandle(), | |
894 builder.TokenPos())); | |
895 builder.AddIntrinsicReturn(new Value(length)); | 825 builder.AddIntrinsicReturn(new Value(length)); |
896 return true; | 826 return true; |
897 } | 827 } |
898 | 828 |
899 | 829 |
900 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) { | 830 bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) { |
901 return BuildLoadField(flow_graph, Array::length_offset()); | 831 return BuildLoadField(flow_graph, Array::length_offset()); |
902 } | 832 } |
903 | 833 |
904 | 834 |
(...skipping 18 matching lines...) Expand all Loading... |
923 | 853 |
924 | 854 |
925 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) { | 855 bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) { |
926 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 856 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
927 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 857 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
928 BlockBuilder builder(flow_graph, normal_entry); | 858 BlockBuilder builder(flow_graph, normal_entry); |
929 | 859 |
930 Definition* array = builder.AddParameter(1); | 860 Definition* array = builder.AddParameter(1); |
931 | 861 |
932 Definition* backing_store = builder.AddDefinition( | 862 Definition* backing_store = builder.AddDefinition( |
933 new LoadFieldInstr(new Value(array), | 863 new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(), |
934 GrowableObjectArray::data_offset(), | 864 Type::ZoneHandle(), builder.TokenPos())); |
935 Type::ZoneHandle(), | |
936 builder.TokenPos())); | |
937 Definition* capacity = builder.AddDefinition( | 865 Definition* capacity = builder.AddDefinition( |
938 new LoadFieldInstr(new Value(backing_store), | 866 new LoadFieldInstr(new Value(backing_store), Array::length_offset(), |
939 Array::length_offset(), | 867 Type::ZoneHandle(), builder.TokenPos())); |
940 Type::ZoneHandle(), | |
941 builder.TokenPos())); | |
942 builder.AddIntrinsicReturn(new Value(capacity)); | 868 builder.AddIntrinsicReturn(new Value(capacity)); |
943 return true; | 869 return true; |
944 } | 870 } |
945 | 871 |
946 | 872 |
947 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { | 873 bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) { |
948 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 874 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
949 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 875 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
950 BlockBuilder builder(flow_graph, normal_entry); | 876 BlockBuilder builder(flow_graph, normal_entry); |
951 | 877 |
952 Definition* index = builder.AddParameter(1); | 878 Definition* index = builder.AddParameter(1); |
953 Definition* growable_array = builder.AddParameter(2); | 879 Definition* growable_array = builder.AddParameter(2); |
954 | 880 |
955 PrepareIndexedOp( | 881 PrepareIndexedOp(&builder, growable_array, index, |
956 &builder, growable_array, index, GrowableObjectArray::length_offset()); | 882 GrowableObjectArray::length_offset()); |
957 | 883 |
958 Definition* backing_store = builder.AddDefinition( | 884 Definition* backing_store = builder.AddDefinition(new LoadFieldInstr( |
959 new LoadFieldInstr(new Value(growable_array), | 885 new Value(growable_array), GrowableObjectArray::data_offset(), |
960 GrowableObjectArray::data_offset(), | 886 Type::ZoneHandle(), builder.TokenPos())); |
961 Type::ZoneHandle(), | 887 Definition* result = builder.AddDefinition(new LoadIndexedInstr( |
962 builder.TokenPos())); | 888 new Value(backing_store), new Value(index), |
963 Definition* result = builder.AddDefinition( | 889 Instance::ElementSizeFor(kArrayCid), // index scale |
964 new LoadIndexedInstr(new Value(backing_store), | 890 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
965 new Value(index), | |
966 Instance::ElementSizeFor(kArrayCid), // index scale | |
967 kArrayCid, | |
968 kAlignedAccess, | |
969 Thread::kNoDeoptId, | |
970 builder.TokenPos())); | |
971 builder.AddIntrinsicReturn(new Value(result)); | 891 builder.AddIntrinsicReturn(new Value(result)); |
972 return true; | 892 return true; |
973 } | 893 } |
974 | 894 |
975 | 895 |
976 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { | 896 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { |
977 if (Isolate::Current()->type_checks()) { | 897 if (Isolate::Current()->type_checks()) { |
978 return false; | 898 return false; |
979 } | 899 } |
980 | 900 |
981 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 901 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
982 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 902 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
983 BlockBuilder builder(flow_graph, normal_entry); | 903 BlockBuilder builder(flow_graph, normal_entry); |
984 | 904 |
985 Definition* value = builder.AddParameter(1); | 905 Definition* value = builder.AddParameter(1); |
986 Definition* index = builder.AddParameter(2); | 906 Definition* index = builder.AddParameter(2); |
987 Definition* array = builder.AddParameter(3); | 907 Definition* array = builder.AddParameter(3); |
988 | 908 |
989 PrepareIndexedOp( | 909 PrepareIndexedOp(&builder, array, index, |
990 &builder, array, index, GrowableObjectArray::length_offset()); | 910 GrowableObjectArray::length_offset()); |
991 | 911 |
992 Definition* backing_store = builder.AddDefinition( | 912 Definition* backing_store = builder.AddDefinition( |
993 new LoadFieldInstr(new Value(array), | 913 new LoadFieldInstr(new Value(array), GrowableObjectArray::data_offset(), |
994 GrowableObjectArray::data_offset(), | 914 Type::ZoneHandle(), builder.TokenPos())); |
995 Type::ZoneHandle(), | |
996 builder.TokenPos())); | |
997 | 915 |
998 builder.AddInstruction( | 916 builder.AddInstruction(new StoreIndexedInstr( |
999 new StoreIndexedInstr(new Value(backing_store), | 917 new Value(backing_store), new Value(index), new Value(value), |
1000 new Value(index), | 918 kEmitStoreBarrier, |
1001 new Value(value), | 919 Instance::ElementSizeFor(kArrayCid), // index scale |
1002 kEmitStoreBarrier, | 920 kArrayCid, kAlignedAccess, Thread::kNoDeoptId, builder.TokenPos())); |
1003 Instance::ElementSizeFor(kArrayCid), // index scale | |
1004 kArrayCid, | |
1005 kAlignedAccess, | |
1006 Thread::kNoDeoptId, | |
1007 builder.TokenPos())); | |
1008 // Return null. | 921 // Return null. |
1009 Definition* null_def = builder.AddNullDefinition(); | 922 Definition* null_def = builder.AddNullDefinition(); |
1010 builder.AddIntrinsicReturn(new Value(null_def)); | 923 builder.AddIntrinsicReturn(new Value(null_def)); |
1011 return true; | 924 return true; |
1012 } | 925 } |
1013 | 926 |
1014 | 927 |
1015 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { | 928 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { |
1016 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 929 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1017 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 930 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1018 BlockBuilder builder(flow_graph, normal_entry); | 931 BlockBuilder builder(flow_graph, normal_entry); |
1019 | 932 |
1020 Definition* data = builder.AddParameter(1); | 933 Definition* data = builder.AddParameter(1); |
1021 Definition* growable_array = builder.AddParameter(2); | 934 Definition* growable_array = builder.AddParameter(2); |
1022 | 935 |
1023 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 936 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
1024 flow_graph->function(), | 937 flow_graph->function(), String::Handle(flow_graph->function().name()), |
1025 String::Handle(flow_graph->function().name()), | |
1026 Object::empty_array(), // Dummy args. descr. | 938 Object::empty_array(), // Dummy args. descr. |
1027 Thread::kNoDeoptId, | 939 Thread::kNoDeoptId, 1, false)); |
1028 1, | |
1029 false)); | |
1030 value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); | 940 value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); |
1031 builder.AddInstruction( | 941 builder.AddInstruction(new CheckClassInstr( |
1032 new CheckClassInstr(new Value(data), | 942 new Value(data), Thread::kNoDeoptId, value_check, builder.TokenPos())); |
1033 Thread::kNoDeoptId, | |
1034 value_check, | |
1035 builder.TokenPos())); | |
1036 | 943 |
1037 builder.AddInstruction( | 944 builder.AddInstruction(new StoreInstanceFieldInstr( |
1038 new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), | 945 GrowableObjectArray::data_offset(), new Value(growable_array), |
1039 new Value(growable_array), | 946 new Value(data), kEmitStoreBarrier, builder.TokenPos())); |
1040 new Value(data), | |
1041 kEmitStoreBarrier, | |
1042 builder.TokenPos())); | |
1043 // Return null. | 947 // Return null. |
1044 Definition* null_def = builder.AddNullDefinition(); | 948 Definition* null_def = builder.AddNullDefinition(); |
1045 builder.AddIntrinsicReturn(new Value(null_def)); | 949 builder.AddIntrinsicReturn(new Value(null_def)); |
1046 return true; | 950 return true; |
1047 } | 951 } |
1048 | 952 |
1049 | 953 |
1050 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { | 954 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { |
1051 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 955 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1052 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 956 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1053 BlockBuilder builder(flow_graph, normal_entry); | 957 BlockBuilder builder(flow_graph, normal_entry); |
1054 | 958 |
1055 Definition* length = builder.AddParameter(1); | 959 Definition* length = builder.AddParameter(1); |
1056 Definition* growable_array = builder.AddParameter(2); | 960 Definition* growable_array = builder.AddParameter(2); |
1057 | 961 |
1058 builder.AddInstruction( | 962 builder.AddInstruction(new CheckSmiInstr( |
1059 new CheckSmiInstr(new Value(length), | 963 new Value(length), Thread::kNoDeoptId, builder.TokenPos())); |
1060 Thread::kNoDeoptId, | 964 builder.AddInstruction(new StoreInstanceFieldInstr( |
1061 builder.TokenPos())); | 965 GrowableObjectArray::length_offset(), new Value(growable_array), |
1062 builder.AddInstruction( | 966 new Value(length), kNoStoreBarrier, builder.TokenPos())); |
1063 new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), | |
1064 new Value(growable_array), | |
1065 new Value(length), | |
1066 kNoStoreBarrier, | |
1067 builder.TokenPos())); | |
1068 Definition* null_def = builder.AddNullDefinition(); | 967 Definition* null_def = builder.AddNullDefinition(); |
1069 builder.AddIntrinsicReturn(new Value(null_def)); | 968 builder.AddIntrinsicReturn(new Value(null_def)); |
1070 return true; | 969 return true; |
1071 } | 970 } |
1072 | 971 |
1073 | 972 |
1074 bool Intrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) { | 973 bool Intrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) { |
1075 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 974 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { |
1076 return false; | 975 return false; |
1077 } | 976 } |
1078 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 977 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1079 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 978 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1080 BlockBuilder builder(flow_graph, normal_entry); | 979 BlockBuilder builder(flow_graph, normal_entry); |
1081 | 980 |
1082 Definition* receiver = builder.AddParameter(1); | 981 Definition* receiver = builder.AddParameter(1); |
1083 Definition* unboxed_value = | 982 Definition* unboxed_value = |
1084 builder.AddUnboxInstr(kUnboxedDouble, | 983 builder.AddUnboxInstr(kUnboxedDouble, new Value(receiver), |
1085 new Value(receiver), | |
1086 /* is_checked = */ true); | 984 /* is_checked = */ true); |
1087 Definition* unboxed_result = builder.AddDefinition( | 985 Definition* unboxed_result = builder.AddDefinition(new UnaryDoubleOpInstr( |
1088 new UnaryDoubleOpInstr(Token::kNEGATE, | 986 Token::kNEGATE, new Value(unboxed_value), Thread::kNoDeoptId)); |
1089 new Value(unboxed_value), | |
1090 Thread::kNoDeoptId)); | |
1091 Definition* result = builder.AddDefinition( | 987 Definition* result = builder.AddDefinition( |
1092 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 988 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
1093 builder.AddIntrinsicReturn(new Value(result)); | 989 builder.AddIntrinsicReturn(new Value(result)); |
1094 return true; | 990 return true; |
1095 } | 991 } |
1096 | 992 |
1097 | 993 |
1098 static bool BuildInvokeMathCFunction(BlockBuilder* builder, | 994 static bool BuildInvokeMathCFunction(BlockBuilder* builder, |
1099 MethodRecognizer::Kind kind, | 995 MethodRecognizer::Kind kind, |
1100 intptr_t num_parameters = 1) { | 996 intptr_t num_parameters = 1) { |
1101 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { | 997 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { |
1102 return false; | 998 return false; |
1103 } | 999 } |
1104 ZoneGrowableArray<Value*>* args = | 1000 ZoneGrowableArray<Value*>* args = |
1105 new ZoneGrowableArray<Value*>(num_parameters); | 1001 new ZoneGrowableArray<Value*>(num_parameters); |
1106 | 1002 |
1107 for (intptr_t i = 0; i < num_parameters; i++) { | 1003 for (intptr_t i = 0; i < num_parameters; i++) { |
1108 const intptr_t parameter_index = (num_parameters - i); | 1004 const intptr_t parameter_index = (num_parameters - i); |
1109 Definition* value = builder->AddParameter(parameter_index); | 1005 Definition* value = builder->AddParameter(parameter_index); |
1110 Definition* unboxed_value = | 1006 Definition* unboxed_value = |
1111 builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false); | 1007 builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false); |
1112 args->Add(new Value(unboxed_value)); | 1008 args->Add(new Value(unboxed_value)); |
1113 } | 1009 } |
1114 | 1010 |
1115 Definition* unboxed_result = | 1011 Definition* unboxed_result = builder->InvokeMathCFunction(kind, args); |
1116 builder->InvokeMathCFunction(kind, args); | |
1117 | 1012 |
1118 Definition* result = builder->AddDefinition( | 1013 Definition* result = builder->AddDefinition( |
1119 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 1014 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
1120 | 1015 |
1121 builder->AddIntrinsicReturn(new Value(result)); | 1016 builder->AddIntrinsicReturn(new Value(result)); |
1122 | 1017 |
1123 return true; | 1018 return true; |
1124 } | 1019 } |
1125 | 1020 |
1126 | 1021 |
1127 bool Intrinsifier::Build_MathSin(FlowGraph* flow_graph) { | 1022 bool Intrinsifier::Build_MathSin(FlowGraph* flow_graph) { |
1128 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1023 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1129 | 1024 |
1130 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1025 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1131 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1026 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1132 BlockBuilder builder(flow_graph, normal_entry); | 1027 BlockBuilder builder(flow_graph, normal_entry); |
1133 | 1028 |
1134 return BuildInvokeMathCFunction(&builder, | 1029 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathSin); |
1135 MethodRecognizer::kMathSin); | |
1136 } | 1030 } |
1137 | 1031 |
1138 | 1032 |
1139 bool Intrinsifier::Build_MathCos(FlowGraph* flow_graph) { | 1033 bool Intrinsifier::Build_MathCos(FlowGraph* flow_graph) { |
1140 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1034 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1141 | 1035 |
1142 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1036 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1143 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1037 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1144 BlockBuilder builder(flow_graph, normal_entry); | 1038 BlockBuilder builder(flow_graph, normal_entry); |
1145 | 1039 |
1146 return BuildInvokeMathCFunction(&builder, | 1040 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathCos); |
1147 MethodRecognizer::kMathCos); | |
1148 } | 1041 } |
1149 | 1042 |
1150 | 1043 |
1151 bool Intrinsifier::Build_MathTan(FlowGraph* flow_graph) { | 1044 bool Intrinsifier::Build_MathTan(FlowGraph* flow_graph) { |
1152 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1045 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1153 | 1046 |
1154 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1047 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1155 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1048 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1156 BlockBuilder builder(flow_graph, normal_entry); | 1049 BlockBuilder builder(flow_graph, normal_entry); |
1157 | 1050 |
1158 return BuildInvokeMathCFunction(&builder, | 1051 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathTan); |
1159 MethodRecognizer::kMathTan); | |
1160 } | 1052 } |
1161 | 1053 |
1162 | 1054 |
1163 bool Intrinsifier::Build_MathAsin(FlowGraph* flow_graph) { | 1055 bool Intrinsifier::Build_MathAsin(FlowGraph* flow_graph) { |
1164 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1056 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1165 | 1057 |
1166 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1058 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1167 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1059 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1168 BlockBuilder builder(flow_graph, normal_entry); | 1060 BlockBuilder builder(flow_graph, normal_entry); |
1169 | 1061 |
1170 return BuildInvokeMathCFunction(&builder, | 1062 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAsin); |
1171 MethodRecognizer::kMathAsin); | |
1172 } | 1063 } |
1173 | 1064 |
1174 | 1065 |
1175 bool Intrinsifier::Build_MathAcos(FlowGraph* flow_graph) { | 1066 bool Intrinsifier::Build_MathAcos(FlowGraph* flow_graph) { |
1176 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1067 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1177 | 1068 |
1178 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1069 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1179 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1070 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1180 BlockBuilder builder(flow_graph, normal_entry); | 1071 BlockBuilder builder(flow_graph, normal_entry); |
1181 | 1072 |
1182 return BuildInvokeMathCFunction(&builder, | 1073 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAcos); |
1183 MethodRecognizer::kMathAcos); | |
1184 } | 1074 } |
1185 | 1075 |
1186 | 1076 |
1187 bool Intrinsifier::Build_MathAtan(FlowGraph* flow_graph) { | 1077 bool Intrinsifier::Build_MathAtan(FlowGraph* flow_graph) { |
1188 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1078 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1189 | 1079 |
1190 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1080 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1191 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1081 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1192 BlockBuilder builder(flow_graph, normal_entry); | 1082 BlockBuilder builder(flow_graph, normal_entry); |
1193 | 1083 |
1194 return BuildInvokeMathCFunction(&builder, | 1084 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan); |
1195 MethodRecognizer::kMathAtan); | |
1196 } | 1085 } |
1197 | 1086 |
1198 | 1087 |
1199 bool Intrinsifier::Build_MathAtan2(FlowGraph* flow_graph) { | 1088 bool Intrinsifier::Build_MathAtan2(FlowGraph* flow_graph) { |
1200 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1089 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1201 | 1090 |
1202 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1091 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1203 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1092 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1204 BlockBuilder builder(flow_graph, normal_entry); | 1093 BlockBuilder builder(flow_graph, normal_entry); |
1205 | 1094 |
1206 return BuildInvokeMathCFunction(&builder, | 1095 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan2, |
1207 MethodRecognizer::kMathAtan2, | |
1208 /* num_parameters = */ 2); | 1096 /* num_parameters = */ 2); |
1209 } | 1097 } |
1210 | 1098 |
1211 | 1099 |
1212 bool Intrinsifier::Build_DoubleMod(FlowGraph* flow_graph) { | 1100 bool Intrinsifier::Build_DoubleMod(FlowGraph* flow_graph) { |
1213 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1101 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1214 | 1102 |
1215 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1103 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1216 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1104 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1217 BlockBuilder builder(flow_graph, normal_entry); | 1105 BlockBuilder builder(flow_graph, normal_entry); |
1218 | 1106 |
1219 return BuildInvokeMathCFunction(&builder, | 1107 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleMod, |
1220 MethodRecognizer::kDoubleMod, | |
1221 /* num_parameters = */ 2); | 1108 /* num_parameters = */ 2); |
1222 } | 1109 } |
1223 | 1110 |
1224 | 1111 |
1225 bool Intrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) { | 1112 bool Intrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) { |
1226 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1113 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1227 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1114 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
1228 // way. | 1115 // way. |
1229 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1116 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
1230 | 1117 |
1231 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1118 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1232 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1119 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1233 BlockBuilder builder(flow_graph, normal_entry); | 1120 BlockBuilder builder(flow_graph, normal_entry); |
1234 | 1121 |
1235 return BuildInvokeMathCFunction(&builder, | 1122 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleCeil); |
1236 MethodRecognizer::kDoubleCeil); | |
1237 } | 1123 } |
1238 | 1124 |
1239 | 1125 |
1240 bool Intrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) { | 1126 bool Intrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) { |
1241 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1127 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1242 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1128 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
1243 // way. | 1129 // way. |
1244 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1130 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
1245 | 1131 |
1246 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1132 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1247 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1133 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1248 BlockBuilder builder(flow_graph, normal_entry); | 1134 BlockBuilder builder(flow_graph, normal_entry); |
1249 | 1135 |
1250 return BuildInvokeMathCFunction(&builder, | 1136 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleFloor); |
1251 MethodRecognizer::kDoubleFloor); | |
1252 } | 1137 } |
1253 | 1138 |
1254 | 1139 |
1255 bool Intrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) { | 1140 bool Intrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) { |
1256 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1141 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1257 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different | 1142 // TODO(johnmccutchan): On X86 this intrinsic can be written in a different |
1258 // way. | 1143 // way. |
1259 if (TargetCPUFeatures::double_truncate_round_supported()) return false; | 1144 if (TargetCPUFeatures::double_truncate_round_supported()) return false; |
1260 | 1145 |
1261 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1146 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1262 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1147 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1263 BlockBuilder builder(flow_graph, normal_entry); | 1148 BlockBuilder builder(flow_graph, normal_entry); |
1264 | 1149 |
1265 return BuildInvokeMathCFunction(&builder, | 1150 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleTruncate); |
1266 MethodRecognizer::kDoubleTruncate); | |
1267 } | 1151 } |
1268 | 1152 |
1269 | 1153 |
1270 bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) { | 1154 bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) { |
1271 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 1155 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
1272 | 1156 |
1273 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 1157 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
1274 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 1158 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
1275 BlockBuilder builder(flow_graph, normal_entry); | 1159 BlockBuilder builder(flow_graph, normal_entry); |
1276 | 1160 |
1277 return BuildInvokeMathCFunction(&builder, | 1161 return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound); |
1278 MethodRecognizer::kDoubleRound); | |
1279 } | 1162 } |
1280 #endif // !defined(TARGET_ARCH_DBC) | 1163 #endif // !defined(TARGET_ARCH_DBC) |
1281 | 1164 |
1282 | 1165 |
1283 } // namespace dart | 1166 } // namespace dart |
OLD | NEW |