Index: src/compiler/simplified-lowering.cc |
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc |
index bf19aec68d28e0e7a3a6fdb6f5fcff8e2caf1ba1..4bfe1e27cac77a881951fc5020693ae9fc781d15 100644 |
--- a/src/compiler/simplified-lowering.cc |
+++ b/src/compiler/simplified-lowering.cc |
@@ -5,59 +5,190 @@ |
#include "src/compiler/simplified-lowering.h" |
#include "src/compiler/graph-inl.h" |
+#include "src/compiler/node-properties-inl.h" |
#include "src/objects.h" |
namespace v8 { |
namespace internal { |
namespace compiler { |
-Node* SimplifiedLowering::DoChangeTaggedToInt32(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+Node* SimplifiedLowering::IsTagged(Node* node) { |
+ // TODO(titzer): factor this out to a TaggingScheme abstraction. |
+ STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. |
+ return graph()->NewNode(machine()->WordAnd(), node, |
+ jsgraph()->Int32Constant(kSmiTagMask)); |
} |
-Node* SimplifiedLowering::DoChangeTaggedToUint32(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+Node* SimplifiedLowering::Untag(Node* node) { |
+ // TODO(titzer): factor this out to a TaggingScheme abstraction. |
+ Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
+ return graph()->NewNode(machine()->WordSar(), node, shift_amount); |
+} |
+ |
+ |
+Node* SimplifiedLowering::SmiTag(Node* node) { |
+ // TODO(titzer): factor this out to a TaggingScheme abstraction. |
+ Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
+ return graph()->NewNode(machine()->WordShl(), node, shift_amount); |
} |
-Node* SimplifiedLowering::DoChangeTaggedToFloat64(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+Node* SimplifiedLowering::OffsetMinusTagConstant(int32_t offset) { |
+ return jsgraph()->Int32Constant(offset - kHeapObjectTag); |
} |
-Node* SimplifiedLowering::DoChangeInt32ToTagged(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+static void UpdateControlSuccessors(Node* before, Node* node) { |
+ ASSERT(IrOpcode::IsControlOpcode(before->opcode())); |
+ UseIter iter = before->uses().begin(); |
+ while (iter != before->uses().end()) { |
+ if (IrOpcode::IsControlOpcode((*iter)->opcode()) && |
+ NodeProperties::IsControlEdge(iter.edge())) { |
+ iter = iter.UpdateToAndIncrement(node); |
+ continue; |
+ } |
+ ++iter; |
+ } |
} |
-Node* SimplifiedLowering::DoChangeUint32ToTagged(Node* node, Node* effect, |
+void SimplifiedLowering::DoChangeTaggedToUI32(Node* node, Node* effect, |
+ Node* control, bool is_signed) { |
+ // if (IsTagged(val)) |
+ // ConvertFloat64To(Int32|Uint32)(Load[kMachineFloat64](input, #value_offset)) |
+ // else Untag(val) |
+ Node* val = node->InputAt(0); |
+ Node* branch = graph()->NewNode(common()->Branch(), IsTagged(val), control); |
+ |
+ // true branch. |
+ Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* loaded = graph()->NewNode( |
+ machine()->Load(kMachineFloat64), val, |
+ OffsetMinusTagConstant(HeapNumber::kValueOffset), effect); |
+ Operator* op = is_signed ? machine()->ConvertFloat64ToInt32() |
+ : machine()->ConvertFloat64ToUint32(); |
+ Node* converted = graph()->NewNode(op, loaded); |
+ |
+ // false branch. |
+ Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* untagged = Untag(val); |
+ |
+ // merge. |
+ Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
+ Node* phi = graph()->NewNode(common()->Phi(2), converted, untagged, merge); |
+ UpdateControlSuccessors(control, merge); |
+ branch->ReplaceInput(1, control); |
+ node->ReplaceUses(phi); |
+} |
+ |
+ |
+void SimplifiedLowering::DoChangeTaggedToFloat64(Node* node, Node* effect, |
Node* control) { |
- return node; |
+ // if (IsTagged(input)) Load[kMachineFloat64](input, #value_offset) |
+ // else ConvertFloat64(Untag(input)) |
+ Node* val = node->InputAt(0); |
+ Node* branch = graph()->NewNode(common()->Branch(), IsTagged(val), control); |
+ |
+ // true branch. |
+ Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* loaded = graph()->NewNode( |
+ machine()->Load(kMachineFloat64), val, |
+ OffsetMinusTagConstant(HeapNumber::kValueOffset), effect); |
+ |
+ // false branch. |
+ Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* untagged = Untag(val); |
+ Node* converted = |
+ graph()->NewNode(machine()->ConvertInt32ToFloat64(), untagged); |
+ |
+ // merge. |
+ Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
+ Node* phi = graph()->NewNode(common()->Phi(2), loaded, converted, merge); |
+ UpdateControlSuccessors(control, merge); |
+ branch->ReplaceInput(1, control); |
+ node->ReplaceUses(phi); |
+} |
+ |
+ |
+void SimplifiedLowering::DoChangeUI32ToTagged(Node* node, Node* effect, |
+ Node* control, bool is_signed) { |
+ Node* val = node->InputAt(0); |
+ Node* is_smi = NULL; |
+ if (is_signed) { |
+ if (SmiValuesAre32Bits()) { |
+ // All int32s fit in this case. |
+ ASSERT(kPointerSize == 8); |
+ return node->ReplaceUses(SmiTag(val)); |
+ } else { |
+ // TODO(turbofan): use an Int32AddWithOverflow to tag and check here. |
+ Node* lt = graph()->NewNode(machine()->Int32LessThanOrEqual(), val, |
+ jsgraph()->Int32Constant(Smi::kMaxValue)); |
+ Node* gt = |
+ graph()->NewNode(machine()->Int32LessThanOrEqual(), |
+ jsgraph()->Int32Constant(Smi::kMinValue), val); |
+ is_smi = graph()->NewNode(machine()->Word32And(), lt, gt); |
+ } |
+ } else { |
+ // Check if Uint32 value is in the smi range. |
+ is_smi = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val, |
+ jsgraph()->Int32Constant(Smi::kMaxValue)); |
+ } |
+ |
+ // TODO(turbofan): fold smi test branch eagerly. |
+ // if (IsSmi(input)) SmiTag(input); |
+ // else InlineAllocAndInitHeapNumber(ConvertToFloat64(input))) |
+ Node* branch = graph()->NewNode(common()->Branch(), is_smi, control); |
+ |
+ // true branch. |
+ Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
+ Node* smi_tagged = SmiTag(val); |
+ |
+ // false branch. |
+ Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
+ Node* heap_num = jsgraph()->Constant(0.0); // TODO(titzer): alloc and init |
+ |
+ // merge. |
+ Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
+ Node* phi = graph()->NewNode(common()->Phi(2), smi_tagged, heap_num, merge); |
+ UpdateControlSuccessors(control, merge); |
+ branch->ReplaceInput(1, control); |
+ node->ReplaceUses(phi); |
} |
-Node* SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+void SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect, |
+ Node* control) { |
+ return; // TODO(titzer): need to call runtime to allocate in one branch |
} |
-Node* SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect, |
- Node* control) { |
+void SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect, |
+ Node* control) { |
Node* val = node->InputAt(0); |
- Operator* op = machine()->WordEqual(); |
- return graph()->NewNode(op, val, jsgraph()->TrueConstant()); |
+ Operator* op = |
+ kPointerSize == 8 ? machine()->Word64Equal() : machine()->Word32Equal(); |
+ Node* cmp = graph()->NewNode(op, val, jsgraph()->TrueConstant()); |
+ node->ReplaceUses(cmp); |
} |
-Node* SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect, |
- Node* control) { |
- return node; |
+void SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect, |
+ Node* control) { |
+ Node* val = node->InputAt(0); |
+ Node* branch = graph()->NewNode(common()->Branch(), val, control); |
+ |
+ // true branch. |
+ Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
+ // false branch. |
+ Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
+ // merge. |
+ Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
+ Node* phi = graph()->NewNode(common()->Phi(2), jsgraph()->TrueConstant(), |
+ jsgraph()->FalseConstant(), merge); |
+ UpdateControlSuccessors(control, merge); |
+ branch->ReplaceInput(1, control); |
+ node->ReplaceUses(phi); |
} |
@@ -71,18 +202,16 @@ static WriteBarrierKind ComputeWriteBarrierKind( |
} |
-Node* SimplifiedLowering::DoLoadField(Node* node, Node* effect, Node* control) { |
+void SimplifiedLowering::DoLoadField(Node* node, Node* effect, Node* control) { |
const FieldAccess& access = FieldAccessOf(node->op()); |
node->set_op(machine_.Load(access.representation)); |
Node* offset = |
graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); |
node->InsertInput(zone(), 1, offset); |
- return node; |
} |
-Node* SimplifiedLowering::DoStoreField(Node* node, Node* effect, |
- Node* control) { |
+void SimplifiedLowering::DoStoreField(Node* node, Node* effect, Node* control) { |
const FieldAccess& access = FieldAccessOf(node->op()); |
WriteBarrierKind kind = |
ComputeWriteBarrierKind(access.representation, access.type); |
@@ -90,7 +219,6 @@ Node* SimplifiedLowering::DoStoreField(Node* node, Node* effect, |
Node* offset = |
graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); |
node->InsertInput(zone(), 1, offset); |
- return node; |
} |
@@ -131,23 +259,21 @@ Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, |
} |
-Node* SimplifiedLowering::DoLoadElement(Node* node, Node* effect, |
- Node* control) { |
+void SimplifiedLowering::DoLoadElement(Node* node, Node* effect, |
+ Node* control) { |
const ElementAccess& access = ElementAccessOf(node->op()); |
node->set_op(machine_.Load(access.representation)); |
node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
- return node; |
} |
-Node* SimplifiedLowering::DoStoreElement(Node* node, Node* effect, |
- Node* control) { |
+void SimplifiedLowering::DoStoreElement(Node* node, Node* effect, |
+ Node* control) { |
const ElementAccess& access = ElementAccessOf(node->op()); |
WriteBarrierKind kind = |
ComputeWriteBarrierKind(access.representation, access.type); |
node->set_op(machine_.Store(access.representation, kind)); |
node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
- return node; |
} |
@@ -172,25 +298,25 @@ void SimplifiedLowering::Lower(Node* node) { |
case IrOpcode::kStringAdd: |
break; |
case IrOpcode::kChangeTaggedToInt32: |
- DoChangeTaggedToInt32(node, start, start); |
+ DoChangeTaggedToUI32(node, start, start, true); |
break; |
case IrOpcode::kChangeTaggedToUint32: |
- DoChangeTaggedToUint32(node, start, start); |
+ DoChangeTaggedToUI32(node, start, start, false); |
break; |
case IrOpcode::kChangeTaggedToFloat64: |
DoChangeTaggedToFloat64(node, start, start); |
break; |
case IrOpcode::kChangeInt32ToTagged: |
- DoChangeInt32ToTagged(node, start, start); |
+ DoChangeUI32ToTagged(node, start, start, true); |
break; |
case IrOpcode::kChangeUint32ToTagged: |
- DoChangeUint32ToTagged(node, start, start); |
+ DoChangeUI32ToTagged(node, start, start, false); |
break; |
case IrOpcode::kChangeFloat64ToTagged: |
DoChangeFloat64ToTagged(node, start, start); |
break; |
case IrOpcode::kChangeBoolToBit: |
- node->ReplaceUses(DoChangeBoolToBit(node, start, start)); |
+ DoChangeBoolToBit(node, start, start); |
break; |
case IrOpcode::kChangeBitToBool: |
DoChangeBitToBool(node, start, start); |