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
GraphAssembler(JSGraph * jsgraph,Node * effect,Node * control,Zone * zone)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
IntPtrConstant(intptr_t value)22 Node* GraphAssembler::IntPtrConstant(intptr_t value) {
23 return jsgraph()->IntPtrConstant(value);
24 }
25
Int32Constant(int32_t value)26 Node* GraphAssembler::Int32Constant(int32_t value) {
27 return jsgraph()->Int32Constant(value);
28 }
29
UniqueInt32Constant(int32_t value)30 Node* GraphAssembler::UniqueInt32Constant(int32_t value) {
31 return graph()->NewNode(common()->Int32Constant(value));
32 }
33
SmiConstant(int32_t value)34 Node* GraphAssembler::SmiConstant(int32_t value) {
35 return jsgraph()->SmiConstant(value);
36 }
37
Uint32Constant(int32_t value)38 Node* GraphAssembler::Uint32Constant(int32_t value) {
39 return jsgraph()->Uint32Constant(value);
40 }
41
Float64Constant(double value)42 Node* GraphAssembler::Float64Constant(double value) {
43 return jsgraph()->Float64Constant(value);
44 }
45
HeapConstant(Handle<HeapObject> object)46 Node* GraphAssembler::HeapConstant(Handle<HeapObject> object) {
47 return jsgraph()->HeapConstant(object);
48 }
49
50
ExternalConstant(ExternalReference ref)51 Node* GraphAssembler::ExternalConstant(ExternalReference ref) {
52 return jsgraph()->ExternalConstant(ref);
53 }
54
CEntryStubConstant(int result_size)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 }
PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF)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
Projection(int index,Node * value)92 Node* GraphAssembler::Projection(int index, Node* value) {
93 return graph()->NewNode(common()->Projection(index), value, current_control_);
94 }
95
Allocate(PretenureFlag pretenure,Node * size)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
LoadField(FieldAccess const & access,Node * object)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
LoadElement(ElementAccess const & access,Node * object,Node * index)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
StoreField(FieldAccess const & access,Node * object,Node * value)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
StoreElement(ElementAccess const & access,Node * object,Node * index,Node * value)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
Store(StoreRepresentation rep,Node * object,Node * offset,Node * value)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
Load(MachineType rep,Node * object,Node * offset)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
Retain(Node * buffer)142 Node* GraphAssembler::Retain(Node* buffer) {
143 return current_effect_ =
144 graph()->NewNode(common()->Retain(), buffer, current_effect_);
145 }
146
UnsafePointerAdd(Node * base,Node * external)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
ToNumber(Node * value)153 Node* GraphAssembler::ToNumber(Node* value) {
154 return current_effect_ =
155 graph()->NewNode(ToNumberOperator(), ToNumberBuiltinConstant(),
156 value, NoContextConstant(), current_effect_);
157 }
158
DeoptimizeIf(DeoptimizeReason reason,Node * condition,Node * frame_state)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
DeoptimizeUnless(DeoptimizeKind kind,DeoptimizeReason reason,Node * condition,Node * frame_state)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
DeoptimizeUnless(DeoptimizeReason reason,Node * condition,Node * frame_state)174 Node* GraphAssembler::DeoptimizeUnless(DeoptimizeReason reason, Node* condition,
175 Node* frame_state) {
176 return DeoptimizeUnless(DeoptimizeKind::kEager, reason, condition,
177 frame_state);
178 }
179
Branch(Node * condition,GraphAssemblerStaticLabel<1> * if_true,GraphAssemblerStaticLabel<1> * if_false)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.
ExtractCurrentControl()204 Node* GraphAssembler::ExtractCurrentControl() {
205 Node* result = current_control_;
206 current_control_ = nullptr;
207 return result;
208 }
209
ExtractCurrentEffect()210 Node* GraphAssembler::ExtractCurrentEffect() {
211 Node* result = current_effect_;
212 current_effect_ = nullptr;
213 return result;
214 }
215
Reset(Node * effect,Node * control)216 void GraphAssembler::Reset(Node* effect, Node* control) {
217 current_effect_ = effect;
218 current_control_ = control;
219 }
220
ToNumberOperator()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
PhiAt(size_t index)233 Node* GraphAssemblerLabel::PhiAt(size_t index) {
234 DCHECK(IsBound());
235 return GetBindingsPtrFor(index)[0];
236 }
237
GraphAssemblerLabel(GraphAssemblerLabelType is_deferred,size_t merge_count,size_t var_count,MachineRepresentation * representations,Zone * zone)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
~GraphAssemblerLabel()267 GraphAssemblerLabel::~GraphAssemblerLabel() {
268 DCHECK(IsBound() || MergedCount() == 0);
269 }
270
GetBindingsPtrFor(size_t phi_index)271 Node** GraphAssemblerLabel::GetBindingsPtrFor(size_t phi_index) {
272 DCHECK_LT(phi_index, PhiCount());
273 return &bindings_[phi_index * (MaxMergeCount() + 1)];
274 }
275
SetBinding(size_t phi_index,size_t merge_index,Node * binding)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
GetRepresentationFor(size_t phi_index)283 MachineRepresentation GraphAssemblerLabel::GetRepresentationFor(
284 size_t phi_index) {
285 DCHECK_LT(phi_index, PhiCount());
286 return representations_[phi_index];
287 }
288
GetControlsPtr()289 Node** GraphAssemblerLabel::GetControlsPtr() { return controls_; }
290
GetEffectsPtr()291 Node** GraphAssemblerLabel::GetEffectsPtr() { return effects_; }
292
293 } // namespace compiler
294 } // namespace internal
295 } // namespace v8
296