| 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 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 | 423 |
| 424 // Instructions. | 424 // Instructions. |
| 425 | 425 |
| 426 // M is a single argument macro. It is applied to each concrete instruction | 426 // M is a single argument macro. It is applied to each concrete instruction |
| 427 // type name. The concrete instruction classes are the name with Instr | 427 // type name. The concrete instruction classes are the name with Instr |
| 428 // concatenated. | 428 // concatenated. |
| 429 #define FOR_EACH_INSTRUCTION(M) \ | 429 #define FOR_EACH_INSTRUCTION(M) \ |
| 430 M(GraphEntry) \ | 430 M(GraphEntry) \ |
| 431 M(JoinEntry) \ | 431 M(JoinEntry) \ |
| 432 M(TargetEntry) \ | 432 M(TargetEntry) \ |
| 433 M(IndirectEntry) \ | |
| 434 M(CatchBlockEntry) \ | 433 M(CatchBlockEntry) \ |
| 435 M(Phi) \ | 434 M(Phi) \ |
| 436 M(Redefinition) \ | 435 M(Redefinition) \ |
| 437 M(Parameter) \ | 436 M(Parameter) \ |
| 438 M(ParallelMove) \ | 437 M(ParallelMove) \ |
| 439 M(PushArgument) \ | 438 M(PushArgument) \ |
| 440 M(Return) \ | 439 M(Return) \ |
| 441 M(Throw) \ | 440 M(Throw) \ |
| 442 M(ReThrow) \ | 441 M(ReThrow) \ |
| 443 M(Goto) \ | 442 M(Goto) \ |
| 444 M(IndirectGoto) \ | |
| 445 M(Branch) \ | 443 M(Branch) \ |
| 446 M(AssertAssignable) \ | 444 M(AssertAssignable) \ |
| 447 M(AssertBoolean) \ | 445 M(AssertBoolean) \ |
| 448 M(CurrentContext) \ | 446 M(CurrentContext) \ |
| 449 M(ClosureCall) \ | 447 M(ClosureCall) \ |
| 450 M(InstanceCall) \ | 448 M(InstanceCall) \ |
| 451 M(PolymorphicInstanceCall) \ | 449 M(PolymorphicInstanceCall) \ |
| 452 M(StaticCall) \ | 450 M(StaticCall) \ |
| 453 M(LoadLocal) \ | 451 M(LoadLocal) \ |
| 454 M(PushTemp) \ | 452 M(PushTemp) \ |
| 455 M(DropTemps) \ | 453 M(DropTemps) \ |
| 456 M(StoreLocal) \ | 454 M(StoreLocal) \ |
| 457 M(StrictCompare) \ | 455 M(StrictCompare) \ |
| 458 M(EqualityCompare) \ | 456 M(EqualityCompare) \ |
| 459 M(RelationalOp) \ | 457 M(RelationalOp) \ |
| 460 M(NativeCall) \ | 458 M(NativeCall) \ |
| 461 M(DebugStepCheck) \ | 459 M(DebugStepCheck) \ |
| 462 M(LoadIndexed) \ | 460 M(LoadIndexed) \ |
| 463 M(LoadCodeUnits) \ | |
| 464 M(StoreIndexed) \ | 461 M(StoreIndexed) \ |
| 465 M(StoreInstanceField) \ | 462 M(StoreInstanceField) \ |
| 466 M(InitStaticField) \ | 463 M(InitStaticField) \ |
| 467 M(LoadStaticField) \ | 464 M(LoadStaticField) \ |
| 468 M(StoreStaticField) \ | 465 M(StoreStaticField) \ |
| 469 M(BooleanNegate) \ | 466 M(BooleanNegate) \ |
| 470 M(InstanceOf) \ | 467 M(InstanceOf) \ |
| 471 M(CreateArray) \ | 468 M(CreateArray) \ |
| 472 M(AllocateObject) \ | 469 M(AllocateObject) \ |
| 473 M(LoadField) \ | 470 M(LoadField) \ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 497 M(Constant) \ | 494 M(Constant) \ |
| 498 M(UnboxedConstant) \ | 495 M(UnboxedConstant) \ |
| 499 M(CheckEitherNonSmi) \ | 496 M(CheckEitherNonSmi) \ |
| 500 M(BinaryDoubleOp) \ | 497 M(BinaryDoubleOp) \ |
| 501 M(MathUnary) \ | 498 M(MathUnary) \ |
| 502 M(MathMinMax) \ | 499 M(MathMinMax) \ |
| 503 M(Box) \ | 500 M(Box) \ |
| 504 M(Unbox) \ | 501 M(Unbox) \ |
| 505 M(BoxInt64) \ | 502 M(BoxInt64) \ |
| 506 M(UnboxInt64) \ | 503 M(UnboxInt64) \ |
| 507 M(CaseInsensitiveCompareUC16) \ | |
| 508 M(BinaryMintOp) \ | 504 M(BinaryMintOp) \ |
| 509 M(ShiftMintOp) \ | 505 M(ShiftMintOp) \ |
| 510 M(UnaryMintOp) \ | 506 M(UnaryMintOp) \ |
| 511 M(CheckArrayBound) \ | 507 M(CheckArrayBound) \ |
| 512 M(Constraint) \ | 508 M(Constraint) \ |
| 513 M(StringToCharCode) \ | 509 M(StringToCharCode) \ |
| 514 M(StringFromCharCode) \ | 510 M(StringFromCharCode) \ |
| 515 M(StringInterpolate) \ | 511 M(StringInterpolate) \ |
| 516 M(InvokeMathCFunction) \ | 512 M(InvokeMathCFunction) \ |
| 517 M(MergedMath) \ | 513 M(MergedMath) \ |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1164 return const_cast<BlockEntryInstr*>(this); | 1160 return const_cast<BlockEntryInstr*>(this); |
| 1165 } | 1161 } |
| 1166 | 1162 |
| 1167 // Helper to mutate the graph during inlining. This block should be | 1163 // Helper to mutate the graph during inlining. This block should be |
| 1168 // replaced with new_block as a predecessor of all of this block's | 1164 // replaced with new_block as a predecessor of all of this block's |
| 1169 // successors. | 1165 // successors. |
| 1170 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); | 1166 void ReplaceAsPredecessorWith(BlockEntryInstr* new_block); |
| 1171 | 1167 |
| 1172 void set_block_id(intptr_t block_id) { block_id_ = block_id; } | 1168 void set_block_id(intptr_t block_id) { block_id_ = block_id; } |
| 1173 | 1169 |
| 1174 intptr_t offset() const { return offset_; } | |
| 1175 void set_offset(intptr_t offset) { offset_ = offset; } | |
| 1176 | |
| 1177 // For all instruction in this block: Remove all inputs (including in the | 1170 // For all instruction in this block: Remove all inputs (including in the |
| 1178 // environment) from their definition's use lists for all instructions. | 1171 // environment) from their definition's use lists for all instructions. |
| 1179 void ClearAllInstructions(); | 1172 void ClearAllInstructions(); |
| 1180 | 1173 |
| 1181 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) | 1174 DEFINE_INSTRUCTION_TYPE_CHECK(BlockEntry) |
| 1182 | 1175 |
| 1183 protected: | 1176 protected: |
| 1184 BlockEntryInstr(intptr_t block_id, intptr_t try_index) | 1177 BlockEntryInstr(intptr_t block_id, intptr_t try_index) |
| 1185 : Instruction(Isolate::Current()->GetNextDeoptId()), | 1178 : Instruction(Isolate::Current()->GetNextDeoptId()), |
| 1186 block_id_(block_id), | 1179 block_id_(block_id), |
| 1187 try_index_(try_index), | 1180 try_index_(try_index), |
| 1188 preorder_number_(-1), | 1181 preorder_number_(-1), |
| 1189 postorder_number_(-1), | 1182 postorder_number_(-1), |
| 1190 dominator_(NULL), | 1183 dominator_(NULL), |
| 1191 dominated_blocks_(1), | 1184 dominated_blocks_(1), |
| 1192 last_instruction_(NULL), | 1185 last_instruction_(NULL), |
| 1193 offset_(-1), | |
| 1194 parallel_move_(NULL), | 1186 parallel_move_(NULL), |
| 1195 loop_info_(NULL) { | 1187 loop_info_(NULL) { |
| 1196 } | 1188 } |
| 1197 | 1189 |
| 1198 private: | 1190 private: |
| 1199 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } | 1191 virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); } |
| 1200 | 1192 |
| 1201 virtual void ClearPredecessors() = 0; | 1193 virtual void ClearPredecessors() = 0; |
| 1202 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; | 1194 virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0; |
| 1203 | 1195 |
| 1204 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } | 1196 void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; } |
| 1205 | 1197 |
| 1206 intptr_t block_id_; | 1198 intptr_t block_id_; |
| 1207 const intptr_t try_index_; | 1199 const intptr_t try_index_; |
| 1208 intptr_t preorder_number_; | 1200 intptr_t preorder_number_; |
| 1209 intptr_t postorder_number_; | 1201 intptr_t postorder_number_; |
| 1210 // Starting and ending lifetime positions for this block. Used by | 1202 // Starting and ending lifetime positions for this block. Used by |
| 1211 // the linear scan register allocator. | 1203 // the linear scan register allocator. |
| 1212 intptr_t start_pos_; | 1204 intptr_t start_pos_; |
| 1213 intptr_t end_pos_; | 1205 intptr_t end_pos_; |
| 1214 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. | 1206 BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry. |
| 1215 // TODO(fschneider): Optimize the case of one child to save space. | 1207 // TODO(fschneider): Optimize the case of one child to save space. |
| 1216 GrowableArray<BlockEntryInstr*> dominated_blocks_; | 1208 GrowableArray<BlockEntryInstr*> dominated_blocks_; |
| 1217 Instruction* last_instruction_; | 1209 Instruction* last_instruction_; |
| 1218 | 1210 |
| 1219 // Offset of this block from the start of the emitted code. | |
| 1220 intptr_t offset_; | |
| 1221 | |
| 1222 // Parallel move that will be used by linear scan register allocator to | 1211 // Parallel move that will be used by linear scan register allocator to |
| 1223 // connect live ranges at the start of the block. | 1212 // connect live ranges at the start of the block. |
| 1224 ParallelMoveInstr* parallel_move_; | 1213 ParallelMoveInstr* parallel_move_; |
| 1225 | 1214 |
| 1226 // Bit vector containg loop blocks for a loop header indexed by block | 1215 // Bit vector containg loop blocks for a loop header indexed by block |
| 1227 // preorder number. | 1216 // preorder number. |
| 1228 BitVector* loop_info_; | 1217 BitVector* loop_info_; |
| 1229 | 1218 |
| 1230 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); | 1219 DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr); |
| 1231 }; | 1220 }; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1292 UNREACHABLE(); | 1281 UNREACHABLE(); |
| 1293 return NULL; | 1282 return NULL; |
| 1294 } | 1283 } |
| 1295 virtual intptr_t SuccessorCount() const; | 1284 virtual intptr_t SuccessorCount() const; |
| 1296 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; | 1285 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; |
| 1297 | 1286 |
| 1298 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } | 1287 void AddCatchEntry(CatchBlockEntryInstr* entry) { catch_entries_.Add(entry); } |
| 1299 | 1288 |
| 1300 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); | 1289 CatchBlockEntryInstr* GetCatchEntry(intptr_t index); |
| 1301 | 1290 |
| 1302 void AddIndirectEntry(IndirectEntryInstr* entry) { | |
| 1303 indirect_entries_.Add(entry); | |
| 1304 } | |
| 1305 | |
| 1306 GrowableArray<Definition*>* initial_definitions() { | 1291 GrowableArray<Definition*>* initial_definitions() { |
| 1307 return &initial_definitions_; | 1292 return &initial_definitions_; |
| 1308 } | 1293 } |
| 1309 ConstantInstr* constant_null(); | 1294 ConstantInstr* constant_null(); |
| 1310 | 1295 |
| 1311 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } | 1296 bool IsCompiledForOsr() const { return osr_id_ != Isolate::kNoDeoptId; } |
| 1312 | 1297 |
| 1313 intptr_t entry_count() const { return entry_count_; } | 1298 intptr_t entry_count() const { return entry_count_; } |
| 1314 void set_entry_count(intptr_t count) { entry_count_ = count; } | 1299 void set_entry_count(intptr_t count) { entry_count_ = count; } |
| 1315 | 1300 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1330 TargetEntryInstr* normal_entry() const { return normal_entry_; } | 1315 TargetEntryInstr* normal_entry() const { return normal_entry_; } |
| 1331 | 1316 |
| 1332 const ParsedFunction& parsed_function() const { | 1317 const ParsedFunction& parsed_function() const { |
| 1333 return *parsed_function_; | 1318 return *parsed_function_; |
| 1334 } | 1319 } |
| 1335 | 1320 |
| 1336 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { | 1321 const GrowableArray<CatchBlockEntryInstr*>& catch_entries() const { |
| 1337 return catch_entries_; | 1322 return catch_entries_; |
| 1338 } | 1323 } |
| 1339 | 1324 |
| 1340 const GrowableArray<IndirectEntryInstr*>& indirect_entries() const { | |
| 1341 return indirect_entries_; | |
| 1342 } | |
| 1343 | |
| 1344 virtual void PrintTo(BufferFormatter* f) const; | 1325 virtual void PrintTo(BufferFormatter* f) const; |
| 1345 | 1326 |
| 1346 private: | 1327 private: |
| 1347 virtual void ClearPredecessors() {} | 1328 virtual void ClearPredecessors() {} |
| 1348 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } | 1329 virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); } |
| 1349 | 1330 |
| 1350 const ParsedFunction* parsed_function_; | 1331 const ParsedFunction* parsed_function_; |
| 1351 TargetEntryInstr* normal_entry_; | 1332 TargetEntryInstr* normal_entry_; |
| 1352 GrowableArray<CatchBlockEntryInstr*> catch_entries_; | 1333 GrowableArray<CatchBlockEntryInstr*> catch_entries_; |
| 1353 // Indirect targets are blocks reachable only through indirect gotos. | |
| 1354 GrowableArray<IndirectEntryInstr*> indirect_entries_; | |
| 1355 GrowableArray<Definition*> initial_definitions_; | 1334 GrowableArray<Definition*> initial_definitions_; |
| 1356 const intptr_t osr_id_; | 1335 const intptr_t osr_id_; |
| 1357 intptr_t entry_count_; | 1336 intptr_t entry_count_; |
| 1358 intptr_t spill_slot_count_; | 1337 intptr_t spill_slot_count_; |
| 1359 intptr_t fixed_slot_count_; // For try-catch in optimized code. | 1338 intptr_t fixed_slot_count_; // For try-catch in optimized code. |
| 1360 | 1339 |
| 1361 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); | 1340 DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr); |
| 1362 }; | 1341 }; |
| 1363 | 1342 |
| 1364 | 1343 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1390 virtual void PrintTo(BufferFormatter* f) const; | 1369 virtual void PrintTo(BufferFormatter* f) const; |
| 1391 | 1370 |
| 1392 virtual EffectSet Effects() const { return EffectSet::None(); } | 1371 virtual EffectSet Effects() const { return EffectSet::None(); } |
| 1393 virtual EffectSet Dependencies() const { return EffectSet::None(); } | 1372 virtual EffectSet Dependencies() const { return EffectSet::None(); } |
| 1394 | 1373 |
| 1395 private: | 1374 private: |
| 1396 // Classes that have access to predecessors_ when inlining. | 1375 // Classes that have access to predecessors_ when inlining. |
| 1397 friend class BlockEntryInstr; | 1376 friend class BlockEntryInstr; |
| 1398 friend class InlineExitCollector; | 1377 friend class InlineExitCollector; |
| 1399 friend class PolymorphicInliner; | 1378 friend class PolymorphicInliner; |
| 1400 friend class IndirectEntryInstr; // Access in il_printer.cc. | |
| 1401 | 1379 |
| 1402 // Direct access to phis_ in order to resize it due to phi elimination. | 1380 // Direct access to phis_ in order to resize it due to phi elimination. |
| 1403 friend class ConstantPropagator; | 1381 friend class ConstantPropagator; |
| 1404 friend class DeadCodeElimination; | 1382 friend class DeadCodeElimination; |
| 1405 | 1383 |
| 1406 virtual void ClearPredecessors() { predecessors_.Clear(); } | 1384 virtual void ClearPredecessors() { predecessors_.Clear(); } |
| 1407 virtual void AddPredecessor(BlockEntryInstr* predecessor); | 1385 virtual void AddPredecessor(BlockEntryInstr* predecessor); |
| 1408 | 1386 |
| 1409 GrowableArray<BlockEntryInstr*> predecessors_; | 1387 GrowableArray<BlockEntryInstr*> predecessors_; |
| 1410 ZoneGrowableArray<PhiInstr*>* phis_; | 1388 ZoneGrowableArray<PhiInstr*>* phis_; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1469 predecessor_ = predecessor; | 1447 predecessor_ = predecessor; |
| 1470 } | 1448 } |
| 1471 | 1449 |
| 1472 BlockEntryInstr* predecessor_; | 1450 BlockEntryInstr* predecessor_; |
| 1473 double edge_weight_; | 1451 double edge_weight_; |
| 1474 | 1452 |
| 1475 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); | 1453 DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr); |
| 1476 }; | 1454 }; |
| 1477 | 1455 |
| 1478 | 1456 |
| 1479 class IndirectEntryInstr : public JoinEntryInstr { | |
| 1480 public: | |
| 1481 IndirectEntryInstr(intptr_t block_id, | |
| 1482 intptr_t indirect_id, | |
| 1483 intptr_t try_index) | |
| 1484 : JoinEntryInstr(block_id, try_index), | |
| 1485 indirect_id_(indirect_id) { } | |
| 1486 | |
| 1487 DECLARE_INSTRUCTION(IndirectEntry) | |
| 1488 | |
| 1489 virtual void PrintTo(BufferFormatter* f) const; | |
| 1490 | |
| 1491 intptr_t indirect_id() const { return indirect_id_; } | |
| 1492 | |
| 1493 private: | |
| 1494 const intptr_t indirect_id_; | |
| 1495 }; | |
| 1496 | |
| 1497 | |
| 1498 class CatchBlockEntryInstr : public BlockEntryInstr { | 1457 class CatchBlockEntryInstr : public BlockEntryInstr { |
| 1499 public: | 1458 public: |
| 1500 CatchBlockEntryInstr(intptr_t block_id, | 1459 CatchBlockEntryInstr(intptr_t block_id, |
| 1501 intptr_t try_index, | 1460 intptr_t try_index, |
| 1502 const Array& handler_types, | 1461 const Array& handler_types, |
| 1503 intptr_t catch_try_index, | 1462 intptr_t catch_try_index, |
| 1504 const LocalVariable& exception_var, | 1463 const LocalVariable& exception_var, |
| 1505 const LocalVariable& stacktrace_var, | 1464 const LocalVariable& stacktrace_var, |
| 1506 bool needs_stacktrace) | 1465 bool needs_stacktrace) |
| 1507 : BlockEntryInstr(block_id, try_index), | 1466 : BlockEntryInstr(block_id, try_index), |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2160 private: | 2119 private: |
| 2161 JoinEntryInstr* successor_; | 2120 JoinEntryInstr* successor_; |
| 2162 double edge_weight_; | 2121 double edge_weight_; |
| 2163 | 2122 |
| 2164 // Parallel move that will be used by linear scan register allocator to | 2123 // Parallel move that will be used by linear scan register allocator to |
| 2165 // connect live ranges at the end of the block and resolve phis. | 2124 // connect live ranges at the end of the block and resolve phis. |
| 2166 ParallelMoveInstr* parallel_move_; | 2125 ParallelMoveInstr* parallel_move_; |
| 2167 }; | 2126 }; |
| 2168 | 2127 |
| 2169 | 2128 |
| 2170 // IndirectGotoInstr represents a dynamically computed jump. Only | |
| 2171 // IndirectEntryInstr targets are valid targets of an indirect goto. The | |
| 2172 // concrete target to jump to is given as a parameter to the indirect goto. | |
| 2173 // | |
| 2174 // In order to preserve split-edge form, an indirect goto does not itself point | |
| 2175 // to its targets. Instead, for each possible target, the successors_ field | |
| 2176 // will contain an ordinary goto instruction that jumps to the target. | |
| 2177 // TODO(zerny): Implement direct support instead of embedding gotos. | |
| 2178 // | |
| 2179 // Byte offsets of all possible targets are stored in the offsets_ array. The | |
| 2180 // desired offset is looked up while the generated code is executing, and passed | |
| 2181 // to IndirectGoto as an input. | |
| 2182 class IndirectGotoInstr : public TemplateInstruction<1, NoThrow> { | |
| 2183 public: | |
| 2184 IndirectGotoInstr(GrowableObjectArray* offsets, | |
| 2185 Value* offset_from_start) | |
| 2186 : offsets_(*offsets) { | |
| 2187 SetInputAt(0, offset_from_start); | |
| 2188 } | |
| 2189 | |
| 2190 DECLARE_INSTRUCTION(IndirectGoto) | |
| 2191 | |
| 2192 virtual intptr_t ArgumentCount() const { return 0; } | |
| 2193 | |
| 2194 void AddSuccessor(TargetEntryInstr* successor) { | |
| 2195 ASSERT(successor->next()->IsGoto()); | |
| 2196 ASSERT(successor->next()->AsGoto()->successor()->IsIndirectEntry()); | |
| 2197 successors_.Add(successor); | |
| 2198 } | |
| 2199 | |
| 2200 virtual intptr_t SuccessorCount() const { return successors_.length(); } | |
| 2201 virtual TargetEntryInstr* SuccessorAt(intptr_t index) const { | |
| 2202 ASSERT(index < SuccessorCount()); | |
| 2203 return successors_[index]; | |
| 2204 } | |
| 2205 | |
| 2206 virtual bool CanDeoptimize() const { return false; } | |
| 2207 virtual bool CanBecomeDeoptimizationTarget() const { return false; } | |
| 2208 | |
| 2209 virtual EffectSet Effects() const { return EffectSet::None(); } | |
| 2210 | |
| 2211 virtual void PrintTo(BufferFormatter* f) const; | |
| 2212 | |
| 2213 const GrowableObjectArray& offsets() const { return offsets_; } | |
| 2214 void ComputeOffsetTable(Isolate* isolate); | |
| 2215 | |
| 2216 private: | |
| 2217 GrowableArray<TargetEntryInstr*> successors_; | |
| 2218 GrowableObjectArray& offsets_; | |
| 2219 }; | |
| 2220 | |
| 2221 | |
| 2222 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { | 2129 class ComparisonInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| 2223 public: | 2130 public: |
| 2224 Value* left() const { return inputs_[0]; } | 2131 Value* left() const { return inputs_[0]; } |
| 2225 Value* right() const { return inputs_[1]; } | 2132 Value* right() const { return inputs_[1]; } |
| 2226 | 2133 |
| 2227 virtual intptr_t token_pos() const { return token_pos_; } | 2134 virtual intptr_t token_pos() const { return token_pos_; } |
| 2228 Token::Kind kind() const { return kind_; } | 2135 Token::Kind kind() const { return kind_; } |
| 2229 | 2136 |
| 2230 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; | 2137 virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right) = 0; |
| 2231 | 2138 |
| (...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3669 | 3576 |
| 3670 private: | 3577 private: |
| 3671 const intptr_t index_scale_; | 3578 const intptr_t index_scale_; |
| 3672 const intptr_t class_id_; | 3579 const intptr_t class_id_; |
| 3673 const intptr_t token_pos_; | 3580 const intptr_t token_pos_; |
| 3674 | 3581 |
| 3675 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); | 3582 DISALLOW_COPY_AND_ASSIGN(LoadIndexedInstr); |
| 3676 }; | 3583 }; |
| 3677 | 3584 |
| 3678 | 3585 |
| 3679 // Loads the specified number of code units from the given string, packing | |
| 3680 // multiple code units into a single datatype. In essence, this is a specialized | |
| 3681 // version of LoadIndexedInstr which accepts only string targets and can load | |
| 3682 // multiple elements at once. The result datatype differs depending on the | |
| 3683 // string type, element count, and architecture; if possible, the result is | |
| 3684 // packed into a Smi, falling back to a Mint otherwise. | |
| 3685 // TODO(zerny): Add support for loading into UnboxedInt32x4. | |
| 3686 class LoadCodeUnitsInstr : public TemplateDefinition<2, NoThrow> { | |
| 3687 public: | |
| 3688 LoadCodeUnitsInstr(Value* str, | |
| 3689 Value* index, | |
| 3690 intptr_t element_count, | |
| 3691 intptr_t class_id, | |
| 3692 intptr_t token_pos) | |
| 3693 : class_id_(class_id), | |
| 3694 token_pos_(token_pos), | |
| 3695 element_count_(element_count), | |
| 3696 representation_(kTagged) { | |
| 3697 ASSERT(element_count == 1 || element_count == 2 || element_count == 4); | |
| 3698 ASSERT(class_id == kOneByteStringCid || class_id == kTwoByteStringCid); | |
| 3699 SetInputAt(0, str); | |
| 3700 SetInputAt(1, index); | |
| 3701 } | |
| 3702 | |
| 3703 intptr_t token_pos() const { return token_pos_; } | |
| 3704 | |
| 3705 DECLARE_INSTRUCTION(LoadCodeUnits) | |
| 3706 virtual CompileType ComputeType() const; | |
| 3707 | |
| 3708 bool IsExternal() const { | |
| 3709 return array()->definition()->representation() == kUntagged; | |
| 3710 } | |
| 3711 | |
| 3712 Value* array() const { return inputs_[0]; } | |
| 3713 Value* index() const { return inputs_[1]; } | |
| 3714 intptr_t index_scale() const { return Instance::ElementSizeFor(class_id_); } | |
| 3715 intptr_t class_id() const { return class_id_; } | |
| 3716 intptr_t element_count() const { return element_count_; } | |
| 3717 | |
| 3718 bool can_pack_into_smi() const { | |
| 3719 return element_count() <= kSmiBits / (index_scale() * kBitsPerByte); | |
| 3720 } | |
| 3721 | |
| 3722 virtual bool CanDeoptimize() const { return false; } | |
| 3723 | |
| 3724 virtual Representation representation() const { return representation_; } | |
| 3725 void set_representation(Representation repr) { representation_ = repr; } | |
| 3726 virtual void InferRange(RangeAnalysis* analysis, Range* range); | |
| 3727 | |
| 3728 virtual EffectSet Effects() const { return EffectSet::None(); } | |
| 3729 | |
| 3730 private: | |
| 3731 const intptr_t class_id_; | |
| 3732 const intptr_t token_pos_; | |
| 3733 const intptr_t element_count_; | |
| 3734 Representation representation_; | |
| 3735 | |
| 3736 DISALLOW_COPY_AND_ASSIGN(LoadCodeUnitsInstr); | |
| 3737 }; | |
| 3738 | |
| 3739 | |
| 3740 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { | 3586 class StringFromCharCodeInstr : public TemplateDefinition<1, NoThrow, Pure> { |
| 3741 public: | 3587 public: |
| 3742 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { | 3588 StringFromCharCodeInstr(Value* char_code, intptr_t cid) : cid_(cid) { |
| 3743 ASSERT(char_code != NULL); | 3589 ASSERT(char_code != NULL); |
| 3744 ASSERT(char_code->definition()->IsLoadIndexed()); | 3590 ASSERT(char_code->definition()->IsLoadIndexed()); |
| 3745 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == | 3591 ASSERT(char_code->definition()->AsLoadIndexed()->class_id() == |
| 3746 kOneByteStringCid); | 3592 kOneByteStringCid); |
| 3747 SetInputAt(0, char_code); | 3593 SetInputAt(0, char_code); |
| 3748 } | 3594 } |
| 3749 | 3595 |
| (...skipping 1184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4934 | 4780 |
| 4935 static const char* KindToCString(MathUnaryKind kind); | 4781 static const char* KindToCString(MathUnaryKind kind); |
| 4936 | 4782 |
| 4937 private: | 4783 private: |
| 4938 const MathUnaryKind kind_; | 4784 const MathUnaryKind kind_; |
| 4939 | 4785 |
| 4940 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); | 4786 DISALLOW_COPY_AND_ASSIGN(MathUnaryInstr); |
| 4941 }; | 4787 }; |
| 4942 | 4788 |
| 4943 | 4789 |
| 4944 // Calls into the runtime and performs a case-insensitive comparison of the | |
| 4945 // UTF16 strings (i.e. TwoByteString or ExternalTwoByteString) located at | |
| 4946 // str[lhs_index:lhs_index + length] and str[rhs_index:rhs_index + length]. | |
| 4947 // | |
| 4948 // TODO(zerny): Remove this once (if) functions inherited from unibrow | |
| 4949 // are moved to dart code. | |
| 4950 class CaseInsensitiveCompareUC16Instr | |
| 4951 : public TemplateDefinition<4, NoThrow, Pure> { | |
| 4952 public: | |
| 4953 CaseInsensitiveCompareUC16Instr( | |
| 4954 Value* str, | |
| 4955 Value* lhs_index, | |
| 4956 Value* rhs_index, | |
| 4957 Value* length, | |
| 4958 intptr_t cid) | |
| 4959 : cid_(cid) { | |
| 4960 ASSERT(cid == kTwoByteStringCid || cid == kExternalTwoByteStringCid); | |
| 4961 ASSERT(index_scale() == 2); | |
| 4962 SetInputAt(0, str); | |
| 4963 SetInputAt(1, lhs_index); | |
| 4964 SetInputAt(2, rhs_index); | |
| 4965 SetInputAt(3, length); | |
| 4966 } | |
| 4967 | |
| 4968 Value* str() const { return inputs_[0]; } | |
| 4969 Value* lhs_index() const { return inputs_[1]; } | |
| 4970 Value* rhs_index() const { return inputs_[2]; } | |
| 4971 Value* length() const { return inputs_[3]; } | |
| 4972 | |
| 4973 const RuntimeEntry& TargetFunction() const; | |
| 4974 bool IsExternal() const { return cid_ == kExternalTwoByteStringCid; } | |
| 4975 intptr_t class_id() const { return cid_; } | |
| 4976 intptr_t index_scale() const { return Instance::ElementSizeFor(cid_); } | |
| 4977 | |
| 4978 virtual bool CanDeoptimize() const { return false; } | |
| 4979 | |
| 4980 virtual Representation representation() const { | |
| 4981 return kTagged; | |
| 4982 } | |
| 4983 | |
| 4984 DECLARE_INSTRUCTION(CaseInsensitiveCompareUC16) | |
| 4985 virtual CompileType ComputeType() const; | |
| 4986 | |
| 4987 virtual bool AttributesEqual(Instruction* other) const { | |
| 4988 return other->AsCaseInsensitiveCompareUC16()->cid_ == cid_; | |
| 4989 } | |
| 4990 | |
| 4991 private: | |
| 4992 const intptr_t cid_; | |
| 4993 | |
| 4994 DISALLOW_COPY_AND_ASSIGN(CaseInsensitiveCompareUC16Instr); | |
| 4995 }; | |
| 4996 | |
| 4997 | |
| 4998 // Represents Math's static min and max functions. | 4790 // Represents Math's static min and max functions. |
| 4999 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { | 4791 class MathMinMaxInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| 5000 public: | 4792 public: |
| 5001 MathMinMaxInstr(MethodRecognizer::Kind op_kind, | 4793 MathMinMaxInstr(MethodRecognizer::Kind op_kind, |
| 5002 Value* left_value, | 4794 Value* left_value, |
| 5003 Value* right_value, | 4795 Value* right_value, |
| 5004 intptr_t deopt_id, | 4796 intptr_t deopt_id, |
| 5005 intptr_t result_cid) | 4797 intptr_t result_cid) |
| 5006 : TemplateDefinition(deopt_id), | 4798 : TemplateDefinition(deopt_id), |
| 5007 op_kind_(op_kind), | 4799 op_kind_(op_kind), |
| (...skipping 2963 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7971 Isolate* isolate, bool opt) const { \ | 7763 Isolate* isolate, bool opt) const { \ |
| 7972 UNIMPLEMENTED(); \ | 7764 UNIMPLEMENTED(); \ |
| 7973 return NULL; \ | 7765 return NULL; \ |
| 7974 } \ | 7766 } \ |
| 7975 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } | 7767 void Name::EmitNativeCode(FlowGraphCompiler* compiler) { UNIMPLEMENTED(); } |
| 7976 | 7768 |
| 7977 | 7769 |
| 7978 } // namespace dart | 7770 } // namespace dart |
| 7979 | 7771 |
| 7980 #endif // VM_INTERMEDIATE_LANGUAGE_H_ | 7772 #endif // VM_INTERMEDIATE_LANGUAGE_H_ |
| OLD | NEW |