| 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 |