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

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

Issue 10696151: Skeleton of a linear scan register allocator. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address comments 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_LOCATIONS_H_ 5 #ifndef VM_LOCATIONS_H_
6 #define VM_LOCATIONS_H_ 6 #define VM_LOCATIONS_H_
7 7
8 #include "vm/allocation.h" 8 #include "vm/allocation.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/bitfield.h" 10 #include "vm/bitfield.h"
11 11
12 namespace dart { 12 namespace dart {
13 13
14 class BufferFormatter;
14 15
15 // Location objects are used to connect register allocator and code generator. 16 // Location objects are used to connect register allocator and code generator.
16 // Instruction templates used by code generator have a corresponding 17 // Instruction templates used by code generator have a corresponding
17 // LocationSummary object which specifies expected location for every input 18 // LocationSummary object which specifies expected location for every input
18 // and output. 19 // and output.
19 // Each location is encoded as a single word: low 2 bits denote location kind, 20 // Each location is encoded as a single word: low 2 bits denote location kind,
20 // rest is kind specific location payload e.g. for REGISTER kind payload is 21 // rest is kind specific location payload e.g. for REGISTER kind payload is
21 // register code (value of the Register enumeration). 22 // register code (value of the Register enumeration).
22 class Location : public ValueObject { 23 class Location : public ValueObject {
23 public: 24 public:
25 // Constant payload can overlap with kind field so Kind values
26 // have to be chosen in a way that their last 2 bits are never
27 // the same as kConstant.
24 enum Kind { 28 enum Kind {
25 kInvalid, 29 kInvalid = 0,
30
31 kConstant = 1,
26 32
27 // Unallocated location represents a location that is not fixed and can be 33 // Unallocated location represents a location that is not fixed and can be
28 // allocated by a register allocator. Each unallocated location has 34 // allocated by a register allocator. Each unallocated location has
29 // a policy that specifies what kind of location is suitable. 35 // a policy that specifies what kind of location is suitable.
30 kUnallocated, 36 kUnallocated = 2,
31 37
32 // Register location represents a fixed register. 38 // Register location represents a fixed register.
33 kRegister 39 kRegister = 3
34 }; 40 };
35 41
36 Location() : value_(KindField::encode(kInvalid)) { } 42 static const uword kInvalidLocation = 0;
43 static const uword kConstantMask = 0x3;
37 44
38 Kind kind() const { return KindField::decode(value_); } 45 Location() : value_(kInvalidLocation) {
46 ASSERT(IsInvalid());
47 }
48
49 bool IsInvalid() const {
50 return value_ == kInvalidLocation;
51 }
52
53 // Constants.
54 bool IsConstant() const {
55 ASSERT((kConstant & kConstantMask) == kConstant);
56 return (value_ & kConstantMask) == kConstant;
57 }
58
59 static Location Constant(const Object& obj) {
60 Location loc(reinterpret_cast<uword>(&obj) | kConstant);
61 ASSERT(&obj == &loc.constant());
62 return loc;
63 }
64
65 const Object& constant() {
66 ASSERT(IsConstant());
67 return *reinterpret_cast<const Object*>(value_ & ~kConstantMask);
68 }
39 69
40 // Unallocated locations. 70 // Unallocated locations.
41 enum Policy { 71 enum Policy {
42 kRequiresRegister, 72 kRequiresRegister,
43 kSameAsFirstInput, 73 kSameAsFirstInput,
44 }; 74 };
45 75
76 bool IsUnallocated() const {
77 return kind() == kUnallocated;
78 }
79
46 static Location UnallocatedLocation(Policy policy) { 80 static Location UnallocatedLocation(Policy policy) {
47 return Location(kUnallocated, PolicyField::encode(policy)); 81 return Location(kUnallocated, PolicyField::encode(policy));
48 } 82 }
49 83
50 // Any free register is suitable to replace this unallocated location. 84 // Any free register is suitable to replace this unallocated location.
51 static Location RequiresRegister() { 85 static Location RequiresRegister() {
52 return UnallocatedLocation(kRequiresRegister); 86 return UnallocatedLocation(kRequiresRegister);
53 } 87 }
54 88
55 // The location of the first input to the instruction will be 89 // The location of the first input to the instruction will be
56 // used to replace this unallocated location. 90 // used to replace this unallocated location.
57 static Location SameAsFirstInput() { 91 static Location SameAsFirstInput() {
58 return UnallocatedLocation(kSameAsFirstInput); 92 return UnallocatedLocation(kSameAsFirstInput);
59 } 93 }
60 94
61 // Empty location. Used if there the location should be ignored. 95 // Empty location. Used if there the location should be ignored.
62 static Location NoLocation() { 96 static Location NoLocation() {
63 return Location(); 97 return Location();
64 } 98 }
65 99
66 Policy policy() const { 100 Policy policy() const {
67 ASSERT(kind() == kUnallocated); 101 ASSERT(IsUnallocated());
68 return PolicyField::decode(payload()); 102 return PolicyField::decode(payload());
69 } 103 }
70 104
71 // Register locations. 105 // Register locations.
72 static Location RegisterLocation(Register reg) { 106 static Location RegisterLocation(Register reg) {
73 return Location(kRegister, static_cast<uword>(reg)); 107 return Location(kRegister, static_cast<uword>(reg));
74 } 108 }
75 109
110 bool IsRegister() const {
111 return kind() == kRegister;
112 }
113
76 Register reg() const { 114 Register reg() const {
77 ASSERT(kind() == kRegister); 115 ASSERT(IsRegister());
78 return static_cast<Register>(payload()); 116 return static_cast<Register>(payload());
79 } 117 }
80 118
119 const char* Name() const;
120
121 // Compare two non-constant locations.
122 bool Equals(Location other) const {
123 ASSERT(!IsConstant() && !other.IsConstant());
124 return value_ == other.value_;
125 }
126
81 private: 127 private:
128 explicit Location(uword value) : value_(value) { }
129
82 Location(Kind kind, uword payload) 130 Location(Kind kind, uword payload)
83 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } 131 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { }
84 132
85 uword payload() const { 133 uword payload() const {
86 return PayloadField::decode(value_); 134 return PayloadField::decode(value_);
87 } 135 }
88 136
137 // If current location is constant might return something that
138 // is not equal to any Kind.
139 Kind kind() const {
140 return KindField::decode(value_);
141 }
142
89 typedef BitField<Kind, 0, 2> KindField; 143 typedef BitField<Kind, 0, 2> KindField;
90 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; 144 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField;
91 145
92 // Layout for kUnallocated locations payload. 146 // Layout for kUnallocated locations payload.
93 typedef BitField<Policy, 0, 1> PolicyField; 147 typedef BitField<Policy, 0, 1> PolicyField;
94 148
95 // TODO(vegorov): choose fixed size for this field. 149 // Location either contains kind and payload fields or a tagged handle for
150 // a constant locations. Values of enumeration Kind are selected in such a
151 // way that none of them can be interpreted as a kConstant tag.
96 uword value_; 152 uword value_;
97 }; 153 };
98 154
99 155
100 // Specification of locations for inputs and output. 156 // Specification of locations for inputs and output.
101 class LocationSummary : public ZoneAllocated { 157 class LocationSummary : public ZoneAllocated {
102 public: 158 public:
103 enum ContainsCall { 159 enum ContainsCall {
104 kNoCall, 160 kNoCall,
105 kCall, 161 kCall,
(...skipping 23 matching lines...) Expand all
129 } 185 }
130 186
131 intptr_t input_count() const { 187 intptr_t input_count() const {
132 return input_locations_.length(); 188 return input_locations_.length();
133 } 189 }
134 190
135 Location in(intptr_t index) const { 191 Location in(intptr_t index) const {
136 return input_locations_[index]; 192 return input_locations_[index];
137 } 193 }
138 194
195 Location* in_slot(intptr_t index) {
196 return &input_locations_[index];
197 }
198
139 void set_in(intptr_t index, Location loc) { 199 void set_in(intptr_t index, Location loc) {
140 input_locations_[index] = loc; 200 input_locations_[index] = loc;
141 } 201 }
142 202
143 intptr_t temp_count() const { 203 intptr_t temp_count() const {
144 return temp_locations_.length(); 204 return temp_locations_.length();
145 } 205 }
146 206
147 Location temp(intptr_t index) const { 207 Location temp(intptr_t index) const {
148 return temp_locations_[index]; 208 return temp_locations_[index];
149 } 209 }
150 210
211 Location* temp_slot(intptr_t index) {
212 return &temp_locations_[index];
213 }
214
151 void set_temp(intptr_t index, Location loc) { 215 void set_temp(intptr_t index, Location loc) {
152 temp_locations_[index] = loc; 216 temp_locations_[index] = loc;
153 } 217 }
154 218
155 Location out() const { 219 Location out() const {
156 return output_location_; 220 return output_location_;
157 } 221 }
158 222
223 Location* out_slot() {
224 return &output_location_;
225 }
226
227
159 void set_out(Location loc) { 228 void set_out(Location loc) {
160 output_location_ = loc; 229 output_location_ = loc;
161 } 230 }
162 231
163 bool is_call() const { 232 bool is_call() const {
164 return is_call_; 233 return is_call_;
165 } 234 }
166 235
167 // TODO(vegorov): this is a temporary solution. Once we will start removing 236 // TODO(vegorov): this is a temporary solution. Once we will start removing
168 // comparison operations from the flow graph when they are fused with a branch 237 // comparison operations from the flow graph when they are fused with a branch
169 // we should eliminate this. 238 // we should eliminate this.
170 bool is_branch() const { 239 bool is_branch() const {
171 return is_branch_; 240 return is_branch_;
172 } 241 }
173 242
243 void PrintTo(BufferFormatter* f) const;
244
174 static LocationSummary* Make(intptr_t input_count, 245 static LocationSummary* Make(intptr_t input_count,
175 Location out, 246 Location out,
176 ContainsCall contains_call = kNoCall, 247 ContainsCall contains_call = kNoCall,
177 ContainsBranch contains_branch = kNoBranch); 248 ContainsBranch contains_branch = kNoBranch);
178 249
179 private: 250 private:
180 // TODO(vegorov): replace with ZoneArray. 251 // TODO(vegorov): replace with ZoneArray.
181 GrowableArray<Location> input_locations_; 252 GrowableArray<Location> input_locations_;
182 GrowableArray<Location> temp_locations_; 253 GrowableArray<Location> temp_locations_;
183 Location output_location_; 254 Location output_location_;
184 255
185 const bool is_call_; 256 const bool is_call_;
186 const bool is_branch_; 257 const bool is_branch_;
187 }; 258 };
188 259
189 260
190 } // namespace dart 261 } // namespace dart
191 262
192 #endif // VM_LOCATIONS_H_ 263 #endif // VM_LOCATIONS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698