Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h
new file mode 100644
index 0000000..aaa248e
--- /dev/null
+++ b/src/compiler/representation-change.h
@@ -0,0 +1,360 @@
+// 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/base/bits.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 {
+
+// 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,
+ Isolate* isolate)
+ : jsgraph_(jsgraph),
+ simplified_(simplified),
+ isolate_(isolate),
+ testing_type_errors_(false),
+ type_error_(false) {}
+
+ // TODO(titzer): should Word64 also be implicitly convertable to others?
+ static const MachineTypeUnion rWord =
+ kRepBit | kRepWord8 | kRepWord16 | kRepWord32;
+
+ Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type,
+ MachineTypeUnion use_type) {
+ if (!base::bits::IsPowerOfTwo32(output_type & kRepMask)) {
+ // There should be only one output representation.
+ return TypeError(node, output_type, use_type);
+ }
+ if ((use_type & kRepMask) == (output_type & kRepMask)) {
+ // Representations are the same. That's a no-op.
+ return node;
+ }
+ if ((use_type & rWord) && (output_type & rWord)) {
+ // Both are words less than or equal to 32-bits.
+ // Since loads of integers from memory implicitly sign or zero extend the
+ // value to the full machine word size and stores implicitly truncate,
+ // no representation change is necessary.
+ return node;
+ }
+ if (use_type & kRepTagged) {
+ return GetTaggedRepresentationFor(node, output_type);
+ } else if (use_type & kRepFloat64) {
+ return GetFloat64RepresentationFor(node, output_type);
+ } else if (use_type & kRepFloat32) {
+ return TypeError(node, output_type, use_type); // TODO(titzer): handle
+ } else if (use_type & kRepBit) {
+ return GetBitRepresentationFor(node, output_type);
+ } else if (use_type & rWord) {
+ return GetWord32RepresentationFor(node, output_type,
+ use_type & kTypeUint32);
+ } else if (use_type & kRepWord64) {
+ return GetWord64RepresentationFor(node, output_type);
+ } else {
+ return node;
+ }
+ }
+
+ Node* GetTaggedRepresentationFor(Node* node, MachineTypeUnion 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 & kTypeUint32) {
+ uint32_t value = OpParameter<uint32_t>(node);
+ return jsgraph()->Constant(static_cast<double>(value));
+ } else if (output_type & kTypeInt32) {
+ int32_t value = OpParameter<int32_t>(node);
+ return jsgraph()->Constant(value);
+ } else if (output_type & kRepBit) {
+ return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
+ : jsgraph()->TrueConstant();
+ } else {
+ return TypeError(node, output_type, kRepTagged);
+ }
+ case IrOpcode::kFloat64Constant:
+ return jsgraph()->Constant(OpParameter<double>(node));
+ default:
+ break;
+ }
+ // Select the correct X -> Tagged operator.
+ const Operator* op;
+ if (output_type & kRepBit) {
+ op = simplified()->ChangeBitToBool();
+ } else if (output_type & rWord) {
+ if (output_type & kTypeUint32) {
+ op = simplified()->ChangeUint32ToTagged();
+ } else if (output_type & kTypeInt32) {
+ op = simplified()->ChangeInt32ToTagged();
+ } else {
+ return TypeError(node, output_type, kRepTagged);
+ }
+ } else if (output_type & kRepFloat64) {
+ op = simplified()->ChangeFloat64ToTagged();
+ } else {
+ return TypeError(node, output_type, kRepTagged);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetFloat64RepresentationFor(Node* node, MachineTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kNumberConstant:
+ return jsgraph()->Float64Constant(OpParameter<double>(node));
+ case IrOpcode::kInt32Constant:
+ if (output_type & kTypeUint32) {
+ uint32_t value = OpParameter<uint32_t>(node);
+ return jsgraph()->Float64Constant(static_cast<double>(value));
+ } else {
+ int32_t value = OpParameter<int32_t>(node);
+ return jsgraph()->Float64Constant(value);
+ }
+ case IrOpcode::kFloat64Constant:
+ return node; // No change necessary.
+ default:
+ break;
+ }
+ // Select the correct X -> Float64 operator.
+ const Operator* op;
+ if (output_type & kRepBit) {
+ return TypeError(node, output_type, kRepFloat64);
+ } else if (output_type & rWord) {
+ if (output_type & kTypeUint32) {
+ op = machine()->ChangeUint32ToFloat64();
+ } else {
+ op = machine()->ChangeInt32ToFloat64();
+ }
+ } else if (output_type & kRepTagged) {
+ op = simplified()->ChangeTaggedToFloat64();
+ } else {
+ return TypeError(node, output_type, kRepFloat64);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetWord32RepresentationFor(Node* node, MachineTypeUnion output_type,
+ bool use_unsigned) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kInt32Constant:
+ return node; // No change necessary.
+ case IrOpcode::kNumberConstant:
+ case IrOpcode::kFloat64Constant: {
+ double value = OpParameter<double>(node);
+ if (value < 0) {
+ DCHECK(IsInt32Double(value));
+ int32_t iv = static_cast<int32_t>(value);
+ return jsgraph()->Int32Constant(iv);
+ } else {
+ DCHECK(IsUint32Double(value));
+ int32_t iv = static_cast<int32_t>(static_cast<uint32_t>(value));
+ return jsgraph()->Int32Constant(iv);
+ }
+ }
+ default:
+ break;
+ }
+ // Select the correct X -> Word32 operator.
+ const Operator* op = NULL;
+ if (output_type & kRepFloat64) {
+ if (output_type & kTypeUint32 || use_unsigned) {
+ op = machine()->ChangeFloat64ToUint32();
+ } else {
+ op = machine()->ChangeFloat64ToInt32();
+ }
+ } else if (output_type & kRepTagged) {
+ if (output_type & kTypeUint32 || use_unsigned) {
+ op = simplified()->ChangeTaggedToUint32();
+ } else {
+ op = simplified()->ChangeTaggedToInt32();
+ }
+ } else {
+ return TypeError(node, output_type, kRepWord32);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) {
+ // Eagerly fold representation changes for constants.
+ switch (node->opcode()) {
+ case IrOpcode::kInt32Constant: {
+ int32_t value = OpParameter<int32_t>(node);
+ if (value == 0 || value == 1) return node;
+ return jsgraph()->OneConstant(); // value != 0
+ }
+ case IrOpcode::kHeapConstant: {
+ Handle<Object> handle = OpParameter<Unique<Object> >(node).handle();
+ DCHECK(*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.
+ const Operator* op;
+ if (output_type & rWord) {
+ return node; // No change necessary.
+ } else if (output_type & kRepWord64) {
+ return node; // TODO(titzer): No change necessary, on 64-bit.
+ } else if (output_type & kRepTagged) {
+ op = simplified()->ChangeBoolToBit();
+ } else {
+ return TypeError(node, output_type, kRepBit);
+ }
+ return jsgraph()->graph()->NewNode(op, node);
+ }
+
+ Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) {
+ if (output_type & kRepBit) {
+ return node; // Sloppy comparison -> word64
+ }
+ // Can't really convert Word64 to anything else. Purported to be internal.
+ return TypeError(node, output_type, kRepWord64);
+ }
+
+ const Operator* Int32OperatorFor(IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kNumberAdd:
+ return machine()->Int32Add();
+ case IrOpcode::kNumberSubtract:
+ return machine()->Int32Sub();
+ case IrOpcode::kNumberMultiply:
+ return machine()->Int32Mul();
+ case IrOpcode::kNumberDivide:
+ return machine()->Int32Div();
+ case IrOpcode::kNumberModulus:
+ return machine()->Int32Mod();
+ case IrOpcode::kNumberEqual:
+ return machine()->Word32Equal();
+ case IrOpcode::kNumberLessThan:
+ return machine()->Int32LessThan();
+ case IrOpcode::kNumberLessThanOrEqual:
+ return machine()->Int32LessThanOrEqual();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+
+ const Operator* Uint32OperatorFor(IrOpcode::Value opcode) {
+ switch (opcode) {
+ case IrOpcode::kNumberAdd:
+ return machine()->Int32Add();
+ case IrOpcode::kNumberSubtract:
+ return machine()->Int32Sub();
+ case IrOpcode::kNumberMultiply:
+ return machine()->Int32Mul();
+ case IrOpcode::kNumberDivide:
+ return machine()->Int32UDiv();
+ case IrOpcode::kNumberModulus:
+ return machine()->Int32UMod();
+ case IrOpcode::kNumberEqual:
+ return machine()->Word32Equal();
+ case IrOpcode::kNumberLessThan:
+ return machine()->Uint32LessThan();
+ case IrOpcode::kNumberLessThanOrEqual:
+ return machine()->Uint32LessThanOrEqual();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+
+ const 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;
+ }
+ }
+
+ MachineType TypeForBasePointer(const FieldAccess& access) {
+ return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
+ }
+
+ MachineType TypeForBasePointer(const ElementAccess& access) {
+ return access.tag() != 0 ? kMachAnyTagged : kMachPtr;
+ }
+
+ MachineType TypeFromUpperBound(Type* type) {
+ if (type->Is(Type::None()))
+ return kTypeAny; // TODO(titzer): should be an error
+ if (type->Is(Type::Signed32())) return kTypeInt32;
+ if (type->Is(Type::Unsigned32())) return kTypeUint32;
+ if (type->Is(Type::Number())) return kTypeNumber;
+ if (type->Is(Type::Boolean())) return kTypeBool;
+ return kTypeAny;
+ }
+
+ private:
+ JSGraph* jsgraph_;
+ SimplifiedOperatorBuilder* simplified_;
+ 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, MachineTypeUnion output_type,
+ MachineTypeUnion use) {
+ type_error_ = true;
+ if (!testing_type_errors_) {
+ OStringStream out_str;
+ out_str << static_cast<MachineType>(output_type);
+
+ OStringStream use_str;
+ use_str << static_cast<MachineType>(use);
+
+ V8_Fatal(__FILE__, __LINE__,
+ "RepresentationChangerError: node #%d:%s of "
+ "%s cannot be changed to %s",
+ node->id(), node->op()->mnemonic(), out_str.c_str(),
+ use_str.c_str());
+ }
+ return node;
+ }
+
+ JSGraph* jsgraph() { return jsgraph_; }
+ Isolate* isolate() { return isolate_; }
+ SimplifiedOperatorBuilder* simplified() { return simplified_; }
+ MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
+};
+}
+}
+} // namespace v8::internal::compiler
+
+#endif // V8_COMPILER_REPRESENTATION_CHANGE_H_