OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 | 4 |
5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ | 5 #ifndef VM_INTERMEDIATE_LANGUAGE_H_ |
6 #define VM_INTERMEDIATE_LANGUAGE_H_ | 6 #define VM_INTERMEDIATE_LANGUAGE_H_ |
7 | 7 |
8 #include "vm/allocation.h" | 8 #include "vm/allocation.h" |
9 #include "vm/ast.h" | 9 #include "vm/ast.h" |
10 #include "vm/growable_array.h" | 10 #include "vm/growable_array.h" |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 | 416 |
417 // Instructions. | 417 // Instructions. |
418 | 418 |
419 // M is a single argument macro. It is applied to each concrete instruction | 419 // M is a single argument macro. It is applied to each concrete instruction |
420 // type name. The concrete instruction classes are the name with Instr | 420 // type name. The concrete instruction classes are the name with Instr |
421 // concatenated. | 421 // concatenated. |
422 #define FOR_EACH_INSTRUCTION(M) \ | 422 #define FOR_EACH_INSTRUCTION(M) \ |
423 M(GraphEntry) \ | 423 M(GraphEntry) \ |
424 M(JoinEntry) \ | 424 M(JoinEntry) \ |
425 M(TargetEntry) \ | 425 M(TargetEntry) \ |
| 426 M(IndirectEntry) \ |
426 M(CatchBlockEntry) \ | 427 M(CatchBlockEntry) \ |
427 M(Phi) \ | 428 M(Phi) \ |
428 M(Redefinition) \ | 429 M(Redefinition) \ |
429 M(Parameter) \ | 430 M(Parameter) \ |
430 M(ParallelMove) \ | 431 M(ParallelMove) \ |
431 M(PushArgument) \ | 432 M(PushArgument) \ |
432 M(Return) \ | 433 M(Return) \ |
433 M(Throw) \ | 434 M(Throw) \ |
434 M(ReThrow) \ | 435 M(ReThrow) \ |
435 M(Goto) \ | 436 M(Goto) \ |
| 437 M(IndirectGoto) \ |
436 M(Branch) \ | 438 M(Branch) \ |
437 M(AssertAssignable) \ | 439 M(AssertAssignable) \ |
438 M(AssertBoolean) \ | 440 M(AssertBoolean) \ |
439 M(CurrentContext) \ | 441 M(CurrentContext) \ |
440 M(StoreContext) \ | 442 M(StoreContext) \ |
441 M(ClosureCall) \ | 443 M(ClosureCall) \ |
442 M(InstanceCall) \ | 444 M(InstanceCall) \ |
443 M(PolymorphicInstanceCall) \ | 445 M(PolymorphicInstanceCall) \ |
444 M(StaticCall) \ | 446 M(StaticCall) \ |
445 M(LoadLocal) \ | 447 M(LoadLocal) \ |
446 M(PushTemp) \ | 448 M(PushTemp) \ |
447 M(DropTemps) \ | 449 M(DropTemps) \ |
448 M(StoreLocal) \ | 450 M(StoreLocal) \ |
449 M(StrictCompare) \ | 451 M(StrictCompare) \ |
450 M(EqualityCompare) \ | 452 M(EqualityCompare) \ |
451 M(RelationalOp) \ | 453 M(RelationalOp) \ |
452 M(NativeCall) \ | 454 M(NativeCall) \ |
453 M(DebugStepCheck) \ | 455 M(DebugStepCheck) \ |
454 M(LoadIndexed) \ | 456 M(LoadIndexed) \ |
| 457 M(LoadCodeUnits) \ |
455 M(StoreIndexed) \ | 458 M(StoreIndexed) \ |
456 M(StoreInstanceField) \ | 459 M(StoreInstanceField) \ |
457 M(InitStaticField) \ | 460 M(InitStaticField) \ |
458 M(LoadStaticField) \ | 461 M(LoadStaticField) \ |
459 M(StoreStaticField) \ | 462 M(StoreStaticField) \ |
460 M(BooleanNegate) \ | 463 M(BooleanNegate) \ |
461 M(InstanceOf) \ | 464 M(InstanceOf) \ |
462 M(CreateArray) \ | 465 M(CreateArray) \ |
463 M(AllocateObject) \ | 466 M(AllocateObject) \ |
464 M(LoadField) \ | 467 M(LoadField) \ |
(...skipping 19 matching lines...) Expand all Loading... |
484 M(FloatToDouble) \ | 487 M(FloatToDouble) \ |
485 M(CheckClass) \ | 488 M(CheckClass) \ |
486 M(CheckClassId) \ | 489 M(CheckClassId) \ |
487 M(CheckSmi) \ | 490 M(CheckSmi) \ |
488 M(Constant) \ | 491 M(Constant) \ |
489 M(UnboxedConstant) \ | 492 M(UnboxedConstant) \ |
490 M(CheckEitherNonSmi) \ | 493 M(CheckEitherNonSmi) \ |
491 M(BinaryDoubleOp) \ | 494 M(BinaryDoubleOp) \ |
492 M(MathUnary) \ | 495 M(MathUnary) \ |
493 M(MathMinMax) \ | 496 M(MathMinMax) \ |
| 497 M(CaseInsensitiveCompareUC16) \ |
494 M(UnboxDouble) \ | 498 M(UnboxDouble) \ |
495 M(BoxDouble) \ | 499 M(BoxDouble) \ |
496 M(BoxFloat32x4) \ | 500 M(BoxFloat32x4) \ |
497 M(UnboxFloat32x4) \ | 501 M(UnboxFloat32x4) \ |
498 M(BoxInt32x4) \ | 502 M(BoxInt32x4) \ |
499 M(UnboxInt32x4) \ | 503 M(UnboxInt32x4) \ |
500 M(UnboxInteger) \ | 504 M(UnboxInteger) \ |
501 M(BoxInteger) \ | 505 M(BoxInteger) \ |
502 M(BinaryMintOp) \ | 506 M(BinaryMintOp) \ |
503 M(ShiftMintOp) \ | 507 M(ShiftMintOp) \ |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1207 return const_cast<BlockEntryInstr*>(this); | 1211 return const_cast<BlockEntryInstr*>(this); |
1208 } | 1212 } |
1209 | 1213 |
1210 // Helper to mutate the graph during inlining. This block should be | 1214 // Helper to mutate the graph during inlining. This block should be |
1211 // replaced with new_block as a predecessor of all of this block's | 1215 // replaced with new_block as a predecessor of all of this block's |
1212 // successors. | 1216 // successors. |
1213 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); | 1217 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); |
1214 | 1218 |
1215 void set_block_id(intptr_t block_id) { block_id_ = block_id; } | 1219 void set_block_id(intptr_t block_id) { block_id_ = block_id; } |
1216 | 1220 |
| 1221 intptr_t offset() const { return offset_; } |
| 1222 void set_offset(intptr_t offset) { offset_ = offset; } |
| 1223 |
1217 // For all instruction in this block: Remove all inputs (including in the | 1224 // For all instruction in this block: Remove all inputs (including in the |
1218 // environment) from their definition's use lists for all instructions. | 1225 // environment) from their definition's use lists for all instructions. |
1219 void ClearAllInstructions(); | 1226 void ClearAllInstructions(); |
1220 | 1227 |
1221 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) | 1228 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) |
1222 | 1229 |
1223 protected: | 1230 protected: |
1224 BlockEntryInstr(intptr_t block_id, intptr_t try_index) | 1231 BlockEntryInstr(intptr_t block_id, intptr_t try_index) |
1225 : block_id_(block_id), | 1232 : block_id_(block_id), |
1226 try_index_(try_index), | 1233 try_index_(try_index), |
1227 preorder_number_(-1), | 1234 preorder_number_(-1), |
1228 postorder_number_(-1), | 1235 postorder_number_(-1), |
1229 dominator_(NULL), | 1236 dominator_(NULL), |
1230 dominated_blocks_(1), | 1237 dominated_blocks_(1), |
1231 last_instruction_(NULL), | 1238 last_instruction_(NULL), |
| 1239 offset_(-1), |
1232 parallel_move_(NULL), | 1240 parallel_move_(NULL), |
1233 loop_info_(NULL) { | 1241 loop_info_(NULL) { |
1234 deopt_id_ = Isolate::Current()->GetNextDeoptId(); | 1242 deopt_id_ = Isolate::Current()->GetNextDeoptId(); |
1235 } | 1243 } |
1236 | 1244 |
1237 private: | 1245 private: |
1238 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } | 1246 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } |
1239 | 1247 |
1240 virtual void ClearPredecessors() = 0; | 1248 virtual void ClearPredecessors() = 0; |
1241 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; | 1249 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; |
1242 | 1250 |
1243 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } | 1251 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } |
1244 | 1252 |
1245 intptr_t block_id_; | 1253 intptr_t block_id_; |
1246 const intptr_t try_index_; | 1254 const intptr_t try_index_; |
1247 intptr_t preorder_number_; | 1255 intptr_t preorder_number_; |
1248 intptr_t postorder_number_; | 1256 intptr_t postorder_number_; |
1249 // Starting and ending lifetime positions for this block. Used by | 1257 // Starting and ending lifetime positions for this block. Used by |
1250 // the linear scan register allocator. | 1258 // the linear scan register allocator. |
1251 intptr_t start_pos_; | 1259 intptr_t start_pos_; |
1252 intptr_t end_pos_; | 1260 intptr_t end_pos_; |
1253 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. | 1261 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. |
1254 // TODO(fschneider): Optimize the case of one child to save space. | 1262 // TODO(fschneider): Optimize the case of one child to save space. |
1255 GrowableArray<BlockEntryInstr*> dominated_blocks_; | 1263 GrowableArray<BlockEntryInstr*> dominated_blocks_; |
1256 Instruction* last_instruction_; | 1264 Instruction* last_instruction_; |
1257 | 1265 |
| 1266 // Offset of this block from the start of the emitted code. |
| 1267 intptr_t offset_; |
| 1268 |
1258 // Parallel move that will be used by linear scan register allocator to | 1269 // Parallel move that will be used by linear scan register allocator to |
1259 // connect live ranges at the start of the block. | 1270 // connect live ranges at the start of the block. |
1260 ParallelMoveInstr* parallel_move_; | 1271 ParallelMoveInstr* parallel_move_; |
1261 | 1272 |
1262 // Bit vector containg loop blocks for a loop header indexed by block | 1273 // Bit vector containg loop blocks for a loop header indexed by block |
1263 // preorder number. | 1274 // preorder number. |
1264 BitVector* loop_info_; | 1275 BitVector* loop_info_; |
1265 | 1276 |
1266 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); | 1277 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); |
1267 }; | 1278 }; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1328 UNREACHABLE(); | 1339 UNREACHABLE(); |
1329 return NULL; | 1340 return NULL; |
1330 } | 1341 } |
1331 virtual intptr_t SuccessorCount() const; | 1342 virtual intptr_t SuccessorCount() const; |
1332 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 1343 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
1333 | 1344 |
1334 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } | 1345 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } |
1335 | 1346 |
1336 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); | 1347 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); |
1337 | 1348 |
| 1349 void AddIndirectEntry(IndirectEntryInstr* entry) { |
| 1350 indirect_entries_.Add(entry); |
| 1351 } |
| 1352 |
1338 GrowableArray<Definition*>* initial_definitions() { | 1353 GrowableArray<Definition*>* initial_definitions() { |
1339 return &initial_definitions_; | 1354 return &initial_definitions_; |
1340 } | 1355 } |
1341 ConstantInstr* constant_null(); | 1356 ConstantInstr* constant_null(); |
1342 | 1357 |
1343 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } | 1358 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } |
1344 | 1359 |
1345 intptr_t entry_count() const { return entry_count_; } | 1360 intptr_t entry_count() const { return entry_count_; } |
1346 void set_entry_count(intptr_t count) { entry_count_ = count; } | 1361 void set_entry_count(intptr_t count) { entry_count_ = count; } |
1347 | 1362 |
(...skipping 14 matching lines...) Expand all Loading... |
1362 TargetEntryInstr* normal_entry() const { return normal_entry_; } | 1377 TargetEntryInstr* normal_entry() const { return normal_entry_; } |
1363 | 1378 |
1364 const ParsedFunction& parsed_function() const { | 1379 const ParsedFunction& parsed_function() const { |
1365 return *parsed_function_; | 1380 return *parsed_function_; |
1366 } | 1381 } |
1367 | 1382 |
1368 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { | 1383 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { |
1369 return catch_entries_; | 1384 return catch_entries_; |
1370 } | 1385 } |
1371 | 1386 |
| 1387 const GrowableArray<IndirectEntryInstr*>& indirect_entries() const { |
| 1388 return indirect_entries_; |
| 1389 } |
| 1390 |
1372 virtual void PrintTo(BufferFormatter* f) const; | 1391 virtual void PrintTo(BufferFormatter* f) const; |
1373 | 1392 |
1374 private: | 1393 private: |
1375 virtual void ClearPredecessors() {} | 1394 virtual void ClearPredecessors() {} |
1376 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 1395 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } |
1377 | 1396 |
1378 const ParsedFunction* parsed_function_; | 1397 const ParsedFunction* parsed_function_; |
1379 TargetEntryInstr* normal_entry_; | 1398 TargetEntryInstr* normal_entry_; |
1380 GrowableArray<CatchBlockEntryInstr*> catch_entries_; | 1399 GrowableArray<CatchBlockEntryInstr*> catch_entries_; |
| 1400 // Indirect targets are blocks reachable only through indirect gotos. |
| 1401 GrowableArray<IndirectEntryInstr*> indirect_entries_; |
1381 GrowableArray<Definition*> initial_definitions_; | 1402 GrowableArray<Definition*> initial_definitions_; |
1382 const intptr_t osr_id_; | 1403 const intptr_t osr_id_; |
1383 intptr_t entry_count_; | 1404 intptr_t entry_count_; |
1384 intptr_t spill_slot_count_; | 1405 intptr_t spill_slot_count_; |
1385 intptr_t fixed_slot_count_; // For try-catch in optimized code. | 1406 intptr_t fixed_slot_count_; // For try-catch in optimized code. |
1386 | 1407 |
1387 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 1408 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); |
1388 }; | 1409 }; |
1389 | 1410 |
1390 | 1411 |
(...skipping 25 matching lines...) Expand all Loading... |
1416 virtual void PrintTo(BufferFormatter* f) const; | 1437 virtual void PrintTo(BufferFormatter* f) const; |
1417 | 1438 |
1418 virtual EffectSet Effects() const { return EffectSet::None(); } | 1439 virtual EffectSet Effects() const { return EffectSet::None(); } |
1419 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 1440 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
1420 | 1441 |
1421 private: | 1442 private: |
1422 // Classes that have access to predecessors_ when inlining. | 1443 // Classes that have access to predecessors_ when inlining. |
1423 friend class BlockEntryInstr; | 1444 friend class BlockEntryInstr; |
1424 friend class InlineExitCollector; | 1445 friend class InlineExitCollector; |
1425 friend class PolymorphicInliner; | 1446 friend class PolymorphicInliner; |
| 1447 friend class IndirectEntryInstr; // Access in il_printer.cc. |
1426 | 1448 |
1427 // Direct access to phis_ in order to resize it due to phi elimination. | 1449 // Direct access to phis_ in order to resize it due to phi elimination. |
1428 friend class ConstantPropagator; | 1450 friend class ConstantPropagator; |
1429 friend class DeadCodeElimination; | 1451 friend class DeadCodeElimination; |
1430 | 1452 |
1431 virtual void ClearPredecessors() { predecessors_.Clear(); } | 1453 virtual void ClearPredecessors() { predecessors_.Clear(); } |
1432 virtual void AddPredecessor(BlockEntryInstr* predecessor); | 1454 virtual void AddPredecessor(BlockEntryInstr* predecessor); |
1433 | 1455 |
1434 GrowableArray<BlockEntryInstr*> predecessors_; | 1456 GrowableArray<BlockEntryInstr*> predecessors_; |
1435 ZoneGrowableArray<PhiInstr*>* phis_; | 1457 ZoneGrowableArray<PhiInstr*>* phis_; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 predecessor_ = predecessor; | 1516 predecessor_ = predecessor; |
1495 } | 1517 } |
1496 | 1518 |
1497 BlockEntryInstr* predecessor_; | 1519 BlockEntryInstr* predecessor_; |
1498 double edge_weight_; | 1520 double edge_weight_; |
1499 | 1521 |
1500 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); | 1522 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); |
1501 }; | 1523 }; |
1502 | 1524 |
1503 | 1525 |
| 1526 class IndirectEntryInstr : public JoinEntryInstr { |
| 1527 public: |
| 1528 IndirectEntryInstr(intptr_t block_id, |
| 1529 intptr_t indirect_id, |
| 1530 intptr_t try_index) |
| 1531 : JoinEntryInstr(block_id, try_index), |
| 1532 indirect_id_(indirect_id) { } |
| 1533 |
| 1534 DECLARE_INSTRUCTION(IndirectEntry) |
| 1535 |
| 1536 virtual void PrintTo(BufferFormatter* f) const; |
| 1537 |
| 1538 intptr_t indirect_id() const { return indirect_id_; } |
| 1539 |
| 1540 private: |
| 1541 const intptr_t indirect_id_; |
| 1542 }; |
| 1543 |
| 1544 |
1504 class CatchBlockEntryInstr : public BlockEntryInstr { | 1545 class CatchBlockEntryInstr : public BlockEntryInstr { |
1505 public: | 1546 public: |
1506 CatchBlockEntryInstr(intptr_t block_id, | 1547 CatchBlockEntryInstr(intptr_t block_id, |
1507 intptr_t try_index, | 1548 intptr_t try_index, |
1508 const Array& handler_types, | 1549 const Array& handler_types, |
1509 intptr_t catch_try_index, | 1550 intptr_t catch_try_index, |
1510 const LocalVariable& exception_var, | 1551 const LocalVariable& exception_var, |
1511 const LocalVariable& stacktrace_var, | 1552 const LocalVariable& stacktrace_var, |
1512 bool needs_stacktrace) | 1553 bool needs_stacktrace) |
1513 : BlockEntryInstr(block_id, try_index), | 1554 : BlockEntryInstr(block_id, try_index), |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2181 private: | 2222 private: |
2182 JoinEntryInstr* successor_; | 2223 JoinEntryInstr* successor_; |
2183 double edge_weight_; | 2224 double edge_weight_; |
2184 | 2225 |
2185 // Parallel move that will be used by linear scan register allocator to | 2226 // Parallel move that will be used by linear scan register allocator to |
2186 // connect live ranges at the end of the block and resolve phis. | 2227 // connect live ranges at the end of the block and resolve phis. |
2187 ParallelMoveInstr* parallel_move_; | 2228 ParallelMoveInstr* parallel_move_; |
2188 }; | 2229 }; |
2189 | 2230 |
2190 | 2231 |
| 2232 // As a high level description, an indirect goto takes the indirect_id of an |
| 2233 // indirect entry as a parameter, and jumps to that location. |
| 2234 // |
| 2235 // In more detail: in order to preserve split-edge form, an intermediate target |
| 2236 // entry consisting of a goto to the final indirect entry is inserted on |
| 2237 // each possible indirect goto -> indirect entry edge. These target entries are |
| 2238 // accessible through successors_. |
| 2239 // |
| 2240 // Byte offsets of all possible indirect targets are stored in the offsets_ |
| 2241 // array. The desired offset is looked up while the generated code is executing, |
| 2242 // and passed to IndirectGoto as an input. |
| 2243 class IndirectGotoInstr : public TemplateInstruction<1> { |
| 2244 public: |
| 2245 IndirectGotoInstr(GrowableObjectArray* offsets, |
| 2246 Value* offset_from_start) |
| 2247 : offsets_(*offsets) { |
| 2248 SetInputAt(0, offset_from_start); |
| 2249 } |
| 2250 |
| 2251 DECLARE_INSTRUCTION(IndirectGoto) |
| 2252 |
| 2253 virtual intptr_t ArgumentCount() const { return 0; } |
| 2254 |
| 2255 void AddSuccessor(TargetEntryInstr* successor) { |
| 2256 ASSERT(successor->next()->IsGoto()); |
| 2257 ASSERT(successor->next()->AsGoto()->successor()->IsIndirectEntry()); |
| 2258 successors_.Add(successor); |
| 2259 } |
| 2260 |
| 2261 virtual intptr_t SuccessorCount() const { return successors_.length(); } |
| 2262 virtual TargetEntryInstr* SuccessorAt(intptr_t index) const { |
| 2263 ASSERT(index < SuccessorCount()); |
| 2264 return successors_[index]; |
| 2265 } |
| 2266 |
| 2267 virtual bool CanDeoptimize() const { return false; } |
| 2268 virtual bool CanBecomeDeoptimizationTarget() const { return false; } |
| 2269 |
| 2270 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 2271 |
| 2272 virtual void PrintTo(BufferFormatter* f) const; |
| 2273 |
| 2274 virtual bool MayThrow() const { return false; } |
| 2275 |
| 2276 const GrowableObjectArray& offsets() const { return offsets_; } |
| 2277 void SetOffsetCount(Isolate* isolate, intptr_t count) { |
| 2278 if (offsets_.Capacity() < count) { |
| 2279 offsets_.Grow(count, Heap::kOld); |
| 2280 } |
| 2281 if (offsets_.Length() < count) { |
| 2282 offsets_.SetLength(count); |
| 2283 } |
| 2284 } |
| 2285 void SetOffsetAt(Isolate* isolate, intptr_t index, intptr_t offset) { |
| 2286 offsets_.SetAt(index, Smi::ZoneHandle(isolate, Smi::New(offset))); |
| 2287 } |
| 2288 |
| 2289 private: |
| 2290 GrowableArray<TargetEntryInstr*> successors_; |
| 2291 GrowableObjectArray& offsets_; |
| 2292 }; |
| 2293 |
| 2294 |
2191 class ComparisonInstr : public TemplateDefinition<2> { | 2295 class ComparisonInstr : public TemplateDefinition<2> { |
2192 public: | 2296 public: |
2193 Value* left() const { return inputs_[0]; } | 2297 Value* left() const { return inputs_[0]; } |
2194 Value* right() const { return inputs_[1]; } | 2298 Value* right() const { return inputs_[1]; } |
2195 | 2299 |
2196 virtual intptr_t token_pos() const { return token_pos_; } | 2300 virtual intptr_t token_pos() const { return token_pos_; } |
2197 Token::Kind kind() const { return kind_; } | 2301 Token::Kind kind() const { return kind_; } |
2198 | 2302 |
2199 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; | 2303 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; |
2200 | 2304 |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3805 | 3909 |
3806 private: | 3910 private: |
3807 const intptr_t index_scale_; | 3911 const intptr_t index_scale_; |
3808 const intptr_t class_id_; | 3912 const intptr_t class_id_; |
3809 const intptr_t token_pos_; | 3913 const intptr_t token_pos_; |
3810 | 3914 |
3811 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); | 3915 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); |
3812 }; | 3916 }; |
3813 | 3917 |
3814 | 3918 |
| 3919 // Loads the specified number of code units from the given string, packing |
| 3920 // multiple code units into a single datatype. In essence, this is a specialized |
| 3921 // version of LoadIndexedInstr which accepts only string targets and can load |
| 3922 // multiple elements at once. The result datatype differs depending on the |
| 3923 // string type, element count, and architecture; if possible, the result is |
| 3924 // packed into a Smi, falling back to a Mint otherwise. |
| 3925 // TODO(jgruber): Add support for loading into UnboxedInt32x4. |
| 3926 class LoadCodeUnitsInstr : public TemplateDefinition<2> { |
| 3927 public: |
| 3928 LoadCodeUnitsInstr(Value* str, |
| 3929 Value* index, |
| 3930 intptr_t element_count, |
| 3931 intptr_t class_id, |
| 3932 intptr_t token_pos) |
| 3933 : class_id_(class_id), |
| 3934 token_pos_(token_pos), |
| 3935 element_count_(element_count) { |
| 3936 ASSERT(element_count == 1 || element_count == 2 || element_count == 4); |
| 3937 ASSERT(class_id == kOneByteStringCid || class_id == kTwoByteStringCid); |
| 3938 SetInputAt(0, str); |
| 3939 SetInputAt(1, index); |
| 3940 } |
| 3941 |
| 3942 intptr_t token_pos() const { return token_pos_; } |
| 3943 |
| 3944 DECLARE_INSTRUCTION(LoadCodeUnits) |
| 3945 virtual CompileType ComputeType() const; |
| 3946 |
| 3947 bool IsExternal() const { |
| 3948 return array()->definition()->representation() == kUntagged; |
| 3949 } |
| 3950 |
| 3951 Value* array() const { return inputs_[0]; } |
| 3952 Value* index() const { return inputs_[1]; } |
| 3953 intptr_t index_scale() const { return Instance::ElementSizeFor(class_id_); } |
| 3954 intptr_t class_id() const { return class_id_; } |
| 3955 intptr_t element_count() const { return element_count_; } |
| 3956 |
| 3957 bool can_pack_into_smi() const { |
| 3958 return element_count() <= kSmiBits / (index_scale() * kBitsPerByte); |
| 3959 } |
| 3960 |
| 3961 virtual bool CanDeoptimize() const { return false; } |
| 3962 |
| 3963 virtual Representation representation() const; |
| 3964 virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| 3965 |
| 3966 virtual bool AllowsCSE() const { return false; } |
| 3967 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 3968 virtual EffectSet Dependencies() const { return EffectSet::All(); } |
| 3969 virtual bool AttributesEqual(Instruction* other) const; |
| 3970 |
| 3971 virtual bool MayThrow() const { return false; } |
| 3972 |
| 3973 private: |
| 3974 const intptr_t class_id_; |
| 3975 const intptr_t token_pos_; |
| 3976 const intptr_t element_count_; |
| 3977 |
| 3978 DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr); |
| 3979 }; |
| 3980 |
| 3981 |
3815 class StringFromCharCodeInstr : public TemplateDefinition<1> { | 3982 class StringFromCharCodeInstr : public TemplateDefinition<1> { |
3816 public: | 3983 public: |
3817 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { | 3984 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { |
3818 ASSERT(char_code != NULL); | 3985 ASSERT(char_code != NULL); |
3819 ASSERT(char_code->definition()->IsLoadIndexed()); | 3986 ASSERT(char_code->definition()->IsLoadIndexed()); |
3820 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == | 3987 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == |
3821 kOneByteStringCid); | 3988 kOneByteStringCid); |
3822 SetInputAt(0, char_code); | 3989 SetInputAt(0, char_code); |
3823 } | 3990 } |
3824 | 3991 |
(...skipping 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5039 | 5206 |
5040 static const char* KindToCString(MathUnaryKind kind); | 5207 static const char* KindToCString(MathUnaryKind kind); |
5041 | 5208 |
5042 private: | 5209 private: |
5043 const MathUnaryKind kind_; | 5210 const MathUnaryKind kind_; |
5044 | 5211 |
5045 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); | 5212 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); |
5046 }; | 5213 }; |
5047 | 5214 |
5048 | 5215 |
| 5216 // Calls into the runtime and performs a case-insensitive comparison of the |
| 5217 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at |
| 5218 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length]. |
| 5219 // |
| 5220 // TODO(jgruber): Remove this once (if) functions inherited from unibrow |
| 5221 // are moved to dart code. |
| 5222 class CaseInsensitiveCompareUC16Instr : public TemplateDefinition<4> { |
| 5223 public: |
| 5224 CaseInsensitiveCompareUC16Instr( |
| 5225 Value* str, |
| 5226 Value* lhs_index, |
| 5227 Value* rhs_index, |
| 5228 Value* length, |
| 5229 intptr_t cid) |
| 5230 : cid_(cid) { |
| 5231 ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid); |
| 5232 ASSERT(index_scale() == 2); |
| 5233 SetInputAt(0, str); |
| 5234 SetInputAt(1, lhs_index); |
| 5235 SetInputAt(2, rhs_index); |
| 5236 SetInputAt(3, length); |
| 5237 } |
| 5238 |
| 5239 Value* str() const { return inputs_[0]; } |
| 5240 Value* lhs_index() const { return inputs_[1]; } |
| 5241 Value* rhs_index() const { return inputs_[2]; } |
| 5242 Value* length() const { return inputs_[3]; } |
| 5243 |
| 5244 const RuntimeEntry& TargetFunction() const; |
| 5245 bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; } |
| 5246 intptr_t class_id() const { return cid_; } |
| 5247 intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); } |
| 5248 |
| 5249 virtual bool CanDeoptimize() const { return false; } |
| 5250 |
| 5251 virtual Representation representation() const { |
| 5252 return kTagged; |
| 5253 } |
| 5254 |
| 5255 DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16) |
| 5256 virtual CompileType ComputeType() const; |
| 5257 |
| 5258 virtual bool AllowsCSE() const { return true; } |
| 5259 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 5260 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| 5261 |
| 5262 virtual bool MayThrow() const { return false; } |
| 5263 |
| 5264 private: |
| 5265 const intptr_t cid_; |
| 5266 |
| 5267 DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr); |
| 5268 }; |
| 5269 |
| 5270 |
5049 // Represents Math's static min and max functions. | 5271 // Represents Math's static min and max functions. |
5050 class MathMinMaxInstr : public TemplateDefinition<2> { | 5272 class MathMinMaxInstr : public TemplateDefinition<2> { |
5051 public: | 5273 public: |
5052 MathMinMaxInstr(MethodRecognizer::Kind op_kind, | 5274 MathMinMaxInstr(MethodRecognizer::Kind op_kind, |
5053 Value* left_value, | 5275 Value* left_value, |
5054 Value* right_value, | 5276 Value* right_value, |
5055 intptr_t deopt_id, | 5277 intptr_t deopt_id, |
5056 intptr_t result_cid) | 5278 intptr_t result_cid) |
5057 : op_kind_(op_kind), result_cid_(result_cid) { | 5279 : op_kind_(op_kind), result_cid_(result_cid) { |
5058 ASSERT((result_cid == kSmiCid) || (result_cid == kDoubleCid)); | 5280 ASSERT((result_cid == kSmiCid) || (result_cid == kDoubleCid)); |
(...skipping 3381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8440 Isolate* isolate, bool opt) const { \ | 8662 Isolate* isolate, bool opt) const { \ |
8441 UNIMPLEMENTED(); \ | 8663 UNIMPLEMENTED(); \ |
8442 return NULL; \ | 8664 return NULL; \ |
8443 } \ | 8665 } \ |
8444 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8666 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
8445 | 8667 |
8446 | 8668 |
8447 } // namespace dart | 8669 } // namespace dart |
8448 | 8670 |
8449 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8671 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |