OLD | NEW |
---|---|
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 static const intptr_t kInvalidLocation = 0; | |
26 | |
27 // Contant payload can overlap with kind field so Kind values | |
28 // have to be choosen in a way that their last 2 bits are never | |
29 // the same as kConstant. | |
24 enum Kind { | 30 enum Kind { |
25 kInvalid, | 31 kInvalid = 0, |
32 | |
33 kConstant = 1, | |
26 | 34 |
27 // Unallocated location represents a location that is not fixed and can be | 35 // Unallocated location represents a location that is not fixed and can be |
28 // allocated by a register allocator. Each unallocated location has | 36 // allocated by a register allocator. Each unallocated location has |
29 // a policy that specifies what kind of location is suitable. | 37 // a policy that specifies what kind of location is suitable. |
30 kUnallocated, | 38 kUnallocated = 2, |
31 | 39 |
32 // Register location represents a fixed register. | 40 // Register location represents a fixed register. |
33 kRegister | 41 kRegister = 3 |
34 }; | 42 }; |
35 | 43 |
36 Location() : value_(KindField::encode(kInvalid)) { } | 44 Location() : value_(kInvalidLocation) { |
45 ASSERT(IsInvalid()); | |
46 } | |
37 | 47 |
38 Kind kind() const { return KindField::decode(value_); } | 48 bool IsInvalid() const { |
49 return value_ == 0; | |
srdjan
2012/07/10 23:27:54
s/0/kInvalidLocation/
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
50 } | |
51 | |
52 // Constants. | |
53 static const intptr_t kConstantMask = 0x3; | |
srdjan
2012/07/10 23:27:54
Eventually move this definition between the commen
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
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<intptr_t>(&obj) | kConstant); | |
srdjan
2012/07/10 23:27:54
Why no uword instead of intptr_t?
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Fixed! Thanks.
| |
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 bool Equals(Location other) const { | |
122 return value_ == other.value_; | |
srdjan
2012/07/10 23:27:54
This does not work for kConstant. Should two const
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Added a comment and assertion. Constants are reall
| |
123 } | |
124 | |
81 private: | 125 private: |
126 explicit Location(intptr_t value) : value_(value) { } | |
srdjan
2012/07/10 23:27:54
Why not uword value?
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Mea culpa! Compiler did not complain and I already
| |
127 | |
82 Location(Kind kind, uword payload) | 128 Location(Kind kind, uword payload) |
83 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } | 129 : value_(KindField::encode(kind) | PayloadField::encode(payload)) { } |
84 | 130 |
85 uword payload() const { | 131 uword payload() const { |
86 return PayloadField::decode(value_); | 132 return PayloadField::decode(value_); |
87 } | 133 } |
88 | 134 |
135 // If current location is constant might return something that | |
136 // is not equal to any Kind. | |
137 Kind kind() const { | |
138 return KindField::decode(value_); | |
139 } | |
140 | |
89 typedef BitField<Kind, 0, 2> KindField; | 141 typedef BitField<Kind, 0, 2> KindField; |
90 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; | 142 typedef BitField<uword, 2, kWordSize * kBitsPerByte - 2> PayloadField; |
91 | 143 |
92 // Layout for kUnallocated locations payload. | 144 // Layout for kUnallocated locations payload. |
93 typedef BitField<Policy, 0, 1> PolicyField; | 145 typedef BitField<Policy, 0, 1> PolicyField; |
94 | 146 |
95 // TODO(vegorov): choose fixed size for this field. | 147 // TODO(vegorov): choose fixed size for this field. |
96 uword value_; | 148 uword value_; |
srdjan
2012/07/10 23:27:54
Explain that this can be Kind or an encoded Object
Vyacheslav Egorov (Google)
2012/07/11 13:27:58
Done.
| |
97 }; | 149 }; |
98 | 150 |
99 | 151 |
100 // Specification of locations for inputs and output. | 152 // Specification of locations for inputs and output. |
101 class LocationSummary : public ZoneAllocated { | 153 class LocationSummary : public ZoneAllocated { |
102 public: | 154 public: |
103 enum ContainsCall { | 155 enum ContainsCall { |
104 kNoCall, | 156 kNoCall, |
105 kCall, | 157 kCall, |
106 }; | 158 }; |
(...skipping 22 matching lines...) Expand all Loading... | |
129 } | 181 } |
130 | 182 |
131 intptr_t input_count() const { | 183 intptr_t input_count() const { |
132 return input_locations_.length(); | 184 return input_locations_.length(); |
133 } | 185 } |
134 | 186 |
135 Location in(intptr_t index) const { | 187 Location in(intptr_t index) const { |
136 return input_locations_[index]; | 188 return input_locations_[index]; |
137 } | 189 } |
138 | 190 |
191 Location* in_slot(intptr_t index) { | |
192 return &input_locations_[index]; | |
193 } | |
194 | |
139 void set_in(intptr_t index, Location loc) { | 195 void set_in(intptr_t index, Location loc) { |
140 input_locations_[index] = loc; | 196 input_locations_[index] = loc; |
141 } | 197 } |
142 | 198 |
143 intptr_t temp_count() const { | 199 intptr_t temp_count() const { |
144 return temp_locations_.length(); | 200 return temp_locations_.length(); |
145 } | 201 } |
146 | 202 |
147 Location temp(intptr_t index) const { | 203 Location temp(intptr_t index) const { |
148 return temp_locations_[index]; | 204 return temp_locations_[index]; |
149 } | 205 } |
150 | 206 |
207 Location* temp_slot(intptr_t index) { | |
208 return &temp_locations_[index]; | |
209 } | |
210 | |
151 void set_temp(intptr_t index, Location loc) { | 211 void set_temp(intptr_t index, Location loc) { |
152 temp_locations_[index] = loc; | 212 temp_locations_[index] = loc; |
153 } | 213 } |
154 | 214 |
155 Location out() const { | 215 Location out() const { |
156 return output_location_; | 216 return output_location_; |
157 } | 217 } |
158 | 218 |
219 Location* out_slot() { | |
220 return &output_location_; | |
221 } | |
222 | |
223 | |
159 void set_out(Location loc) { | 224 void set_out(Location loc) { |
160 output_location_ = loc; | 225 output_location_ = loc; |
161 } | 226 } |
162 | 227 |
163 bool is_call() const { | 228 bool is_call() const { |
164 return is_call_; | 229 return is_call_; |
165 } | 230 } |
166 | 231 |
167 // TODO(vegorov): this is a temporary solution. Once we will start removing | 232 // 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 | 233 // comparison operations from the flow graph when they are fused with a branch |
169 // we should eliminate this. | 234 // we should eliminate this. |
170 bool is_branch() const { | 235 bool is_branch() const { |
171 return is_branch_; | 236 return is_branch_; |
172 } | 237 } |
173 | 238 |
239 void PrintTo(BufferFormatter* f) const; | |
240 | |
174 static LocationSummary* Make(intptr_t input_count, | 241 static LocationSummary* Make(intptr_t input_count, |
175 Location out, | 242 Location out, |
176 ContainsCall contains_call = kNoCall, | 243 ContainsCall contains_call = kNoCall, |
177 ContainsBranch contains_branch = kNoBranch); | 244 ContainsBranch contains_branch = kNoBranch); |
178 | 245 |
179 private: | 246 private: |
180 // TODO(vegorov): replace with ZoneArray. | 247 // TODO(vegorov): replace with ZoneArray. |
181 GrowableArray<Location> input_locations_; | 248 GrowableArray<Location> input_locations_; |
182 GrowableArray<Location> temp_locations_; | 249 GrowableArray<Location> temp_locations_; |
183 Location output_location_; | 250 Location output_location_; |
184 | 251 |
185 const bool is_call_; | 252 const bool is_call_; |
186 const bool is_branch_; | 253 const bool is_branch_; |
187 }; | 254 }; |
188 | 255 |
189 | 256 |
190 } // namespace dart | 257 } // namespace dart |
191 | 258 |
192 #endif // VM_LOCATIONS_H_ | 259 #endif // VM_LOCATIONS_H_ |
OLD | NEW |