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