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

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

Issue 1480433003: [turbofan] Introduce representation-change.cc, move stuff there, minus dead code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_ 5 #ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_ 6 #define V8_COMPILER_REPRESENTATION_CHANGE_H_
7 7
8 #include <sstream>
9
10 #include "src/base/bits.h"
11 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
12 #include "src/compiler/machine-operator.h"
13 #include "src/compiler/simplified-operator.h" 9 #include "src/compiler/simplified-operator.h"
14 10
15 namespace v8 { 11 namespace v8 {
16 namespace internal { 12 namespace internal {
17 namespace compiler { 13 namespace compiler {
18 14
19 class Truncation final { 15 class Truncation final {
20 public: 16 public:
21 // Constructors. 17 // Constructors.
22 static Truncation None() { return Truncation(TruncationKind::kNone); } 18 static Truncation None() { return Truncation(TruncationKind::kNone); }
23 static Truncation Bool() { return Truncation(TruncationKind::kBool); } 19 static Truncation Bool() { return Truncation(TruncationKind::kBool); }
24 static Truncation Word32() { return Truncation(TruncationKind::kWord32); } 20 static Truncation Word32() { return Truncation(TruncationKind::kWord32); }
25 static Truncation Word64() { return Truncation(TruncationKind::kWord64); } 21 static Truncation Word64() { return Truncation(TruncationKind::kWord64); }
26 static Truncation Float32() { return Truncation(TruncationKind::kFloat32); } 22 static Truncation Float32() { return Truncation(TruncationKind::kFloat32); }
27 static Truncation Float64() { return Truncation(TruncationKind::kFloat64); } 23 static Truncation Float64() { return Truncation(TruncationKind::kFloat64); }
28 static Truncation Any() { return Truncation(TruncationKind::kAny); } 24 static Truncation Any() { return Truncation(TruncationKind::kAny); }
29 25
30 static Truncation Generalize(Truncation t1, Truncation t2) { 26 static Truncation Generalize(Truncation t1, Truncation t2) {
31 return Truncation(Generalize(t1.kind(), t2.kind())); 27 return Truncation(Generalize(t1.kind(), t2.kind()));
32 } 28 }
33 29
34 // Queries. 30 // Queries.
35 bool TruncatesToWord32() const { 31 bool TruncatesToWord32() const {
36 return LessGeneral(kind_, TruncationKind::kWord32); 32 return LessGeneral(kind_, TruncationKind::kWord32);
37 } 33 }
38
39 bool TruncatesNaNToZero() { 34 bool TruncatesNaNToZero() {
40 return LessGeneral(kind_, TruncationKind::kWord32) || 35 return LessGeneral(kind_, TruncationKind::kWord32) ||
41 LessGeneral(kind_, TruncationKind::kBool); 36 LessGeneral(kind_, TruncationKind::kBool);
42 } 37 }
43
44 bool TruncatesUndefinedToZeroOrNaN() { 38 bool TruncatesUndefinedToZeroOrNaN() {
45 return LessGeneral(kind_, TruncationKind::kFloat64) || 39 return LessGeneral(kind_, TruncationKind::kFloat64) ||
46 LessGeneral(kind_, TruncationKind::kWord64); 40 LessGeneral(kind_, TruncationKind::kWord64);
47 } 41 }
48 42
49 // Operators. 43 // Operators.
50 bool operator==(Truncation other) const { return kind() == other.kind(); } 44 bool operator==(Truncation other) const { return kind() == other.kind(); }
51 bool operator!=(Truncation other) const { return !(*this == other); } 45 bool operator!=(Truncation other) const { return !(*this == other); }
52 46
53 // Debug utilities. 47 // Debug utilities.
54 const char* description() { 48 const char* description() const;
55 switch (kind()) {
56 case TruncationKind::kNone:
57 return "no-value-use";
58 case TruncationKind::kBool:
59 return "truncate-to-bool";
60 case TruncationKind::kWord32:
61 return "truncate-to-word32";
62 case TruncationKind::kWord64:
63 return "truncate-to-word64";
64 case TruncationKind::kFloat32:
65 return "truncate-to-float32";
66 case TruncationKind::kFloat64:
67 return "truncate-to-float64";
68 case TruncationKind::kAny:
69 return "no-truncation";
70 }
71 UNREACHABLE();
72 return nullptr;
73 }
74 49
75 private: 50 private:
76 enum class TruncationKind : uint8_t { 51 enum class TruncationKind : uint8_t {
77 kNone, 52 kNone,
78 kBool, 53 kBool,
79 kWord32, 54 kWord32,
80 kWord64, 55 kWord64,
81 kFloat32, 56 kFloat32,
82 kFloat64, 57 kFloat64,
83 kAny 58 kAny
84 }; 59 };
85 60
86 explicit Truncation(TruncationKind kind) : kind_(kind) {} 61 explicit Truncation(TruncationKind kind) : kind_(kind) {}
87 TruncationKind kind() const { return kind_; } 62 TruncationKind kind() const { return kind_; }
88 63
89 TruncationKind kind_; 64 TruncationKind kind_;
90 65
91 // Partial order for truncations: 66 static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2);
92 // 67 static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
93 // kWord64 kAny
94 // ^ ^
95 // \ |
96 // \ kFloat64 <--+
97 // \ ^ ^ |
98 // \ / | |
99 // kWord32 kFloat32 kBool
100 // ^ ^ ^
101 // \ | /
102 // \ | /
103 // \ | /
104 // \ | /
105 // \ | /
106 // kNone
107 static TruncationKind Generalize(TruncationKind rep1, TruncationKind rep2) {
108 if (LessGeneral(rep1, rep2)) return rep2;
109 if (LessGeneral(rep2, rep1)) return rep1;
110 // Handle the generalization of float64-representable values.
111 if (LessGeneral(rep1, TruncationKind::kFloat64) &&
112 LessGeneral(rep2, TruncationKind::kFloat64)) {
113 return TruncationKind::kFloat64;
114 }
115 // All other combinations are illegal.
116 FATAL("Tried to combine incompatible representations");
117 return TruncationKind::kNone;
118 }
119
120 static bool LessGeneral(TruncationKind rep1, TruncationKind rep2) {
121 switch (rep1) {
122 case TruncationKind::kNone:
123 return true;
124 case TruncationKind::kBool:
125 return rep2 == TruncationKind::kBool || rep2 == TruncationKind::kAny;
126 case TruncationKind::kWord32:
127 return rep2 == TruncationKind::kWord32 ||
128 rep2 == TruncationKind::kWord64 ||
129 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
130 case TruncationKind::kWord64:
131 return rep2 == TruncationKind::kWord64;
132 case TruncationKind::kFloat32:
133 return rep2 == TruncationKind::kFloat32 ||
134 rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
135 case TruncationKind::kFloat64:
136 return rep2 == TruncationKind::kFloat64 || rep2 == TruncationKind::kAny;
137 case TruncationKind::kAny:
138 return rep2 == TruncationKind::kAny;
139 }
140 UNREACHABLE();
141 return false;
142 }
143 }; 68 };
144 69
145 70
146 // Contains logic related to changing the representation of values for constants 71 // Contains logic related to changing the representation of values for constants
147 // and other nodes, as well as lowering Simplified->Machine operators. 72 // and other nodes, as well as lowering Simplified->Machine operators.
148 // Eagerly folds any representation changes for constants. 73 // Eagerly folds any representation changes for constants.
149 class RepresentationChanger final { 74 class RepresentationChanger final {
150 public: 75 public:
151 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate) 76 RepresentationChanger(JSGraph* jsgraph, Isolate* isolate)
152 : jsgraph_(jsgraph), 77 : jsgraph_(jsgraph),
153 isolate_(isolate), 78 isolate_(isolate),
154 testing_type_errors_(false), 79 testing_type_errors_(false),
155 type_error_(false) {} 80 type_error_(false) {}
156 81
157 // TODO(titzer): should Word64 also be implicitly convertable to others?
158 static bool IsWord(MachineTypeUnion type) {
159 return (type & (kRepWord8 | kRepWord16 | kRepWord32)) != 0;
160 }
161
162 // Changes representation from {output_type} to {use_rep}. The {truncation} 82 // Changes representation from {output_type} to {use_rep}. The {truncation}
163 // parameter is only used for sanity checking - if the changer cannot figure 83 // parameter is only used for sanity checking - if the changer cannot figure
164 // out signedness for the word32->float64 conversion, then we check that the 84 // out signedness for the word32->float64 conversion, then we check that the
165 // uses truncate to word32 (so they do not care about signedness). 85 // uses truncate to word32 (so they do not care about signedness).
166 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type, 86 Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type,
167 MachineTypeUnion use_rep, 87 MachineTypeUnion use_rep,
168 Truncation truncation = Truncation::None()) { 88 Truncation truncation = Truncation::None());
169 DCHECK((use_rep & kRepMask) == use_rep); 89 const Operator* Int32OperatorFor(IrOpcode::Value opcode);
170 if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) { 90 const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
171 // There should be only one output representation. 91 const Operator* Float64OperatorFor(IrOpcode::Value opcode);
172 return TypeError(node, output_type, use_rep); 92 MachineType TypeFromUpperBound(Type* type);
173 }
174 if (use_rep == (output_type & kRepMask)) {
175 // Representations are the same. That's a no-op.
176 return node;
177 }
178 if (IsWord(use_rep) && IsWord(output_type)) {
179 // Both are words less than or equal to 32-bits.
180 // Since loads of integers from memory implicitly sign or zero extend the
181 // value to the full machine word size and stores implicitly truncate,
182 // no representation change is necessary.
183 return node;
184 }
185 if (use_rep & kRepTagged) {
186 return GetTaggedRepresentationFor(node, output_type);
187 } else if (use_rep & kRepFloat32) {
188 return GetFloat32RepresentationFor(node, output_type, truncation);
189 } else if (use_rep & kRepFloat64) {
190 return GetFloat64RepresentationFor(node, output_type, truncation);
191 } else if (use_rep & kRepBit) {
192 return GetBitRepresentationFor(node, output_type);
193 } else if (IsWord(use_rep)) {
194 return GetWord32RepresentationFor(node, output_type);
195 } else if (use_rep & kRepWord64) {
196 return GetWord64RepresentationFor(node, output_type);
197 } else {
198 return node;
199 }
200 }
201
202 Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion output_type) {
203 // Eagerly fold representation changes for constants.
204 switch (node->opcode()) {
205 case IrOpcode::kNumberConstant:
206 case IrOpcode::kHeapConstant:
207 return node; // No change necessary.
208 case IrOpcode::kInt32Constant:
209 if (output_type & kTypeUint32) {
210 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
211 return jsgraph()->Constant(static_cast<double>(value));
212 } else if (output_type & kTypeInt32) {
213 int32_t value = OpParameter<int32_t>(node);
214 return jsgraph()->Constant(value);
215 } else if (output_type & kRepBit) {
216 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
217 : jsgraph()->TrueConstant();
218 } else {
219 return TypeError(node, output_type, kRepTagged);
220 }
221 case IrOpcode::kFloat64Constant:
222 return jsgraph()->Constant(OpParameter<double>(node));
223 case IrOpcode::kFloat32Constant:
224 return jsgraph()->Constant(OpParameter<float>(node));
225 default:
226 break;
227 }
228 // Select the correct X -> Tagged operator.
229 const Operator* op;
230 if (output_type & kRepBit) {
231 op = simplified()->ChangeBitToBool();
232 } else if (IsWord(output_type)) {
233 if (output_type & kTypeUint32) {
234 op = simplified()->ChangeUint32ToTagged();
235 } else if (output_type & kTypeInt32) {
236 op = simplified()->ChangeInt32ToTagged();
237 } else {
238 return TypeError(node, output_type, kRepTagged);
239 }
240 } else if (output_type & kRepFloat32) { // float32 -> float64 -> tagged
241 node = InsertChangeFloat32ToFloat64(node);
242 op = simplified()->ChangeFloat64ToTagged();
243 } else if (output_type & kRepFloat64) {
244 op = simplified()->ChangeFloat64ToTagged();
245 } else {
246 return TypeError(node, output_type, kRepTagged);
247 }
248 return jsgraph()->graph()->NewNode(op, node);
249 }
250
251 Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type,
252 Truncation truncation) {
253 // Eagerly fold representation changes for constants.
254 switch (node->opcode()) {
255 case IrOpcode::kFloat64Constant:
256 case IrOpcode::kNumberConstant:
257 return jsgraph()->Float32Constant(
258 DoubleToFloat32(OpParameter<double>(node)));
259 case IrOpcode::kInt32Constant:
260 if (output_type & kTypeUint32) {
261 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
262 return jsgraph()->Float32Constant(static_cast<float>(value));
263 } else {
264 int32_t value = OpParameter<int32_t>(node);
265 return jsgraph()->Float32Constant(static_cast<float>(value));
266 }
267 case IrOpcode::kFloat32Constant:
268 return node; // No change necessary.
269 default:
270 break;
271 }
272 // Select the correct X -> Float32 operator.
273 const Operator* op;
274 if (output_type & kRepBit) {
275 return TypeError(node, output_type, kRepFloat32);
276 } else if (IsWord(output_type)) {
277 if (output_type & kTypeUint32) {
278 op = machine()->ChangeUint32ToFloat64();
279 } else {
280 // Either the output is int32 or the uses only care about the
281 // low 32 bits (so we can pick int32 safely).
282 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
283 op = machine()->ChangeInt32ToFloat64();
284 }
285 // int32 -> float64 -> float32
286 node = jsgraph()->graph()->NewNode(op, node);
287 op = machine()->TruncateFloat64ToFloat32();
288 } else if (output_type & kRepTagged) {
289 op = simplified()
290 ->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
291 node = jsgraph()->graph()->NewNode(op, node);
292 op = machine()->TruncateFloat64ToFloat32();
293 } else if (output_type & kRepFloat64) {
294 op = machine()->TruncateFloat64ToFloat32();
295 } else {
296 return TypeError(node, output_type, kRepFloat32);
297 }
298 return jsgraph()->graph()->NewNode(op, node);
299 }
300
301 Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type,
302 Truncation truncation) {
303 // Eagerly fold representation changes for constants.
304 switch (node->opcode()) {
305 case IrOpcode::kNumberConstant:
306 return jsgraph()->Float64Constant(OpParameter<double>(node));
307 case IrOpcode::kInt32Constant:
308 if (output_type & kTypeUint32) {
309 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
310 return jsgraph()->Float64Constant(static_cast<double>(value));
311 } else {
312 int32_t value = OpParameter<int32_t>(node);
313 return jsgraph()->Float64Constant(value);
314 }
315 case IrOpcode::kFloat64Constant:
316 return node; // No change necessary.
317 case IrOpcode::kFloat32Constant:
318 return jsgraph()->Float64Constant(OpParameter<float>(node));
319 default:
320 break;
321 }
322 // Select the correct X -> Float64 operator.
323 const Operator* op;
324 if (output_type & kRepBit) {
325 return TypeError(node, output_type, kRepFloat64);
326 } else if (IsWord(output_type)) {
327 if (output_type & kTypeUint32) {
328 op = machine()->ChangeUint32ToFloat64();
329 } else {
330 // Either the output is int32 or the uses only care about the
331 // low 32 bits (so we can pick int32 safely).
332 DCHECK(output_type & kTypeInt32 || truncation.TruncatesToWord32());
333 op = machine()->ChangeInt32ToFloat64();
334 }
335 } else if (output_type & kRepTagged) {
336 op = simplified()->ChangeTaggedToFloat64();
337 } else if (output_type & kRepFloat32) {
338 op = machine()->ChangeFloat32ToFloat64();
339 } else {
340 return TypeError(node, output_type, kRepFloat64);
341 }
342 return jsgraph()->graph()->NewNode(op, node);
343 }
344
345 Node* MakeTruncatedInt32Constant(double value) {
346 return jsgraph()->Int32Constant(DoubleToInt32(value));
347 }
348
349 Node* GetTruncatedWord32For(Node* node, MachineTypeUnion output_type) {
350 // Eagerly fold truncations for constants.
351 switch (node->opcode()) {
352 case IrOpcode::kInt32Constant:
353 return node; // No change necessary.
354 case IrOpcode::kFloat32Constant:
355 return jsgraph()->Int32Constant(
356 DoubleToInt32(OpParameter<float>(node)));
357 case IrOpcode::kNumberConstant:
358 case IrOpcode::kFloat64Constant:
359 return jsgraph()->Int32Constant(
360 DoubleToInt32(OpParameter<double>(node)));
361 default:
362 break;
363 }
364 // Select the correct X -> Word32 truncation operator.
365 const Operator* op = NULL;
366 if (output_type & kRepFloat64) {
367 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
368 } else if (output_type & kRepFloat32) {
369 node = InsertChangeFloat32ToFloat64(node);
370 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
371 } else if (output_type & kRepTagged) {
372 node = InsertChangeTaggedToFloat64(node);
373 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
374 } else {
375 return TypeError(node, output_type, kRepWord32);
376 }
377 return jsgraph()->graph()->NewNode(op, node);
378 }
379
380 Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type) {
381 // Eagerly fold representation changes for constants.
382 switch (node->opcode()) {
383 case IrOpcode::kInt32Constant:
384 return node; // No change necessary.
385 case IrOpcode::kFloat32Constant:
386 return MakeTruncatedInt32Constant(OpParameter<float>(node));
387 case IrOpcode::kNumberConstant:
388 case IrOpcode::kFloat64Constant:
389 return MakeTruncatedInt32Constant(OpParameter<double>(node));
390 default:
391 break;
392 }
393 // Select the correct X -> Word32 operator.
394 const Operator* op;
395 Type* type = NodeProperties::GetType(node);
396
397 if (output_type & kRepBit) {
398 return node; // Sloppy comparison -> word32
399 } else if (output_type & kRepFloat64) {
400 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
401 op = machine()->ChangeFloat64ToUint32();
402 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
403 op = machine()->ChangeFloat64ToInt32();
404 } else {
405 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
406 }
407 } else if (output_type & kRepFloat32) {
408 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
409 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
410 op = machine()->ChangeFloat64ToUint32();
411 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
412 op = machine()->ChangeFloat64ToInt32();
413 } else {
414 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
415 }
416 } else if (output_type & kRepTagged) {
417 if (output_type & kTypeUint32 || type->Is(Type::Unsigned32())) {
418 op = simplified()->ChangeTaggedToUint32();
419 } else if (output_type & kTypeInt32 || type->Is(Type::Signed32())) {
420 op = simplified()->ChangeTaggedToInt32();
421 } else {
422 node = InsertChangeTaggedToFloat64(node);
423 op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
424 }
425 } else {
426 return TypeError(node, output_type, kRepWord32);
427 }
428 return jsgraph()->graph()->NewNode(op, node);
429 }
430
431 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) {
432 // Eagerly fold representation changes for constants.
433 switch (node->opcode()) {
434 case IrOpcode::kHeapConstant: {
435 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
436 DCHECK(value.is_identical_to(factory()->true_value()) ||
437 value.is_identical_to(factory()->false_value()));
438 return jsgraph()->Int32Constant(
439 value.is_identical_to(factory()->true_value()) ? 1 : 0);
440 }
441 default:
442 break;
443 }
444 // Select the correct X -> Bit operator.
445 const Operator* op;
446 if (output_type & kRepTagged) {
447 op = simplified()->ChangeBoolToBit();
448 } else {
449 return TypeError(node, output_type, kRepBit);
450 }
451 return jsgraph()->graph()->NewNode(op, node);
452 }
453
454 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) {
455 if (output_type & kRepBit) {
456 return node; // Sloppy comparison -> word64
457 }
458 // Can't really convert Word64 to anything else. Purported to be internal.
459 return TypeError(node, output_type, kRepWord64);
460 }
461
462 const Operator* Int32OperatorFor(IrOpcode::Value opcode) {
463 switch (opcode) {
464 case IrOpcode::kNumberAdd:
465 return machine()->Int32Add();
466 case IrOpcode::kNumberSubtract:
467 return machine()->Int32Sub();
468 case IrOpcode::kNumberMultiply:
469 return machine()->Int32Mul();
470 case IrOpcode::kNumberDivide:
471 return machine()->Int32Div();
472 case IrOpcode::kNumberModulus:
473 return machine()->Int32Mod();
474 case IrOpcode::kNumberBitwiseOr:
475 return machine()->Word32Or();
476 case IrOpcode::kNumberBitwiseXor:
477 return machine()->Word32Xor();
478 case IrOpcode::kNumberBitwiseAnd:
479 return machine()->Word32And();
480 case IrOpcode::kNumberEqual:
481 return machine()->Word32Equal();
482 case IrOpcode::kNumberLessThan:
483 return machine()->Int32LessThan();
484 case IrOpcode::kNumberLessThanOrEqual:
485 return machine()->Int32LessThanOrEqual();
486 default:
487 UNREACHABLE();
488 return NULL;
489 }
490 }
491
492 const Operator* Uint32OperatorFor(IrOpcode::Value opcode) {
493 switch (opcode) {
494 case IrOpcode::kNumberAdd:
495 return machine()->Int32Add();
496 case IrOpcode::kNumberSubtract:
497 return machine()->Int32Sub();
498 case IrOpcode::kNumberMultiply:
499 return machine()->Int32Mul();
500 case IrOpcode::kNumberDivide:
501 return machine()->Uint32Div();
502 case IrOpcode::kNumberModulus:
503 return machine()->Uint32Mod();
504 case IrOpcode::kNumberEqual:
505 return machine()->Word32Equal();
506 case IrOpcode::kNumberLessThan:
507 return machine()->Uint32LessThan();
508 case IrOpcode::kNumberLessThanOrEqual:
509 return machine()->Uint32LessThanOrEqual();
510 default:
511 UNREACHABLE();
512 return NULL;
513 }
514 }
515
516 const Operator* Float64OperatorFor(IrOpcode::Value opcode) {
517 switch (opcode) {
518 case IrOpcode::kNumberAdd:
519 return machine()->Float64Add();
520 case IrOpcode::kNumberSubtract:
521 return machine()->Float64Sub();
522 case IrOpcode::kNumberMultiply:
523 return machine()->Float64Mul();
524 case IrOpcode::kNumberDivide:
525 return machine()->Float64Div();
526 case IrOpcode::kNumberModulus:
527 return machine()->Float64Mod();
528 case IrOpcode::kNumberEqual:
529 return machine()->Float64Equal();
530 case IrOpcode::kNumberLessThan:
531 return machine()->Float64LessThan();
532 case IrOpcode::kNumberLessThanOrEqual:
533 return machine()->Float64LessThanOrEqual();
534 default:
535 UNREACHABLE();
536 return NULL;
537 }
538 }
539 93
540 MachineType TypeForBasePointer(const FieldAccess& access) { 94 MachineType TypeForBasePointer(const FieldAccess& access) {
541 return access.tag() != 0 ? kMachAnyTagged : kMachPtr; 95 return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
542 } 96 }
543 97
544 MachineType TypeForBasePointer(const ElementAccess& access) { 98 MachineType TypeForBasePointer(const ElementAccess& access) {
545 return access.tag() != 0 ? kMachAnyTagged : kMachPtr; 99 return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
546 } 100 }
547 101
548 MachineType TypeFromUpperBound(Type* type) {
549 if (type->Is(Type::None()))
550 return kTypeAny; // TODO(titzer): should be an error
551 if (type->Is(Type::Signed32())) return kTypeInt32;
552 if (type->Is(Type::Unsigned32())) return kTypeUint32;
553 if (type->Is(Type::Number())) return kTypeNumber;
554 if (type->Is(Type::Boolean())) return kTypeBool;
555 return kTypeAny;
556 }
557
558 private: 102 private:
559 JSGraph* jsgraph_; 103 JSGraph* jsgraph_;
560 Isolate* isolate_; 104 Isolate* isolate_;
561 105
562 friend class RepresentationChangerTester; // accesses the below fields. 106 friend class RepresentationChangerTester; // accesses the below fields.
563 107
564 bool testing_type_errors_; // If {true}, don't abort on a type error. 108 bool testing_type_errors_; // If {true}, don't abort on a type error.
565 bool type_error_; // Set when a type error is detected. 109 bool type_error_; // Set when a type error is detected.
566 110
111 Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion output_type);
112 Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type,
113 Truncation truncation);
114 Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type,
115 Truncation truncation);
116 Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type);
117 Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type);
118 Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type);
567 Node* TypeError(Node* node, MachineTypeUnion output_type, 119 Node* TypeError(Node* node, MachineTypeUnion output_type,
568 MachineTypeUnion use) { 120 MachineTypeUnion use);
569 type_error_ = true; 121 Node* MakeTruncatedInt32Constant(double value);
570 if (!testing_type_errors_) { 122 Node* InsertChangeFloat32ToFloat64(Node* node);
571 std::ostringstream out_str; 123 Node* InsertChangeTaggedToFloat64(Node* node);
572 out_str << static_cast<MachineType>(output_type);
573
574 std::ostringstream use_str;
575 use_str << static_cast<MachineType>(use);
576
577 V8_Fatal(__FILE__, __LINE__,
578 "RepresentationChangerError: node #%d:%s of "
579 "%s cannot be changed to %s",
580 node->id(), node->op()->mnemonic(), out_str.str().c_str(),
581 use_str.str().c_str());
582 }
583 return node;
584 }
585
586 Node* InsertChangeFloat32ToFloat64(Node* node) {
587 return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
588 node);
589 }
590
591 Node* InsertChangeTaggedToFloat64(Node* node) {
592 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
593 node);
594 }
595 124
596 JSGraph* jsgraph() const { return jsgraph_; } 125 JSGraph* jsgraph() const { return jsgraph_; }
597 Isolate* isolate() const { return isolate_; } 126 Isolate* isolate() const { return isolate_; }
598 Factory* factory() const { return isolate()->factory(); } 127 Factory* factory() const { return isolate()->factory(); }
599 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); } 128 SimplifiedOperatorBuilder* simplified() { return jsgraph()->simplified(); }
600 MachineOperatorBuilder* machine() { return jsgraph()->machine(); } 129 MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
601 }; 130 };
602 131
603 } // namespace compiler 132 } // namespace compiler
604 } // namespace internal 133 } // namespace internal
605 } // namespace v8 134 } // namespace v8
606 135
607 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_ 136 #endif // V8_COMPILER_REPRESENTATION_CHANGE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698