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