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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/register-allocator.cc ('k') | src/compiler/schedule.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/representation-change.h
diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
new file mode 100644
index 0000000000000000000000000000000000000000..824e22ba29f1a42070b62084f9b8ac9b9f8570e9
--- /dev/null
+++ b/src/compiler/representation-change.h
@@ -0,0 +1,383 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_REPRESENTATION_CHANGE_H_
+#define V8_COMPILER_REPRESENTATION_CHANGE_H_
+
+#include "src/compiler/js-graph.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// The types and representations tracked during representation inference
+// and change insertion.
+// TODO(titzer): First, merge MachineRepresentation and RepType.
+// TODO(titzer): Second, Use the real type system instead of RepType.
+enum RepType {
+ // Representations.
+ rBit = 1 << 0,
+ rWord32 = 1 << 1,
+ rWord64 = 1 << 2,
+ rFloat64 = 1 << 3,
+ rTagged = 1 << 4,
+
+ // Types.
+ tBool = 1 << 5,
+ tInt32 = 1 << 6,
+ tUint32 = 1 << 7,
+ tInt64 = 1 << 8,
+ tUint64 = 1 << 9,
+ tNumber = 1 << 10,
+ tAny = 1 << 11
+};
+
+typedef uint16_t RepTypeUnion;
+
+const RepTypeUnion rMask = rBit | rWord32 | rWord64 | rFloat64 | rTagged;
+const RepTypeUnion tMask =
+ tBool | tInt32 | tUint32 | tInt64 | tUint64 | tNumber | tAny;
+const RepType rPtr = kPointerSize == 4 ? rWord32 : rWord64;
+
+
+// Contains logic related to changing the representation of values for constants
+// and other nodes, as well as lowering Simplified->Machine operators.
+// Eagerly folds any representation changes for constants.
+class RepresentationChanger {
+ public:
+ RepresentationChanger(JSGraph* jsgraph, SimplifiedOperatorBuilder* simplified,
+ MachineOperatorBuilder* machine, Isolate* isolate)
+ : jsgraph_(jsgraph),
+ simplified_(simplified),
+ machine_(machine),
+ isolate_(isolate),
+ testing_type_errors_(false),
+ type_error_(false) {}
+
+
+ Node* GetRepresentationFor(Node* node, RepTypeUnion output_type,
+ RepTypeUnion use_type) {
+ if (!IsPowerOf2(output_type & rMask)) {
+ // There should be only one output representation.
+ return TypeError(node, output_type, use_type);
+ }
+ if ((use_type & rMask) == (output_type & rMask)) {
+ // Representations are the same. That's a no-op.
+ return node;
+ }
+ if (use_type & rTagged) {
+ return GetTaggedRepresentationFor(node, output_type);
+ } else if (use_type & rFloat64) {
+ return GetFloat64RepresentationFor(node, output_type);
+ } else if (use_type & rWord32) {
+ return GetWord32RepresentationFor(node, output_type);
+ } else if (use_type & rBit) {
+ return GetBitRepresentationFor(node, output_type);
+ } else if (use_type & rWord64) {
+ return GetWord64RepresentationFor(node, output_type);
+ } else {
+ return node;
+ }
+ }
+
+ Node* GetTaggedRepresentationFor(Node* node, RepTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kNumberConstant:
+ case IrOpcode::kHeapConstant:
+ return node; // No change necessary.
+ case IrOpcode::kInt32Constant:
+ if (output_type & tUint32) {
+ uint32_t value = ValueOf<uint32_t>(node->op());
+ return jsgraph()->Constant(static_cast<double>(value));
+ } else if (output_type & tInt32) {
+ int32_t value = ValueOf<int32_t>(node->op());
+ return jsgraph()->Constant(value);
+ } else if (output_type & rBit) {
+ return ValueOf<int32_t>(node->op()) == 0 ? jsgraph()->FalseConstant()
+ : jsgraph()->TrueConstant();
+ } else {
+ return TypeError(node, output_type, rTagged);
+ }
+ case IrOpcode::kFloat64Constant:
+ return jsgraph()->Constant(ValueOf<double>(node->op()));
+ default:
+ break;
+ }
+ // Select the correct X -> Tagged operator.
+ Operator* op;
+ if (output_type & rBit) {
+ op = simplified()->ChangeBitToBool();
+ } else if (output_type & rWord32) {
+ if (output_type & tUint32) {
+ op = simplified()->ChangeUint32ToTagged();
+ } else if (output_type & tInt32) {
+ op = simplified()->ChangeInt32ToTagged();
+ } else {
+ return TypeError(node, output_type, rTagged);
+ }
+ } else if (output_type & rFloat64) {
+ op = simplified()->ChangeFloat64ToTagged();
+ } else {
+ return TypeError(node, output_type, rTagged);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetFloat64RepresentationFor(Node* node, RepTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kNumberConstant:
+ return jsgraph()->Float64Constant(ValueOf<double>(node->op()));
+ case IrOpcode::kInt32Constant:
+ if (output_type & tUint32) {
+ uint32_t value = ValueOf<uint32_t>(node->op());
+ return jsgraph()->Float64Constant(static_cast<double>(value));
+ } else {
+ int32_t value = ValueOf<int32_t>(node->op());
+ return jsgraph()->Float64Constant(value);
+ }
+ case IrOpcode::kFloat64Constant:
+ return node; // No change necessary.
+ default:
+ break;
+ }
+ // Select the correct X -> Float64 operator.
+ Operator* op;
+ if (output_type & rWord32) {
+ if (output_type & tUint32) {
+ op = machine()->ConvertUint32ToFloat64();
+ } else if (output_type & tInt32) {
+ op = machine()->ConvertInt32ToFloat64();
+ } else {
+ return TypeError(node, output_type, rFloat64);
+ }
+ } else if (output_type & rTagged) {
+ op = simplified()->ChangeTaggedToFloat64();
+ } else {
+ return TypeError(node, output_type, rFloat64);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetWord32RepresentationFor(Node* node, RepTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kInt32Constant:
+ return node; // No change necessary.
+ case IrOpcode::kNumberConstant:
+ case IrOpcode::kFloat64Constant: {
+ if (output_type & tUint32) {
+ int32_t value = static_cast<int32_t>(
+ static_cast<uint32_t>(ValueOf<double>(node->op())));
+ return jsgraph()->Int32Constant(value);
+ } else if (output_type & tInt32) {
+ int32_t value = FastD2I(ValueOf<double>(node->op()));
+ return jsgraph()->Int32Constant(value);
+ } else {
+ return TypeError(node, output_type, rWord32);
+ }
+ }
+ default:
+ break;
+ }
+ // Select the correct X -> Word32 operator.
+ Operator* op = NULL;
+ if (output_type & rFloat64) {
+ // TODO(turbofan): could have cheaper float64 conversions that don't do
+ // the full JavaScript truncation here.
+ if (output_type & tUint32) {
+ op = machine()->ConvertFloat64ToUint32();
+ } else if (output_type & tInt32) {
+ op = machine()->ConvertFloat64ToInt32();
+ } else {
+ return TypeError(node, output_type, rWord32);
+ }
+ } else if (output_type & rTagged) {
+ if (output_type & tUint32) {
+ op = simplified()->ChangeTaggedToUint32();
+ } else if (output_type & tInt32) {
+ op = simplified()->ChangeTaggedToInt32();
+ } else {
+ return TypeError(node, output_type, rWord32);
+ }
+ } else if (output_type & rBit) {
+ return node; // Sloppy comparison -> word32.
+ } else {
+ return TypeError(node, output_type, rWord32);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetBitRepresentationFor(Node* node, RepTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kInt32Constant: {
+ int32_t value = ValueOf<int32_t>(node->op());
+ if (value == 0 || value == 1) return node;
+ return jsgraph()->OneConstant(); // value != 0
+ }
+ case IrOpcode::kHeapConstant: {
+ Handle<Object> handle = ValueOf<Handle<Object> >(node->op());
+ ASSERT(*handle == isolate()->heap()->true_value() ||
+ *handle == isolate()->heap()->false_value());
+ return jsgraph()->Int32Constant(
+ *handle == isolate()->heap()->true_value() ? 1 : 0);
+ }
+ default:
+ break;
+ }
+ // Select the correct X -> Bit operator.
+ Operator* op;
+ if (output_type & rWord32) {
+ return node; // No change necessary.
+ } else if (output_type & rWord64) {
+ return node; // TODO(titzer): No change necessary, on 64-bit.
+ } else if (output_type & rTagged) {
+ op = simplified()->ChangeBoolToBit();
+ } else {
+ return TypeError(node, output_type, rBit);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetWord64RepresentationFor(Node* node, RepTypeUnion output_type) {
+ if (output_type & rBit) {
+ return node; // Sloppy comparison -> word64
+ }
+ // Can't really convert Word64 to anything else. Purported to be internal.
+ return TypeError(node, output_type, rWord64);
+ }
+
+ static RepType TypeForMachineRepresentation(MachineRepresentation rep) {
+ // TODO(titzer): merge MachineRepresentation and RepType.
+ switch (rep) {
+ case kMachineWord8:
+ return rWord32;
+ case kMachineWord16:
+ return rWord32;
+ case kMachineWord32:
+ return rWord32;
+ case kMachineWord64:
+ return rWord64;
+ case kMachineFloat64:
+ return rFloat64;
+ case kMachineTagged:
+ return rTagged;
+ default:
+ UNREACHABLE();
+ return static_cast<RepType>(0);
+ }
+ }
+
+ Operator* Int32OperatorFor(IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kNumberAdd:
+ return machine()->Int32Add();
+ case IrOpcode::kNumberSubtract:
+ return machine()->Int32Sub();
+ case IrOpcode::kNumberEqual:
+ return machine()->Word32Equal();
+ case IrOpcode::kNumberLessThan:
+ return machine()->Int32LessThan();
+ case IrOpcode::kNumberLessThanOrEqual:
+ return machine()->Int32LessThanOrEqual();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+
+ Operator* Uint32OperatorFor(IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kNumberAdd:
+ return machine()->Int32Add();
+ case IrOpcode::kNumberSubtract:
+ return machine()->Int32Sub();
+ case IrOpcode::kNumberEqual:
+ return machine()->Word32Equal();
+ case IrOpcode::kNumberLessThan:
+ return machine()->Uint32LessThan();
+ case IrOpcode::kNumberLessThanOrEqual:
+ return machine()->Uint32LessThanOrEqual();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+
+ Operator* Float64OperatorFor(IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kNumberAdd:
+ return machine()->Float64Add();
+ case IrOpcode::kNumberSubtract:
+ return machine()->Float64Sub();
+ case IrOpcode::kNumberMultiply:
+ return machine()->Float64Mul();
+ case IrOpcode::kNumberDivide:
+ return machine()->Float64Div();
+ case IrOpcode::kNumberModulus:
+ return machine()->Float64Mod();
+ case IrOpcode::kNumberEqual:
+ return machine()->Float64Equal();
+ case IrOpcode::kNumberLessThan:
+ return machine()->Float64LessThan();
+ case IrOpcode::kNumberLessThanOrEqual:
+ return machine()->Float64LessThanOrEqual();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+
+ RepType TypeForField(const FieldAccess& access) {
+ RepType tElement = static_cast<RepType>(0); // TODO(titzer)
+ RepType rElement = TypeForMachineRepresentation(access.representation);
+ return static_cast<RepType>(tElement | rElement);
+ }
+
+ RepType TypeForElement(const ElementAccess& access) {
+ RepType tElement = static_cast<RepType>(0); // TODO(titzer)
+ RepType rElement = TypeForMachineRepresentation(access.representation);
+ return static_cast<RepType>(tElement | rElement);
+ }
+
+ RepType TypeForBasePointer(Node* node) {
+ Type* upper = NodeProperties::GetBounds(node).upper;
+ if (upper->Is(Type::UntaggedPtr())) return rPtr;
+ return static_cast<RepType>(tAny | rTagged);
+ }
+
+ private:
+ JSGraph* jsgraph_;
+ SimplifiedOperatorBuilder* simplified_;
+ MachineOperatorBuilder* machine_;
+ Isolate* isolate_;
+
+ friend class RepresentationChangerTester; // accesses the below fields.
+
+ bool testing_type_errors_; // If {true}, don't abort on a type error.
+ bool type_error_; // Set when a type error is detected.
+
+ Node* TypeError(Node* node, RepTypeUnion output_type, RepTypeUnion use) {
+ type_error_ = true;
+ if (!testing_type_errors_) {
+ UNREACHABLE(); // TODO(titzer): report nicer type error
+ }
+ return node;
+ }
+
+ JSGraph* jsgraph() { return jsgraph_; }
+ Isolate* isolate() { return isolate_; }
+ SimplifiedOperatorBuilder* simplified() { return simplified_; }
+ MachineOperatorBuilder* machine() { return machine_; }
+};
+}
+}
+} // namespace v8::internal::compiler
+
+#endif // V8_COMPILER_REPRESENTATION_CHANGE_H_
« 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