Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: runtime/vm/intermediate_language.h

Issue 10802025: Fuse compare with branch at graph building time. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 104
105 105
106 #define FORWARD_DECLARATION(ShortName, ClassName) class ClassName; 106 #define FORWARD_DECLARATION(ShortName, ClassName) class ClassName;
107 FOR_EACH_COMPUTATION(FORWARD_DECLARATION) 107 FOR_EACH_COMPUTATION(FORWARD_DECLARATION)
108 #undef FORWARD_DECLARATION 108 #undef FORWARD_DECLARATION
109 109
110 // Forward declarations. 110 // Forward declarations.
111 class BindInstr; 111 class BindInstr;
112 class BranchInstr; 112 class BranchInstr;
113 class BufferFormatter; 113 class BufferFormatter;
114 class ComparisonComp;
Kevin Millikin (Google) 2012/07/19 12:28:05 My high level comment is that we should look for a
srdjan 2012/07/19 15:33:58 I agree.
114 class Instruction; 115 class Instruction;
115 class Value; 116 class Value;
116 117
117 class Computation : public ZoneAllocated { 118 class Computation : public ZoneAllocated {
118 public: 119 public:
119 static const int kNoCid = -1; 120 static const int kNoCid = -1;
120 121
121 Computation() : cid_(-1), ic_data_(NULL), locs_(NULL) { 122 Computation() : cid_(-1), ic_data_(NULL), locs_(NULL) {
122 Isolate* isolate = Isolate::Current(); 123 Isolate* isolate = Isolate::Current();
123 cid_ = GetNextCid(isolate); 124 cid_ = GetNextCid(isolate);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 157
157 // Returns structure describing location constraints required 158 // Returns structure describing location constraints required
158 // to emit native code for this computation. 159 // to emit native code for this computation.
159 LocationSummary* locs() { 160 LocationSummary* locs() {
160 if (locs_ == NULL) { 161 if (locs_ == NULL) {
161 locs_ = MakeLocationSummary(); 162 locs_ = MakeLocationSummary();
162 } 163 }
163 return locs_; 164 return locs_;
164 } 165 }
165 166
167 virtual ComparisonComp* AsComparison() { return NULL; }
168
166 // Create a location summary for this computation. 169 // Create a location summary for this computation.
167 // TODO(fschneider): Temporarily returns NULL for instructions 170 // TODO(fschneider): Temporarily returns NULL for instructions
168 // that are not yet converted to the location based code generation. 171 // that are not yet converted to the location based code generation.
169 virtual LocationSummary* MakeLocationSummary() const = 0; 172 virtual LocationSummary* MakeLocationSummary() const = 0;
170 173
171 // TODO(fschneider): Make EmitNativeCode and locs const. 174 // TODO(fschneider): Make EmitNativeCode and locs const.
172 virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0; 175 virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
173 176
174 static LocationSummary* MakeCallSummary(); 177 static LocationSummary* MakeCallSummary();
175 178
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 572
570 private: 573 private:
571 InstanceCallComp* instance_call_; 574 InstanceCallComp* instance_call_;
572 575
573 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallComp); 576 DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallComp);
574 }; 577 };
575 578
576 579
577 class ComparisonComp : public TemplateComputation<2> { 580 class ComparisonComp : public TemplateComputation<2> {
578 public: 581 public:
579 ComparisonComp(Value* left, Value* right) 582 ComparisonComp(Value* left, Value* right) {
580 : fused_with_branch_(NULL) {
581 ASSERT(left != NULL); 583 ASSERT(left != NULL);
582 ASSERT(right != NULL); 584 ASSERT(right != NULL);
583 inputs_[0] = left; 585 inputs_[0] = left;
584 inputs_[1] = right; 586 inputs_[1] = right;
585 } 587 }
586 588
587 void MarkFusedWithBranch(BranchInstr* branch) {
588 fused_with_branch_ = branch;
589 }
590
591 BranchInstr* fused_with_branch() const {
592 ASSERT(is_fused_with_branch());
593 return fused_with_branch_;
594 }
595
596 bool is_fused_with_branch() const {
597 return fused_with_branch_ != NULL;
598 }
599
600 Value* left() const { return inputs_[0]; } 589 Value* left() const { return inputs_[0]; }
601 Value* right() const { return inputs_[1]; } 590 Value* right() const { return inputs_[1]; }
602 591
603 private: 592 virtual ComparisonComp* AsComparison() { return this; }
604 BranchInstr* fused_with_branch_; 593
594 virtual Token::Kind kind() const = 0;
Kevin Millikin (Google) 2012/07/19 12:28:05 I would implement this as a member variable in cla
srdjan 2012/07/19 15:33:58 Done.
605 }; 595 };
606 596
607 597
608 class StrictCompareComp : public ComparisonComp { 598 class StrictCompareComp : public ComparisonComp {
609 public: 599 public:
610 StrictCompareComp(Token::Kind kind, Value* left, Value* right) 600 StrictCompareComp(Token::Kind kind, Value* left, Value* right)
611 : ComparisonComp(left, right), kind_(kind) { 601 : ComparisonComp(left, right), kind_(kind) {
612 ASSERT((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kNE_STRICT)); 602 ASSERT((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kNE_STRICT));
613 } 603 }
614 604
615 DECLARE_COMPUTATION(StrictCompare) 605 DECLARE_COMPUTATION(StrictCompare)
616 606
617 Token::Kind kind() const { return kind_; } 607 virtual Token::Kind kind() const { return kind_; }
618 608
619 virtual void PrintOperandsTo(BufferFormatter* f) const; 609 virtual void PrintOperandsTo(BufferFormatter* f) const;
620 610
621 private: 611 private:
622 const Token::Kind kind_; 612 const Token::Kind kind_;
623 613
624 DISALLOW_COPY_AND_ASSIGN(StrictCompareComp); 614 DISALLOW_COPY_AND_ASSIGN(StrictCompareComp);
625 }; 615 };
626 616
627 617
(...skipping 11 matching lines...) Expand all
639 629
640 DECLARE_COMPUTATION(EqualityCompare) 630 DECLARE_COMPUTATION(EqualityCompare)
641 631
642 intptr_t token_pos() const { return token_pos_; } 632 intptr_t token_pos() const { return token_pos_; }
643 intptr_t try_index() const { return try_index_; } 633 intptr_t try_index() const { return try_index_; }
644 634
645 void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; } 635 void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
646 intptr_t receiver_class_id() const { return receiver_class_id_; } 636 intptr_t receiver_class_id() const { return receiver_class_id_; }
647 virtual void PrintOperandsTo(BufferFormatter* f) const; 637 virtual void PrintOperandsTo(BufferFormatter* f) const;
648 638
639 virtual Token::Kind kind() const { return Token::kEQ; }
640
649 private: 641 private:
650 const intptr_t token_pos_; 642 const intptr_t token_pos_;
651 const intptr_t try_index_; 643 const intptr_t try_index_;
652 intptr_t receiver_class_id_; // Set by optimizer. 644 intptr_t receiver_class_id_; // Set by optimizer.
653 645
654 DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp); 646 DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp);
655 }; 647 };
656 648
657 649
658 class RelationalOpComp : public ComparisonComp { 650 class RelationalOpComp : public ComparisonComp {
659 public: 651 public:
660 RelationalOpComp(intptr_t token_pos, 652 RelationalOpComp(intptr_t token_pos,
661 intptr_t try_index, 653 intptr_t try_index,
662 Token::Kind kind, 654 Token::Kind kind,
663 Value* left, 655 Value* left,
664 Value* right) 656 Value* right)
665 : ComparisonComp(left, right), 657 : ComparisonComp(left, right),
666 token_pos_(token_pos), 658 token_pos_(token_pos),
667 try_index_(try_index), 659 try_index_(try_index),
668 kind_(kind), 660 kind_(kind),
669 operands_class_id_(kObject) { 661 operands_class_id_(kObject) {
670 ASSERT(Token::IsRelationalOperator(kind)); 662 ASSERT(Token::IsRelationalOperator(kind));
671 } 663 }
672 664
673 DECLARE_COMPUTATION(RelationalOp) 665 DECLARE_COMPUTATION(RelationalOp)
674 666
675 intptr_t token_pos() const { return token_pos_; } 667 intptr_t token_pos() const { return token_pos_; }
676 intptr_t try_index() const { return try_index_; } 668 intptr_t try_index() const { return try_index_; }
677 Token::Kind kind() const { return kind_; } 669 virtual Token::Kind kind() const { return kind_; }
678 670
679 // TODO(srdjan): instead of class-id pass an enum that can differentiate 671 // TODO(srdjan): instead of class-id pass an enum that can differentiate
680 // between boxed and unboxed doubles and integers. 672 // between boxed and unboxed doubles and integers.
681 void set_operands_class_id(intptr_t value) { 673 void set_operands_class_id(intptr_t value) {
682 operands_class_id_ = value; 674 operands_class_id_ = value;
683 } 675 }
684 676
685 intptr_t operands_class_id() const { return operands_class_id_; } 677 intptr_t operands_class_id() const { return operands_class_id_; }
686 678
687 virtual void PrintOperandsTo(BufferFormatter* f) const; 679 virtual void PrintOperandsTo(BufferFormatter* f) const;
(...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 Isolate* isolate = Isolate::Current(); 1725 Isolate* isolate = Isolate::Current();
1734 cid_ = Computation::GetNextCid(isolate); 1726 cid_ = Computation::GetNextCid(isolate);
1735 ic_data_ = Computation::GetICDataForCid(cid_, isolate); 1727 ic_data_ = Computation::GetICDataForCid(cid_, isolate);
1736 } 1728 }
1737 1729
1738 // Unique computation/instruction id, used for deoptimization, e.g. for 1730 // Unique computation/instruction id, used for deoptimization, e.g. for
1739 // ReturnInstr, ThrowInstr and ReThrowInstr. 1731 // ReturnInstr, ThrowInstr and ReThrowInstr.
1740 intptr_t cid() const { return cid_; } 1732 intptr_t cid() const { return cid_; }
1741 1733
1742 const ICData* ic_data() const { return ic_data_; } 1734 const ICData* ic_data() const { return ic_data_; }
1735 bool HasICData() const {
1736 return (ic_data() != NULL) && !ic_data()->IsNull();
1737 }
1743 1738
1744 virtual bool IsBlockEntry() const { return false; } 1739 virtual bool IsBlockEntry() const { return false; }
1745 BlockEntryInstr* AsBlockEntry() { 1740 BlockEntryInstr* AsBlockEntry() {
1746 return IsBlockEntry() ? reinterpret_cast<BlockEntryInstr*>(this) : NULL; 1741 return IsBlockEntry() ? reinterpret_cast<BlockEntryInstr*>(this) : NULL;
1747 } 1742 }
1748 virtual bool IsDefinition() const { return false; } 1743 virtual bool IsDefinition() const { return false; }
1749 virtual Definition* AsDefinition() { return NULL; } 1744 virtual Definition* AsDefinition() { return NULL; }
1750 1745
1751 virtual intptr_t InputCount() const = 0; 1746 virtual intptr_t InputCount() const = 0;
1752 virtual Value* InputAt(intptr_t i) const = 0; 1747 virtual Value* InputAt(intptr_t i) const = 0;
(...skipping 12 matching lines...) Expand all
1765 void set_next(Instruction* instr) { 1760 void set_next(Instruction* instr) {
1766 ASSERT(!IsGraphEntry()); 1761 ASSERT(!IsGraphEntry());
1767 ASSERT(!IsReturn()); 1762 ASSERT(!IsReturn());
1768 ASSERT(!IsBranch()); 1763 ASSERT(!IsBranch());
1769 ASSERT(!IsPhi()); 1764 ASSERT(!IsPhi());
1770 // TODO(fschneider): Also add Throw and ReThrow to the list of instructions 1765 // TODO(fschneider): Also add Throw and ReThrow to the list of instructions
1771 // that do not have a successor. Currently, the graph builder will continue 1766 // that do not have a successor. Currently, the graph builder will continue
1772 // to append instruction in case of a Throw inside an expression. This 1767 // to append instruction in case of a Throw inside an expression. This
1773 // condition should be handled in the graph builder 1768 // condition should be handled in the graph builder
1774 next_ = instr; 1769 next_ = instr;
1770 if ((instr != NULL) && !instr->IsBlockEntry()) {
1771 instr->set_previous(this);
Kevin Millikin (Google) 2012/07/19 12:28:05 I see why you did this, but I think we should avoi
srdjan 2012/07/19 15:33:58 I will avoid it with the better way to construct t
1772 }
1775 } 1773 }
1776 1774
1777 // Normal instructions can have 0 (inside a block) or 1 (last instruction in 1775 // Normal instructions can have 0 (inside a block) or 1 (last instruction in
1778 // a block) successors. Branch instruction with >1 successors override this 1776 // a block) successors. Branch instruction with >1 successors override this
1779 // function. 1777 // function.
1780 virtual intptr_t SuccessorCount() const; 1778 virtual intptr_t SuccessorCount() const;
1781 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; 1779 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
1782 1780
1783 // Discover basic-block structure by performing a recursive depth first 1781 // Discover basic-block structure by performing a recursive depth first
1784 // traversal of the instruction graph reachable from this instruction. As 1782 // traversal of the instruction graph reachable from this instruction. As
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after
2287 const intptr_t try_index_; 2285 const intptr_t try_index_;
2288 Value* exception_; 2286 Value* exception_;
2289 Value* stack_trace_; 2287 Value* stack_trace_;
2290 2288
2291 DISALLOW_COPY_AND_ASSIGN(ReThrowInstr); 2289 DISALLOW_COPY_AND_ASSIGN(ReThrowInstr);
2292 }; 2290 };
2293 2291
2294 2292
2295 class BranchInstr : public InstructionWithInputs { 2293 class BranchInstr : public InstructionWithInputs {
2296 public: 2294 public:
2297 explicit BranchInstr(Value* value) 2295 BranchInstr(intptr_t token_pos,
Kevin Millikin (Google) 2012/07/19 12:28:05 Indentation is weird.
2296 intptr_t try_index,
2297 Value* left,
2298 Value* right,
2299 Token::Kind kind)
2298 : InstructionWithInputs(), 2300 : InstructionWithInputs(),
2299 value_(value), 2301 token_pos_(token_pos),
2302 try_index_(try_index),
2303 left_(left),
2304 right_(right),
2305 kind_(kind),
2300 true_successor_(NULL), 2306 true_successor_(NULL),
2301 false_successor_(NULL), 2307 false_successor_(NULL) {
2302 fused_with_comparison_(NULL), 2308 ASSERT(left_ != NULL);
2303 is_negated_(false) { } 2309 ASSERT(right_ != NULL);
2310 ASSERT(Token::IsEqualityOperator(kind) ||
2311 Token::IsRelationalOperator(kind) ||
2312 Token::IsTypeTestOperator(kind));
2313 }
2304 2314
2305 DECLARE_INSTRUCTION(Branch) 2315 DECLARE_INSTRUCTION(Branch)
2306 2316
2307 Value* value() const { return value_; } 2317 Value* left() const { return left_; }
2318 Value* right() const { return right_; }
2319 Token::Kind kind() const { return kind_; }
2320 void set_kind(Token::Kind kind) {
2321 ASSERT(Token::IsEqualityOperator(kind) ||
2322 Token::IsRelationalOperator(kind) ||
2323 Token::IsTypeTestOperator(kind));
2324 kind_ = kind;
2325 }
2326 intptr_t token_pos() const { return token_pos_;}
2327 intptr_t try_index() const { return try_index_; }
2328
2308 TargetEntryInstr* true_successor() const { return true_successor_; } 2329 TargetEntryInstr* true_successor() const { return true_successor_; }
2309 TargetEntryInstr* false_successor() const { return false_successor_; } 2330 TargetEntryInstr* false_successor() const { return false_successor_; }
2310 2331
2311 TargetEntryInstr** true_successor_address() { return &true_successor_; } 2332 TargetEntryInstr** true_successor_address() { return &true_successor_; }
2312 TargetEntryInstr** false_successor_address() { return &false_successor_; } 2333 TargetEntryInstr** false_successor_address() { return &false_successor_; }
2313 2334
2314 virtual intptr_t SuccessorCount() const; 2335 virtual intptr_t SuccessorCount() const;
2315 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const; 2336 virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
2316 2337
2317 virtual void DiscoverBlocks( 2338 virtual void DiscoverBlocks(
2318 BlockEntryInstr* current_block, 2339 BlockEntryInstr* current_block,
2319 GrowableArray<BlockEntryInstr*>* preorder, 2340 GrowableArray<BlockEntryInstr*>* preorder,
2320 GrowableArray<BlockEntryInstr*>* postorder, 2341 GrowableArray<BlockEntryInstr*>* postorder,
2321 GrowableArray<intptr_t>* parent, 2342 GrowableArray<intptr_t>* parent,
2322 GrowableArray<BitVector*>* assigned_vars, 2343 GrowableArray<BitVector*>* assigned_vars,
2323 intptr_t variable_count); 2344 intptr_t variable_count);
2324 2345
2325 virtual LocationSummary* MakeLocationSummary() const; 2346 virtual LocationSummary* MakeLocationSummary() const;
2326 2347
2327 virtual void EmitNativeCode(FlowGraphCompiler* compiler); 2348 virtual void EmitNativeCode(FlowGraphCompiler* compiler);
2328 2349
2329 void EmitBranchOnCondition(FlowGraphCompiler* compiler, 2350 void EmitBranchOnCondition(FlowGraphCompiler* compiler,
2330 Condition true_condition); 2351 Condition true_condition);
2331 2352
2332 void MarkFusedWithComparison(ComparisonComp* comp) {
2333 fused_with_comparison_ = comp;
2334 }
2335
2336 bool is_fused_with_comparison() const {
2337 return fused_with_comparison_ != NULL;
2338 }
2339 bool is_negated() const { return is_negated_; }
2340 void set_is_negated(bool value) { is_negated_ = value; }
2341
2342 private: 2353 private:
2343 Value* value_; 2354 const intptr_t token_pos_;
2355 const intptr_t try_index_;
2356 Value* left_;
2357 Value* right_;
2358 Token::Kind kind_;
2344 TargetEntryInstr* true_successor_; 2359 TargetEntryInstr* true_successor_;
2345 TargetEntryInstr* false_successor_; 2360 TargetEntryInstr* false_successor_;
2346 ComparisonComp* fused_with_comparison_;
2347 bool is_negated_;
2348 2361
2349 DISALLOW_COPY_AND_ASSIGN(BranchInstr); 2362 DISALLOW_COPY_AND_ASSIGN(BranchInstr);
2350 }; 2363 };
2351 2364
2352 2365
2353 // This class is often passed by value. Add additional fields with caution. 2366 // This class is often passed by value. Add additional fields with caution.
2354 class MoveOperands : public ValueObject { 2367 class MoveOperands : public ValueObject {
2355 public: 2368 public:
2356 MoveOperands(Location dest, Location src) : dest_(dest), src_(src) { } 2369 MoveOperands(Location dest, Location src) : dest_(dest), src_(src) { }
2357 2370
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2490 const GrowableArray<BlockEntryInstr*>& block_order_; 2503 const GrowableArray<BlockEntryInstr*>& block_order_;
2491 2504
2492 private: 2505 private:
2493 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor); 2506 DISALLOW_COPY_AND_ASSIGN(FlowGraphVisitor);
2494 }; 2507 };
2495 2508
2496 2509
2497 } // namespace dart 2510 } // namespace dart
2498 2511
2499 #endif // VM_INTERMEDIATE_LANGUAGE_H_ 2512 #endif // VM_INTERMEDIATE_LANGUAGE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698