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/codegen/code-factory.h"
8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/graph-reducer.h"
10 #include "src/compiler/linkage.h"
11 #include "src/compiler/schedule.h"
12 // For TNode types.
13 #include "src/objects/heap-number.h"
14 #include "src/objects/oddball.h"
15 #include "src/objects/smi.h"
16 #include "src/objects/string.h"
17
18 namespace v8 {
19 namespace internal {
20 namespace compiler {
21
22 class V8_NODISCARD GraphAssembler::BlockInlineReduction {
23 public:
BlockInlineReduction(GraphAssembler * gasm)24 explicit BlockInlineReduction(GraphAssembler* gasm) : gasm_(gasm) {
25 DCHECK(!gasm_->inline_reductions_blocked_);
26 gasm_->inline_reductions_blocked_ = true;
27 }
~BlockInlineReduction()28 ~BlockInlineReduction() {
29 DCHECK(gasm_->inline_reductions_blocked_);
30 gasm_->inline_reductions_blocked_ = false;
31 }
32
33 private:
34 GraphAssembler* gasm_;
35 };
36
GraphAssembler(MachineGraph * mcgraph,Zone * zone,base::Optional<NodeChangedCallback> node_changed_callback,bool mark_loop_exits)37 GraphAssembler::GraphAssembler(
38 MachineGraph* mcgraph, Zone* zone,
39 base::Optional<NodeChangedCallback> node_changed_callback,
40 bool mark_loop_exits)
41 : temp_zone_(zone),
42 mcgraph_(mcgraph),
43 effect_(nullptr),
44 control_(nullptr),
45 node_changed_callback_(node_changed_callback),
46 inline_reducers_(zone),
47 inline_reductions_blocked_(false),
48 loop_headers_(zone),
49 mark_loop_exits_(mark_loop_exits) {}
50
~GraphAssembler()51 GraphAssembler::~GraphAssembler() { DCHECK_EQ(loop_nesting_level_, 0); }
52
IntPtrConstant(intptr_t value)53 Node* GraphAssembler::IntPtrConstant(intptr_t value) {
54 return AddClonedNode(mcgraph()->IntPtrConstant(value));
55 }
56
UintPtrConstant(uintptr_t value)57 Node* GraphAssembler::UintPtrConstant(uintptr_t value) {
58 return AddClonedNode(mcgraph()->UintPtrConstant(value));
59 }
60
Int32Constant(int32_t value)61 Node* GraphAssembler::Int32Constant(int32_t value) {
62 return AddClonedNode(mcgraph()->Int32Constant(value));
63 }
64
Uint32Constant(uint32_t value)65 Node* GraphAssembler::Uint32Constant(uint32_t value) {
66 return AddClonedNode(mcgraph()->Uint32Constant(value));
67 }
68
Int64Constant(int64_t value)69 Node* GraphAssembler::Int64Constant(int64_t value) {
70 return AddClonedNode(mcgraph()->Int64Constant(value));
71 }
72
Uint64Constant(uint64_t value)73 Node* GraphAssembler::Uint64Constant(uint64_t value) {
74 return AddClonedNode(mcgraph()->Uint64Constant(value));
75 }
76
UniqueIntPtrConstant(intptr_t value)77 Node* GraphAssembler::UniqueIntPtrConstant(intptr_t value) {
78 return AddNode(graph()->NewNode(
79 machine()->Is64()
80 ? common()->Int64Constant(value)
81 : common()->Int32Constant(static_cast<int32_t>(value))));
82 }
83
SmiConstant(int32_t value)84 Node* JSGraphAssembler::SmiConstant(int32_t value) {
85 return AddClonedNode(jsgraph()->SmiConstant(value));
86 }
87
Float64Constant(double value)88 Node* GraphAssembler::Float64Constant(double value) {
89 return AddClonedNode(mcgraph()->Float64Constant(value));
90 }
91
HeapConstant(Handle<HeapObject> object)92 TNode<HeapObject> JSGraphAssembler::HeapConstant(Handle<HeapObject> object) {
93 return TNode<HeapObject>::UncheckedCast(
94 AddClonedNode(jsgraph()->HeapConstant(object)));
95 }
96
Constant(const ObjectRef & ref)97 TNode<Object> JSGraphAssembler::Constant(const ObjectRef& ref) {
98 return TNode<Object>::UncheckedCast(AddClonedNode(jsgraph()->Constant(ref)));
99 }
100
NumberConstant(double value)101 TNode<Number> JSGraphAssembler::NumberConstant(double value) {
102 return TNode<Number>::UncheckedCast(
103 AddClonedNode(jsgraph()->Constant(value)));
104 }
105
ExternalConstant(ExternalReference ref)106 Node* GraphAssembler::ExternalConstant(ExternalReference ref) {
107 return AddClonedNode(mcgraph()->ExternalConstant(ref));
108 }
109
Parameter(int index)110 Node* GraphAssembler::Parameter(int index) {
111 return AddNode(
112 graph()->NewNode(common()->Parameter(index), graph()->start()));
113 }
114
CEntryStubConstant(int result_size)115 Node* JSGraphAssembler::CEntryStubConstant(int result_size) {
116 return AddClonedNode(jsgraph()->CEntryStubConstant(result_size));
117 }
118
LoadFramePointer()119 Node* GraphAssembler::LoadFramePointer() {
120 return AddNode(graph()->NewNode(machine()->LoadFramePointer()));
121 }
122
LoadHeapNumberValue(Node * heap_number)123 Node* GraphAssembler::LoadHeapNumberValue(Node* heap_number) {
124 return Load(MachineType::Float64(), heap_number,
125 IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag));
126 }
127
128 #define SINGLETON_CONST_DEF(Name, Type) \
129 TNode<Type> JSGraphAssembler::Name##Constant() { \
130 return TNode<Type>::UncheckedCast( \
131 AddClonedNode(jsgraph()->Name##Constant())); \
132 }
133 JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DEF)
134 #undef SINGLETON_CONST_DEF
135
136 #define SINGLETON_CONST_TEST_DEF(Name, ...) \
137 TNode<Boolean> JSGraphAssembler::Is##Name(TNode<Object> value) { \
138 return TNode<Boolean>::UncheckedCast( \
139 ReferenceEqual(value, Name##Constant())); \
140 }
JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DEF)141 JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_TEST_DEF)
142 #undef SINGLETON_CONST_TEST_DEF
143
144 #define PURE_UNOP_DEF(Name) \
145 Node* GraphAssembler::Name(Node* input) { \
146 return AddNode(graph()->NewNode(machine()->Name(), input)); \
147 }
148 PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DEF)
149 #undef PURE_UNOP_DEF
150
151 #define PURE_BINOP_DEF(Name) \
152 Node* GraphAssembler::Name(Node* left, Node* right) { \
153 return AddNode(graph()->NewNode(machine()->Name(), left, right)); \
154 }
155 PURE_ASSEMBLER_MACH_BINOP_LIST(PURE_BINOP_DEF)
156 #undef PURE_BINOP_DEF
157
158 #define CHECKED_BINOP_DEF(Name) \
159 Node* GraphAssembler::Name(Node* left, Node* right) { \
160 return AddNode( \
161 graph()->NewNode(machine()->Name(), left, right, control())); \
162 }
163 CHECKED_ASSEMBLER_MACH_BINOP_LIST(CHECKED_BINOP_DEF)
164 #undef CHECKED_BINOP_DEF
165
166 Node* GraphAssembler::IntPtrEqual(Node* left, Node* right) {
167 return WordEqual(left, right);
168 }
169
TaggedEqual(Node * left,Node * right)170 Node* GraphAssembler::TaggedEqual(Node* left, Node* right) {
171 if (COMPRESS_POINTERS_BOOL) {
172 return Word32Equal(left, right);
173 } else {
174 return WordEqual(left, right);
175 }
176 }
177
SmiSub(Node * left,Node * right)178 Node* GraphAssembler::SmiSub(Node* left, Node* right) {
179 if (COMPRESS_POINTERS_BOOL) {
180 return Int32Sub(left, right);
181 } else {
182 return IntSub(left, right);
183 }
184 }
185
SmiLessThan(Node * left,Node * right)186 Node* GraphAssembler::SmiLessThan(Node* left, Node* right) {
187 if (COMPRESS_POINTERS_BOOL) {
188 return Int32LessThan(left, right);
189 } else {
190 return IntLessThan(left, right);
191 }
192 }
193
Float64RoundDown(Node * value)194 Node* GraphAssembler::Float64RoundDown(Node* value) {
195 CHECK(machine()->Float64RoundDown().IsSupported());
196 return AddNode(graph()->NewNode(machine()->Float64RoundDown().op(), value));
197 }
198
Float64RoundTruncate(Node * value)199 Node* GraphAssembler::Float64RoundTruncate(Node* value) {
200 CHECK(machine()->Float64RoundTruncate().IsSupported());
201 return AddNode(
202 graph()->NewNode(machine()->Float64RoundTruncate().op(), value));
203 }
204
TruncateFloat64ToInt64(Node * value,TruncateKind kind)205 Node* GraphAssembler::TruncateFloat64ToInt64(Node* value, TruncateKind kind) {
206 return AddNode(
207 graph()->NewNode(machine()->TruncateFloat64ToInt64(kind), value));
208 }
209
Projection(int index,Node * value)210 Node* GraphAssembler::Projection(int index, Node* value) {
211 return AddNode(
212 graph()->NewNode(common()->Projection(index), value, control()));
213 }
214
Allocate(AllocationType allocation,Node * size)215 Node* JSGraphAssembler::Allocate(AllocationType allocation, Node* size) {
216 return AddNode(
217 graph()->NewNode(simplified()->AllocateRaw(Type::Any(), allocation), size,
218 effect(), control()));
219 }
220
LoadField(FieldAccess const & access,Node * object)221 Node* JSGraphAssembler::LoadField(FieldAccess const& access, Node* object) {
222 Node* value = AddNode(graph()->NewNode(simplified()->LoadField(access),
223 object, effect(), control()));
224 return value;
225 }
226
LoadElement(ElementAccess const & access,Node * object,Node * index)227 Node* JSGraphAssembler::LoadElement(ElementAccess const& access, Node* object,
228 Node* index) {
229 Node* value = AddNode(graph()->NewNode(simplified()->LoadElement(access),
230 object, index, effect(), control()));
231 return value;
232 }
233
StoreField(FieldAccess const & access,Node * object,Node * value)234 Node* JSGraphAssembler::StoreField(FieldAccess const& access, Node* object,
235 Node* value) {
236 return AddNode(graph()->NewNode(simplified()->StoreField(access), object,
237 value, effect(), control()));
238 }
239
240 #ifdef V8_MAP_PACKING
UnpackMapWord(Node * map_word)241 TNode<Map> GraphAssembler::UnpackMapWord(Node* map_word) {
242 map_word = BitcastTaggedToWordForTagAndSmiBits(map_word);
243 // TODO(wenyuzhao): Clear header metadata.
244 Node* map = WordXor(map_word, IntPtrConstant(Internals::kMapWordXorMask));
245 return TNode<Map>::UncheckedCast(BitcastWordToTagged(map));
246 }
247
PackMapWord(TNode<Map> map)248 Node* GraphAssembler::PackMapWord(TNode<Map> map) {
249 Node* map_word = BitcastTaggedToWordForTagAndSmiBits(map);
250 Node* packed = WordXor(map_word, IntPtrConstant(Internals::kMapWordXorMask));
251 return BitcastWordToTaggedSigned(packed);
252 }
253 #endif
254
LoadMap(Node * object)255 TNode<Map> GraphAssembler::LoadMap(Node* object) {
256 Node* map_word = Load(MachineType::TaggedPointer(), object,
257 HeapObject::kMapOffset - kHeapObjectTag);
258 #ifdef V8_MAP_PACKING
259 return UnpackMapWord(map_word);
260 #else
261 return TNode<Map>::UncheckedCast(map_word);
262 #endif
263 }
264
StoreElement(ElementAccess const & access,Node * object,Node * index,Node * value)265 Node* JSGraphAssembler::StoreElement(ElementAccess const& access, Node* object,
266 Node* index, Node* value) {
267 return AddNode(graph()->NewNode(simplified()->StoreElement(access), object,
268 index, value, effect(), control()));
269 }
270
TransitionAndStoreElement(MapRef double_map,MapRef fast_map,TNode<HeapObject> object,TNode<Number> index,TNode<Object> value)271 void JSGraphAssembler::TransitionAndStoreElement(MapRef double_map,
272 MapRef fast_map,
273 TNode<HeapObject> object,
274 TNode<Number> index,
275 TNode<Object> value) {
276 AddNode(graph()->NewNode(simplified()->TransitionAndStoreElement(
277 double_map.object(), fast_map.object()),
278 object, index, value, effect(), control()));
279 }
280
StringLength(TNode<String> string)281 TNode<Number> JSGraphAssembler::StringLength(TNode<String> string) {
282 return AddNode<Number>(
283 graph()->NewNode(simplified()->StringLength(), string));
284 }
285
ReferenceEqual(TNode<Object> lhs,TNode<Object> rhs)286 TNode<Boolean> JSGraphAssembler::ReferenceEqual(TNode<Object> lhs,
287 TNode<Object> rhs) {
288 return AddNode<Boolean>(
289 graph()->NewNode(simplified()->ReferenceEqual(), lhs, rhs));
290 }
291
NumberEqual(TNode<Number> lhs,TNode<Number> rhs)292 TNode<Boolean> JSGraphAssembler::NumberEqual(TNode<Number> lhs,
293 TNode<Number> rhs) {
294 return AddNode<Boolean>(
295 graph()->NewNode(simplified()->NumberEqual(), lhs, rhs));
296 }
297
NumberMin(TNode<Number> lhs,TNode<Number> rhs)298 TNode<Number> JSGraphAssembler::NumberMin(TNode<Number> lhs,
299 TNode<Number> rhs) {
300 return AddNode<Number>(graph()->NewNode(simplified()->NumberMin(), lhs, rhs));
301 }
302
NumberMax(TNode<Number> lhs,TNode<Number> rhs)303 TNode<Number> JSGraphAssembler::NumberMax(TNode<Number> lhs,
304 TNode<Number> rhs) {
305 return AddNode<Number>(graph()->NewNode(simplified()->NumberMax(), lhs, rhs));
306 }
307
NumberAdd(TNode<Number> lhs,TNode<Number> rhs)308 TNode<Number> JSGraphAssembler::NumberAdd(TNode<Number> lhs,
309 TNode<Number> rhs) {
310 return AddNode<Number>(graph()->NewNode(simplified()->NumberAdd(), lhs, rhs));
311 }
312
NumberSubtract(TNode<Number> lhs,TNode<Number> rhs)313 TNode<Number> JSGraphAssembler::NumberSubtract(TNode<Number> lhs,
314 TNode<Number> rhs) {
315 return AddNode<Number>(
316 graph()->NewNode(simplified()->NumberSubtract(), lhs, rhs));
317 }
318
NumberLessThan(TNode<Number> lhs,TNode<Number> rhs)319 TNode<Boolean> JSGraphAssembler::NumberLessThan(TNode<Number> lhs,
320 TNode<Number> rhs) {
321 return AddNode<Boolean>(
322 graph()->NewNode(simplified()->NumberLessThan(), lhs, rhs));
323 }
324
NumberLessThanOrEqual(TNode<Number> lhs,TNode<Number> rhs)325 TNode<Boolean> JSGraphAssembler::NumberLessThanOrEqual(TNode<Number> lhs,
326 TNode<Number> rhs) {
327 return AddNode<Boolean>(
328 graph()->NewNode(simplified()->NumberLessThanOrEqual(), lhs, rhs));
329 }
330
StringSubstring(TNode<String> string,TNode<Number> from,TNode<Number> to)331 TNode<String> JSGraphAssembler::StringSubstring(TNode<String> string,
332 TNode<Number> from,
333 TNode<Number> to) {
334 return AddNode<String>(graph()->NewNode(
335 simplified()->StringSubstring(), string, from, to, effect(), control()));
336 }
337
ObjectIsCallable(TNode<Object> value)338 TNode<Boolean> JSGraphAssembler::ObjectIsCallable(TNode<Object> value) {
339 return AddNode<Boolean>(
340 graph()->NewNode(simplified()->ObjectIsCallable(), value));
341 }
342
ObjectIsUndetectable(TNode<Object> value)343 TNode<Boolean> JSGraphAssembler::ObjectIsUndetectable(TNode<Object> value) {
344 return AddNode<Boolean>(
345 graph()->NewNode(simplified()->ObjectIsUndetectable(), value));
346 }
347
CheckIf(Node * cond,DeoptimizeReason reason)348 Node* JSGraphAssembler::CheckIf(Node* cond, DeoptimizeReason reason) {
349 return AddNode(graph()->NewNode(simplified()->CheckIf(reason), cond, effect(),
350 control()));
351 }
352
NumberIsFloat64Hole(TNode<Number> value)353 TNode<Boolean> JSGraphAssembler::NumberIsFloat64Hole(TNode<Number> value) {
354 return AddNode<Boolean>(
355 graph()->NewNode(simplified()->NumberIsFloat64Hole(), value));
356 }
357
ToBoolean(TNode<Object> value)358 TNode<Boolean> JSGraphAssembler::ToBoolean(TNode<Object> value) {
359 return AddNode<Boolean>(graph()->NewNode(simplified()->ToBoolean(), value));
360 }
361
ConvertTaggedHoleToUndefined(TNode<Object> value)362 TNode<Object> JSGraphAssembler::ConvertTaggedHoleToUndefined(
363 TNode<Object> value) {
364 return AddNode<Object>(
365 graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(), value));
366 }
367
MaybeGrowFastElements(ElementsKind kind,const FeedbackSource & feedback,TNode<JSArray> array,TNode<FixedArrayBase> elements,TNode<Number> new_length,TNode<Number> old_length)368 TNode<FixedArrayBase> JSGraphAssembler::MaybeGrowFastElements(
369 ElementsKind kind, const FeedbackSource& feedback, TNode<JSArray> array,
370 TNode<FixedArrayBase> elements, TNode<Number> new_length,
371 TNode<Number> old_length) {
372 GrowFastElementsMode mode = IsDoubleElementsKind(kind)
373 ? GrowFastElementsMode::kDoubleElements
374 : GrowFastElementsMode::kSmiOrObjectElements;
375 return AddNode<FixedArrayBase>(graph()->NewNode(
376 simplified()->MaybeGrowFastElements(mode, feedback), array, elements,
377 new_length, old_length, effect(), control()));
378 }
379
StringCharCodeAt(TNode<String> string,TNode<Number> position)380 Node* JSGraphAssembler::StringCharCodeAt(TNode<String> string,
381 TNode<Number> position) {
382 return AddNode(graph()->NewNode(simplified()->StringCharCodeAt(), string,
383 position, effect(), control()));
384 }
385
TypeGuard(Type type,Node * value)386 Node* GraphAssembler::TypeGuard(Type type, Node* value) {
387 return AddNode(
388 graph()->NewNode(common()->TypeGuard(type), value, effect(), control()));
389 }
390
Checkpoint(FrameState frame_state)391 Node* GraphAssembler::Checkpoint(FrameState frame_state) {
392 return AddNode(graph()->NewNode(common()->Checkpoint(), frame_state, effect(),
393 control()));
394 }
395
DebugBreak()396 Node* GraphAssembler::DebugBreak() {
397 return AddNode(
398 graph()->NewNode(machine()->DebugBreak(), effect(), control()));
399 }
400
Unreachable(GraphAssemblerLabel<0u> * block_updater_successor)401 Node* GraphAssembler::Unreachable(
402 GraphAssemblerLabel<0u>* block_updater_successor) {
403 Node* result = UnreachableWithoutConnectToEnd();
404 ConnectUnreachableToEnd();
405 InitializeEffectControl(nullptr, nullptr);
406 return result;
407 }
408
UnreachableWithoutConnectToEnd()409 Node* GraphAssembler::UnreachableWithoutConnectToEnd() {
410 return AddNode(
411 graph()->NewNode(common()->Unreachable(), effect(), control()));
412 }
413
StackSlot(int size,int alignment)414 TNode<RawPtrT> GraphAssembler::StackSlot(int size, int alignment) {
415 return AddNode<RawPtrT>(
416 graph()->NewNode(machine()->StackSlot(size, alignment)));
417 }
418
Store(StoreRepresentation rep,Node * object,Node * offset,Node * value)419 Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, Node* offset,
420 Node* value) {
421 return AddNode(graph()->NewNode(machine()->Store(rep), object, offset, value,
422 effect(), control()));
423 }
424
Store(StoreRepresentation rep,Node * object,int offset,Node * value)425 Node* GraphAssembler::Store(StoreRepresentation rep, Node* object, int offset,
426 Node* value) {
427 return Store(rep, object, Int32Constant(offset), value);
428 }
429
Load(MachineType type,Node * object,Node * offset)430 Node* GraphAssembler::Load(MachineType type, Node* object, Node* offset) {
431 return AddNode(graph()->NewNode(machine()->Load(type), object, offset,
432 effect(), control()));
433 }
434
Load(MachineType type,Node * object,int offset)435 Node* GraphAssembler::Load(MachineType type, Node* object, int offset) {
436 return Load(type, object, Int32Constant(offset));
437 }
438
StoreUnaligned(MachineRepresentation rep,Node * object,Node * offset,Node * value)439 Node* GraphAssembler::StoreUnaligned(MachineRepresentation rep, Node* object,
440 Node* offset, Node* value) {
441 Operator const* const op =
442 (rep == MachineRepresentation::kWord8 ||
443 machine()->UnalignedStoreSupported(rep))
444 ? machine()->Store(StoreRepresentation(rep, kNoWriteBarrier))
445 : machine()->UnalignedStore(rep);
446 return AddNode(
447 graph()->NewNode(op, object, offset, value, effect(), control()));
448 }
449
LoadUnaligned(MachineType type,Node * object,Node * offset)450 Node* GraphAssembler::LoadUnaligned(MachineType type, Node* object,
451 Node* offset) {
452 Operator const* const op =
453 (type.representation() == MachineRepresentation::kWord8 ||
454 machine()->UnalignedLoadSupported(type.representation()))
455 ? machine()->Load(type)
456 : machine()->UnalignedLoad(type);
457 return AddNode(graph()->NewNode(op, object, offset, effect(), control()));
458 }
459
ProtectedStore(MachineRepresentation rep,Node * object,Node * offset,Node * value)460 Node* GraphAssembler::ProtectedStore(MachineRepresentation rep, Node* object,
461 Node* offset, Node* value) {
462 return AddNode(graph()->NewNode(machine()->ProtectedStore(rep), object,
463 offset, value, effect(), control()));
464 }
465
ProtectedLoad(MachineType type,Node * object,Node * offset)466 Node* GraphAssembler::ProtectedLoad(MachineType type, Node* object,
467 Node* offset) {
468 return AddNode(graph()->NewNode(machine()->ProtectedLoad(type), object,
469 offset, effect(), control()));
470 }
471
Retain(Node * buffer)472 Node* GraphAssembler::Retain(Node* buffer) {
473 return AddNode(graph()->NewNode(common()->Retain(), buffer, effect()));
474 }
475
UnsafePointerAdd(Node * base,Node * external)476 Node* GraphAssembler::UnsafePointerAdd(Node* base, Node* external) {
477 return AddNode(graph()->NewNode(machine()->UnsafePointerAdd(), base, external,
478 effect(), control()));
479 }
480
PlainPrimitiveToNumber(TNode<Object> value)481 TNode<Number> JSGraphAssembler::PlainPrimitiveToNumber(TNode<Object> value) {
482 return AddNode<Number>(graph()->NewNode(
483 PlainPrimitiveToNumberOperator(), PlainPrimitiveToNumberBuiltinConstant(),
484 value, effect()));
485 }
486
BitcastWordToTaggedSigned(Node * value)487 Node* GraphAssembler::BitcastWordToTaggedSigned(Node* value) {
488 return AddNode(
489 graph()->NewNode(machine()->BitcastWordToTaggedSigned(), value));
490 }
491
BitcastWordToTagged(Node * value)492 Node* GraphAssembler::BitcastWordToTagged(Node* value) {
493 return AddNode(graph()->NewNode(machine()->BitcastWordToTagged(), value,
494 effect(), control()));
495 }
496
BitcastTaggedToWord(Node * value)497 Node* GraphAssembler::BitcastTaggedToWord(Node* value) {
498 return AddNode(graph()->NewNode(machine()->BitcastTaggedToWord(), value,
499 effect(), control()));
500 }
501
BitcastTaggedToWordForTagAndSmiBits(Node * value)502 Node* GraphAssembler::BitcastTaggedToWordForTagAndSmiBits(Node* value) {
503 return AddNode(graph()->NewNode(
504 machine()->BitcastTaggedToWordForTagAndSmiBits(), value));
505 }
506
BitcastMaybeObjectToWord(Node * value)507 Node* GraphAssembler::BitcastMaybeObjectToWord(Node* value) {
508 return AddNode(graph()->NewNode(machine()->BitcastMaybeObjectToWord(), value,
509 effect(), control()));
510 }
511
DeoptimizeIf(DeoptimizeReason reason,FeedbackSource const & feedback,Node * condition,Node * frame_state)512 Node* GraphAssembler::DeoptimizeIf(DeoptimizeReason reason,
513 FeedbackSource const& feedback,
514 Node* condition, Node* frame_state) {
515 return AddNode(graph()->NewNode(common()->DeoptimizeIf(reason, feedback),
516 condition, frame_state, effect(), control()));
517 }
518
DeoptimizeIfNot(DeoptimizeReason reason,FeedbackSource const & feedback,Node * condition,Node * frame_state)519 Node* GraphAssembler::DeoptimizeIfNot(DeoptimizeReason reason,
520 FeedbackSource const& feedback,
521 Node* condition, Node* frame_state) {
522 return AddNode(graph()->NewNode(common()->DeoptimizeUnless(reason, feedback),
523 condition, frame_state, effect(), control()));
524 }
525
Call(const CallDescriptor * call_descriptor,int inputs_size,Node ** inputs)526 TNode<Object> GraphAssembler::Call(const CallDescriptor* call_descriptor,
527 int inputs_size, Node** inputs) {
528 return Call(common()->Call(call_descriptor), inputs_size, inputs);
529 }
530
Call(const Operator * op,int inputs_size,Node ** inputs)531 TNode<Object> GraphAssembler::Call(const Operator* op, int inputs_size,
532 Node** inputs) {
533 DCHECK_EQ(IrOpcode::kCall, op->opcode());
534 return AddNode<Object>(graph()->NewNode(op, inputs_size, inputs));
535 }
536
TailCall(const CallDescriptor * call_descriptor,int inputs_size,Node ** inputs)537 void GraphAssembler::TailCall(const CallDescriptor* call_descriptor,
538 int inputs_size, Node** inputs) {
539 #ifdef DEBUG
540 static constexpr int kTargetEffectControl = 3;
541 DCHECK_EQ(inputs_size,
542 call_descriptor->ParameterCount() + kTargetEffectControl);
543 #endif // DEBUG
544
545 Node* node = AddNode(graph()->NewNode(common()->TailCall(call_descriptor),
546 inputs_size, inputs));
547
548 // Unlike ConnectUnreachableToEnd, the TailCall node terminates a block; to
549 // keep it live, it *must* be connected to End (also in Turboprop schedules).
550 NodeProperties::MergeControlToEnd(graph(), common(), node);
551
552 // Setting effect, control to nullptr effectively terminates the current block
553 // by disallowing the addition of new nodes until a new label has been bound.
554 InitializeEffectControl(nullptr, nullptr);
555 }
556
BranchWithCriticalSafetyCheck(Node * condition,GraphAssemblerLabel<0u> * if_true,GraphAssemblerLabel<0u> * if_false)557 void GraphAssembler::BranchWithCriticalSafetyCheck(
558 Node* condition, GraphAssemblerLabel<0u>* if_true,
559 GraphAssemblerLabel<0u>* if_false) {
560 BranchHint hint = BranchHint::kNone;
561 if (if_true->IsDeferred() != if_false->IsDeferred()) {
562 hint = if_false->IsDeferred() ? BranchHint::kTrue : BranchHint::kFalse;
563 }
564
565 BranchImpl(condition, if_true, if_false, hint);
566 }
567
ConnectUnreachableToEnd()568 void GraphAssembler::ConnectUnreachableToEnd() {
569 DCHECK_EQ(effect()->opcode(), IrOpcode::kUnreachable);
570 Node* throw_node = graph()->NewNode(common()->Throw(), effect(), control());
571 NodeProperties::MergeControlToEnd(graph(), common(), throw_node);
572 if (node_changed_callback_.has_value()) {
573 (*node_changed_callback_)(graph()->end());
574 }
575 effect_ = control_ = mcgraph()->Dead();
576 }
577
AddClonedNode(Node * node)578 Node* GraphAssembler::AddClonedNode(Node* node) {
579 DCHECK(node->op()->HasProperty(Operator::kPure));
580 UpdateEffectControlWith(node);
581 return node;
582 }
583
AddNode(Node * node)584 Node* GraphAssembler::AddNode(Node* node) {
585 if (!inline_reducers_.empty() && !inline_reductions_blocked_) {
586 // Reducers may add new nodes to the graph using this graph assembler,
587 // however they should never introduce nodes that need further reduction,
588 // so block reduction
589 BlockInlineReduction scope(this);
590 Reduction reduction;
591 for (auto reducer : inline_reducers_) {
592 reduction = reducer->Reduce(node, nullptr);
593 if (reduction.Changed()) break;
594 }
595 if (reduction.Changed()) {
596 Node* replacement = reduction.replacement();
597 if (replacement != node) {
598 // Replace all uses of node and kill the node to make sure we don't
599 // leave dangling dead uses.
600 NodeProperties::ReplaceUses(node, replacement, effect(), control());
601 node->Kill();
602 return replacement;
603 }
604 }
605 }
606
607 if (node->opcode() == IrOpcode::kTerminate) {
608 return node;
609 }
610
611 UpdateEffectControlWith(node);
612 return node;
613 }
614
Reset()615 void GraphAssembler::Reset() {
616 effect_ = nullptr;
617 control_ = nullptr;
618 }
619
InitializeEffectControl(Node * effect,Node * control)620 void GraphAssembler::InitializeEffectControl(Node* effect, Node* control) {
621 effect_ = effect;
622 control_ = control;
623 }
624
PlainPrimitiveToNumberOperator()625 Operator const* JSGraphAssembler::PlainPrimitiveToNumberOperator() {
626 if (!to_number_operator_.is_set()) {
627 Callable callable =
628 Builtins::CallableFor(isolate(), Builtin::kPlainPrimitiveToNumber);
629 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
630 auto call_descriptor = Linkage::GetStubCallDescriptor(
631 graph()->zone(), callable.descriptor(),
632 callable.descriptor().GetStackParameterCount(), flags,
633 Operator::kEliminatable);
634 to_number_operator_.set(common()->Call(call_descriptor));
635 }
636 return to_number_operator_.get();
637 }
638
639 } // namespace compiler
640 } // namespace internal
641 } // namespace v8
642