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(ClosureCall) \ | 442 M(ClosureCall) \ |
441 M(InstanceCall) \ | 443 M(InstanceCall) \ |
442 M(PolymorphicInstanceCall) \ | 444 M(PolymorphicInstanceCall) \ |
443 M(StaticCall) \ | 445 M(StaticCall) \ |
444 M(LoadLocal) \ | 446 M(LoadLocal) \ |
445 M(PushTemp) \ | 447 M(PushTemp) \ |
446 M(DropTemps) \ | 448 M(DropTemps) \ |
447 M(StoreLocal) \ | 449 M(StoreLocal) \ |
448 M(StrictCompare) \ | 450 M(StrictCompare) \ |
449 M(EqualityCompare) \ | 451 M(EqualityCompare) \ |
450 M(RelationalOp) \ | 452 M(RelationalOp) \ |
451 M(NativeCall) \ | 453 M(NativeCall) \ |
452 M(DebugStepCheck) \ | 454 M(DebugStepCheck) \ |
453 M(LoadIndexed) \ | 455 M(LoadIndexed) \ |
| 456 M(LoadCodeUnits) \ |
454 M(StoreIndexed) \ | 457 M(StoreIndexed) \ |
455 M(StoreInstanceField) \ | 458 M(StoreInstanceField) \ |
456 M(InitStaticField) \ | 459 M(InitStaticField) \ |
457 M(LoadStaticField) \ | 460 M(LoadStaticField) \ |
458 M(StoreStaticField) \ | 461 M(StoreStaticField) \ |
459 M(BooleanNegate) \ | 462 M(BooleanNegate) \ |
460 M(InstanceOf) \ | 463 M(InstanceOf) \ |
461 M(CreateArray) \ | 464 M(CreateArray) \ |
462 M(AllocateObject) \ | 465 M(AllocateObject) \ |
463 M(LoadField) \ | 466 M(LoadField) \ |
(...skipping 19 matching lines...) Expand all Loading... |
483 M(FloatToDouble) \ | 486 M(FloatToDouble) \ |
484 M(CheckClass) \ | 487 M(CheckClass) \ |
485 M(CheckClassId) \ | 488 M(CheckClassId) \ |
486 M(CheckSmi) \ | 489 M(CheckSmi) \ |
487 M(Constant) \ | 490 M(Constant) \ |
488 M(UnboxedConstant) \ | 491 M(UnboxedConstant) \ |
489 M(CheckEitherNonSmi) \ | 492 M(CheckEitherNonSmi) \ |
490 M(BinaryDoubleOp) \ | 493 M(BinaryDoubleOp) \ |
491 M(MathUnary) \ | 494 M(MathUnary) \ |
492 M(MathMinMax) \ | 495 M(MathMinMax) \ |
| 496 M(CaseInsensitiveCompareUC16) \ |
493 M(UnboxDouble) \ | 497 M(UnboxDouble) \ |
494 M(BoxDouble) \ | 498 M(BoxDouble) \ |
495 M(BoxFloat32x4) \ | 499 M(BoxFloat32x4) \ |
496 M(UnboxFloat32x4) \ | 500 M(UnboxFloat32x4) \ |
497 M(BoxInt32x4) \ | 501 M(BoxInt32x4) \ |
498 M(UnboxInt32x4) \ | 502 M(UnboxInt32x4) \ |
499 M(UnboxInteger) \ | 503 M(UnboxInteger) \ |
500 M(BoxInteger) \ | 504 M(BoxInteger) \ |
501 M(BinaryMintOp) \ | 505 M(BinaryMintOp) \ |
502 M(ShiftMintOp) \ | 506 M(ShiftMintOp) \ |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 return const_cast<BlockEntryInstr*>(this); | 1161 return const_cast<BlockEntryInstr*>(this); |
1158 } | 1162 } |
1159 | 1163 |
1160 // Helper to mutate the graph during inlining. This block should be | 1164 // Helper to mutate the graph during inlining. This block should be |
1161 // replaced with new_block as a predecessor of all of this block's | 1165 // replaced with new_block as a predecessor of all of this block's |
1162 // successors. | 1166 // successors. |
1163 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); | 1167 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); |
1164 | 1168 |
1165 void set_block_id(intptr_t block_id) { block_id_ = block_id; } | 1169 void set_block_id(intptr_t block_id) { block_id_ = block_id; } |
1166 | 1170 |
| 1171 intptr_t offset() const { return offset_; } |
| 1172 void set_offset(intptr_t offset) { offset_ = offset; } |
| 1173 |
1167 // For all instruction in this block: Remove all inputs (including in the | 1174 // For all instruction in this block: Remove all inputs (including in the |
1168 // environment) from their definition's use lists for all instructions. | 1175 // environment) from their definition's use lists for all instructions. |
1169 void ClearAllInstructions(); | 1176 void ClearAllInstructions(); |
1170 | 1177 |
1171 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) | 1178 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) |
1172 | 1179 |
1173 protected: | 1180 protected: |
1174 BlockEntryInstr(intptr_t block_id, intptr_t try_index) | 1181 BlockEntryInstr(intptr_t block_id, intptr_t try_index) |
1175 : Instruction(Isolate::Current()->GetNextDeoptId()), | 1182 : Instruction(Isolate::Current()->GetNextDeoptId()), |
1176 block_id_(block_id), | 1183 block_id_(block_id), |
1177 try_index_(try_index), | 1184 try_index_(try_index), |
1178 preorder_number_(-1), | 1185 preorder_number_(-1), |
1179 postorder_number_(-1), | 1186 postorder_number_(-1), |
1180 dominator_(NULL), | 1187 dominator_(NULL), |
1181 dominated_blocks_(1), | 1188 dominated_blocks_(1), |
1182 last_instruction_(NULL), | 1189 last_instruction_(NULL), |
| 1190 offset_(-1), |
1183 parallel_move_(NULL), | 1191 parallel_move_(NULL), |
1184 loop_info_(NULL) { | 1192 loop_info_(NULL) { |
1185 } | 1193 } |
1186 | 1194 |
1187 private: | 1195 private: |
1188 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } | 1196 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } |
1189 | 1197 |
1190 virtual void ClearPredecessors() = 0; | 1198 virtual void ClearPredecessors() = 0; |
1191 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; | 1199 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; |
1192 | 1200 |
1193 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } | 1201 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } |
1194 | 1202 |
1195 intptr_t block_id_; | 1203 intptr_t block_id_; |
1196 const intptr_t try_index_; | 1204 const intptr_t try_index_; |
1197 intptr_t preorder_number_; | 1205 intptr_t preorder_number_; |
1198 intptr_t postorder_number_; | 1206 intptr_t postorder_number_; |
1199 // Starting and ending lifetime positions for this block. Used by | 1207 // Starting and ending lifetime positions for this block. Used by |
1200 // the linear scan register allocator. | 1208 // the linear scan register allocator. |
1201 intptr_t start_pos_; | 1209 intptr_t start_pos_; |
1202 intptr_t end_pos_; | 1210 intptr_t end_pos_; |
1203 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. | 1211 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. |
1204 // TODO(fschneider): Optimize the case of one child to save space. | 1212 // TODO(fschneider): Optimize the case of one child to save space. |
1205 GrowableArray<BlockEntryInstr*> dominated_blocks_; | 1213 GrowableArray<BlockEntryInstr*> dominated_blocks_; |
1206 Instruction* last_instruction_; | 1214 Instruction* last_instruction_; |
1207 | 1215 |
| 1216 // Offset of this block from the start of the emitted code. |
| 1217 intptr_t offset_; |
| 1218 |
1208 // Parallel move that will be used by linear scan register allocator to | 1219 // Parallel move that will be used by linear scan register allocator to |
1209 // connect live ranges at the start of the block. | 1220 // connect live ranges at the start of the block. |
1210 ParallelMoveInstr* parallel_move_; | 1221 ParallelMoveInstr* parallel_move_; |
1211 | 1222 |
1212 // Bit vector containg loop blocks for a loop header indexed by block | 1223 // Bit vector containg loop blocks for a loop header indexed by block |
1213 // preorder number. | 1224 // preorder number. |
1214 BitVector* loop_info_; | 1225 BitVector* loop_info_; |
1215 | 1226 |
1216 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); | 1227 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); |
1217 }; | 1228 }; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1278 UNREACHABLE(); | 1289 UNREACHABLE(); |
1279 return NULL; | 1290 return NULL; |
1280 } | 1291 } |
1281 virtual intptr_t SuccessorCount() const; | 1292 virtual intptr_t SuccessorCount() const; |
1282 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 1293 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
1283 | 1294 |
1284 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } | 1295 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } |
1285 | 1296 |
1286 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); | 1297 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); |
1287 | 1298 |
| 1299 void AddIndirectEntry(IndirectEntryInstr* entry) { |
| 1300 indirect_entries_.Add(entry); |
| 1301 } |
| 1302 |
1288 GrowableArray<Definition*>* initial_definitions() { | 1303 GrowableArray<Definition*>* initial_definitions() { |
1289 return &initial_definitions_; | 1304 return &initial_definitions_; |
1290 } | 1305 } |
1291 ConstantInstr* constant_null(); | 1306 ConstantInstr* constant_null(); |
1292 | 1307 |
1293 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } | 1308 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } |
1294 | 1309 |
1295 intptr_t entry_count() const { return entry_count_; } | 1310 intptr_t entry_count() const { return entry_count_; } |
1296 void set_entry_count(intptr_t count) { entry_count_ = count; } | 1311 void set_entry_count(intptr_t count) { entry_count_ = count; } |
1297 | 1312 |
(...skipping 14 matching lines...) Expand all Loading... |
1312 TargetEntryInstr* normal_entry() const { return normal_entry_; } | 1327 TargetEntryInstr* normal_entry() const { return normal_entry_; } |
1313 | 1328 |
1314 const ParsedFunction& parsed_function() const { | 1329 const ParsedFunction& parsed_function() const { |
1315 return *parsed_function_; | 1330 return *parsed_function_; |
1316 } | 1331 } |
1317 | 1332 |
1318 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { | 1333 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { |
1319 return catch_entries_; | 1334 return catch_entries_; |
1320 } | 1335 } |
1321 | 1336 |
| 1337 const GrowableArray<IndirectEntryInstr*>& indirect_entries() const { |
| 1338 return indirect_entries_; |
| 1339 } |
| 1340 |
1322 virtual void PrintTo(BufferFormatter* f) const; | 1341 virtual void PrintTo(BufferFormatter* f) const; |
1323 | 1342 |
1324 private: | 1343 private: |
1325 virtual void ClearPredecessors() {} | 1344 virtual void ClearPredecessors() {} |
1326 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 1345 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } |
1327 | 1346 |
1328 const ParsedFunction* parsed_function_; | 1347 const ParsedFunction* parsed_function_; |
1329 TargetEntryInstr* normal_entry_; | 1348 TargetEntryInstr* normal_entry_; |
1330 GrowableArray<CatchBlockEntryInstr*> catch_entries_; | 1349 GrowableArray<CatchBlockEntryInstr*> catch_entries_; |
| 1350 // Indirect targets are blocks reachable only through indirect gotos. |
| 1351 GrowableArray<IndirectEntryInstr*> indirect_entries_; |
1331 GrowableArray<Definition*> initial_definitions_; | 1352 GrowableArray<Definition*> initial_definitions_; |
1332 const intptr_t osr_id_; | 1353 const intptr_t osr_id_; |
1333 intptr_t entry_count_; | 1354 intptr_t entry_count_; |
1334 intptr_t spill_slot_count_; | 1355 intptr_t spill_slot_count_; |
1335 intptr_t fixed_slot_count_; // For try-catch in optimized code. | 1356 intptr_t fixed_slot_count_; // For try-catch in optimized code. |
1336 | 1357 |
1337 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 1358 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); |
1338 }; | 1359 }; |
1339 | 1360 |
1340 | 1361 |
(...skipping 25 matching lines...) Expand all Loading... |
1366 virtual void PrintTo(BufferFormatter* f) const; | 1387 virtual void PrintTo(BufferFormatter* f) const; |
1367 | 1388 |
1368 virtual EffectSet Effects() const { return EffectSet::None(); } | 1389 virtual EffectSet Effects() const { return EffectSet::None(); } |
1369 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 1390 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
1370 | 1391 |
1371 private: | 1392 private: |
1372 // Classes that have access to predecessors_ when inlining. | 1393 // Classes that have access to predecessors_ when inlining. |
1373 friend class BlockEntryInstr; | 1394 friend class BlockEntryInstr; |
1374 friend class InlineExitCollector; | 1395 friend class InlineExitCollector; |
1375 friend class PolymorphicInliner; | 1396 friend class PolymorphicInliner; |
| 1397 friend class IndirectEntryInstr; // Access in il_printer.cc. |
1376 | 1398 |
1377 // Direct access to phis_ in order to resize it due to phi elimination. | 1399 // Direct access to phis_ in order to resize it due to phi elimination. |
1378 friend class ConstantPropagator; | 1400 friend class ConstantPropagator; |
1379 friend class DeadCodeElimination; | 1401 friend class DeadCodeElimination; |
1380 | 1402 |
1381 virtual void ClearPredecessors() { predecessors_.Clear(); } | 1403 virtual void ClearPredecessors() { predecessors_.Clear(); } |
1382 virtual void AddPredecessor(BlockEntryInstr* predecessor); | 1404 virtual void AddPredecessor(BlockEntryInstr* predecessor); |
1383 | 1405 |
1384 GrowableArray<BlockEntryInstr*> predecessors_; | 1406 GrowableArray<BlockEntryInstr*> predecessors_; |
1385 ZoneGrowableArray<PhiInstr*>* phis_; | 1407 ZoneGrowableArray<PhiInstr*>* phis_; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 predecessor_ = predecessor; | 1466 predecessor_ = predecessor; |
1445 } | 1467 } |
1446 | 1468 |
1447 BlockEntryInstr* predecessor_; | 1469 BlockEntryInstr* predecessor_; |
1448 double edge_weight_; | 1470 double edge_weight_; |
1449 | 1471 |
1450 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); | 1472 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); |
1451 }; | 1473 }; |
1452 | 1474 |
1453 | 1475 |
| 1476 class IndirectEntryInstr : public JoinEntryInstr { |
| 1477 public: |
| 1478 IndirectEntryInstr(intptr_t block_id, |
| 1479 intptr_t indirect_id, |
| 1480 intptr_t try_index) |
| 1481 : JoinEntryInstr(block_id, try_index), |
| 1482 indirect_id_(indirect_id) { } |
| 1483 |
| 1484 DECLARE_INSTRUCTION(IndirectEntry) |
| 1485 |
| 1486 virtual void PrintTo(BufferFormatter* f) const; |
| 1487 |
| 1488 intptr_t indirect_id() const { return indirect_id_; } |
| 1489 |
| 1490 private: |
| 1491 const intptr_t indirect_id_; |
| 1492 }; |
| 1493 |
| 1494 |
1454 class CatchBlockEntryInstr : public BlockEntryInstr { | 1495 class CatchBlockEntryInstr : public BlockEntryInstr { |
1455 public: | 1496 public: |
1456 CatchBlockEntryInstr(intptr_t block_id, | 1497 CatchBlockEntryInstr(intptr_t block_id, |
1457 intptr_t try_index, | 1498 intptr_t try_index, |
1458 const Array& handler_types, | 1499 const Array& handler_types, |
1459 intptr_t catch_try_index, | 1500 intptr_t catch_try_index, |
1460 const LocalVariable& exception_var, | 1501 const LocalVariable& exception_var, |
1461 const LocalVariable& stacktrace_var, | 1502 const LocalVariable& stacktrace_var, |
1462 bool needs_stacktrace) | 1503 bool needs_stacktrace) |
1463 : BlockEntryInstr(block_id, try_index), | 1504 : BlockEntryInstr(block_id, try_index), |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2149 private: | 2190 private: |
2150 JoinEntryInstr* successor_; | 2191 JoinEntryInstr* successor_; |
2151 double edge_weight_; | 2192 double edge_weight_; |
2152 | 2193 |
2153 // Parallel move that will be used by linear scan register allocator to | 2194 // Parallel move that will be used by linear scan register allocator to |
2154 // connect live ranges at the end of the block and resolve phis. | 2195 // connect live ranges at the end of the block and resolve phis. |
2155 ParallelMoveInstr* parallel_move_; | 2196 ParallelMoveInstr* parallel_move_; |
2156 }; | 2197 }; |
2157 | 2198 |
2158 | 2199 |
| 2200 // As a high level description, an indirect goto takes the indirect_id of an |
| 2201 // indirect entry as a parameter, and jumps to that location. |
| 2202 // |
| 2203 // In more detail: in order to preserve split-edge form, an intermediate target |
| 2204 // entry consisting of a goto to the final indirect entry is inserted on |
| 2205 // each possible indirect goto -> indirect entry edge. These target entries are |
| 2206 // accessible through successors_. |
| 2207 // |
| 2208 // Byte offsets of all possible indirect targets are stored in the offsets_ |
| 2209 // array. The desired offset is looked up while the generated code is executing, |
| 2210 // and passed to IndirectGoto as an input. |
| 2211 class IndirectGotoInstr : public TemplateInstruction<1, NoThrow> { |
| 2212 public: |
| 2213 IndirectGotoInstr(GrowableObjectArray* offsets, |
| 2214 Value* offset_from_start) |
| 2215 : offsets_(*offsets) { |
| 2216 SetInputAt(0, offset_from_start); |
| 2217 } |
| 2218 |
| 2219 DECLARE_INSTRUCTION(IndirectGoto) |
| 2220 |
| 2221 virtual intptr_t ArgumentCount() const { return 0; } |
| 2222 |
| 2223 void AddSuccessor(TargetEntryInstr* successor) { |
| 2224 ASSERT(successor->next()->IsGoto()); |
| 2225 ASSERT(successor->next()->AsGoto()->successor()->IsIndirectEntry()); |
| 2226 successors_.Add(successor); |
| 2227 } |
| 2228 |
| 2229 virtual intptr_t SuccessorCount() const { return successors_.length(); } |
| 2230 virtual TargetEntryInstr* SuccessorAt(intptr_t index) const { |
| 2231 ASSERT(index < SuccessorCount()); |
| 2232 return successors_[index]; |
| 2233 } |
| 2234 |
| 2235 virtual bool CanDeoptimize() const { return false; } |
| 2236 virtual bool CanBecomeDeoptimizationTarget() const { return false; } |
| 2237 |
| 2238 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 2239 |
| 2240 virtual void PrintTo(BufferFormatter* f) const; |
| 2241 |
| 2242 const GrowableObjectArray& offsets() const { return offsets_; } |
| 2243 void SetOffsetCount(Isolate* isolate, intptr_t count) { |
| 2244 if (offsets_.Capacity() < count) { |
| 2245 offsets_.Grow(count, Heap::kOld); |
| 2246 } |
| 2247 if (offsets_.Length() < count) { |
| 2248 offsets_.SetLength(count); |
| 2249 } |
| 2250 } |
| 2251 void SetOffsetAt(Isolate* isolate, intptr_t index, intptr_t offset) { |
| 2252 offsets_.SetAt(index, Smi::ZoneHandle(isolate, Smi::New(offset))); |
| 2253 } |
| 2254 |
| 2255 private: |
| 2256 GrowableArray<TargetEntryInstr*> successors_; |
| 2257 GrowableObjectArray& offsets_; |
| 2258 }; |
| 2259 |
| 2260 |
2159 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { | 2261 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { |
2160 public: | 2262 public: |
2161 Value* left() const { return inputs_[0]; } | 2263 Value* left() const { return inputs_[0]; } |
2162 Value* right() const { return inputs_[1]; } | 2264 Value* right() const { return inputs_[1]; } |
2163 | 2265 |
2164 virtual intptr_t token_pos() const { return token_pos_; } | 2266 virtual intptr_t token_pos() const { return token_pos_; } |
2165 Token::Kind kind() const { return kind_; } | 2267 Token::Kind kind() const { return kind_; } |
2166 | 2268 |
2167 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; | 2269 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; |
2168 | 2270 |
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3618 | 3720 |
3619 private: | 3721 private: |
3620 const intptr_t index_scale_; | 3722 const intptr_t index_scale_; |
3621 const intptr_t class_id_; | 3723 const intptr_t class_id_; |
3622 const intptr_t token_pos_; | 3724 const intptr_t token_pos_; |
3623 | 3725 |
3624 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); | 3726 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); |
3625 }; | 3727 }; |
3626 | 3728 |
3627 | 3729 |
| 3730 // Loads the specified number of code units from the given string, packing |
| 3731 // multiple code units into a single datatype. In essence, this is a specialized |
| 3732 // version of LoadIndexedInstr which accepts only string targets and can load |
| 3733 // multiple elements at once. The result datatype differs depending on the |
| 3734 // string type, element count, and architecture; if possible, the result is |
| 3735 // packed into a Smi, falling back to a Mint otherwise. |
| 3736 // TODO(zerny): Add support for loading into UnboxedInt32x4. |
| 3737 class LoadCodeUnitsInstr : public TemplateDefinition<2, NoThrow> { |
| 3738 public: |
| 3739 LoadCodeUnitsInstr(Value* str, |
| 3740 Value* index, |
| 3741 intptr_t element_count, |
| 3742 intptr_t class_id, |
| 3743 intptr_t token_pos) |
| 3744 : class_id_(class_id), |
| 3745 token_pos_(token_pos), |
| 3746 element_count_(element_count) { |
| 3747 ASSERT(element_count == 1 || element_count == 2 || element_count == 4); |
| 3748 ASSERT(class_id == kOneByteStringCid || class_id == kTwoByteStringCid); |
| 3749 SetInputAt(0, str); |
| 3750 SetInputAt(1, index); |
| 3751 } |
| 3752 |
| 3753 intptr_t token_pos() const { return token_pos_; } |
| 3754 |
| 3755 DECLARE_INSTRUCTION(LoadCodeUnits) |
| 3756 virtual CompileType ComputeType() const; |
| 3757 |
| 3758 bool IsExternal() const { |
| 3759 return array()->definition()->representation() == kUntagged; |
| 3760 } |
| 3761 |
| 3762 Value* array() const { return inputs_[0]; } |
| 3763 Value* index() const { return inputs_[1]; } |
| 3764 intptr_t index_scale() const { return Instance::ElementSizeFor(class_id_); } |
| 3765 intptr_t class_id() const { return class_id_; } |
| 3766 intptr_t element_count() const { return element_count_; } |
| 3767 |
| 3768 bool can_pack_into_smi() const { |
| 3769 return element_count() <= kSmiBits / (index_scale() * kBitsPerByte); |
| 3770 } |
| 3771 |
| 3772 virtual bool CanDeoptimize() const { return false; } |
| 3773 |
| 3774 virtual Representation representation() const; |
| 3775 virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| 3776 |
| 3777 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 3778 |
| 3779 private: |
| 3780 const intptr_t class_id_; |
| 3781 const intptr_t token_pos_; |
| 3782 const intptr_t element_count_; |
| 3783 |
| 3784 DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr); |
| 3785 }; |
| 3786 |
| 3787 |
3628 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { | 3788 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { |
3629 public: | 3789 public: |
3630 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { | 3790 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { |
3631 ASSERT(char_code != NULL); | 3791 ASSERT(char_code != NULL); |
3632 ASSERT(char_code->definition()->IsLoadIndexed()); | 3792 ASSERT(char_code->definition()->IsLoadIndexed()); |
3633 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == | 3793 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == |
3634 kOneByteStringCid); | 3794 kOneByteStringCid); |
3635 SetInputAt(0, char_code); | 3795 SetInputAt(0, char_code); |
3636 } | 3796 } |
3637 | 3797 |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4756 | 4916 |
4757 static const char* KindToCString(MathUnaryKind kind); | 4917 static const char* KindToCString(MathUnaryKind kind); |
4758 | 4918 |
4759 private: | 4919 private: |
4760 const MathUnaryKind kind_; | 4920 const MathUnaryKind kind_; |
4761 | 4921 |
4762 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); | 4922 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); |
4763 }; | 4923 }; |
4764 | 4924 |
4765 | 4925 |
| 4926 // Calls into the runtime and performs a case-insensitive comparison of the |
| 4927 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at |
| 4928 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length]. |
| 4929 // |
| 4930 // TODO(zerny): Remove this once (if) functions inherited from unibrow |
| 4931 // are moved to dart code. |
| 4932 class CaseInsensitiveCompareUC16Instr |
| 4933 : public TemplateDefinition<4, NoThrow, Pure> { |
| 4934 public: |
| 4935 CaseInsensitiveCompareUC16Instr( |
| 4936 Value* str, |
| 4937 Value* lhs_index, |
| 4938 Value* rhs_index, |
| 4939 Value* length, |
| 4940 intptr_t cid) |
| 4941 : cid_(cid) { |
| 4942 ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid); |
| 4943 ASSERT(index_scale() == 2); |
| 4944 SetInputAt(0, str); |
| 4945 SetInputAt(1, lhs_index); |
| 4946 SetInputAt(2, rhs_index); |
| 4947 SetInputAt(3, length); |
| 4948 } |
| 4949 |
| 4950 Value* str() const { return inputs_[0]; } |
| 4951 Value* lhs_index() const { return inputs_[1]; } |
| 4952 Value* rhs_index() const { return inputs_[2]; } |
| 4953 Value* length() const { return inputs_[3]; } |
| 4954 |
| 4955 const RuntimeEntry& TargetFunction() const; |
| 4956 bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; } |
| 4957 intptr_t class_id() const { return cid_; } |
| 4958 intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); } |
| 4959 |
| 4960 virtual bool CanDeoptimize() const { return false; } |
| 4961 |
| 4962 virtual Representation representation() const { |
| 4963 return kTagged; |
| 4964 } |
| 4965 |
| 4966 DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16) |
| 4967 virtual CompileType ComputeType() const; |
| 4968 |
| 4969 virtual bool AttributesEqual(Instruction* other) const { |
| 4970 return other->AsCaseInsensitiveCompareUC16()->cid_ == cid_; |
| 4971 } |
| 4972 |
| 4973 private: |
| 4974 const intptr_t cid_; |
| 4975 |
| 4976 DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr); |
| 4977 }; |
| 4978 |
| 4979 |
4766 // Represents Math's static min and max functions. | 4980 // Represents Math's static min and max functions. |
4767 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { | 4981 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { |
4768 public: | 4982 public: |
4769 MathMinMaxInstr(MethodRecognizer::Kind op_kind, | 4983 MathMinMaxInstr(MethodRecognizer::Kind op_kind, |
4770 Value* left_value, | 4984 Value* left_value, |
4771 Value* right_value, | 4985 Value* right_value, |
4772 intptr_t deopt_id, | 4986 intptr_t deopt_id, |
4773 intptr_t result_cid) | 4987 intptr_t result_cid) |
4774 : TemplateDefinition(deopt_id), | 4988 : TemplateDefinition(deopt_id), |
4775 op_kind_(op_kind), | 4989 op_kind_(op_kind), |
(...skipping 3117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7893 Isolate* isolate, bool opt) const { \ | 8107 Isolate* isolate, bool opt) const { \ |
7894 UNIMPLEMENTED(); \ | 8108 UNIMPLEMENTED(); \ |
7895 return NULL; \ | 8109 return NULL; \ |
7896 } \ | 8110 } \ |
7897 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8111 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
7898 | 8112 |
7899 | 8113 |
7900 } // namespace dart | 8114 } // namespace dart |
7901 | 8115 |
7902 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8116 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
OLD | NEW |