| 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 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 return const_cast<BlockEntryInstr*>(this); | 1162 return const_cast<BlockEntryInstr*>(this); |
| 1159 } | 1163 } |
| 1160 | 1164 |
| 1161 // Helper to mutate the graph during inlining. This block should be | 1165 // Helper to mutate the graph during inlining. This block should be |
| 1162 // replaced with new_block as a predecessor of all of this block's | 1166 // replaced with new_block as a predecessor of all of this block's |
| 1163 // successors. | 1167 // successors. |
| 1164 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); | 1168 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); |
| 1165 | 1169 |
| 1166 void set_block_id(intptr_t block_id) { block_id_ = block_id; } | 1170 void set_block_id(intptr_t block_id) { block_id_ = block_id; } |
| 1167 | 1171 |
| 1172 intptr_t offset() const { return offset_; } |
| 1173 void set_offset(intptr_t offset) { offset_ = offset; } |
| 1174 |
| 1168 // For all instruction in this block: Remove all inputs (including in the | 1175 // For all instruction in this block: Remove all inputs (including in the |
| 1169 // environment) from their definition's use lists for all instructions. | 1176 // environment) from their definition's use lists for all instructions. |
| 1170 void ClearAllInstructions(); | 1177 void ClearAllInstructions(); |
| 1171 | 1178 |
| 1172 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) | 1179 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) |
| 1173 | 1180 |
| 1174 protected: | 1181 protected: |
| 1175 BlockEntryInstr(intptr_t block_id, intptr_t try_index) | 1182 BlockEntryInstr(intptr_t block_id, intptr_t try_index) |
| 1176 : Instruction(Isolate::Current()->GetNextDeoptId()), | 1183 : Instruction(Isolate::Current()->GetNextDeoptId()), |
| 1177 block_id_(block_id), | 1184 block_id_(block_id), |
| 1178 try_index_(try_index), | 1185 try_index_(try_index), |
| 1179 preorder_number_(-1), | 1186 preorder_number_(-1), |
| 1180 postorder_number_(-1), | 1187 postorder_number_(-1), |
| 1181 dominator_(NULL), | 1188 dominator_(NULL), |
| 1182 dominated_blocks_(1), | 1189 dominated_blocks_(1), |
| 1183 last_instruction_(NULL), | 1190 last_instruction_(NULL), |
| 1191 offset_(-1), |
| 1184 parallel_move_(NULL), | 1192 parallel_move_(NULL), |
| 1185 loop_info_(NULL) { | 1193 loop_info_(NULL) { |
| 1186 } | 1194 } |
| 1187 | 1195 |
| 1188 private: | 1196 private: |
| 1189 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } | 1197 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } |
| 1190 | 1198 |
| 1191 virtual void ClearPredecessors() = 0; | 1199 virtual void ClearPredecessors() = 0; |
| 1192 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; | 1200 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; |
| 1193 | 1201 |
| 1194 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } | 1202 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } |
| 1195 | 1203 |
| 1196 intptr_t block_id_; | 1204 intptr_t block_id_; |
| 1197 const intptr_t try_index_; | 1205 const intptr_t try_index_; |
| 1198 intptr_t preorder_number_; | 1206 intptr_t preorder_number_; |
| 1199 intptr_t postorder_number_; | 1207 intptr_t postorder_number_; |
| 1200 // Starting and ending lifetime positions for this block. Used by | 1208 // Starting and ending lifetime positions for this block. Used by |
| 1201 // the linear scan register allocator. | 1209 // the linear scan register allocator. |
| 1202 intptr_t start_pos_; | 1210 intptr_t start_pos_; |
| 1203 intptr_t end_pos_; | 1211 intptr_t end_pos_; |
| 1204 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. | 1212 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. |
| 1205 // TODO(fschneider): Optimize the case of one child to save space. | 1213 // TODO(fschneider): Optimize the case of one child to save space. |
| 1206 GrowableArray<BlockEntryInstr*> dominated_blocks_; | 1214 GrowableArray<BlockEntryInstr*> dominated_blocks_; |
| 1207 Instruction* last_instruction_; | 1215 Instruction* last_instruction_; |
| 1208 | 1216 |
| 1217 // Offset of this block from the start of the emitted code. |
| 1218 intptr_t offset_; |
| 1219 |
| 1209 // Parallel move that will be used by linear scan register allocator to | 1220 // Parallel move that will be used by linear scan register allocator to |
| 1210 // connect live ranges at the start of the block. | 1221 // connect live ranges at the start of the block. |
| 1211 ParallelMoveInstr* parallel_move_; | 1222 ParallelMoveInstr* parallel_move_; |
| 1212 | 1223 |
| 1213 // Bit vector containg loop blocks for a loop header indexed by block | 1224 // Bit vector containg loop blocks for a loop header indexed by block |
| 1214 // preorder number. | 1225 // preorder number. |
| 1215 BitVector* loop_info_; | 1226 BitVector* loop_info_; |
| 1216 | 1227 |
| 1217 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); | 1228 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); |
| 1218 }; | 1229 }; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 UNREACHABLE(); | 1290 UNREACHABLE(); |
| 1280 return NULL; | 1291 return NULL; |
| 1281 } | 1292 } |
| 1282 virtual intptr_t SuccessorCount() const; | 1293 virtual intptr_t SuccessorCount() const; |
| 1283 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 1294 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
| 1284 | 1295 |
| 1285 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } | 1296 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } |
| 1286 | 1297 |
| 1287 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); | 1298 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); |
| 1288 | 1299 |
| 1300 void AddIndirectEntry(IndirectEntryInstr* entry) { |
| 1301 indirect_entries_.Add(entry); |
| 1302 } |
| 1303 |
| 1289 GrowableArray<Definition*>* initial_definitions() { | 1304 GrowableArray<Definition*>* initial_definitions() { |
| 1290 return &initial_definitions_; | 1305 return &initial_definitions_; |
| 1291 } | 1306 } |
| 1292 ConstantInstr* constant_null(); | 1307 ConstantInstr* constant_null(); |
| 1293 | 1308 |
| 1294 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } | 1309 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } |
| 1295 | 1310 |
| 1296 intptr_t entry_count() const { return entry_count_; } | 1311 intptr_t entry_count() const { return entry_count_; } |
| 1297 void set_entry_count(intptr_t count) { entry_count_ = count; } | 1312 void set_entry_count(intptr_t count) { entry_count_ = count; } |
| 1298 | 1313 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1313 TargetEntryInstr* normal_entry() const { return normal_entry_; } | 1328 TargetEntryInstr* normal_entry() const { return normal_entry_; } |
| 1314 | 1329 |
| 1315 const ParsedFunction& parsed_function() const { | 1330 const ParsedFunction& parsed_function() const { |
| 1316 return *parsed_function_; | 1331 return *parsed_function_; |
| 1317 } | 1332 } |
| 1318 | 1333 |
| 1319 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { | 1334 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { |
| 1320 return catch_entries_; | 1335 return catch_entries_; |
| 1321 } | 1336 } |
| 1322 | 1337 |
| 1338 const GrowableArray<IndirectEntryInstr*>& indirect_entries() const { |
| 1339 return indirect_entries_; |
| 1340 } |
| 1341 |
| 1323 virtual void PrintTo(BufferFormatter* f) const; | 1342 virtual void PrintTo(BufferFormatter* f) const; |
| 1324 | 1343 |
| 1325 private: | 1344 private: |
| 1326 virtual void ClearPredecessors() {} | 1345 virtual void ClearPredecessors() {} |
| 1327 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 1346 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } |
| 1328 | 1347 |
| 1329 const ParsedFunction* parsed_function_; | 1348 const ParsedFunction* parsed_function_; |
| 1330 TargetEntryInstr* normal_entry_; | 1349 TargetEntryInstr* normal_entry_; |
| 1331 GrowableArray<CatchBlockEntryInstr*> catch_entries_; | 1350 GrowableArray<CatchBlockEntryInstr*> catch_entries_; |
| 1351 // Indirect targets are blocks reachable only through indirect gotos. |
| 1352 GrowableArray<IndirectEntryInstr*> indirect_entries_; |
| 1332 GrowableArray<Definition*> initial_definitions_; | 1353 GrowableArray<Definition*> initial_definitions_; |
| 1333 const intptr_t osr_id_; | 1354 const intptr_t osr_id_; |
| 1334 intptr_t entry_count_; | 1355 intptr_t entry_count_; |
| 1335 intptr_t spill_slot_count_; | 1356 intptr_t spill_slot_count_; |
| 1336 intptr_t fixed_slot_count_; // For try-catch in optimized code. | 1357 intptr_t fixed_slot_count_; // For try-catch in optimized code. |
| 1337 | 1358 |
| 1338 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 1359 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); |
| 1339 }; | 1360 }; |
| 1340 | 1361 |
| 1341 | 1362 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1367 virtual void PrintTo(BufferFormatter* f) const; | 1388 virtual void PrintTo(BufferFormatter* f) const; |
| 1368 | 1389 |
| 1369 virtual EffectSet Effects() const { return EffectSet::None(); } | 1390 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 1370 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 1391 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| 1371 | 1392 |
| 1372 private: | 1393 private: |
| 1373 // Classes that have access to predecessors_ when inlining. | 1394 // Classes that have access to predecessors_ when inlining. |
| 1374 friend class BlockEntryInstr; | 1395 friend class BlockEntryInstr; |
| 1375 friend class InlineExitCollector; | 1396 friend class InlineExitCollector; |
| 1376 friend class PolymorphicInliner; | 1397 friend class PolymorphicInliner; |
| 1398 friend class IndirectEntryInstr; // Access in il_printer.cc. |
| 1377 | 1399 |
| 1378 // Direct access to phis_ in order to resize it due to phi elimination. | 1400 // Direct access to phis_ in order to resize it due to phi elimination. |
| 1379 friend class ConstantPropagator; | 1401 friend class ConstantPropagator; |
| 1380 friend class DeadCodeElimination; | 1402 friend class DeadCodeElimination; |
| 1381 | 1403 |
| 1382 virtual void ClearPredecessors() { predecessors_.Clear(); } | 1404 virtual void ClearPredecessors() { predecessors_.Clear(); } |
| 1383 virtual void AddPredecessor(BlockEntryInstr* predecessor); | 1405 virtual void AddPredecessor(BlockEntryInstr* predecessor); |
| 1384 | 1406 |
| 1385 GrowableArray<BlockEntryInstr*> predecessors_; | 1407 GrowableArray<BlockEntryInstr*> predecessors_; |
| 1386 ZoneGrowableArray<PhiInstr*>* phis_; | 1408 ZoneGrowableArray<PhiInstr*>* phis_; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1445 predecessor_ = predecessor; | 1467 predecessor_ = predecessor; |
| 1446 } | 1468 } |
| 1447 | 1469 |
| 1448 BlockEntryInstr* predecessor_; | 1470 BlockEntryInstr* predecessor_; |
| 1449 double edge_weight_; | 1471 double edge_weight_; |
| 1450 | 1472 |
| 1451 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); | 1473 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); |
| 1452 }; | 1474 }; |
| 1453 | 1475 |
| 1454 | 1476 |
| 1477 class IndirectEntryInstr : public JoinEntryInstr { |
| 1478 public: |
| 1479 IndirectEntryInstr(intptr_t block_id, |
| 1480 intptr_t indirect_id, |
| 1481 intptr_t try_index) |
| 1482 : JoinEntryInstr(block_id, try_index), |
| 1483 indirect_id_(indirect_id) { } |
| 1484 |
| 1485 DECLARE_INSTRUCTION(IndirectEntry) |
| 1486 |
| 1487 virtual void PrintTo(BufferFormatter* f) const; |
| 1488 |
| 1489 intptr_t indirect_id() const { return indirect_id_; } |
| 1490 |
| 1491 private: |
| 1492 const intptr_t indirect_id_; |
| 1493 }; |
| 1494 |
| 1495 |
| 1455 class CatchBlockEntryInstr : public BlockEntryInstr { | 1496 class CatchBlockEntryInstr : public BlockEntryInstr { |
| 1456 public: | 1497 public: |
| 1457 CatchBlockEntryInstr(intptr_t block_id, | 1498 CatchBlockEntryInstr(intptr_t block_id, |
| 1458 intptr_t try_index, | 1499 intptr_t try_index, |
| 1459 const Array& handler_types, | 1500 const Array& handler_types, |
| 1460 intptr_t catch_try_index, | 1501 intptr_t catch_try_index, |
| 1461 const LocalVariable& exception_var, | 1502 const LocalVariable& exception_var, |
| 1462 const LocalVariable& stacktrace_var, | 1503 const LocalVariable& stacktrace_var, |
| 1463 bool needs_stacktrace) | 1504 bool needs_stacktrace) |
| 1464 : BlockEntryInstr(block_id, try_index), | 1505 : BlockEntryInstr(block_id, try_index), |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2150 private: | 2191 private: |
| 2151 JoinEntryInstr* successor_; | 2192 JoinEntryInstr* successor_; |
| 2152 double edge_weight_; | 2193 double edge_weight_; |
| 2153 | 2194 |
| 2154 // Parallel move that will be used by linear scan register allocator to | 2195 // Parallel move that will be used by linear scan register allocator to |
| 2155 // connect live ranges at the end of the block and resolve phis. | 2196 // connect live ranges at the end of the block and resolve phis. |
| 2156 ParallelMoveInstr* parallel_move_; | 2197 ParallelMoveInstr* parallel_move_; |
| 2157 }; | 2198 }; |
| 2158 | 2199 |
| 2159 | 2200 |
| 2201 // As a high level description, an indirect goto takes the indirect_id of an |
| 2202 // indirect entry as a parameter, and jumps to that location. |
| 2203 // |
| 2204 // In more detail: in order to preserve split-edge form, an intermediate target |
| 2205 // entry consisting of a goto to the final indirect entry is inserted on |
| 2206 // each possible indirect goto -> indirect entry edge. These target entries are |
| 2207 // accessible through successors_. |
| 2208 // |
| 2209 // Byte offsets of all possible indirect targets are stored in the offsets_ |
| 2210 // array. The desired offset is looked up while the generated code is executing, |
| 2211 // and passed to IndirectGoto as an input. |
| 2212 class IndirectGotoInstr : public TemplateInstruction<1, NoThrow> { |
| 2213 public: |
| 2214 IndirectGotoInstr(GrowableObjectArray* offsets, |
| 2215 Value* offset_from_start) |
| 2216 : offsets_(*offsets) { |
| 2217 SetInputAt(0, offset_from_start); |
| 2218 } |
| 2219 |
| 2220 DECLARE_INSTRUCTION(IndirectGoto) |
| 2221 |
| 2222 virtual intptr_t ArgumentCount() const { return 0; } |
| 2223 |
| 2224 void AddSuccessor(TargetEntryInstr* successor) { |
| 2225 ASSERT(successor->next()->IsGoto()); |
| 2226 ASSERT(successor->next()->AsGoto()->successor()->IsIndirectEntry()); |
| 2227 successors_.Add(successor); |
| 2228 } |
| 2229 |
| 2230 virtual intptr_t SuccessorCount() const { return successors_.length(); } |
| 2231 virtual TargetEntryInstr* SuccessorAt(intptr_t index) const { |
| 2232 ASSERT(index < SuccessorCount()); |
| 2233 return successors_[index]; |
| 2234 } |
| 2235 |
| 2236 virtual bool CanDeoptimize() const { return false; } |
| 2237 virtual bool CanBecomeDeoptimizationTarget() const { return false; } |
| 2238 |
| 2239 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 2240 |
| 2241 virtual void PrintTo(BufferFormatter* f) const; |
| 2242 |
| 2243 const GrowableObjectArray& offsets() const { return offsets_; } |
| 2244 void SetOffsetCount(Isolate* isolate, intptr_t count) { |
| 2245 if (offsets_.Capacity() < count) { |
| 2246 offsets_.Grow(count, Heap::kOld); |
| 2247 } |
| 2248 if (offsets_.Length() < count) { |
| 2249 offsets_.SetLength(count); |
| 2250 } |
| 2251 } |
| 2252 void SetOffsetAt(Isolate* isolate, intptr_t index, intptr_t offset) { |
| 2253 offsets_.SetAt(index, Smi::ZoneHandle(isolate, Smi::New(offset))); |
| 2254 } |
| 2255 |
| 2256 private: |
| 2257 GrowableArray<TargetEntryInstr*> successors_; |
| 2258 GrowableObjectArray& offsets_; |
| 2259 }; |
| 2260 |
| 2261 |
| 2160 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { | 2262 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| 2161 public: | 2263 public: |
| 2162 Value* left() const { return inputs_[0]; } | 2264 Value* left() const { return inputs_[0]; } |
| 2163 Value* right() const { return inputs_[1]; } | 2265 Value* right() const { return inputs_[1]; } |
| 2164 | 2266 |
| 2165 virtual intptr_t token_pos() const { return token_pos_; } | 2267 virtual intptr_t token_pos() const { return token_pos_; } |
| 2166 Token::Kind kind() const { return kind_; } | 2268 Token::Kind kind() const { return kind_; } |
| 2167 | 2269 |
| 2168 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; | 2270 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; |
| 2169 | 2271 |
| (...skipping 1474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3644 | 3746 |
| 3645 private: | 3747 private: |
| 3646 const intptr_t index_scale_; | 3748 const intptr_t index_scale_; |
| 3647 const intptr_t class_id_; | 3749 const intptr_t class_id_; |
| 3648 const intptr_t token_pos_; | 3750 const intptr_t token_pos_; |
| 3649 | 3751 |
| 3650 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); | 3752 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); |
| 3651 }; | 3753 }; |
| 3652 | 3754 |
| 3653 | 3755 |
| 3756 // Loads the specified number of code units from the given string, packing |
| 3757 // multiple code units into a single datatype. In essence, this is a specialized |
| 3758 // version of LoadIndexedInstr which accepts only string targets and can load |
| 3759 // multiple elements at once. The result datatype differs depending on the |
| 3760 // string type, element count, and architecture; if possible, the result is |
| 3761 // packed into a Smi, falling back to a Mint otherwise. |
| 3762 // TODO(jgruber): Add support for loading into UnboxedInt32x4. |
| 3763 class LoadCodeUnitsInstr : public TemplateDefinition<2, NoThrow> { |
| 3764 public: |
| 3765 LoadCodeUnitsInstr(Value* str, |
| 3766 Value* index, |
| 3767 intptr_t element_count, |
| 3768 intptr_t class_id, |
| 3769 intptr_t token_pos) |
| 3770 : class_id_(class_id), |
| 3771 token_pos_(token_pos), |
| 3772 element_count_(element_count) { |
| 3773 ASSERT(element_count == 1 || element_count == 2 || element_count == 4); |
| 3774 ASSERT(class_id == kOneByteStringCid || class_id == kTwoByteStringCid); |
| 3775 SetInputAt(0, str); |
| 3776 SetInputAt(1, index); |
| 3777 } |
| 3778 |
| 3779 intptr_t token_pos() const { return token_pos_; } |
| 3780 |
| 3781 DECLARE_INSTRUCTION(LoadCodeUnits) |
| 3782 virtual CompileType ComputeType() const; |
| 3783 |
| 3784 bool IsExternal() const { |
| 3785 return array()->definition()->representation() == kUntagged; |
| 3786 } |
| 3787 |
| 3788 Value* array() const { return inputs_[0]; } |
| 3789 Value* index() const { return inputs_[1]; } |
| 3790 intptr_t index_scale() const { return Instance::ElementSizeFor(class_id_); } |
| 3791 intptr_t class_id() const { return class_id_; } |
| 3792 intptr_t element_count() const { return element_count_; } |
| 3793 |
| 3794 bool can_pack_into_smi() const { |
| 3795 return element_count() <= kSmiBits / (index_scale() * kBitsPerByte); |
| 3796 } |
| 3797 |
| 3798 virtual bool CanDeoptimize() const { return false; } |
| 3799 |
| 3800 virtual Representation representation() const; |
| 3801 virtual void InferRange(RangeAnalysis* analysis, Range* range); |
| 3802 |
| 3803 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 3804 |
| 3805 private: |
| 3806 const intptr_t class_id_; |
| 3807 const intptr_t token_pos_; |
| 3808 const intptr_t element_count_; |
| 3809 |
| 3810 DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr); |
| 3811 }; |
| 3812 |
| 3813 |
| 3654 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { | 3814 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { |
| 3655 public: | 3815 public: |
| 3656 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { | 3816 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { |
| 3657 ASSERT(char_code != NULL); | 3817 ASSERT(char_code != NULL); |
| 3658 ASSERT(char_code->definition()->IsLoadIndexed()); | 3818 ASSERT(char_code->definition()->IsLoadIndexed()); |
| 3659 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == | 3819 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == |
| 3660 kOneByteStringCid); | 3820 kOneByteStringCid); |
| 3661 SetInputAt(0, char_code); | 3821 SetInputAt(0, char_code); |
| 3662 } | 3822 } |
| 3663 | 3823 |
| (...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4782 | 4942 |
| 4783 static const char* KindToCString(MathUnaryKind kind); | 4943 static const char* KindToCString(MathUnaryKind kind); |
| 4784 | 4944 |
| 4785 private: | 4945 private: |
| 4786 const MathUnaryKind kind_; | 4946 const MathUnaryKind kind_; |
| 4787 | 4947 |
| 4788 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); | 4948 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); |
| 4789 }; | 4949 }; |
| 4790 | 4950 |
| 4791 | 4951 |
| 4952 // Calls into the runtime and performs a case-insensitive comparison of the |
| 4953 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at |
| 4954 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length]. |
| 4955 // |
| 4956 // TODO(jgruber): Remove this once (if) functions inherited from unibrow |
| 4957 // are moved to dart code. |
| 4958 class CaseInsensitiveCompareUC16Instr |
| 4959 : public TemplateDefinition<4, NoThrow, Pure> { |
| 4960 public: |
| 4961 CaseInsensitiveCompareUC16Instr( |
| 4962 Value* str, |
| 4963 Value* lhs_index, |
| 4964 Value* rhs_index, |
| 4965 Value* length, |
| 4966 intptr_t cid) |
| 4967 : cid_(cid) { |
| 4968 ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid); |
| 4969 ASSERT(index_scale() == 2); |
| 4970 SetInputAt(0, str); |
| 4971 SetInputAt(1, lhs_index); |
| 4972 SetInputAt(2, rhs_index); |
| 4973 SetInputAt(3, length); |
| 4974 } |
| 4975 |
| 4976 Value* str() const { return inputs_[0]; } |
| 4977 Value* lhs_index() const { return inputs_[1]; } |
| 4978 Value* rhs_index() const { return inputs_[2]; } |
| 4979 Value* length() const { return inputs_[3]; } |
| 4980 |
| 4981 const RuntimeEntry& TargetFunction() const; |
| 4982 bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; } |
| 4983 intptr_t class_id() const { return cid_; } |
| 4984 intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); } |
| 4985 |
| 4986 virtual bool CanDeoptimize() const { return false; } |
| 4987 |
| 4988 virtual Representation representation() const { |
| 4989 return kTagged; |
| 4990 } |
| 4991 |
| 4992 DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16) |
| 4993 virtual CompileType ComputeType() const; |
| 4994 |
| 4995 virtual bool AttributesEqual(Instruction* other) const { |
| 4996 return other->AsCaseInsensitiveCompareUC16()->cid_ == cid_; |
| 4997 } |
| 4998 |
| 4999 private: |
| 5000 const intptr_t cid_; |
| 5001 |
| 5002 DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr); |
| 5003 }; |
| 5004 |
| 5005 |
| 4792 // Represents Math's static min and max functions. | 5006 // Represents Math's static min and max functions. |
| 4793 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { | 5007 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| 4794 public: | 5008 public: |
| 4795 MathMinMaxInstr(MethodRecognizer::Kind op_kind, | 5009 MathMinMaxInstr(MethodRecognizer::Kind op_kind, |
| 4796 Value* left_value, | 5010 Value* left_value, |
| 4797 Value* right_value, | 5011 Value* right_value, |
| 4798 intptr_t deopt_id, | 5012 intptr_t deopt_id, |
| 4799 intptr_t result_cid) | 5013 intptr_t result_cid) |
| 4800 : TemplateDefinition(deopt_id), | 5014 : TemplateDefinition(deopt_id), |
| 4801 op_kind_(op_kind), | 5015 op_kind_(op_kind), |
| (...skipping 3117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7919 Isolate* isolate, bool opt) const { \ | 8133 Isolate* isolate, bool opt) const { \ |
| 7920 UNIMPLEMENTED(); \ | 8134 UNIMPLEMENTED(); \ |
| 7921 return NULL; \ | 8135 return NULL; \ |
| 7922 } \ | 8136 } \ |
| 7923 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 8137 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
| 7924 | 8138 |
| 7925 | 8139 |
| 7926 } // namespace dart | 8140 } // namespace dart |
| 7927 | 8141 |
| 7928 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 8142 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |