• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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