| 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/intrinsifier.h" | 7 #include "vm/intrinsifier.h" |
| 8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
| 9 #include "vm/object.h" | 9 #include "vm/object.h" |
| 10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, | 129 bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function, |
| 130 FlowGraphCompiler* compiler) { | 130 FlowGraphCompiler* compiler) { |
| 131 ZoneGrowableArray<const ICData*>* ic_data_array = | 131 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 132 new ZoneGrowableArray<const ICData*>(); | 132 new ZoneGrowableArray<const ICData*>(); |
| 133 FlowGraphBuilder builder(parsed_function, | 133 FlowGraphBuilder builder(parsed_function, |
| 134 *ic_data_array, | 134 *ic_data_array, |
| 135 NULL, // NULL = not inlining. | 135 NULL, // NULL = not inlining. |
| 136 Isolate::kNoDeoptId); // No OSR id. | 136 Thread::kNoDeoptId); // No OSR id. |
| 137 | 137 |
| 138 intptr_t block_id = builder.AllocateBlockId(); | 138 intptr_t block_id = builder.AllocateBlockId(); |
| 139 TargetEntryInstr* normal_entry = | 139 TargetEntryInstr* normal_entry = |
| 140 new TargetEntryInstr(block_id, | 140 new TargetEntryInstr(block_id, |
| 141 CatchClauseNode::kInvalidTryIndex); | 141 CatchClauseNode::kInvalidTryIndex); |
| 142 GraphEntryInstr* graph_entry = new GraphEntryInstr( | 142 GraphEntryInstr* graph_entry = new GraphEntryInstr( |
| 143 parsed_function, normal_entry, Isolate::kNoDeoptId); // No OSR id. | 143 parsed_function, normal_entry, Thread::kNoDeoptId); // No OSR id. |
| 144 FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); | 144 FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id); |
| 145 const Function& function = parsed_function.function(); | 145 const Function& function = parsed_function.function(); |
| 146 switch (function.recognized_kind()) { | 146 switch (function.recognized_kind()) { |
| 147 #define EMIT_CASE(class_name, function_name, enum_name, fp) \ | 147 #define EMIT_CASE(class_name, function_name, enum_name, fp) \ |
| 148 case MethodRecognizer::k##enum_name: \ | 148 case MethodRecognizer::k##enum_name: \ |
| 149 if (!Build_##enum_name(graph)) return false; \ | 149 if (!Build_##enum_name(graph)) return false; \ |
| 150 break; | 150 break; |
| 151 | 151 |
| 152 GRAPH_INTRINSICS_LIST(EMIT_CASE); | 152 GRAPH_INTRINSICS_LIST(EMIT_CASE); |
| 153 default: | 153 default: |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 return flow_graph_->function().token_pos(); | 267 return flow_graph_->function().token_pos(); |
| 268 } | 268 } |
| 269 | 269 |
| 270 Definition* AddNullDefinition() { | 270 Definition* AddNullDefinition() { |
| 271 return AddDefinition( | 271 return AddDefinition( |
| 272 new ConstantInstr(Object::ZoneHandle(Object::null()))); | 272 new ConstantInstr(Object::ZoneHandle(Object::null()))); |
| 273 } | 273 } |
| 274 | 274 |
| 275 Definition* AddUnboxInstr(Representation rep, Value* value) { | 275 Definition* AddUnboxInstr(Representation rep, Value* value) { |
| 276 Definition* unboxed_value = AddDefinition( | 276 Definition* unboxed_value = AddDefinition( |
| 277 UnboxInstr::Create(rep, value, Isolate::kNoDeoptId)); | 277 UnboxInstr::Create(rep, value, Thread::kNoDeoptId)); |
| 278 // Manually adjust reaching type because there is no type propagation | 278 // Manually adjust reaching type because there is no type propagation |
| 279 // when building intrinsics. | 279 // when building intrinsics. |
| 280 unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( | 280 unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( |
| 281 CompileType::FromCid(CidForRepresentation(rep)))); | 281 CompileType::FromCid(CidForRepresentation(rep)))); |
| 282 return unboxed_value; | 282 return unboxed_value; |
| 283 } | 283 } |
| 284 | 284 |
| 285 private: | 285 private: |
| 286 FlowGraph* flow_graph_; | 286 FlowGraph* flow_graph_; |
| 287 BlockEntryInstr* entry_; | 287 BlockEntryInstr* entry_; |
| 288 Instruction* current_; | 288 Instruction* current_; |
| 289 }; | 289 }; |
| 290 | 290 |
| 291 | 291 |
| 292 static void PrepareIndexedOp(BlockBuilder* builder, | 292 static void PrepareIndexedOp(BlockBuilder* builder, |
| 293 Definition* array, | 293 Definition* array, |
| 294 Definition* index, | 294 Definition* index, |
| 295 intptr_t length_offset) { | 295 intptr_t length_offset) { |
| 296 intptr_t token_pos = builder->TokenPos(); | 296 intptr_t token_pos = builder->TokenPos(); |
| 297 builder->AddInstruction( | 297 builder->AddInstruction( |
| 298 new CheckSmiInstr(new Value(index), | 298 new CheckSmiInstr(new Value(index), |
| 299 Isolate::kNoDeoptId, | 299 Thread::kNoDeoptId, |
| 300 token_pos)); | 300 token_pos)); |
| 301 | 301 |
| 302 Definition* length = builder->AddDefinition( | 302 Definition* length = builder->AddDefinition( |
| 303 new LoadFieldInstr(new Value(array), | 303 new LoadFieldInstr(new Value(array), |
| 304 length_offset, | 304 length_offset, |
| 305 Type::ZoneHandle(Type::SmiType()), | 305 Type::ZoneHandle(Type::SmiType()), |
| 306 Scanner::kNoSourcePos)); | 306 Scanner::kNoSourcePos)); |
| 307 builder->AddInstruction( | 307 builder->AddInstruction( |
| 308 new CheckArrayBoundInstr(new Value(length), | 308 new CheckArrayBoundInstr(new Value(length), |
| 309 new Value(index), | 309 new Value(index), |
| 310 Isolate::kNoDeoptId)); | 310 Thread::kNoDeoptId)); |
| 311 } | 311 } |
| 312 | 312 |
| 313 | 313 |
| 314 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { | 314 bool Intrinsifier::Build_ObjectArrayGetIndexed(FlowGraph* flow_graph) { |
| 315 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 315 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 316 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 316 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 317 BlockBuilder builder(flow_graph, normal_entry); | 317 BlockBuilder builder(flow_graph, normal_entry); |
| 318 | 318 |
| 319 Definition* index = builder.AddParameter(1); | 319 Definition* index = builder.AddParameter(1); |
| 320 Definition* array = builder.AddParameter(2); | 320 Definition* array = builder.AddParameter(2); |
| 321 | 321 |
| 322 PrepareIndexedOp(&builder, array, index, Array::length_offset()); | 322 PrepareIndexedOp(&builder, array, index, Array::length_offset()); |
| 323 | 323 |
| 324 Definition* result = builder.AddDefinition( | 324 Definition* result = builder.AddDefinition( |
| 325 new LoadIndexedInstr(new Value(array), | 325 new LoadIndexedInstr(new Value(array), |
| 326 new Value(index), | 326 new Value(index), |
| 327 Instance::ElementSizeFor(kArrayCid), // index scale | 327 Instance::ElementSizeFor(kArrayCid), // index scale |
| 328 kArrayCid, | 328 kArrayCid, |
| 329 Isolate::kNoDeoptId, | 329 Thread::kNoDeoptId, |
| 330 builder.TokenPos())); | 330 builder.TokenPos())); |
| 331 builder.AddIntrinsicReturn(new Value(result)); | 331 builder.AddIntrinsicReturn(new Value(result)); |
| 332 return true; | 332 return true; |
| 333 } | 333 } |
| 334 | 334 |
| 335 | 335 |
| 336 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { | 336 bool Intrinsifier::Build_ImmutableArrayGetIndexed(FlowGraph* flow_graph) { |
| 337 return Build_ObjectArrayGetIndexed(flow_graph); | 337 return Build_ObjectArrayGetIndexed(flow_graph); |
| 338 } | 338 } |
| 339 | 339 |
| 340 | 340 |
| 341 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { | 341 bool Intrinsifier::Build_Uint8ArrayGetIndexed(FlowGraph* flow_graph) { |
| 342 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 342 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 343 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 343 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 344 BlockBuilder builder(flow_graph, normal_entry); | 344 BlockBuilder builder(flow_graph, normal_entry); |
| 345 | 345 |
| 346 Definition* index = builder.AddParameter(1); | 346 Definition* index = builder.AddParameter(1); |
| 347 Definition* array = builder.AddParameter(2); | 347 Definition* array = builder.AddParameter(2); |
| 348 | 348 |
| 349 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 349 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 350 | 350 |
| 351 Definition* result = builder.AddDefinition( | 351 Definition* result = builder.AddDefinition( |
| 352 new LoadIndexedInstr(new Value(array), | 352 new LoadIndexedInstr(new Value(array), |
| 353 new Value(index), | 353 new Value(index), |
| 354 1, // index scale | 354 1, // index scale |
| 355 kTypedDataUint8ArrayCid, | 355 kTypedDataUint8ArrayCid, |
| 356 Isolate::kNoDeoptId, | 356 Thread::kNoDeoptId, |
| 357 builder.TokenPos())); | 357 builder.TokenPos())); |
| 358 builder.AddIntrinsicReturn(new Value(result)); | 358 builder.AddIntrinsicReturn(new Value(result)); |
| 359 return true; | 359 return true; |
| 360 } | 360 } |
| 361 | 361 |
| 362 | 362 |
| 363 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { | 363 bool Intrinsifier::Build_ExternalUint8ArrayGetIndexed(FlowGraph* flow_graph) { |
| 364 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 364 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 365 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 365 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 366 BlockBuilder builder(flow_graph, normal_entry); | 366 BlockBuilder builder(flow_graph, normal_entry); |
| 367 | 367 |
| 368 Definition* index = builder.AddParameter(1); | 368 Definition* index = builder.AddParameter(1); |
| 369 Definition* array = builder.AddParameter(2); | 369 Definition* array = builder.AddParameter(2); |
| 370 | 370 |
| 371 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | 371 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); |
| 372 | 372 |
| 373 Definition* elements = builder.AddDefinition( | 373 Definition* elements = builder.AddDefinition( |
| 374 new LoadUntaggedInstr(new Value(array), | 374 new LoadUntaggedInstr(new Value(array), |
| 375 ExternalTypedData::data_offset())); | 375 ExternalTypedData::data_offset())); |
| 376 Definition* result = builder.AddDefinition( | 376 Definition* result = builder.AddDefinition( |
| 377 new LoadIndexedInstr(new Value(elements), | 377 new LoadIndexedInstr(new Value(elements), |
| 378 new Value(index), | 378 new Value(index), |
| 379 1, // index scale | 379 1, // index scale |
| 380 kExternalTypedDataUint8ArrayCid, | 380 kExternalTypedDataUint8ArrayCid, |
| 381 Isolate::kNoDeoptId, | 381 Thread::kNoDeoptId, |
| 382 builder.TokenPos())); | 382 builder.TokenPos())); |
| 383 builder.AddIntrinsicReturn(new Value(result)); | 383 builder.AddIntrinsicReturn(new Value(result)); |
| 384 return true; | 384 return true; |
| 385 } | 385 } |
| 386 | 386 |
| 387 | 387 |
| 388 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { | 388 bool Intrinsifier::Build_Uint8ArraySetIndexed(FlowGraph* flow_graph) { |
| 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 389 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 390 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 391 BlockBuilder builder(flow_graph, normal_entry); | 391 BlockBuilder builder(flow_graph, normal_entry); |
| 392 | 392 |
| 393 Definition* value = builder.AddParameter(1); | 393 Definition* value = builder.AddParameter(1); |
| 394 Definition* index = builder.AddParameter(2); | 394 Definition* index = builder.AddParameter(2); |
| 395 Definition* array = builder.AddParameter(3); | 395 Definition* array = builder.AddParameter(3); |
| 396 | 396 |
| 397 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 397 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 398 | 398 |
| 399 builder.AddInstruction( | 399 builder.AddInstruction( |
| 400 new CheckSmiInstr(new Value(value), | 400 new CheckSmiInstr(new Value(value), |
| 401 Isolate::kNoDeoptId, | 401 Thread::kNoDeoptId, |
| 402 builder.TokenPos())); | 402 builder.TokenPos())); |
| 403 | 403 |
| 404 builder.AddInstruction( | 404 builder.AddInstruction( |
| 405 new StoreIndexedInstr(new Value(array), | 405 new StoreIndexedInstr(new Value(array), |
| 406 new Value(index), | 406 new Value(index), |
| 407 new Value(value), | 407 new Value(value), |
| 408 kNoStoreBarrier, | 408 kNoStoreBarrier, |
| 409 1, // index scale | 409 1, // index scale |
| 410 kTypedDataUint8ArrayCid, | 410 kTypedDataUint8ArrayCid, |
| 411 Isolate::kNoDeoptId, | 411 Thread::kNoDeoptId, |
| 412 builder.TokenPos())); | 412 builder.TokenPos())); |
| 413 // Return null. | 413 // Return null. |
| 414 Definition* null_def = builder.AddNullDefinition(); | 414 Definition* null_def = builder.AddNullDefinition(); |
| 415 builder.AddIntrinsicReturn(new Value(null_def)); | 415 builder.AddIntrinsicReturn(new Value(null_def)); |
| 416 return true; | 416 return true; |
| 417 } | 417 } |
| 418 | 418 |
| 419 | 419 |
| 420 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { | 420 bool Intrinsifier::Build_ExternalUint8ArraySetIndexed(FlowGraph* flow_graph) { |
| 421 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 421 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 422 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 422 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 423 BlockBuilder builder(flow_graph, normal_entry); | 423 BlockBuilder builder(flow_graph, normal_entry); |
| 424 | 424 |
| 425 Definition* value = builder.AddParameter(1); | 425 Definition* value = builder.AddParameter(1); |
| 426 Definition* index = builder.AddParameter(2); | 426 Definition* index = builder.AddParameter(2); |
| 427 Definition* array = builder.AddParameter(3); | 427 Definition* array = builder.AddParameter(3); |
| 428 | 428 |
| 429 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); | 429 PrepareIndexedOp(&builder, array, index, ExternalTypedData::length_offset()); |
| 430 | 430 |
| 431 builder.AddInstruction( | 431 builder.AddInstruction( |
| 432 new CheckSmiInstr(new Value(value), | 432 new CheckSmiInstr(new Value(value), |
| 433 Isolate::kNoDeoptId, | 433 Thread::kNoDeoptId, |
| 434 builder.TokenPos())); | 434 builder.TokenPos())); |
| 435 Definition* elements = builder.AddDefinition( | 435 Definition* elements = builder.AddDefinition( |
| 436 new LoadUntaggedInstr(new Value(array), | 436 new LoadUntaggedInstr(new Value(array), |
| 437 ExternalTypedData::data_offset())); | 437 ExternalTypedData::data_offset())); |
| 438 builder.AddInstruction( | 438 builder.AddInstruction( |
| 439 new StoreIndexedInstr(new Value(elements), | 439 new StoreIndexedInstr(new Value(elements), |
| 440 new Value(index), | 440 new Value(index), |
| 441 new Value(value), | 441 new Value(value), |
| 442 kNoStoreBarrier, | 442 kNoStoreBarrier, |
| 443 1, // index scale | 443 1, // index scale |
| 444 kExternalTypedDataUint8ArrayCid, | 444 kExternalTypedDataUint8ArrayCid, |
| 445 Isolate::kNoDeoptId, | 445 Thread::kNoDeoptId, |
| 446 builder.TokenPos())); | 446 builder.TokenPos())); |
| 447 // Return null. | 447 // Return null. |
| 448 Definition* null_def = builder.AddNullDefinition(); | 448 Definition* null_def = builder.AddNullDefinition(); |
| 449 builder.AddIntrinsicReturn(new Value(null_def)); | 449 builder.AddIntrinsicReturn(new Value(null_def)); |
| 450 return true; | 450 return true; |
| 451 } | 451 } |
| 452 | 452 |
| 453 | 453 |
| 454 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { | 454 bool Intrinsifier::Build_Uint32ArraySetIndexed(FlowGraph* flow_graph) { |
| 455 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 455 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 456 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 456 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 457 BlockBuilder builder(flow_graph, normal_entry); | 457 BlockBuilder builder(flow_graph, normal_entry); |
| 458 | 458 |
| 459 Definition* value = builder.AddParameter(1); | 459 Definition* value = builder.AddParameter(1); |
| 460 Definition* index = builder.AddParameter(2); | 460 Definition* index = builder.AddParameter(2); |
| 461 Definition* array = builder.AddParameter(3); | 461 Definition* array = builder.AddParameter(3); |
| 462 | 462 |
| 463 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 463 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 464 | 464 |
| 465 Definition* unboxed_value = | 465 Definition* unboxed_value = |
| 466 builder.AddUnboxInstr(kUnboxedUint32, new Value(value)); | 466 builder.AddUnboxInstr(kUnboxedUint32, new Value(value)); |
| 467 | 467 |
| 468 builder.AddInstruction( | 468 builder.AddInstruction( |
| 469 new StoreIndexedInstr(new Value(array), | 469 new StoreIndexedInstr(new Value(array), |
| 470 new Value(index), | 470 new Value(index), |
| 471 new Value(unboxed_value), | 471 new Value(unboxed_value), |
| 472 kNoStoreBarrier, | 472 kNoStoreBarrier, |
| 473 4, // index scale | 473 4, // index scale |
| 474 kTypedDataUint32ArrayCid, | 474 kTypedDataUint32ArrayCid, |
| 475 Isolate::kNoDeoptId, | 475 Thread::kNoDeoptId, |
| 476 builder.TokenPos())); | 476 builder.TokenPos())); |
| 477 // Return null. | 477 // Return null. |
| 478 Definition* null_def = builder.AddNullDefinition(); | 478 Definition* null_def = builder.AddNullDefinition(); |
| 479 builder.AddIntrinsicReturn(new Value(null_def)); | 479 builder.AddIntrinsicReturn(new Value(null_def)); |
| 480 return true; | 480 return true; |
| 481 } | 481 } |
| 482 | 482 |
| 483 | 483 |
| 484 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { | 484 bool Intrinsifier::Build_Uint32ArrayGetIndexed(FlowGraph* flow_graph) { |
| 485 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 485 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 486 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 486 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 487 BlockBuilder builder(flow_graph, normal_entry); | 487 BlockBuilder builder(flow_graph, normal_entry); |
| 488 | 488 |
| 489 Definition* index = builder.AddParameter(1); | 489 Definition* index = builder.AddParameter(1); |
| 490 Definition* array = builder.AddParameter(2); | 490 Definition* array = builder.AddParameter(2); |
| 491 | 491 |
| 492 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 492 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 493 | 493 |
| 494 Definition* unboxed_value = builder.AddDefinition( | 494 Definition* unboxed_value = builder.AddDefinition( |
| 495 new LoadIndexedInstr(new Value(array), | 495 new LoadIndexedInstr(new Value(array), |
| 496 new Value(index), | 496 new Value(index), |
| 497 4, // index scale | 497 4, // index scale |
| 498 kTypedDataUint32ArrayCid, | 498 kTypedDataUint32ArrayCid, |
| 499 Isolate::kNoDeoptId, | 499 Thread::kNoDeoptId, |
| 500 builder.TokenPos())); | 500 builder.TokenPos())); |
| 501 Definition* result = builder.AddDefinition( | 501 Definition* result = builder.AddDefinition( |
| 502 BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); | 502 BoxInstr::Create(kUnboxedUint32, new Value(unboxed_value))); |
| 503 builder.AddIntrinsicReturn(new Value(result)); | 503 builder.AddIntrinsicReturn(new Value(result)); |
| 504 return true; | 504 return true; |
| 505 } | 505 } |
| 506 | 506 |
| 507 | 507 |
| 508 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { | 508 bool Intrinsifier::Build_Float64ArraySetIndexed(FlowGraph* flow_graph) { |
| 509 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 509 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 510 | 510 |
| 511 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 511 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 512 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 512 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 513 BlockBuilder builder(flow_graph, normal_entry); | 513 BlockBuilder builder(flow_graph, normal_entry); |
| 514 | 514 |
| 515 Definition* value = builder.AddParameter(1); | 515 Definition* value = builder.AddParameter(1); |
| 516 Definition* index = builder.AddParameter(2); | 516 Definition* index = builder.AddParameter(2); |
| 517 Definition* array = builder.AddParameter(3); | 517 Definition* array = builder.AddParameter(3); |
| 518 | 518 |
| 519 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 519 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 520 | 520 |
| 521 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 521 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 522 flow_graph->function(), | 522 flow_graph->function(), |
| 523 String::Handle(flow_graph->function().name()), | 523 String::Handle(flow_graph->function().name()), |
| 524 Object::empty_array(), // Dummy args. descr. | 524 Object::empty_array(), // Dummy args. descr. |
| 525 Isolate::kNoDeoptId, | 525 Thread::kNoDeoptId, |
| 526 1)); | 526 1)); |
| 527 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); | 527 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); |
| 528 builder.AddInstruction( | 528 builder.AddInstruction( |
| 529 new CheckClassInstr(new Value(value), | 529 new CheckClassInstr(new Value(value), |
| 530 Isolate::kNoDeoptId, | 530 Thread::kNoDeoptId, |
| 531 value_check, | 531 value_check, |
| 532 builder.TokenPos())); | 532 builder.TokenPos())); |
| 533 Definition* double_value = | 533 Definition* double_value = |
| 534 builder.AddUnboxInstr(kUnboxedDouble, new Value(value)); | 534 builder.AddUnboxInstr(kUnboxedDouble, new Value(value)); |
| 535 | 535 |
| 536 builder.AddInstruction( | 536 builder.AddInstruction( |
| 537 new StoreIndexedInstr(new Value(array), | 537 new StoreIndexedInstr(new Value(array), |
| 538 new Value(index), | 538 new Value(index), |
| 539 new Value(double_value), | 539 new Value(double_value), |
| 540 kNoStoreBarrier, | 540 kNoStoreBarrier, |
| 541 8, // index scale | 541 8, // index scale |
| 542 kTypedDataFloat64ArrayCid, | 542 kTypedDataFloat64ArrayCid, |
| 543 Isolate::kNoDeoptId, | 543 Thread::kNoDeoptId, |
| 544 builder.TokenPos())); | 544 builder.TokenPos())); |
| 545 // Return null. | 545 // Return null. |
| 546 Definition* null_def = builder.AddNullDefinition(); | 546 Definition* null_def = builder.AddNullDefinition(); |
| 547 builder.AddIntrinsicReturn(new Value(null_def)); | 547 builder.AddIntrinsicReturn(new Value(null_def)); |
| 548 return true; | 548 return true; |
| 549 } | 549 } |
| 550 | 550 |
| 551 | 551 |
| 552 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { | 552 bool Intrinsifier::Build_Float64ArrayGetIndexed(FlowGraph* flow_graph) { |
| 553 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; | 553 if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false; |
| 554 | 554 |
| 555 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 555 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 556 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 556 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 557 BlockBuilder builder(flow_graph, normal_entry); | 557 BlockBuilder builder(flow_graph, normal_entry); |
| 558 | 558 |
| 559 Definition* index = builder.AddParameter(1); | 559 Definition* index = builder.AddParameter(1); |
| 560 Definition* array = builder.AddParameter(2); | 560 Definition* array = builder.AddParameter(2); |
| 561 | 561 |
| 562 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); | 562 PrepareIndexedOp(&builder, array, index, TypedData::length_offset()); |
| 563 | 563 |
| 564 Definition* unboxed_value = builder.AddDefinition( | 564 Definition* unboxed_value = builder.AddDefinition( |
| 565 new LoadIndexedInstr(new Value(array), | 565 new LoadIndexedInstr(new Value(array), |
| 566 new Value(index), | 566 new Value(index), |
| 567 8, // index scale | 567 8, // index scale |
| 568 kTypedDataFloat64ArrayCid, | 568 kTypedDataFloat64ArrayCid, |
| 569 Isolate::kNoDeoptId, | 569 Thread::kNoDeoptId, |
| 570 builder.TokenPos())); | 570 builder.TokenPos())); |
| 571 Definition* result = builder.AddDefinition( | 571 Definition* result = builder.AddDefinition( |
| 572 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); | 572 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); |
| 573 builder.AddIntrinsicReturn(new Value(result)); | 573 builder.AddIntrinsicReturn(new Value(result)); |
| 574 return true; | 574 return true; |
| 575 } | 575 } |
| 576 | 576 |
| 577 | 577 |
| 578 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { | 578 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { |
| 579 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; | 579 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |
| 580 | 580 |
| 581 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 581 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 582 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 582 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 583 BlockBuilder builder(flow_graph, normal_entry); | 583 BlockBuilder builder(flow_graph, normal_entry); |
| 584 | 584 |
| 585 Definition* right = builder.AddParameter(1); | 585 Definition* right = builder.AddParameter(1); |
| 586 Definition* left = builder.AddParameter(2); | 586 Definition* left = builder.AddParameter(2); |
| 587 | 587 |
| 588 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 588 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 589 flow_graph->function(), | 589 flow_graph->function(), |
| 590 String::Handle(flow_graph->function().name()), | 590 String::Handle(flow_graph->function().name()), |
| 591 Object::empty_array(), // Dummy args. descr. | 591 Object::empty_array(), // Dummy args. descr. |
| 592 Isolate::kNoDeoptId, | 592 Thread::kNoDeoptId, |
| 593 1)); | 593 1)); |
| 594 value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); | 594 value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); |
| 595 // Check argument. Receiver (left) is known to be a Float32x4. | 595 // Check argument. Receiver (left) is known to be a Float32x4. |
| 596 builder.AddInstruction( | 596 builder.AddInstruction( |
| 597 new CheckClassInstr(new Value(right), | 597 new CheckClassInstr(new Value(right), |
| 598 Isolate::kNoDeoptId, | 598 Thread::kNoDeoptId, |
| 599 value_check, | 599 value_check, |
| 600 builder.TokenPos())); | 600 builder.TokenPos())); |
| 601 Definition* left_simd = | 601 Definition* left_simd = |
| 602 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left)); | 602 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left)); |
| 603 | 603 |
| 604 Definition* right_simd = | 604 Definition* right_simd = |
| 605 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right)); | 605 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right)); |
| 606 | 606 |
| 607 Definition* unboxed_result = builder.AddDefinition( | 607 Definition* unboxed_result = builder.AddDefinition( |
| 608 new BinaryFloat32x4OpInstr(kind, | 608 new BinaryFloat32x4OpInstr(kind, |
| 609 new Value(left_simd), | 609 new Value(left_simd), |
| 610 new Value(right_simd), | 610 new Value(right_simd), |
| 611 Isolate::kNoDeoptId)); | 611 Thread::kNoDeoptId)); |
| 612 Definition* result = builder.AddDefinition( | 612 Definition* result = builder.AddDefinition( |
| 613 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); | 613 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); |
| 614 builder.AddIntrinsicReturn(new Value(result)); | 614 builder.AddIntrinsicReturn(new Value(result)); |
| 615 return true; | 615 return true; |
| 616 } | 616 } |
| 617 | 617 |
| 618 | 618 |
| 619 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { | 619 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { |
| 620 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); | 620 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); |
| 621 } | 621 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 640 | 640 |
| 641 Definition* receiver = builder.AddParameter(1); | 641 Definition* receiver = builder.AddParameter(1); |
| 642 | 642 |
| 643 Definition* unboxed_receiver = | 643 Definition* unboxed_receiver = |
| 644 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver)); | 644 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver)); |
| 645 | 645 |
| 646 Definition* unboxed_result = builder.AddDefinition( | 646 Definition* unboxed_result = builder.AddDefinition( |
| 647 new Simd32x4ShuffleInstr(kind, | 647 new Simd32x4ShuffleInstr(kind, |
| 648 new Value(unboxed_receiver), | 648 new Value(unboxed_receiver), |
| 649 0, | 649 0, |
| 650 Isolate::kNoDeoptId)); | 650 Thread::kNoDeoptId)); |
| 651 | 651 |
| 652 Definition* result = builder.AddDefinition( | 652 Definition* result = builder.AddDefinition( |
| 653 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); | 653 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
| 654 builder.AddIntrinsicReturn(new Value(result)); | 654 builder.AddIntrinsicReturn(new Value(result)); |
| 655 return true; | 655 return true; |
| 656 } | 656 } |
| 657 | 657 |
| 658 | 658 |
| 659 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { | 659 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { |
| 660 return BuildFloat32x4Shuffle(flow_graph, | 660 return BuildFloat32x4Shuffle(flow_graph, |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 Definition* backing_store = builder.AddDefinition( | 758 Definition* backing_store = builder.AddDefinition( |
| 759 new LoadFieldInstr(new Value(growable_array), | 759 new LoadFieldInstr(new Value(growable_array), |
| 760 GrowableObjectArray::data_offset(), | 760 GrowableObjectArray::data_offset(), |
| 761 Type::ZoneHandle(), | 761 Type::ZoneHandle(), |
| 762 builder.TokenPos())); | 762 builder.TokenPos())); |
| 763 Definition* result = builder.AddDefinition( | 763 Definition* result = builder.AddDefinition( |
| 764 new LoadIndexedInstr(new Value(backing_store), | 764 new LoadIndexedInstr(new Value(backing_store), |
| 765 new Value(index), | 765 new Value(index), |
| 766 Instance::ElementSizeFor(kArrayCid), // index scale | 766 Instance::ElementSizeFor(kArrayCid), // index scale |
| 767 kArrayCid, | 767 kArrayCid, |
| 768 Isolate::kNoDeoptId, | 768 Thread::kNoDeoptId, |
| 769 builder.TokenPos())); | 769 builder.TokenPos())); |
| 770 builder.AddIntrinsicReturn(new Value(result)); | 770 builder.AddIntrinsicReturn(new Value(result)); |
| 771 return true; | 771 return true; |
| 772 } | 772 } |
| 773 | 773 |
| 774 | 774 |
| 775 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { | 775 bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) { |
| 776 if (Isolate::Current()->flags().type_checks()) { | 776 if (Isolate::Current()->flags().type_checks()) { |
| 777 return false; | 777 return false; |
| 778 } | 778 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 794 Type::ZoneHandle(), | 794 Type::ZoneHandle(), |
| 795 builder.TokenPos())); | 795 builder.TokenPos())); |
| 796 | 796 |
| 797 builder.AddInstruction( | 797 builder.AddInstruction( |
| 798 new StoreIndexedInstr(new Value(backing_store), | 798 new StoreIndexedInstr(new Value(backing_store), |
| 799 new Value(index), | 799 new Value(index), |
| 800 new Value(value), | 800 new Value(value), |
| 801 kEmitStoreBarrier, | 801 kEmitStoreBarrier, |
| 802 Instance::ElementSizeFor(kArrayCid), // index scale | 802 Instance::ElementSizeFor(kArrayCid), // index scale |
| 803 kArrayCid, | 803 kArrayCid, |
| 804 Isolate::kNoDeoptId, | 804 Thread::kNoDeoptId, |
| 805 builder.TokenPos())); | 805 builder.TokenPos())); |
| 806 // Return null. | 806 // Return null. |
| 807 Definition* null_def = builder.AddNullDefinition(); | 807 Definition* null_def = builder.AddNullDefinition(); |
| 808 builder.AddIntrinsicReturn(new Value(null_def)); | 808 builder.AddIntrinsicReturn(new Value(null_def)); |
| 809 return true; | 809 return true; |
| 810 } | 810 } |
| 811 | 811 |
| 812 | 812 |
| 813 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { | 813 bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) { |
| 814 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 814 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 815 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 815 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 816 BlockBuilder builder(flow_graph, normal_entry); | 816 BlockBuilder builder(flow_graph, normal_entry); |
| 817 | 817 |
| 818 Definition* data = builder.AddParameter(1); | 818 Definition* data = builder.AddParameter(1); |
| 819 Definition* growable_array = builder.AddParameter(2); | 819 Definition* growable_array = builder.AddParameter(2); |
| 820 | 820 |
| 821 const ICData& value_check = ICData::ZoneHandle(ICData::New( | 821 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 822 flow_graph->function(), | 822 flow_graph->function(), |
| 823 String::Handle(flow_graph->function().name()), | 823 String::Handle(flow_graph->function().name()), |
| 824 Object::empty_array(), // Dummy args. descr. | 824 Object::empty_array(), // Dummy args. descr. |
| 825 Isolate::kNoDeoptId, | 825 Thread::kNoDeoptId, |
| 826 1)); | 826 1)); |
| 827 value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); | 827 value_check.AddReceiverCheck(kArrayCid, flow_graph->function()); |
| 828 builder.AddInstruction( | 828 builder.AddInstruction( |
| 829 new CheckClassInstr(new Value(data), | 829 new CheckClassInstr(new Value(data), |
| 830 Isolate::kNoDeoptId, | 830 Thread::kNoDeoptId, |
| 831 value_check, | 831 value_check, |
| 832 builder.TokenPos())); | 832 builder.TokenPos())); |
| 833 | 833 |
| 834 builder.AddInstruction( | 834 builder.AddInstruction( |
| 835 new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), | 835 new StoreInstanceFieldInstr(GrowableObjectArray::data_offset(), |
| 836 new Value(growable_array), | 836 new Value(growable_array), |
| 837 new Value(data), | 837 new Value(data), |
| 838 kEmitStoreBarrier, | 838 kEmitStoreBarrier, |
| 839 builder.TokenPos())); | 839 builder.TokenPos())); |
| 840 // Return null. | 840 // Return null. |
| 841 Definition* null_def = builder.AddNullDefinition(); | 841 Definition* null_def = builder.AddNullDefinition(); |
| 842 builder.AddIntrinsicReturn(new Value(null_def)); | 842 builder.AddIntrinsicReturn(new Value(null_def)); |
| 843 return true; | 843 return true; |
| 844 } | 844 } |
| 845 | 845 |
| 846 | 846 |
| 847 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { | 847 bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) { |
| 848 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 848 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 849 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 849 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 850 BlockBuilder builder(flow_graph, normal_entry); | 850 BlockBuilder builder(flow_graph, normal_entry); |
| 851 | 851 |
| 852 Definition* length = builder.AddParameter(1); | 852 Definition* length = builder.AddParameter(1); |
| 853 Definition* growable_array = builder.AddParameter(2); | 853 Definition* growable_array = builder.AddParameter(2); |
| 854 | 854 |
| 855 builder.AddInstruction( | 855 builder.AddInstruction( |
| 856 new CheckSmiInstr(new Value(length), | 856 new CheckSmiInstr(new Value(length), |
| 857 Isolate::kNoDeoptId, | 857 Thread::kNoDeoptId, |
| 858 builder.TokenPos())); | 858 builder.TokenPos())); |
| 859 builder.AddInstruction( | 859 builder.AddInstruction( |
| 860 new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), | 860 new StoreInstanceFieldInstr(GrowableObjectArray::length_offset(), |
| 861 new Value(growable_array), | 861 new Value(growable_array), |
| 862 new Value(length), | 862 new Value(length), |
| 863 kNoStoreBarrier, | 863 kNoStoreBarrier, |
| 864 builder.TokenPos())); | 864 builder.TokenPos())); |
| 865 Definition* null_def = builder.AddNullDefinition(); | 865 Definition* null_def = builder.AddNullDefinition(); |
| 866 builder.AddIntrinsicReturn(new Value(null_def)); | 866 builder.AddIntrinsicReturn(new Value(null_def)); |
| 867 return true; | 867 return true; |
| 868 } | 868 } |
| 869 | 869 |
| 870 } // namespace dart | 870 } // namespace dart |
| OLD | NEW |