|
|
|
// 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 <sstream>
|
|
|
|
|
|
|
|
#include "src/base/bits.h"
|
|
|
|
#include "src/compiler/js-graph.h"
|
|
|
|
#include "src/compiler/machine-operator.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 = 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 & kRepFloat32) {
|
|
|
|
return GetFloat32RepresentationFor(node, output_type);
|
|
|
|
} else if (use_type & kRepFloat64) {
|
|
|
|
return GetFloat64RepresentationFor(node, output_type);
|
|
|
|
} 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));
|
|
|
|
case IrOpcode::kFloat32Constant:
|
|
|
|
return jsgraph()->Constant(OpParameter<float>(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 & kRepFloat32) { // float32 -> float64 -> tagged
|
|
|
|
node = InsertChangeFloat32ToFloat64(node);
|
|
|
|
op = simplified()->ChangeFloat64ToTagged();
|
|
|
|
} else if (output_type & kRepFloat64) {
|
|
|
|
op = simplified()->ChangeFloat64ToTagged();
|
|
|
|
} else {
|
|
|
|
return TypeError(node, output_type, kRepTagged);
|
|
|
|
}
|
|
|
|
return jsgraph()->graph()->NewNode(op, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* GetFloat32RepresentationFor(Node* node, MachineTypeUnion output_type) {
|
|
|
|
// Eagerly fold representation changes for constants.
|
|
|
|
switch (node->opcode()) {
|
|
|
|
case IrOpcode::kFloat64Constant:
|
|
|
|
case IrOpcode::kNumberConstant:
|
|
|
|
return jsgraph()->Float32Constant(
|
|
|
|
DoubleToFloat32(OpParameter<double>(node)));
|
|
|
|
case IrOpcode::kInt32Constant:
|
|
|
|
if (output_type & kTypeUint32) {
|
|
|
|
uint32_t value = OpParameter<uint32_t>(node);
|
|
|
|
return jsgraph()->Float32Constant(static_cast<float>(value));
|
|
|
|
} else {
|
|
|
|
int32_t value = OpParameter<int32_t>(node);
|
|
|
|
return jsgraph()->Float32Constant(static_cast<float>(value));
|
|
|
|
}
|
|
|
|
case IrOpcode::kFloat32Constant:
|
|
|
|
return node; // No change necessary.
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Select the correct X -> Float32 operator.
|
|
|
|
const Operator* op;
|
|
|
|
if (output_type & kRepBit) {
|
|
|
|
return TypeError(node, output_type, kRepFloat32);
|
|
|
|
} else if (output_type & rWord) {
|
|
|
|
if (output_type & kTypeUint32) {
|
|
|
|
op = machine()->ChangeUint32ToFloat64();
|
|
|
|
} else {
|
|
|
|
op = machine()->ChangeInt32ToFloat64();
|
|
|
|
}
|
|
|
|
// int32 -> float64 -> float32
|
|
|
|
node = jsgraph()->graph()->NewNode(op, node);
|
|
|
|
op = machine()->TruncateFloat64ToFloat32();
|
|
|
|
} else if (output_type & kRepTagged) {
|
|
|
|
op = simplified()
|
|
|
|
->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
|
|
|
|
node = jsgraph()->graph()->NewNode(op, node);
|
|
|
|
op = machine()->TruncateFloat64ToFloat32();
|
|
|
|
} else if (output_type & kRepFloat64) {
|
|
|
|
op = machine()->TruncateFloat64ToFloat32();
|
|
|
|
} else {
|
|
|
|
return TypeError(node, output_type, kRepFloat32);
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
case IrOpcode::kFloat32Constant:
|
|
|
|
return jsgraph()->Float64Constant(OpParameter<float>(node));
|
|
|
|
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 if (output_type & kRepFloat32) {
|
|
|
|
op = machine()->ChangeFloat32ToFloat64();
|
|
|
|
} else {
|
|
|
|
return TypeError(node, output_type, kRepFloat64);
|
|
|
|
}
|
|
|
|
return jsgraph()->graph()->NewNode(op, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* MakeInt32Constant(double value) {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* GetTruncatedWord32For(Node* node, MachineTypeUnion output_type) {
|
|
|
|
// Eagerly fold truncations for constants.
|
|
|
|
switch (node->opcode()) {
|
|
|
|
case IrOpcode::kInt32Constant:
|
|
|
|
return node; // No change necessary.
|
|
|
|
case IrOpcode::kFloat32Constant:
|
|
|
|
return jsgraph()->Int32Constant(
|
|
|
|
DoubleToInt32(OpParameter<float>(node)));
|
|
|
|
case IrOpcode::kNumberConstant:
|
|
|
|
case IrOpcode::kFloat64Constant:
|
|
|
|
return jsgraph()->Int32Constant(
|
|
|
|
DoubleToInt32(OpParameter<double>(node)));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Select the correct X -> Word32 truncation operator.
|
|
|
|
const Operator* op = NULL;
|
|
|
|
if (output_type & kRepFloat64) {
|
|
|
|
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
|
|
|
} else if (output_type & kRepFloat32) {
|
|
|
|
node = InsertChangeFloat32ToFloat64(node);
|
|
|
|
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
|
|
|
} else if (output_type & kRepTagged) {
|
|
|
|
node = InsertChangeTaggedToFloat64(node);
|
|
|
|
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
|
|
|
|
} else {
|
|
|
|
return TypeError(node, output_type, kRepWord32);
|
|
|
|
}
|
|
|
|
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::kFloat32Constant:
|
|
|
|
return MakeInt32Constant(OpParameter<float>(node));
|
|
|
|
case IrOpcode::kNumberConstant:
|
|
|
|
case IrOpcode::kFloat64Constant:
|
|
|
|
return MakeInt32Constant(OpParameter<double>(node));
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Select the correct X -> Word32 operator.
|
|
|
|
const Operator* op;
|
|
|
|
if (output_type & kRepBit) {
|
|
|
|
return node; // Sloppy comparison -> word32
|
|
|
|
} else if (output_type & kRepFloat64) {
|
|
|
|
if (output_type & kTypeUint32 || use_unsigned) {
|
|
|
|
op = machine()->ChangeFloat64ToUint32();
|
|
|
|
} else {
|
|
|
|
op = machine()->ChangeFloat64ToInt32();
|
|
|
|
}
|
|
|
|
} else if (output_type & kRepFloat32) {
|
|
|
|
node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
|
|
|
|
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::kHeapConstant: {
|
|
|
|
Handle<Object> value = OpParameter<Unique<Object> >(node).handle();
|
|
|
|
DCHECK(value.is_identical_to(factory()->true_value()) ||
|
|
|
|
value.is_identical_to(factory()->false_value()));
|
|
|
|
return jsgraph()->Int32Constant(
|
|
|
|
value.is_identical_to(factory()->true_value()) ? 1 : 0);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Select the correct X -> Bit operator.
|
|
|
|
const Operator* op;
|
|
|
|
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()->Uint32Div();
|
|
|
|
case IrOpcode::kNumberModulus:
|
|
|
|
return machine()->Uint32Mod();
|
|
|
|
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_) {
|
|
|
|
std::ostringstream out_str;
|
|
|
|
out_str << static_cast<MachineType>(output_type);
|
|
|
|
|
|
|
|
std::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.str().c_str(),
|
|
|
|
use_str.str().c_str());
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* InsertChangeFloat32ToFloat64(Node* node) {
|
|
|
|
return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
|
|
|
|
node);
|
|
|
|
}
|
|
|
|
|
|
|
|
Node* InsertChangeTaggedToFloat64(Node* node) {
|
|
|
|
return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
|
|
|
|
node);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSGraph* jsgraph() const { return jsgraph_; }
|
|
|
|
Isolate* isolate() const { return isolate_; }
|
|
|
|
Factory* factory() const { return isolate()->factory(); }
|
|
|
|
SimplifiedOperatorBuilder* simplified() { return simplified_; }
|
|
|
|
MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace compiler
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_COMPILER_REPRESENTATION_CHANGE_H_
|