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 |