1 // Copyright 2015 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/graph-assembler.h" 6 7 #include "src/code-factory.h" 8 #include "src/compiler/linkage.h" 9 #include "src/objects-inl.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace compiler { 14 15 GraphAssembler::GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, 16 Zone* zone) 17 : temp_zone_(zone), 18 jsgraph_(jsgraph), 19 current_effect_(effect), 20 current_control_(control) {} 21 22 Node* GraphAssembler::IntPtrConstant(intptr_t value) { 23 return jsgraph()->IntPtrConstant(value); 24 } 25 26 Node* GraphAssembler::Int32Constant(int32_t value) { 27 return jsgraph()->Int32Constant(value); 28 } 29 30 Node* GraphAssembler::UniqueInt32Constant(int32_t value) { 31 return graph()->NewNode(common()->Int32Constant(value)); 32 } 33 34 Node* GraphAssembler::SmiConstant(int32_t value) { 35 return jsgraph()->SmiConstant(value); 36 } 37 38 Node* GraphAssembler::Uint32Constant(int32_t value) { 39 return jsgraph()->Uint32Constant(value); 40 } 41 42 Node* GraphAssembler::Float64Constant(double value) { 43 return jsgraph()->Float64Constant(value); 44 } 45 46 Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) { 47 return jsgraph()->HeapConstant(object); 48 } 49 50 51 Node* GraphAssembler::ExternalConstant(ExternalReference ref) { 52 return jsgraph()->ExternalConstant(ref); 53 } 54 55 Node* GraphAssembler::CEntryStubConstant(int result_size) { 56 return jsgraph()->CEntryStubConstant(result_size); 57 } 58 59 #define SINGLETON_CONST_DEF(Name) \ 60 Node* GraphAssembler::Name() { return jsgraph()->Name(); } 61 JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF) 62 #undef SINGLETON_CONST_DEF 63 64 #define PURE_UNOP_DEF(Name) \ 65 Node* GraphAssembler::Name(Node* input) { \ 66 return graph()->NewNode(machine()->Name(), input); \ 67 } 68 PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF) 69 #undef PURE_UNOP_DEF 70 71 #define PURE_BINOP_DEF(Name) \ 72 Node* GraphAssembler::Name(Node* left, Node* right) { \ 73 return graph()->NewNode(machine()->Name(), left, right); \ 74 } 75 PURE_ASSEMBLER_MACH_BINOP_LIST(PURE_BINOP_DEF) 76 #undef PURE_BINOP_DEF 77 78 #define CHECKED_BINOP_DEF(Name) \ 79 Node* GraphAssembler::Name(Node* left, Node* right) { \ 80 return graph()->NewNode(machine()->Name(), left, right, current_control_); \ 81 } 82 CHECKED_ASSEMBLER_MACH_BINOP_LIST(CHECKED_BINOP_DEF) 83 #undef CHECKED_BINOP_DEF 84 85 Node* GraphAssembler::Float64RoundDown(Node* value) { 86 if (machine()->Float64RoundDown().IsSupported()) { 87 return graph()->NewNode(machine()->Float64RoundDown().op(), value); 88 } 89 return nullptr; 90 } 91 92 Node* GraphAssembler::Projection(int index, Node* value) { 93 return graph()->NewNode(common()->Projection(index), value, current_control_); 94 } 95 96 Node* GraphAssembler::Allocate(PretenureFlag pretenure, Node* size) { 97 return current_effect_ = 98 graph()->NewNode(simplified()->Allocate(NOT_TENURED), size, 99 current_effect_, current_control_); 100 } 101 102 Node* GraphAssembler::LoadField(FieldAccess const& access, Node* object) { 103 return current_effect_ = 104 graph()->NewNode(simplified()->LoadField(access), object, 105 current_effect_, current_control_); 106 } 107 108 Node* GraphAssembler::LoadElement(ElementAccess const& access, Node* object, 109 Node* index) { 110 return current_effect_ = 111 graph()->NewNode(simplified()->LoadElement(access), object, index, 112 current_effect_, current_control_); 113 } 114 115 Node* GraphAssembler::StoreField(FieldAccess const& access, Node* object, 116 Node* value) { 117 return current_effect_ = 118 graph()->NewNode(simplified()->StoreField(access), object, value, 119 current_effect_, current_control_); 120 } 121 122 Node* GraphAssembler::StoreElement(ElementAccess const& access, Node* object, 123 Node* index, Node* value) { 124 return current_effect_ = 125 graph()->NewNode(simplified()->StoreElement(access), object, index, 126 value, current_effect_, current_control_); 127 } 128 129 Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, Node* offset, 130 Node* value) { 131 return current_effect_ = 132 graph()->NewNode(machine()->Store(rep), object, offset, value, 133 current_effect_, current_control_); 134 } 135 136 Node* GraphAssembler::Load(MachineType rep, Node* object, Node* offset) { 137 return current_effect_ = 138 graph()->NewNode(machine()->Load(rep), object, offset, 139 current_effect_, current_control_); 140 } 141 142 Node* GraphAssembler::Retain(Node* buffer) { 143 return current_effect_ = 144 graph()->NewNode(common()->Retain(), buffer, current_effect_); 145 } 146 147 Node* GraphAssembler::UnsafePointerAdd(Node* base, Node* external) { 148 return current_effect_ = 149 graph()->NewNode(machine()->UnsafePointerAdd(), base, external, 150 current_effect_, current_control_); 151 } 152 153 Node* GraphAssembler::ToNumber(Node* value) { 154 return current_effect_ = 155 graph()->NewNode(ToNumberOperator(), ToNumberBuiltinConstant(), 156 value, NoContextConstant(), current_effect_); 157 } 158 159 Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason, Node* condition, 160 Node* frame_state) { 161 return current_control_ = current_effect_ = graph()->NewNode( 162 common()->DeoptimizeIf(DeoptimizeKind::kEager, reason), condition, 163 frame_state, current_effect_, current_control_); 164 } 165 166 Node* GraphAssembler::DeoptimizeUnless(DeoptimizeKind kind, 167 DeoptimizeReason reason, Node* condition, 168 Node* frame_state) { 169 return current_control_ = current_effect_ = graph()->NewNode( 170 common()->DeoptimizeUnless(kind, reason), condition, frame_state, 171 current_effect_, current_control_); 172 } 173 174 Node* GraphAssembler::DeoptimizeUnless(DeoptimizeReason reason, Node* condition, 175 Node* frame_state) { 176 return DeoptimizeUnless(DeoptimizeKind::kEager, reason, condition, 177 frame_state); 178 } 179 180 void GraphAssembler::Branch(Node* condition, 181 GraphAssemblerStaticLabel<1>* if_true, 182 GraphAssemblerStaticLabel<1>* if_false) { 183 DCHECK_NOT_NULL(current_control_); 184 185 BranchHint hint = BranchHint::kNone; 186 if (if_true->IsDeferred() != if_false->IsDeferred()) { 187 hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse; 188 } 189 190 Node* branch = 191 graph()->NewNode(common()->Branch(hint), condition, current_control_); 192 193 current_control_ = graph()->NewNode(common()->IfTrue(), branch); 194 MergeState(if_true); 195 196 current_control_ = graph()->NewNode(common()->IfFalse(), branch); 197 MergeState(if_false); 198 199 current_control_ = nullptr; 200 current_effect_ = nullptr; 201 } 202 203 // Extractors (should be only used when destructing the assembler. 204 Node* GraphAssembler::ExtractCurrentControl() { 205 Node* result = current_control_; 206 current_control_ = nullptr; 207 return result; 208 } 209 210 Node* GraphAssembler::ExtractCurrentEffect() { 211 Node* result = current_effect_; 212 current_effect_ = nullptr; 213 return result; 214 } 215 216 void GraphAssembler::Reset(Node* effect, Node* control) { 217 current_effect_ = effect; 218 current_control_ = control; 219 } 220 221 Operator const* GraphAssembler::ToNumberOperator() { 222 if (!to_number_operator_.is_set()) { 223 Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); 224 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; 225 CallDescriptor* desc = Linkage::GetStubCallDescriptor( 226 jsgraph()->isolate(), graph()->zone(), callable.descriptor(), 0, flags, 227 Operator::kEliminatable); 228 to_number_operator_.set(common()->Call(desc)); 229 } 230 return to_number_operator_.get(); 231 } 232 233 Node* GraphAssemblerLabel::PhiAt(size_t index) { 234 DCHECK(IsBound()); 235 return GetBindingsPtrFor(index)[0]; 236 } 237 238 GraphAssemblerLabel::GraphAssemblerLabel(GraphAssemblerLabelType is_deferred, 239 size_t merge_count, size_t var_count, 240 MachineRepresentation* representations, 241 Zone* zone) 242 : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred), 243 max_merge_count_(merge_count), 244 var_count_(var_count) { 245 effects_ = zone->NewArray<Node*>(MaxMergeCount() + 1); 246 for (size_t i = 0; i < MaxMergeCount() + 1; i++) { 247 effects_[i] = nullptr; 248 } 249 250 controls_ = zone->NewArray<Node*>(MaxMergeCount()); 251 for (size_t i = 0; i < MaxMergeCount(); i++) { 252 controls_[i] = nullptr; 253 } 254 255 size_t num_bindings = (MaxMergeCount() + 1) * PhiCount() + 1; 256 bindings_ = zone->NewArray<Node*>(num_bindings); 257 for (size_t i = 0; i < num_bindings; i++) { 258 bindings_[i] = nullptr; 259 } 260 261 representations_ = zone->NewArray<MachineRepresentation>(PhiCount() + 1); 262 for (size_t i = 0; i < PhiCount(); i++) { 263 representations_[i] = representations[i]; 264 } 265 } 266 267 GraphAssemblerLabel::~GraphAssemblerLabel() { 268 DCHECK(IsBound() || MergedCount() == 0); 269 } 270 271 Node** GraphAssemblerLabel::GetBindingsPtrFor(size_t phi_index) { 272 DCHECK_LT(phi_index, PhiCount()); 273 return &bindings_[phi_index * (MaxMergeCount() + 1)]; 274 } 275 276 void GraphAssemblerLabel::SetBinding(size_t phi_index, size_t merge_index, 277 Node* binding) { 278 DCHECK_LT(phi_index, PhiCount()); 279 DCHECK_LT(merge_index, MaxMergeCount()); 280 bindings_[phi_index * (MaxMergeCount() + 1) + merge_index] = binding; 281 } 282 283 MachineRepresentation GraphAssemblerLabel::GetRepresentationFor( 284 size_t phi_index) { 285 DCHECK_LT(phi_index, PhiCount()); 286 return representations_[phi_index]; 287 } 288 289 Node** GraphAssemblerLabel::GetControlsPtr() { return controls_; } 290 291 Node** GraphAssemblerLabel::GetEffectsPtr() { return effects_; } 292 293 } // namespace compiler 294 } // namespace internal 295 } // namespace v8 296