| OLD | NEW |
| 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 #include "src/compiler/simplified-lowering.h" | 5 #include "src/compiler/simplified-lowering.h" |
| 6 | 6 |
| 7 #include "src/compiler/graph-inl.h" | 7 #include "src/compiler/graph-inl.h" |
| 8 #include "src/compiler/node-properties-inl.h" |
| 8 #include "src/objects.h" | 9 #include "src/objects.h" |
| 9 | 10 |
| 10 namespace v8 { | 11 namespace v8 { |
| 11 namespace internal { | 12 namespace internal { |
| 12 namespace compiler { | 13 namespace compiler { |
| 13 | 14 |
| 14 Node* SimplifiedLowering::DoChangeTaggedToInt32(Node* node, Node* effect, | 15 Node* SimplifiedLowering::IsTagged(Node* node) { |
| 15 Node* control) { | 16 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 16 return node; | 17 STATIC_ASSERT(kSmiTagMask == 1); // Only works if tag is the low bit. |
| 18 return graph()->NewNode(machine()->WordAnd(), node, |
| 19 jsgraph()->Int32Constant(kSmiTagMask)); |
| 17 } | 20 } |
| 18 | 21 |
| 19 | 22 |
| 20 Node* SimplifiedLowering::DoChangeTaggedToUint32(Node* node, Node* effect, | 23 Node* SimplifiedLowering::Untag(Node* node) { |
| 21 Node* control) { | 24 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 22 return node; | 25 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
| 26 return graph()->NewNode(machine()->WordSar(), node, shift_amount); |
| 23 } | 27 } |
| 24 | 28 |
| 25 | 29 |
| 26 Node* SimplifiedLowering::DoChangeTaggedToFloat64(Node* node, Node* effect, | 30 Node* SimplifiedLowering::SmiTag(Node* node) { |
| 27 Node* control) { | 31 // TODO(titzer): factor this out to a TaggingScheme abstraction. |
| 28 return node; | 32 Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize); |
| 33 return graph()->NewNode(machine()->WordShl(), node, shift_amount); |
| 29 } | 34 } |
| 30 | 35 |
| 31 | 36 |
| 32 Node* SimplifiedLowering::DoChangeInt32ToTagged(Node* node, Node* effect, | 37 Node* SimplifiedLowering::OffsetMinusTagConstant(int32_t offset) { |
| 33 Node* control) { | 38 return jsgraph()->Int32Constant(offset - kHeapObjectTag); |
| 34 return node; | |
| 35 } | 39 } |
| 36 | 40 |
| 37 | 41 |
| 38 Node* SimplifiedLowering::DoChangeUint32ToTagged(Node* node, Node* effect, | 42 static void UpdateControlSuccessors(Node* before, Node* node) { |
| 39 Node* control) { | 43 ASSERT(IrOpcode::IsControlOpcode(before->opcode())); |
| 40 return node; | 44 UseIter iter = before->uses().begin(); |
| 45 while (iter != before->uses().end()) { |
| 46 if (IrOpcode::IsControlOpcode((*iter)->opcode()) && |
| 47 NodeProperties::IsControlEdge(iter.edge())) { |
| 48 iter = iter.UpdateToAndIncrement(node); |
| 49 continue; |
| 50 } |
| 51 ++iter; |
| 52 } |
| 41 } | 53 } |
| 42 | 54 |
| 43 | 55 |
| 44 Node* SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect, | 56 void SimplifiedLowering::DoChangeTaggedToUI32(Node* node, Node* effect, |
| 45 Node* control) { | 57 Node* control, bool is_signed) { |
| 46 return node; | 58 // if (IsTagged(val)) |
| 59 // ConvertFloat64To(Int32|Uint32)(Load[kMachineFloat64](input, #value_offset)) |
| 60 // else Untag(val) |
| 61 Node* val = node->InputAt(0); |
| 62 Node* branch = graph()->NewNode(common()->Branch(), IsTagged(val), control); |
| 63 |
| 64 // true branch. |
| 65 Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
| 66 Node* loaded = graph()->NewNode( |
| 67 machine()->Load(kMachineFloat64), val, |
| 68 OffsetMinusTagConstant(HeapNumber::kValueOffset), effect); |
| 69 Operator* op = is_signed ? machine()->ConvertFloat64ToInt32() |
| 70 : machine()->ConvertFloat64ToUint32(); |
| 71 Node* converted = graph()->NewNode(op, loaded); |
| 72 |
| 73 // false branch. |
| 74 Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
| 75 Node* untagged = Untag(val); |
| 76 |
| 77 // merge. |
| 78 Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
| 79 Node* phi = graph()->NewNode(common()->Phi(2), converted, untagged, merge); |
| 80 UpdateControlSuccessors(control, merge); |
| 81 branch->ReplaceInput(1, control); |
| 82 node->ReplaceUses(phi); |
| 47 } | 83 } |
| 48 | 84 |
| 49 | 85 |
| 50 Node* SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect, | 86 void SimplifiedLowering::DoChangeTaggedToFloat64(Node* node, Node* effect, |
| 51 Node* control) { | 87 Node* control) { |
| 88 // if (IsTagged(input)) Load[kMachineFloat64](input, #value_offset) |
| 89 // else ConvertFloat64(Untag(input)) |
| 52 Node* val = node->InputAt(0); | 90 Node* val = node->InputAt(0); |
| 53 Operator* op = machine()->WordEqual(); | 91 Node* branch = graph()->NewNode(common()->Branch(), IsTagged(val), control); |
| 54 return graph()->NewNode(op, val, jsgraph()->TrueConstant()); | 92 |
| 93 // true branch. |
| 94 Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
| 95 Node* loaded = graph()->NewNode( |
| 96 machine()->Load(kMachineFloat64), val, |
| 97 OffsetMinusTagConstant(HeapNumber::kValueOffset), effect); |
| 98 |
| 99 // false branch. |
| 100 Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
| 101 Node* untagged = Untag(val); |
| 102 Node* converted = |
| 103 graph()->NewNode(machine()->ConvertInt32ToFloat64(), untagged); |
| 104 |
| 105 // merge. |
| 106 Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
| 107 Node* phi = graph()->NewNode(common()->Phi(2), loaded, converted, merge); |
| 108 UpdateControlSuccessors(control, merge); |
| 109 branch->ReplaceInput(1, control); |
| 110 node->ReplaceUses(phi); |
| 55 } | 111 } |
| 56 | 112 |
| 57 | 113 |
| 58 Node* SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect, | 114 void SimplifiedLowering::DoChangeUI32ToTagged(Node* node, Node* effect, |
| 59 Node* control) { | 115 Node* control, bool is_signed) { |
| 60 return node; | 116 Node* val = node->InputAt(0); |
| 117 Node* is_smi = NULL; |
| 118 if (is_signed) { |
| 119 if (SmiValuesAre32Bits()) { |
| 120 // All int32s fit in this case. |
| 121 ASSERT(kPointerSize == 8); |
| 122 return node->ReplaceUses(SmiTag(val)); |
| 123 } else { |
| 124 // TODO(turbofan): use an Int32AddWithOverflow to tag and check here. |
| 125 Node* lt = graph()->NewNode(machine()->Int32LessThanOrEqual(), val, |
| 126 jsgraph()->Int32Constant(Smi::kMaxValue)); |
| 127 Node* gt = |
| 128 graph()->NewNode(machine()->Int32LessThanOrEqual(), |
| 129 jsgraph()->Int32Constant(Smi::kMinValue), val); |
| 130 is_smi = graph()->NewNode(machine()->Word32And(), lt, gt); |
| 131 } |
| 132 } else { |
| 133 // Check if Uint32 value is in the smi range. |
| 134 is_smi = graph()->NewNode(machine()->Uint32LessThanOrEqual(), val, |
| 135 jsgraph()->Int32Constant(Smi::kMaxValue)); |
| 136 } |
| 137 |
| 138 // TODO(turbofan): fold smi test branch eagerly. |
| 139 // if (IsSmi(input)) SmiTag(input); |
| 140 // else InlineAllocAndInitHeapNumber(ConvertToFloat64(input))) |
| 141 Node* branch = graph()->NewNode(common()->Branch(), is_smi, control); |
| 142 |
| 143 // true branch. |
| 144 Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
| 145 Node* smi_tagged = SmiTag(val); |
| 146 |
| 147 // false branch. |
| 148 Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
| 149 Node* heap_num = jsgraph()->Constant(0.0); // TODO(titzer): alloc and init |
| 150 |
| 151 // merge. |
| 152 Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
| 153 Node* phi = graph()->NewNode(common()->Phi(2), smi_tagged, heap_num, merge); |
| 154 UpdateControlSuccessors(control, merge); |
| 155 branch->ReplaceInput(1, control); |
| 156 node->ReplaceUses(phi); |
| 61 } | 157 } |
| 62 | 158 |
| 63 | 159 |
| 160 void SimplifiedLowering::DoChangeFloat64ToTagged(Node* node, Node* effect, |
| 161 Node* control) { |
| 162 return; // TODO(titzer): need to call runtime to allocate in one branch |
| 163 } |
| 164 |
| 165 |
| 166 void SimplifiedLowering::DoChangeBoolToBit(Node* node, Node* effect, |
| 167 Node* control) { |
| 168 Node* val = node->InputAt(0); |
| 169 Operator* op = |
| 170 kPointerSize == 8 ? machine()->Word64Equal() : machine()->Word32Equal(); |
| 171 Node* cmp = graph()->NewNode(op, val, jsgraph()->TrueConstant()); |
| 172 node->ReplaceUses(cmp); |
| 173 } |
| 174 |
| 175 |
| 176 void SimplifiedLowering::DoChangeBitToBool(Node* node, Node* effect, |
| 177 Node* control) { |
| 178 Node* val = node->InputAt(0); |
| 179 Node* branch = graph()->NewNode(common()->Branch(), val, control); |
| 180 |
| 181 // true branch. |
| 182 Node* tbranch = graph()->NewNode(common()->IfTrue(), branch); |
| 183 // false branch. |
| 184 Node* fbranch = graph()->NewNode(common()->IfFalse(), branch); |
| 185 // merge. |
| 186 Node* merge = graph()->NewNode(common()->Merge(2), tbranch, fbranch); |
| 187 Node* phi = graph()->NewNode(common()->Phi(2), jsgraph()->TrueConstant(), |
| 188 jsgraph()->FalseConstant(), merge); |
| 189 UpdateControlSuccessors(control, merge); |
| 190 branch->ReplaceInput(1, control); |
| 191 node->ReplaceUses(phi); |
| 192 } |
| 193 |
| 194 |
| 64 static WriteBarrierKind ComputeWriteBarrierKind( | 195 static WriteBarrierKind ComputeWriteBarrierKind( |
| 65 MachineRepresentation representation, Type* type) { | 196 MachineRepresentation representation, Type* type) { |
| 66 // TODO(turbofan): skip write barriers for Smis, etc. | 197 // TODO(turbofan): skip write barriers for Smis, etc. |
| 67 if (representation == kMachineTagged) { | 198 if (representation == kMachineTagged) { |
| 68 return kFullWriteBarrier; | 199 return kFullWriteBarrier; |
| 69 } | 200 } |
| 70 return kNoWriteBarrier; | 201 return kNoWriteBarrier; |
| 71 } | 202 } |
| 72 | 203 |
| 73 | 204 |
| 74 Node* SimplifiedLowering::DoLoadField(Node* node, Node* effect, Node* control) { | 205 void SimplifiedLowering::DoLoadField(Node* node, Node* effect, Node* control) { |
| 75 const FieldAccess& access = FieldAccessOf(node->op()); | 206 const FieldAccess& access = FieldAccessOf(node->op()); |
| 76 node->set_op(machine_.Load(access.representation)); | 207 node->set_op(machine_.Load(access.representation)); |
| 77 Node* offset = | 208 Node* offset = |
| 78 graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); | 209 graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); |
| 79 node->InsertInput(zone(), 1, offset); | 210 node->InsertInput(zone(), 1, offset); |
| 80 return node; | |
| 81 } | 211 } |
| 82 | 212 |
| 83 | 213 |
| 84 Node* SimplifiedLowering::DoStoreField(Node* node, Node* effect, | 214 void SimplifiedLowering::DoStoreField(Node* node, Node* effect, Node* control) { |
| 85 Node* control) { | |
| 86 const FieldAccess& access = FieldAccessOf(node->op()); | 215 const FieldAccess& access = FieldAccessOf(node->op()); |
| 87 WriteBarrierKind kind = | 216 WriteBarrierKind kind = |
| 88 ComputeWriteBarrierKind(access.representation, access.type); | 217 ComputeWriteBarrierKind(access.representation, access.type); |
| 89 node->set_op(machine_.Store(access.representation, kind)); | 218 node->set_op(machine_.Store(access.representation, kind)); |
| 90 Node* offset = | 219 Node* offset = |
| 91 graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); | 220 graph()->NewNode(common()->Int32Constant(access.offset - kHeapObjectTag)); |
| 92 node->InsertInput(zone(), 1, offset); | 221 node->InsertInput(zone(), 1, offset); |
| 93 return node; | |
| 94 } | 222 } |
| 95 | 223 |
| 96 | 224 |
| 97 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, | 225 Node* SimplifiedLowering::ComputeIndex(const ElementAccess& access, |
| 98 Node* index) { | 226 Node* index) { |
| 99 int element_size = 0; | 227 int element_size = 0; |
| 100 switch (access.representation) { | 228 switch (access.representation) { |
| 101 case kMachineTagged: | 229 case kMachineTagged: |
| 102 element_size = kPointerSize; | 230 element_size = kPointerSize; |
| 103 break; | 231 break; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 124 graph()->NewNode(common()->Int32Constant(element_size)), index); | 252 graph()->NewNode(common()->Int32Constant(element_size)), index); |
| 125 } | 253 } |
| 126 int fixed_offset = access.header_size - kHeapObjectTag; | 254 int fixed_offset = access.header_size - kHeapObjectTag; |
| 127 if (fixed_offset == 0) return index; | 255 if (fixed_offset == 0) return index; |
| 128 return graph()->NewNode( | 256 return graph()->NewNode( |
| 129 machine()->Int32Add(), | 257 machine()->Int32Add(), |
| 130 graph()->NewNode(common()->Int32Constant(fixed_offset)), index); | 258 graph()->NewNode(common()->Int32Constant(fixed_offset)), index); |
| 131 } | 259 } |
| 132 | 260 |
| 133 | 261 |
| 134 Node* SimplifiedLowering::DoLoadElement(Node* node, Node* effect, | 262 void SimplifiedLowering::DoLoadElement(Node* node, Node* effect, |
| 135 Node* control) { | 263 Node* control) { |
| 136 const ElementAccess& access = ElementAccessOf(node->op()); | 264 const ElementAccess& access = ElementAccessOf(node->op()); |
| 137 node->set_op(machine_.Load(access.representation)); | 265 node->set_op(machine_.Load(access.representation)); |
| 138 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); | 266 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
| 139 return node; | |
| 140 } | 267 } |
| 141 | 268 |
| 142 | 269 |
| 143 Node* SimplifiedLowering::DoStoreElement(Node* node, Node* effect, | 270 void SimplifiedLowering::DoStoreElement(Node* node, Node* effect, |
| 144 Node* control) { | 271 Node* control) { |
| 145 const ElementAccess& access = ElementAccessOf(node->op()); | 272 const ElementAccess& access = ElementAccessOf(node->op()); |
| 146 WriteBarrierKind kind = | 273 WriteBarrierKind kind = |
| 147 ComputeWriteBarrierKind(access.representation, access.type); | 274 ComputeWriteBarrierKind(access.representation, access.type); |
| 148 node->set_op(machine_.Store(access.representation, kind)); | 275 node->set_op(machine_.Store(access.representation, kind)); |
| 149 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); | 276 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); |
| 150 return node; | |
| 151 } | 277 } |
| 152 | 278 |
| 153 | 279 |
| 154 void SimplifiedLowering::Lower(Node* node) { | 280 void SimplifiedLowering::Lower(Node* node) { |
| 155 Node* start = graph()->start(); | 281 Node* start = graph()->start(); |
| 156 switch (node->opcode()) { | 282 switch (node->opcode()) { |
| 157 case IrOpcode::kBooleanNot: | 283 case IrOpcode::kBooleanNot: |
| 158 case IrOpcode::kNumberEqual: | 284 case IrOpcode::kNumberEqual: |
| 159 case IrOpcode::kNumberLessThan: | 285 case IrOpcode::kNumberLessThan: |
| 160 case IrOpcode::kNumberLessThanOrEqual: | 286 case IrOpcode::kNumberLessThanOrEqual: |
| 161 case IrOpcode::kNumberAdd: | 287 case IrOpcode::kNumberAdd: |
| 162 case IrOpcode::kNumberSubtract: | 288 case IrOpcode::kNumberSubtract: |
| 163 case IrOpcode::kNumberMultiply: | 289 case IrOpcode::kNumberMultiply: |
| 164 case IrOpcode::kNumberDivide: | 290 case IrOpcode::kNumberDivide: |
| 165 case IrOpcode::kNumberModulus: | 291 case IrOpcode::kNumberModulus: |
| 166 case IrOpcode::kNumberToInt32: | 292 case IrOpcode::kNumberToInt32: |
| 167 case IrOpcode::kNumberToUint32: | 293 case IrOpcode::kNumberToUint32: |
| 168 case IrOpcode::kReferenceEqual: | 294 case IrOpcode::kReferenceEqual: |
| 169 case IrOpcode::kStringEqual: | 295 case IrOpcode::kStringEqual: |
| 170 case IrOpcode::kStringLessThan: | 296 case IrOpcode::kStringLessThan: |
| 171 case IrOpcode::kStringLessThanOrEqual: | 297 case IrOpcode::kStringLessThanOrEqual: |
| 172 case IrOpcode::kStringAdd: | 298 case IrOpcode::kStringAdd: |
| 173 break; | 299 break; |
| 174 case IrOpcode::kChangeTaggedToInt32: | 300 case IrOpcode::kChangeTaggedToInt32: |
| 175 DoChangeTaggedToInt32(node, start, start); | 301 DoChangeTaggedToUI32(node, start, start, true); |
| 176 break; | 302 break; |
| 177 case IrOpcode::kChangeTaggedToUint32: | 303 case IrOpcode::kChangeTaggedToUint32: |
| 178 DoChangeTaggedToUint32(node, start, start); | 304 DoChangeTaggedToUI32(node, start, start, false); |
| 179 break; | 305 break; |
| 180 case IrOpcode::kChangeTaggedToFloat64: | 306 case IrOpcode::kChangeTaggedToFloat64: |
| 181 DoChangeTaggedToFloat64(node, start, start); | 307 DoChangeTaggedToFloat64(node, start, start); |
| 182 break; | 308 break; |
| 183 case IrOpcode::kChangeInt32ToTagged: | 309 case IrOpcode::kChangeInt32ToTagged: |
| 184 DoChangeInt32ToTagged(node, start, start); | 310 DoChangeUI32ToTagged(node, start, start, true); |
| 185 break; | 311 break; |
| 186 case IrOpcode::kChangeUint32ToTagged: | 312 case IrOpcode::kChangeUint32ToTagged: |
| 187 DoChangeUint32ToTagged(node, start, start); | 313 DoChangeUI32ToTagged(node, start, start, false); |
| 188 break; | 314 break; |
| 189 case IrOpcode::kChangeFloat64ToTagged: | 315 case IrOpcode::kChangeFloat64ToTagged: |
| 190 DoChangeFloat64ToTagged(node, start, start); | 316 DoChangeFloat64ToTagged(node, start, start); |
| 191 break; | 317 break; |
| 192 case IrOpcode::kChangeBoolToBit: | 318 case IrOpcode::kChangeBoolToBit: |
| 193 node->ReplaceUses(DoChangeBoolToBit(node, start, start)); | 319 DoChangeBoolToBit(node, start, start); |
| 194 break; | 320 break; |
| 195 case IrOpcode::kChangeBitToBool: | 321 case IrOpcode::kChangeBitToBool: |
| 196 DoChangeBitToBool(node, start, start); | 322 DoChangeBitToBool(node, start, start); |
| 197 break; | 323 break; |
| 198 case IrOpcode::kLoadField: | 324 case IrOpcode::kLoadField: |
| 199 DoLoadField(node, start, start); | 325 DoLoadField(node, start, start); |
| 200 break; | 326 break; |
| 201 case IrOpcode::kStoreField: | 327 case IrOpcode::kStoreField: |
| 202 DoStoreField(node, start, start); | 328 DoStoreField(node, start, start); |
| 203 break; | 329 break; |
| 204 case IrOpcode::kLoadElement: | 330 case IrOpcode::kLoadElement: |
| 205 DoLoadElement(node, start, start); | 331 DoLoadElement(node, start, start); |
| 206 break; | 332 break; |
| 207 case IrOpcode::kStoreElement: | 333 case IrOpcode::kStoreElement: |
| 208 DoStoreElement(node, start, start); | 334 DoStoreElement(node, start, start); |
| 209 break; | 335 break; |
| 210 default: | 336 default: |
| 211 break; | 337 break; |
| 212 } | 338 } |
| 213 } | 339 } |
| 214 | 340 |
| 215 } // namespace compiler | 341 } // namespace compiler |
| 216 } // namespace internal | 342 } // namespace internal |
| 217 } // namespace v8 | 343 } // namespace v8 |
| OLD | NEW |