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

Side by Side Diff: src/compiler/representation-change.h

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 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
« no previous file with comments | « src/compiler/register-allocator.cc ('k') | src/compiler/schedule.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_
7
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/machine-operator.h"
10 #include "src/compiler/node-properties-inl.h"
11 #include "src/compiler/simplified-operator.h"
12
13 namespace v8 {
14 namespace internal {
15 namespace compiler {
16
17 // The types and representations tracked during representation inference
18 // and change insertion.
19 // TODO(titzer): First, merge MachineRepresentation and RepType.
20 // TODO(titzer): Second, Use the real type system instead of RepType.
21 enum RepType {
22 // Representations.
23 rBit = 1 << 0,
24 rWord32 = 1 << 1,
25 rWord64 = 1 << 2,
26 rFloat64 = 1 << 3,
27 rTagged = 1 << 4,
28
29 // Types.
30 tBool = 1 << 5,
31 tInt32 = 1 << 6,
32 tUint32 = 1 << 7,
33 tInt64 = 1 << 8,
34 tUint64 = 1 << 9,
35 tNumber = 1 << 10,
36 tAny = 1 << 11
37 };
38
39 typedef uint16_t RepTypeUnion;
40
41 const RepTypeUnion rMask = rBit | rWord32 | rWord64 | rFloat64 | rTagged;
42 const RepTypeUnion tMask =
43 tBool | tInt32 | tUint32 | tInt64 | tUint64 | tNumber | tAny;
44 const RepType rPtr = kPointerSize == 4 ? rWord32 : rWord64;
45
46
47 // Contains logic related to changing the representation of values for constants
48 // and other nodes, as well as lowering Simplified->Machine operators.
49 // Eagerly folds any representation changes for constants.
50 class RepresentationChanger {
51 public:
52 RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified,
53 MachineOperatorBuilder* machine, Isolate* isolate)
54 : jsgraph_(jsgraph),
55 simplified_(simplified),
56 machine_(machine),
57 isolate_(isolate),
58 testing_type_errors_(false),
59 type_error_(false) {}
60
61
62 Node* GetRepresentationFor(Node* node, RepTypeUnion output_type,
63 RepTypeUnion use_type) {
64 if (!IsPowerOf2(output_type & rMask)) {
65 // There should be only one output representation.
66 return TypeError(node, output_type, use_type);
67 }
68 if ((use_type & rMask) == (output_type & rMask)) {
69 // Representations are the same. That's a no-op.
70 return node;
71 }
72 if (use_type & rTagged) {
73 return GetTaggedRepresentationFor(node, output_type);
74 } else if (use_type & rFloat64) {
75 return GetFloat64RepresentationFor(node, output_type);
76 } else if (use_type & rWord32) {
77 return GetWord32RepresentationFor(node, output_type);
78 } else if (use_type & rBit) {
79 return GetBitRepresentationFor(node, output_type);
80 } else if (use_type & rWord64) {
81 return GetWord64RepresentationFor(node, output_type);
82 } else {
83 return node;
84 }
85 }
86
87 Node* GetTaggedRepresentationFor(Node* node, RepTypeUnion output_type) {
88 // Eagerly fold representation changes for constants.
89 switch (node->opcode()) {
90 case IrOpcode::kNumberConstant:
91 case IrOpcode::kHeapConstant:
92 return node; // No change necessary.
93 case IrOpcode::kInt32Constant:
94 if (output_type & tUint32) {
95 uint32_t value = ValueOf<uint32_t>(node->op());
96 return jsgraph()->Constant(static_cast<double>(value));
97 } else if (output_type & tInt32) {
98 int32_t value = ValueOf<int32_t>(node->op());
99 return jsgraph()->Constant(value);
100 } else if (output_type & rBit) {
101 return ValueOf<int32_t>(node->op()) == 0 ? jsgraph()->FalseConstant()
102 : jsgraph()->TrueConstant();
103 } else {
104 return TypeError(node, output_type, rTagged);
105 }
106 case IrOpcode::kFloat64Constant:
107 return jsgraph()->Constant(ValueOf<double>(node->op()));
108 default:
109 break;
110 }
111 // Select the correct X -> Tagged operator.
112 Operator* op;
113 if (output_type & rBit) {
114 op = simplified()->ChangeBitToBool();
115 } else if (output_type & rWord32) {
116 if (output_type & tUint32) {
117 op = simplified()->ChangeUint32ToTagged();
118 } else if (output_type & tInt32) {
119 op = simplified()->ChangeInt32ToTagged();
120 } else {
121 return TypeError(node, output_type, rTagged);
122 }
123 } else if (output_type & rFloat64) {
124 op = simplified()->ChangeFloat64ToTagged();
125 } else {
126 return TypeError(node, output_type, rTagged);
127 }
128 return jsgraph()->graph()->NewNode(op, node);
129 }
130
131 Node* GetFloat64RepresentationFor(Node* node, RepTypeUnion output_type) {
132 // Eagerly fold representation changes for constants.
133 switch (node->opcode()) {
134 case IrOpcode::kNumberConstant:
135 return jsgraph()->Float64Constant(ValueOf<double>(node->op()));
136 case IrOpcode::kInt32Constant:
137 if (output_type & tUint32) {
138 uint32_t value = ValueOf<uint32_t>(node->op());
139 return jsgraph()->Float64Constant(static_cast<double>(value));
140 } else {
141 int32_t value = ValueOf<int32_t>(node->op());
142 return jsgraph()->Float64Constant(value);
143 }
144 case IrOpcode::kFloat64Constant:
145 return node; // No change necessary.
146 default:
147 break;
148 }
149 // Select the correct X -> Float64 operator.
150 Operator* op;
151 if (output_type & rWord32) {
152 if (output_type & tUint32) {
153 op = machine()->ConvertUint32ToFloat64();
154 } else if (output_type & tInt32) {
155 op = machine()->ConvertInt32ToFloat64();
156 } else {
157 return TypeError(node, output_type, rFloat64);
158 }
159 } else if (output_type & rTagged) {
160 op = simplified()->ChangeTaggedToFloat64();
161 } else {
162 return TypeError(node, output_type, rFloat64);
163 }
164 return jsgraph()->graph()->NewNode(op, node);
165 }
166
167 Node* GetWord32RepresentationFor(Node* node, RepTypeUnion output_type) {
168 // Eagerly fold representation changes for constants.
169 switch (node->opcode()) {
170 case IrOpcode::kInt32Constant:
171 return node; // No change necessary.
172 case IrOpcode::kNumberConstant:
173 case IrOpcode::kFloat64Constant: {
174 if (output_type & tUint32) {
175 int32_t value = static_cast<int32_t>(
176 static_cast<uint32_t>(ValueOf<double>(node->op())));
177 return jsgraph()->Int32Constant(value);
178 } else if (output_type & tInt32) {
179 int32_t value = FastD2I(ValueOf<double>(node->op()));
180 return jsgraph()->Int32Constant(value);
181 } else {
182 return TypeError(node, output_type, rWord32);
183 }
184 }
185 default:
186 break;
187 }
188 // Select the correct X -> Word32 operator.
189 Operator* op = NULL;
190 if (output_type & rFloat64) {
191 // TODO(turbofan): could have cheaper float64 conversions that don't do
192 // the full JavaScript truncation here.
193 if (output_type & tUint32) {
194 op = machine()->ConvertFloat64ToUint32();
195 } else if (output_type & tInt32) {
196 op = machine()->ConvertFloat64ToInt32();
197 } else {
198 return TypeError(node, output_type, rWord32);
199 }
200 } else if (output_type & rTagged) {
201 if (output_type & tUint32) {
202 op = simplified()->ChangeTaggedToUint32();
203 } else if (output_type & tInt32) {
204 op = simplified()->ChangeTaggedToInt32();
205 } else {
206 return TypeError(node, output_type, rWord32);
207 }
208 } else if (output_type & rBit) {
209 return node; // Sloppy comparison -> word32.
210 } else {
211 return TypeError(node, output_type, rWord32);
212 }
213 return jsgraph()->graph()->NewNode(op, node);
214 }
215
216 Node* GetBitRepresentationFor(Node* node, RepTypeUnion output_type) {
217 // Eagerly fold representation changes for constants.
218 switch (node->opcode()) {
219 case IrOpcode::kInt32Constant: {
220 int32_t value = ValueOf<int32_t>(node->op());
221 if (value == 0 || value == 1) return node;
222 return jsgraph()->OneConstant(); // value != 0
223 }
224 case IrOpcode::kHeapConstant: {
225 Handle<Object> handle = ValueOf<Handle<Object> >(node->op());
226 ASSERT(*handle == isolate()->heap()->true_value() ||
227 *handle == isolate()->heap()->false_value());
228 return jsgraph()->Int32Constant(
229 *handle == isolate()->heap()->true_value() ? 1 : 0);
230 }
231 default:
232 break;
233 }
234 // Select the correct X -> Bit operator.
235 Operator* op;
236 if (output_type & rWord32) {
237 return node; // No change necessary.
238 } else if (output_type & rWord64) {
239 return node; // TODO(titzer): No change necessary, on 64-bit.
240 } else if (output_type & rTagged) {
241 op = simplified()->ChangeBoolToBit();
242 } else {
243 return TypeError(node, output_type, rBit);
244 }
245 return jsgraph()->graph()->NewNode(op, node);
246 }
247
248 Node* GetWord64RepresentationFor(Node* node, RepTypeUnion output_type) {
249 if (output_type & rBit) {
250 return node; // Sloppy comparison -> word64
251 }
252 // Can't really convert Word64 to anything else. Purported to be internal.
253 return TypeError(node, output_type, rWord64);
254 }
255
256 static RepType TypeForMachineRepresentation(MachineRepresentation rep) {
257 // TODO(titzer): merge MachineRepresentation and RepType.
258 switch (rep) {
259 case kMachineWord8:
260 return rWord32;
261 case kMachineWord16:
262 return rWord32;
263 case kMachineWord32:
264 return rWord32;
265 case kMachineWord64:
266 return rWord64;
267 case kMachineFloat64:
268 return rFloat64;
269 case kMachineTagged:
270 return rTagged;
271 default:
272 UNREACHABLE();
273 return static_cast<RepType>(0);
274 }
275 }
276
277 Operator* Int32OperatorFor(IrOpcode::Value opcode) {
278 switch (opcode) {
279 case IrOpcode::kNumberAdd:
280 return machine()->Int32Add();
281 case IrOpcode::kNumberSubtract:
282 return machine()->Int32Sub();
283 case IrOpcode::kNumberEqual:
284 return machine()->Word32Equal();
285 case IrOpcode::kNumberLessThan:
286 return machine()->Int32LessThan();
287 case IrOpcode::kNumberLessThanOrEqual:
288 return machine()->Int32LessThanOrEqual();
289 default:
290 UNREACHABLE();
291 return NULL;
292 }
293 }
294
295 Operator* Uint32OperatorFor(IrOpcode::Value opcode) {
296 switch (opcode) {
297 case IrOpcode::kNumberAdd:
298 return machine()->Int32Add();
299 case IrOpcode::kNumberSubtract:
300 return machine()->Int32Sub();
301 case IrOpcode::kNumberEqual:
302 return machine()->Word32Equal();
303 case IrOpcode::kNumberLessThan:
304 return machine()->Uint32LessThan();
305 case IrOpcode::kNumberLessThanOrEqual:
306 return machine()->Uint32LessThanOrEqual();
307 default:
308 UNREACHABLE();
309 return NULL;
310 }
311 }
312
313 Operator* Float64OperatorFor(IrOpcode::Value opcode) {
314 switch (opcode) {
315 case IrOpcode::kNumberAdd:
316 return machine()->Float64Add();
317 case IrOpcode::kNumberSubtract:
318 return machine()->Float64Sub();
319 case IrOpcode::kNumberMultiply:
320 return machine()->Float64Mul();
321 case IrOpcode::kNumberDivide:
322 return machine()->Float64Div();
323 case IrOpcode::kNumberModulus:
324 return machine()->Float64Mod();
325 case IrOpcode::kNumberEqual:
326 return machine()->Float64Equal();
327 case IrOpcode::kNumberLessThan:
328 return machine()->Float64LessThan();
329 case IrOpcode::kNumberLessThanOrEqual:
330 return machine()->Float64LessThanOrEqual();
331 default:
332 UNREACHABLE();
333 return NULL;
334 }
335 }
336
337 RepType TypeForField(const FieldAccess& access) {
338 RepType tElement = static_cast<RepType>(0); // TODO(titzer)
339 RepType rElement = TypeForMachineRepresentation(access.representation);
340 return static_cast<RepType>(tElement | rElement);
341 }
342
343 RepType TypeForElement(const ElementAccess& access) {
344 RepType tElement = static_cast<RepType>(0); // TODO(titzer)
345 RepType rElement = TypeForMachineRepresentation(access.representation);
346 return static_cast<RepType>(tElement | rElement);
347 }
348
349 RepType TypeForBasePointer(Node* node) {
350 Type* upper = NodeProperties::GetBounds(node).upper;
351 if (upper->Is(Type::UntaggedPtr())) return rPtr;
352 return static_cast<RepType>(tAny | rTagged);
353 }
354
355 private:
356 JSGraph* jsgraph_;
357 SimplifiedOperatorBuilder* simplified_;
358 MachineOperatorBuilder* machine_;
359 Isolate* isolate_;
360
361 friend class RepresentationChangerTester; // accesses the below fields.
362
363 bool testing_type_errors_; // If {true}, don't abort on a type error.
364 bool type_error_; // Set when a type error is detected.
365
366 Node* TypeError(Node* node, RepTypeUnion output_type, RepTypeUnion use) {
367 type_error_ = true;
368 if (!testing_type_errors_) {
369 UNREACHABLE(); // TODO(titzer): report nicer type error
370 }
371 return node;
372 }
373
374 JSGraph* jsgraph() { return jsgraph_; }
375 Isolate* isolate() { return isolate_; }
376 SimplifiedOperatorBuilder* simplified() { return simplified_; }
377 MachineOperatorBuilder* machine() { return machine_; }
378 };
379 }
380 }
381 } // namespace v8::internal::compiler
382
383 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_
OLDNEW
« no previous file with comments | « src/compiler/register-allocator.cc ('k') | src/compiler/schedule.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698