| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/compiler/change-lowering.h" | |
| 6 | |
| 7 #include "src/compiler/js-graph.h" | |
| 8 #include "src/compiler/linkage.h" | |
| 9 #include "src/compiler/machine-operator.h" | |
| 10 #include "src/compiler/node-properties.h" | |
| 11 #include "src/compiler/simplified-operator.h" | |
| 12 | |
| 13 namespace v8 { | |
| 14 namespace internal { | |
| 15 namespace compiler { | |
| 16 | |
| 17 ChangeLowering::~ChangeLowering() {} | |
| 18 | |
| 19 | |
| 20 Reduction ChangeLowering::Reduce(Node* node) { | |
| 21 switch (node->opcode()) { | |
| 22 case IrOpcode::kLoadField: | |
| 23 return ReduceLoadField(node); | |
| 24 case IrOpcode::kStoreField: | |
| 25 return ReduceStoreField(node); | |
| 26 case IrOpcode::kLoadElement: | |
| 27 return ReduceLoadElement(node); | |
| 28 case IrOpcode::kStoreElement: | |
| 29 return ReduceStoreElement(node); | |
| 30 case IrOpcode::kAllocate: | |
| 31 return ReduceAllocate(node); | |
| 32 default: | |
| 33 return NoChange(); | |
| 34 } | |
| 35 UNREACHABLE(); | |
| 36 return NoChange(); | |
| 37 } | |
| 38 | |
| 39 Reduction ChangeLowering::ReduceLoadField(Node* node) { | |
| 40 const FieldAccess& access = FieldAccessOf(node->op()); | |
| 41 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); | |
| 42 node->InsertInput(graph()->zone(), 1, offset); | |
| 43 NodeProperties::ChangeOp(node, machine()->Load(access.machine_type)); | |
| 44 return Changed(node); | |
| 45 } | |
| 46 | |
| 47 Reduction ChangeLowering::ReduceStoreField(Node* node) { | |
| 48 const FieldAccess& access = FieldAccessOf(node->op()); | |
| 49 Node* offset = jsgraph()->IntPtrConstant(access.offset - access.tag()); | |
| 50 node->InsertInput(graph()->zone(), 1, offset); | |
| 51 NodeProperties::ChangeOp(node, machine()->Store(StoreRepresentation( | |
| 52 access.machine_type.representation(), | |
| 53 access.write_barrier_kind))); | |
| 54 return Changed(node); | |
| 55 } | |
| 56 | |
| 57 | |
| 58 Node* ChangeLowering::ComputeIndex(const ElementAccess& access, | |
| 59 Node* const key) { | |
| 60 Node* index = key; | |
| 61 const int element_size_shift = | |
| 62 ElementSizeLog2Of(access.machine_type.representation()); | |
| 63 if (element_size_shift) { | |
| 64 index = graph()->NewNode(machine()->Word32Shl(), index, | |
| 65 jsgraph()->Int32Constant(element_size_shift)); | |
| 66 } | |
| 67 const int fixed_offset = access.header_size - access.tag(); | |
| 68 if (fixed_offset) { | |
| 69 index = graph()->NewNode(machine()->Int32Add(), index, | |
| 70 jsgraph()->Int32Constant(fixed_offset)); | |
| 71 } | |
| 72 if (machine()->Is64()) { | |
| 73 // TODO(turbofan): This is probably only correct for typed arrays, and only | |
| 74 // if the typed arrays are at most 2GiB in size, which happens to match | |
| 75 // exactly our current situation. | |
| 76 index = graph()->NewNode(machine()->ChangeUint32ToUint64(), index); | |
| 77 } | |
| 78 return index; | |
| 79 } | |
| 80 | |
| 81 Reduction ChangeLowering::ReduceLoadElement(Node* node) { | |
| 82 const ElementAccess& access = ElementAccessOf(node->op()); | |
| 83 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); | |
| 84 NodeProperties::ChangeOp(node, machine()->Load(access.machine_type)); | |
| 85 return Changed(node); | |
| 86 } | |
| 87 | |
| 88 Reduction ChangeLowering::ReduceStoreElement(Node* node) { | |
| 89 const ElementAccess& access = ElementAccessOf(node->op()); | |
| 90 node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1))); | |
| 91 NodeProperties::ChangeOp(node, machine()->Store(StoreRepresentation( | |
| 92 access.machine_type.representation(), | |
| 93 access.write_barrier_kind))); | |
| 94 return Changed(node); | |
| 95 } | |
| 96 | |
| 97 Reduction ChangeLowering::ReduceAllocate(Node* node) { | |
| 98 PretenureFlag const pretenure = OpParameter<PretenureFlag>(node->op()); | |
| 99 | |
| 100 Node* size = node->InputAt(0); | |
| 101 Node* effect = node->InputAt(1); | |
| 102 Node* control = node->InputAt(2); | |
| 103 | |
| 104 if (machine()->Is64()) { | |
| 105 size = graph()->NewNode(machine()->ChangeInt32ToInt64(), size); | |
| 106 } | |
| 107 | |
| 108 Node* top_address = jsgraph()->ExternalConstant( | |
| 109 pretenure == NOT_TENURED | |
| 110 ? ExternalReference::new_space_allocation_top_address(isolate()) | |
| 111 : ExternalReference::old_space_allocation_top_address(isolate())); | |
| 112 Node* limit_address = jsgraph()->ExternalConstant( | |
| 113 pretenure == NOT_TENURED | |
| 114 ? ExternalReference::new_space_allocation_limit_address(isolate()) | |
| 115 : ExternalReference::old_space_allocation_limit_address(isolate())); | |
| 116 | |
| 117 Node* top = effect = | |
| 118 graph()->NewNode(machine()->Load(MachineType::Pointer()), top_address, | |
| 119 jsgraph()->IntPtrConstant(0), effect, control); | |
| 120 Node* limit = effect = | |
| 121 graph()->NewNode(machine()->Load(MachineType::Pointer()), limit_address, | |
| 122 jsgraph()->IntPtrConstant(0), effect, control); | |
| 123 | |
| 124 Node* new_top = graph()->NewNode(machine()->IntAdd(), top, size); | |
| 125 | |
| 126 Node* check = graph()->NewNode(machine()->UintLessThan(), new_top, limit); | |
| 127 Node* branch = | |
| 128 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 129 | |
| 130 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 131 Node* etrue = effect; | |
| 132 Node* vtrue; | |
| 133 { | |
| 134 etrue = graph()->NewNode( | |
| 135 machine()->Store(StoreRepresentation( | |
| 136 MachineType::PointerRepresentation(), kNoWriteBarrier)), | |
| 137 top_address, jsgraph()->IntPtrConstant(0), new_top, etrue, if_true); | |
| 138 vtrue = graph()->NewNode( | |
| 139 machine()->BitcastWordToTagged(), | |
| 140 graph()->NewNode(machine()->IntAdd(), top, | |
| 141 jsgraph()->IntPtrConstant(kHeapObjectTag))); | |
| 142 } | |
| 143 | |
| 144 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 145 Node* efalse = effect; | |
| 146 Node* vfalse; | |
| 147 { | |
| 148 Node* target = pretenure == NOT_TENURED | |
| 149 ? jsgraph()->AllocateInNewSpaceStubConstant() | |
| 150 : jsgraph()->AllocateInOldSpaceStubConstant(); | |
| 151 if (!allocate_operator_.is_set()) { | |
| 152 CallDescriptor* descriptor = | |
| 153 Linkage::GetAllocateCallDescriptor(graph()->zone()); | |
| 154 allocate_operator_.set(common()->Call(descriptor)); | |
| 155 } | |
| 156 vfalse = efalse = graph()->NewNode(allocate_operator_.get(), target, size, | |
| 157 efalse, if_false); | |
| 158 } | |
| 159 | |
| 160 control = graph()->NewNode(common()->Merge(2), if_true, if_false); | |
| 161 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); | |
| 162 Node* value = graph()->NewNode( | |
| 163 common()->Phi(MachineRepresentation::kTagged, 2), vtrue, vfalse, control); | |
| 164 | |
| 165 ReplaceWithValue(node, value, effect); | |
| 166 return Replace(value); | |
| 167 } | |
| 168 | |
| 169 Isolate* ChangeLowering::isolate() const { return jsgraph()->isolate(); } | |
| 170 | |
| 171 | |
| 172 Graph* ChangeLowering::graph() const { return jsgraph()->graph(); } | |
| 173 | |
| 174 | |
| 175 CommonOperatorBuilder* ChangeLowering::common() const { | |
| 176 return jsgraph()->common(); | |
| 177 } | |
| 178 | |
| 179 | |
| 180 MachineOperatorBuilder* ChangeLowering::machine() const { | |
| 181 return jsgraph()->machine(); | |
| 182 } | |
| 183 | |
| 184 } // namespace compiler | |
| 185 } // namespace internal | |
| 186 } // namespace v8 | |
| OLD | NEW |