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/change-lowering.h" | 5 #include "src/compiler/change-lowering.h" |
6 | 6 |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 namespace compiler { | 11 namespace compiler { |
12 | 12 |
13 ChangeLowering::~ChangeLowering() {} | 13 ChangeLowering::~ChangeLowering() {} |
14 | 14 |
15 | 15 |
16 Reduction ChangeLowering::Reduce(Node* node) { | 16 Reduction ChangeLowering::Reduce(Node* node) { |
17 Node* control = graph()->start(); | 17 Node* control = graph()->start(); |
18 switch (node->opcode()) { | 18 switch (node->opcode()) { |
19 case IrOpcode::kChangeBitToBool: | 19 case IrOpcode::kChangeBitToBool: |
20 return ChangeBitToBool(node->InputAt(0), control); | 20 return ChangeBitToBool(node->InputAt(0), control); |
21 case IrOpcode::kChangeBoolToBit: | 21 case IrOpcode::kChangeBoolToBit: |
22 return ChangeBoolToBit(node->InputAt(0)); | 22 return ChangeBoolToBit(node->InputAt(0)); |
23 case IrOpcode::kChangeFloat64ToTagged: | 23 case IrOpcode::kChangeFloat64ToTagged: |
24 return ChangeFloat64ToTagged(node->InputAt(0), control); | 24 return ChangeFloat64ToTagged(node->InputAt(0), control); |
25 case IrOpcode::kChangeInt32ToTagged: | 25 case IrOpcode::kChangeInt32ToTagged: |
26 return ChangeInt32ToTagged(node->InputAt(0), control); | 26 return ChangeInt32ToTagged(node->InputAt(0), control); |
27 case IrOpcode::kChangeTaggedToFloat64: | 27 case IrOpcode::kChangeTaggedToFloat64: |
28 return ChangeTaggedToFloat64(node->InputAt(0), control); | 28 return ChangeTaggedToFloat64(node->InputAt(0), control); |
29 case IrOpcode::kChangeTaggedToInt32: | 29 case IrOpcode::kChangeTaggedToInt32: |
| 30 case IrOpcode::kChangeTaggedToUint32: |
| 31 // ToInt32 and ToUint32 perform exactly the same operation, just the |
| 32 // interpretation of the resulting 32 bit value is different, so we can |
| 33 // use the same subgraph for both operations. |
| 34 // See ECMA-262 9.5: ToInt32 and ECMA-262 9.6: ToUint32. |
30 return ChangeTaggedToInt32(node->InputAt(0), control); | 35 return ChangeTaggedToInt32(node->InputAt(0), control); |
31 case IrOpcode::kChangeUint32ToTagged: | 36 case IrOpcode::kChangeUint32ToTagged: |
32 return ChangeUint32ToTagged(node->InputAt(0), control); | 37 return ChangeUint32ToTagged(node->InputAt(0), control); |
33 default: | 38 default: |
34 return NoChange(); | 39 return NoChange(); |
35 } | 40 } |
36 UNREACHABLE(); | 41 UNREACHABLE(); |
37 return NoChange(); | 42 return NoChange(); |
38 } | 43 } |
39 | 44 |
(...skipping 26 matching lines...) Expand all Loading... |
66 // `v8::internal::SmiTagging<4u>::kSmiShiftSize' | 71 // `v8::internal::SmiTagging<4u>::kSmiShiftSize' |
67 // src/compiler/change-lowering.cc:46: undefined reference to | 72 // src/compiler/change-lowering.cc:46: undefined reference to |
68 // `v8::internal::SmiTagging<8u>::kSmiShiftSize' | 73 // `v8::internal::SmiTagging<8u>::kSmiShiftSize' |
69 STATIC_ASSERT(SmiTagging<4>::kSmiShiftSize == 0); | 74 STATIC_ASSERT(SmiTagging<4>::kSmiShiftSize == 0); |
70 STATIC_ASSERT(SmiTagging<8>::kSmiShiftSize == 31); | 75 STATIC_ASSERT(SmiTagging<8>::kSmiShiftSize == 31); |
71 const int smi_shift_size = machine()->is64() ? 31 : 0; | 76 const int smi_shift_size = machine()->is64() ? 31 : 0; |
72 return jsgraph()->Int32Constant(smi_shift_size + kSmiTagSize); | 77 return jsgraph()->Int32Constant(smi_shift_size + kSmiTagSize); |
73 } | 78 } |
74 | 79 |
75 | 80 |
| 81 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { |
| 82 // The AllocateHeapNumber() runtime function does not use the context, so we |
| 83 // can safely pass in Smi zero here. |
| 84 Node* context = jsgraph()->ZeroConstant(); |
| 85 Node* effect = graph()->NewNode(common()->ValueEffect(1), value); |
| 86 const Runtime::Function* function = |
| 87 Runtime::FunctionForId(Runtime::kAllocateHeapNumber); |
| 88 DCHECK_EQ(0, function->nargs); |
| 89 CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor( |
| 90 function->function_id, 0, Operator::kNoProperties); |
| 91 Node* heap_number = graph()->NewNode( |
| 92 common()->Call(desc), jsgraph()->CEntryStubConstant(), |
| 93 jsgraph()->ExternalConstant(ExternalReference(function, isolate())), |
| 94 jsgraph()->Int32Constant(function->nargs), context, effect, control); |
| 95 Node* store = graph()->NewNode( |
| 96 machine()->Store(kMachFloat64, kNoWriteBarrier), heap_number, |
| 97 HeapNumberValueIndexConstant(), value, heap_number, control); |
| 98 return graph()->NewNode(common()->Finish(1), heap_number, store); |
| 99 } |
| 100 |
| 101 |
| 102 Node* ChangeLowering::ChangeSmiToInt32(Node* value) { |
| 103 value = graph()->NewNode(machine()->WordSar(), value, SmiShiftBitsConstant()); |
| 104 if (machine()->is64()) { |
| 105 value = graph()->NewNode(machine()->TruncateInt64ToInt32(), value); |
| 106 } |
| 107 return value; |
| 108 } |
| 109 |
| 110 |
| 111 Node* ChangeLowering::LoadHeapNumberValue(Node* value, Node* control) { |
| 112 return graph()->NewNode(machine()->Load(kMachFloat64), value, |
| 113 HeapNumberValueIndexConstant(), |
| 114 graph()->NewNode(common()->ControlEffect(), control)); |
| 115 } |
| 116 |
| 117 |
76 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) { | 118 Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) { |
77 Node* branch = graph()->NewNode(common()->Branch(), val, control); | 119 Node* branch = graph()->NewNode(common()->Branch(), val, control); |
78 | 120 |
79 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 121 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
80 Node* true_value = jsgraph()->TrueConstant(); | 122 Node* true_value = jsgraph()->TrueConstant(); |
81 | 123 |
82 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 124 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
83 Node* false_value = jsgraph()->FalseConstant(); | 125 Node* false_value = jsgraph()->FalseConstant(); |
84 | 126 |
85 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 127 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 | 172 |
131 Reduction ChangeLowering::ChangeTaggedToInt32(Node* val, Node* control) { | 173 Reduction ChangeLowering::ChangeTaggedToInt32(Node* val, Node* control) { |
132 STATIC_ASSERT(kSmiTag == 0); | 174 STATIC_ASSERT(kSmiTag == 0); |
133 STATIC_ASSERT(kSmiTagMask == 1); | 175 STATIC_ASSERT(kSmiTagMask == 1); |
134 | 176 |
135 Node* tag = graph()->NewNode(machine()->WordAnd(), val, | 177 Node* tag = graph()->NewNode(machine()->WordAnd(), val, |
136 jsgraph()->Int32Constant(kSmiTagMask)); | 178 jsgraph()->Int32Constant(kSmiTagMask)); |
137 Node* branch = graph()->NewNode(common()->Branch(), tag, control); | 179 Node* branch = graph()->NewNode(common()->Branch(), tag, control); |
138 | 180 |
139 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 181 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
140 Node* load = graph()->NewNode( | 182 Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(), |
141 machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(), | 183 LoadHeapNumberValue(val, if_true)); |
142 graph()->NewNode(common()->ControlEffect(), if_true)); | |
143 Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(), load); | |
144 | 184 |
145 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 185 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
146 Node* integer = | 186 Node* number = ChangeSmiToInt32(val); |
147 graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant()); | |
148 Node* number = | |
149 machine()->is64() | |
150 ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer) | |
151 : integer; | |
152 | 187 |
153 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 188 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
154 Node* phi = graph()->NewNode(common()->Phi(2), change, number, merge); | 189 Node* phi = graph()->NewNode(common()->Phi(2), change, number, merge); |
155 | 190 |
156 return Replace(phi); | 191 return Replace(phi); |
157 } | 192 } |
158 | 193 |
159 | 194 |
160 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) { | 195 Reduction ChangeLowering::ChangeTaggedToFloat64(Node* val, Node* control) { |
161 STATIC_ASSERT(kSmiTag == 0); | 196 STATIC_ASSERT(kSmiTag == 0); |
162 STATIC_ASSERT(kSmiTagMask == 1); | 197 STATIC_ASSERT(kSmiTagMask == 1); |
163 | 198 |
164 Node* tag = graph()->NewNode(machine()->WordAnd(), val, | 199 Node* tag = graph()->NewNode(machine()->WordAnd(), val, |
165 jsgraph()->Int32Constant(kSmiTagMask)); | 200 jsgraph()->Int32Constant(kSmiTagMask)); |
166 Node* branch = graph()->NewNode(common()->Branch(), tag, control); | 201 Node* branch = graph()->NewNode(common()->Branch(), tag, control); |
167 | 202 |
168 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | 203 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); |
169 Node* load = graph()->NewNode( | 204 Node* load = LoadHeapNumberValue(val, if_true); |
170 machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(), | |
171 graph()->NewNode(common()->ControlEffect(), if_true)); | |
172 | 205 |
173 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 206 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
174 Node* integer = | 207 Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(), |
175 graph()->NewNode(machine()->WordSar(), val, SmiShiftBitsConstant()); | 208 ChangeSmiToInt32(val)); |
176 Node* number = graph()->NewNode( | |
177 machine()->ChangeInt32ToFloat64(), | |
178 machine()->is64() | |
179 ? graph()->NewNode(machine()->TruncateInt64ToInt32(), integer) | |
180 : integer); | |
181 | 209 |
182 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); | 210 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false); |
183 Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge); | 211 Node* phi = graph()->NewNode(common()->Phi(2), load, number, merge); |
184 | 212 |
185 return Replace(phi); | 213 return Replace(phi); |
186 } | 214 } |
187 | 215 |
188 | 216 |
189 Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) { | 217 Reduction ChangeLowering::ChangeUint32ToTagged(Node* val, Node* control) { |
190 STATIC_ASSERT(kSmiTag == 0); | 218 STATIC_ASSERT(kSmiTag == 0); |
(...skipping 25 matching lines...) Expand all Loading... |
216 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } | 244 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } |
217 | 245 |
218 | 246 |
219 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } | 247 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } |
220 | 248 |
221 | 249 |
222 CommonOperatorBuilder* ChangeLowering::common() const { | 250 CommonOperatorBuilder* ChangeLowering::common() const { |
223 return jsgraph()->common(); | 251 return jsgraph()->common(); |
224 } | 252 } |
225 | 253 |
226 | |
227 Node* ChangeLowering::AllocateHeapNumberWithValue(Node* value, Node* control) { | |
228 // The AllocateHeapNumber() runtime function does not use the context, so we | |
229 // can safely pass in Smi zero here. | |
230 Node* context = jsgraph()->ZeroConstant(); | |
231 Node* effect = graph()->NewNode(common()->ValueEffect(1), value); | |
232 const Runtime::Function* function = | |
233 Runtime::FunctionForId(Runtime::kAllocateHeapNumber); | |
234 DCHECK_EQ(0, function->nargs); | |
235 CallDescriptor* desc = linkage()->GetRuntimeCallDescriptor( | |
236 function->function_id, 0, Operator::kNoProperties); | |
237 Node* heap_number = graph()->NewNode( | |
238 common()->Call(desc), jsgraph()->CEntryStubConstant(), | |
239 jsgraph()->ExternalConstant(ExternalReference(function, isolate())), | |
240 jsgraph()->Int32Constant(function->nargs), context, effect, control); | |
241 Node* store = graph()->NewNode( | |
242 machine()->Store(kMachFloat64, kNoWriteBarrier), heap_number, | |
243 HeapNumberValueIndexConstant(), value, heap_number, control); | |
244 return graph()->NewNode(common()->Finish(1), heap_number, store); | |
245 } | |
246 | |
247 } // namespace compiler | 254 } // namespace compiler |
248 } // namespace internal | 255 } // namespace internal |
249 } // namespace v8 | 256 } // namespace v8 |
OLD | NEW |