• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #ifndef V8_CODEGEN_CODE_STUB_ASSEMBLER_H_
6 #define V8_CODEGEN_CODE_STUB_ASSEMBLER_H_
7 
8 #include <functional>
9 
10 #include "src/base/macros.h"
11 #include "src/codegen/bailout-reason.h"
12 #include "src/common/external-pointer.h"
13 #include "src/common/globals.h"
14 #include "src/common/message-template.h"
15 #include "src/compiler/code-assembler.h"
16 #include "src/objects/arguments.h"
17 #include "src/objects/bigint.h"
18 #include "src/objects/feedback-vector.h"
19 #include "src/objects/js-function.h"
20 #include "src/objects/objects.h"
21 #include "src/objects/promise.h"
22 #include "src/objects/shared-function-info.h"
23 #include "src/objects/smi.h"
24 #include "src/objects/tagged-index.h"
25 #include "src/roots/roots.h"
26 #include "torque-generated/exported-macros-assembler.h"
27 
28 namespace v8 {
29 namespace internal {
30 
31 class CallInterfaceDescriptor;
32 class CodeStubArguments;
33 class CodeStubAssembler;
34 class StatsCounter;
35 class StubCache;
36 
37 enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
38 
39 #define HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V)                                  \
40   V(ArrayIteratorProtector, array_iterator_protector, ArrayIteratorProtector)  \
41   V(ArraySpeciesProtector, array_species_protector, ArraySpeciesProtector)     \
42   V(AsyncFunctionAwaitRejectSharedFun, async_function_await_reject_shared_fun, \
43     AsyncFunctionAwaitRejectSharedFun)                                         \
44   V(AsyncFunctionAwaitResolveSharedFun,                                        \
45     async_function_await_resolve_shared_fun,                                   \
46     AsyncFunctionAwaitResolveSharedFun)                                        \
47   V(AsyncGeneratorAwaitRejectSharedFun,                                        \
48     async_generator_await_reject_shared_fun,                                   \
49     AsyncGeneratorAwaitRejectSharedFun)                                        \
50   V(AsyncGeneratorAwaitResolveSharedFun,                                       \
51     async_generator_await_resolve_shared_fun,                                  \
52     AsyncGeneratorAwaitResolveSharedFun)                                       \
53   V(AsyncGeneratorReturnClosedRejectSharedFun,                                 \
54     async_generator_return_closed_reject_shared_fun,                           \
55     AsyncGeneratorReturnClosedRejectSharedFun)                                 \
56   V(AsyncGeneratorReturnClosedResolveSharedFun,                                \
57     async_generator_return_closed_resolve_shared_fun,                          \
58     AsyncGeneratorReturnClosedResolveSharedFun)                                \
59   V(AsyncGeneratorReturnResolveSharedFun,                                      \
60     async_generator_return_resolve_shared_fun,                                 \
61     AsyncGeneratorReturnResolveSharedFun)                                      \
62   V(AsyncGeneratorYieldResolveSharedFun,                                       \
63     async_generator_yield_resolve_shared_fun,                                  \
64     AsyncGeneratorYieldResolveSharedFun)                                       \
65   V(AsyncIteratorValueUnwrapSharedFun, async_iterator_value_unwrap_shared_fun, \
66     AsyncIteratorValueUnwrapSharedFun)                                         \
67   V(MapIteratorProtector, map_iterator_protector, MapIteratorProtector)        \
68   V(NoElementsProtector, no_elements_protector, NoElementsProtector)           \
69   V(NumberStringCache, number_string_cache, NumberStringCache)                 \
70   V(PromiseAllResolveElementSharedFun, promise_all_resolve_element_shared_fun, \
71     PromiseAllResolveElementSharedFun)                                         \
72   V(PromiseAllSettledRejectElementSharedFun,                                   \
73     promise_all_settled_reject_element_shared_fun,                             \
74     PromiseAllSettledRejectElementSharedFun)                                   \
75   V(PromiseAllSettledResolveElementSharedFun,                                  \
76     promise_all_settled_resolve_element_shared_fun,                            \
77     PromiseAllSettledResolveElementSharedFun)                                  \
78   V(PromiseAnyRejectElementSharedFun, promise_any_reject_element_shared_fun,   \
79     PromiseAnyRejectElementSharedFun)                                          \
80   V(PromiseCapabilityDefaultRejectSharedFun,                                   \
81     promise_capability_default_reject_shared_fun,                              \
82     PromiseCapabilityDefaultRejectSharedFun)                                   \
83   V(PromiseCapabilityDefaultResolveSharedFun,                                  \
84     promise_capability_default_resolve_shared_fun,                             \
85     PromiseCapabilityDefaultResolveSharedFun)                                  \
86   V(PromiseCatchFinallySharedFun, promise_catch_finally_shared_fun,            \
87     PromiseCatchFinallySharedFun)                                              \
88   V(PromiseGetCapabilitiesExecutorSharedFun,                                   \
89     promise_get_capabilities_executor_shared_fun,                              \
90     PromiseGetCapabilitiesExecutorSharedFun)                                   \
91   V(PromiseResolveProtector, promise_resolve_protector,                        \
92     PromiseResolveProtector)                                                   \
93   V(PromiseSpeciesProtector, promise_species_protector,                        \
94     PromiseSpeciesProtector)                                                   \
95   V(PromiseThenFinallySharedFun, promise_then_finally_shared_fun,              \
96     PromiseThenFinallySharedFun)                                               \
97   V(PromiseThenProtector, promise_then_protector, PromiseThenProtector)        \
98   V(PromiseThrowerFinallySharedFun, promise_thrower_finally_shared_fun,        \
99     PromiseThrowerFinallySharedFun)                                            \
100   V(PromiseValueThunkFinallySharedFun, promise_value_thunk_finally_shared_fun, \
101     PromiseValueThunkFinallySharedFun)                                         \
102   V(ProxyRevokeSharedFun, proxy_revoke_shared_fun, ProxyRevokeSharedFun)       \
103   V(RegExpSpeciesProtector, regexp_species_protector, RegExpSpeciesProtector)  \
104   V(SetIteratorProtector, set_iterator_protector, SetIteratorProtector)        \
105   V(SingleCharacterStringCache, single_character_string_cache,                 \
106     SingleCharacterStringCache)                                                \
107   V(StringIteratorProtector, string_iterator_protector,                        \
108     StringIteratorProtector)                                                   \
109   V(TypedArraySpeciesProtector, typed_array_species_protector,                 \
110     TypedArraySpeciesProtector)
111 
112 #define UNIQUE_INSTANCE_TYPE_IMMUTABLE_IMMOVABLE_MAP_ADAPTER( \
113     V, rootIndexName, rootAccessorName, class_name)           \
114   V(rootIndexName, rootAccessorName, class_name##Map)
115 
116 #define HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V)                              \
117   V(AllocationSiteWithoutWeakNextMap, allocation_site_without_weaknext_map,  \
118     AllocationSiteWithoutWeakNextMap)                                        \
119   V(AllocationSiteWithWeakNextMap, allocation_site_map, AllocationSiteMap)   \
120   V(arguments_to_string, arguments_to_string, ArgumentsToString)             \
121   V(Array_string, Array_string, ArrayString)                                 \
122   V(array_to_string, array_to_string, ArrayToString)                         \
123   V(BooleanMap, boolean_map, BooleanMap)                                     \
124   V(boolean_to_string, boolean_to_string, BooleanToString)                   \
125   V(ConsOneByteStringMap, cons_one_byte_string_map, ConsOneByteStringMap)    \
126   V(ConsStringMap, cons_string_map, ConsStringMap)                           \
127   V(constructor_string, constructor_string, ConstructorString)               \
128   V(date_to_string, date_to_string, DateToString)                            \
129   V(default_string, default_string, DefaultString)                           \
130   V(EmptyByteArray, empty_byte_array, EmptyByteArray)                        \
131   V(EmptyFixedArray, empty_fixed_array, EmptyFixedArray)                     \
132   V(EmptyScopeInfo, empty_scope_info, EmptyScopeInfo)                        \
133   V(EmptyPropertyDictionary, empty_property_dictionary,                      \
134     EmptyPropertyDictionary)                                                 \
135   V(EmptySlowElementDictionary, empty_slow_element_dictionary,               \
136     EmptySlowElementDictionary)                                              \
137   V(empty_string, empty_string, EmptyString)                                 \
138   V(error_to_string, error_to_string, ErrorToString)                         \
139   V(errors_string, errors_string, ErrorsString)                              \
140   V(FalseValue, false_value, False)                                          \
141   V(FixedArrayMap, fixed_array_map, FixedArrayMap)                           \
142   V(FixedCOWArrayMap, fixed_cow_array_map, FixedCOWArrayMap)                 \
143   V(Function_string, function_string, FunctionString)                        \
144   V(function_to_string, function_to_string, FunctionToString)                \
145   V(GlobalPropertyCellMap, global_property_cell_map, PropertyCellMap)        \
146   V(has_instance_symbol, has_instance_symbol, HasInstanceSymbol)             \
147   V(Infinity_string, Infinity_string, InfinityString)                        \
148   V(is_concat_spreadable_symbol, is_concat_spreadable_symbol,                \
149     IsConcatSpreadableSymbol)                                                \
150   V(iterator_symbol, iterator_symbol, IteratorSymbol)                        \
151   V(length_string, length_string, LengthString)                              \
152   V(ManyClosuresCellMap, many_closures_cell_map, ManyClosuresCellMap)        \
153   V(match_symbol, match_symbol, MatchSymbol)                                 \
154   V(megamorphic_symbol, megamorphic_symbol, MegamorphicSymbol)               \
155   V(message_string, message_string, MessageString)                           \
156   V(minus_Infinity_string, minus_Infinity_string, MinusInfinityString)       \
157   V(MinusZeroValue, minus_zero_value, MinusZero)                             \
158   V(name_string, name_string, NameString)                                    \
159   V(NanValue, nan_value, Nan)                                                \
160   V(NaN_string, NaN_string, NaNString)                                       \
161   V(next_string, next_string, NextString)                                    \
162   V(NoClosuresCellMap, no_closures_cell_map, NoClosuresCellMap)              \
163   V(null_to_string, null_to_string, NullToString)                            \
164   V(NullValue, null_value, Null)                                             \
165   V(number_string, number_string, NumberString)                              \
166   V(number_to_string, number_to_string, NumberToString)                      \
167   V(Object_string, Object_string, ObjectString)                              \
168   V(object_to_string, object_to_string, ObjectToString)                      \
169   V(OneByteStringMap, one_byte_string_map, OneByteStringMap)                 \
170   V(OneClosureCellMap, one_closure_cell_map, OneClosureCellMap)              \
171   V(OnePointerFillerMap, one_pointer_filler_map, OnePointerFillerMap)        \
172   V(PromiseCapabilityMap, promise_capability_map, PromiseCapabilityMap)      \
173   V(promise_forwarding_handler_symbol, promise_forwarding_handler_symbol,    \
174     PromiseForwardingHandlerSymbol)                                          \
175   V(PromiseFulfillReactionJobTaskMap, promise_fulfill_reaction_job_task_map, \
176     PromiseFulfillReactionJobTaskMap)                                        \
177   V(promise_handled_by_symbol, promise_handled_by_symbol,                    \
178     PromiseHandledBySymbol)                                                  \
179   V(PromiseReactionMap, promise_reaction_map, PromiseReactionMap)            \
180   V(PromiseRejectReactionJobTaskMap, promise_reject_reaction_job_task_map,   \
181     PromiseRejectReactionJobTaskMap)                                         \
182   V(PromiseResolveThenableJobTaskMap, promise_resolve_thenable_job_task_map, \
183     PromiseResolveThenableJobTaskMap)                                        \
184   V(prototype_string, prototype_string, PrototypeString)                     \
185   V(replace_symbol, replace_symbol, ReplaceSymbol)                           \
186   V(regexp_to_string, regexp_to_string, RegexpToString)                      \
187   V(resolve_string, resolve_string, ResolveString)                           \
188   V(return_string, return_string, ReturnString)                              \
189   V(species_symbol, species_symbol, SpeciesSymbol)                           \
190   V(StaleRegister, stale_register, StaleRegister)                            \
191   V(StoreHandler0Map, store_handler0_map, StoreHandler0Map)                  \
192   V(string_string, string_string, StringString)                              \
193   V(string_to_string, string_to_string, StringToString)                      \
194   V(StringMap, string_map, StringMap)                                        \
195   V(TheHoleValue, the_hole_value, TheHole)                                   \
196   V(then_string, then_string, ThenString)                                    \
197   V(toString_string, toString_string, ToStringString)                        \
198   V(to_primitive_symbol, to_primitive_symbol, ToPrimitiveSymbol)             \
199   V(to_string_tag_symbol, to_string_tag_symbol, ToStringTagSymbol)           \
200   V(TrueValue, true_value, True)                                             \
201   V(undefined_to_string, undefined_to_string, UndefinedToString)             \
202   V(UndefinedValue, undefined_value, Undefined)                              \
203   V(uninitialized_symbol, uninitialized_symbol, UninitializedSymbol)         \
204   V(valueOf_string, valueOf_string, ValueOfString)                           \
205   V(wasm_wrapped_object_symbol, wasm_wrapped_object_symbol,                  \
206     WasmWrappedObjectSymbol)                                                 \
207   V(zero_string, zero_string, ZeroString)                                    \
208   UNIQUE_INSTANCE_TYPE_MAP_LIST_GENERATOR(                                   \
209       UNIQUE_INSTANCE_TYPE_IMMUTABLE_IMMOVABLE_MAP_ADAPTER, V)
210 
211 #define HEAP_IMMOVABLE_OBJECT_LIST(V)   \
212   HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \
213   HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V)
214 
215 #ifdef DEBUG
216 #define CSA_CHECK(csa, x) \
217   (csa)->Check([&]() -> TNode<BoolT> { return x; }, #x, __FILE__, __LINE__)
218 #else
219 #define CSA_CHECK(csa, x) (csa)->FastCheck(x)
220 #endif
221 
222 #ifdef DEBUG
223 // CSA_ASSERT_ARGS generates an
224 // std::initializer_list<CodeStubAssembler::ExtraNode> from __VA_ARGS__. It
225 // currently supports between 0 and 2 arguments.
226 
227 // clang-format off
228 #define CSA_ASSERT_0_ARGS(...) {}
229 #define CSA_ASSERT_1_ARG(a, ...) {{a, #a}}
230 #define CSA_ASSERT_2_ARGS(a, b, ...) {{a, #a}, {b, #b}}
231 // clang-format on
232 #define SWITCH_CSA_ASSERT_ARGS(dummy, a, b, FUNC, ...) FUNC(a, b)
233 #define CSA_ASSERT_ARGS(...)                                        \
234   CALL(SWITCH_CSA_ASSERT_ARGS, (, ##__VA_ARGS__, CSA_ASSERT_2_ARGS, \
235                                 CSA_ASSERT_1_ARG, CSA_ASSERT_0_ARGS))
236 // Workaround for MSVC to skip comma in empty __VA_ARGS__.
237 #define CALL(x, y) x y
238 
239 // CSA_ASSERT(csa, <condition>, <extra values to print...>)
240 
241 #define CSA_ASSERT(csa, condition_node, ...)                         \
242   (csa)->Assert(condition_node, #condition_node, __FILE__, __LINE__, \
243                 CSA_ASSERT_ARGS(__VA_ARGS__))
244 
245 // CSA_ASSERT_BRANCH(csa, [](Label* ok, Label* not_ok) {...},
246 //     <extra values to print...>)
247 
248 #define CSA_ASSERT_BRANCH(csa, gen, ...) \
249   (csa)->Assert(gen, #gen, __FILE__, __LINE__, CSA_ASSERT_ARGS(__VA_ARGS__))
250 
251 #define CSA_ASSERT_JS_ARGC_OP(csa, Op, op, expected)                    \
252   (csa)->Assert(                                                        \
253       [&]() -> TNode<BoolT> {                                           \
254         const TNode<Word32T> argc = (csa)->UncheckedParameter<Word32T>( \
255             Descriptor::kJSActualArgumentsCount);                       \
256         return (csa)->Op(argc, (csa)->Int32Constant(expected));         \
257       },                                                                \
258       "argc " #op " " #expected, __FILE__, __LINE__,                    \
259       {{SmiFromInt32((csa)->UncheckedParameter<Int32T>(                 \
260             Descriptor::kJSActualArgumentsCount)),                      \
261         "argc"}})
262 
263 #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) \
264   CSA_ASSERT_JS_ARGC_OP(csa, Word32Equal, ==, expected)
265 
266 #define CSA_DEBUG_INFO(name) \
267   { #name, __FILE__, __LINE__ }
268 #define BIND(label) Bind(label, CSA_DEBUG_INFO(label))
269 #define TYPED_VARIABLE_DEF(type, name, ...) \
270   TVariable<type> name(CSA_DEBUG_INFO(name), __VA_ARGS__)
271 #define TYPED_VARIABLE_CONSTRUCTOR(name, ...) \
272   name(CSA_DEBUG_INFO(name), __VA_ARGS__)
273 #else  // DEBUG
274 #define CSA_ASSERT(csa, ...) ((void)0)
275 #define CSA_ASSERT_BRANCH(csa, ...) ((void)0)
276 #define CSA_ASSERT_JS_ARGC_EQ(csa, expected) ((void)0)
277 #define BIND(label) Bind(label)
278 #define TYPED_VARIABLE_DEF(type, name, ...) TVariable<type> name(__VA_ARGS__)
279 #define TYPED_VARIABLE_CONSTRUCTOR(name, ...) name(__VA_ARGS__)
280 #endif  // DEBUG
281 
282 #define TVARIABLE(...) EXPAND(TYPED_VARIABLE_DEF(__VA_ARGS__, this))
283 #define TVARIABLE_CONSTRUCTOR(...) \
284   EXPAND(TYPED_VARIABLE_CONSTRUCTOR(__VA_ARGS__, this))
285 
286 #ifdef ENABLE_SLOW_DCHECKS
287 #define CSA_SLOW_ASSERT(csa, ...) \
288   if (FLAG_enable_slow_asserts) { \
289     CSA_ASSERT(csa, __VA_ARGS__); \
290   }
291 #else
292 #define CSA_SLOW_ASSERT(csa, ...) ((void)0)
293 #endif
294 
295 // Provides a constexpr boolean to be used inside Torque.
296 #ifdef V8_NO_ARGUMENTS_ADAPTOR
297 constexpr bool kNoArgumentsAdaptor = true;
298 #else
299 constexpr bool kNoArgumentsAdaptor = false;
300 #endif
301 
302 // Provides JavaScript-specific "macro-assembler" functionality on top of the
303 // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
304 // it's possible to add JavaScript-specific useful CodeAssembler "macros"
305 // without modifying files in the compiler directory (and requiring a review
306 // from a compiler directory OWNER).
307 class V8_EXPORT_PRIVATE CodeStubAssembler
308     : public compiler::CodeAssembler,
309       public TorqueGeneratedExportedMacrosAssembler {
310  public:
311   using Node = compiler::Node;
312   using ScopedExceptionHandler = compiler::ScopedExceptionHandler;
313 
314   template <typename T>
315   using LazyNode = std::function<TNode<T>()>;
316 
317   explicit CodeStubAssembler(compiler::CodeAssemblerState* state);
318 
319   enum AllocationFlag : uint8_t {
320     kNone = 0,
321     kDoubleAlignment = 1,
322     kPretenured = 1 << 1,
323     kAllowLargeObjectAllocation = 1 << 2,
324   };
325 
326   enum SlackTrackingMode { kWithSlackTracking, kNoSlackTracking };
327 
328   using AllocationFlags = base::Flags<AllocationFlag>;
329 
ParameterToIntPtr(TNode<Smi> value)330   TNode<IntPtrT> ParameterToIntPtr(TNode<Smi> value) { return SmiUntag(value); }
ParameterToIntPtr(TNode<IntPtrT> value)331   TNode<IntPtrT> ParameterToIntPtr(TNode<IntPtrT> value) { return value; }
ParameterToIntPtr(TNode<UintPtrT> value)332   TNode<IntPtrT> ParameterToIntPtr(TNode<UintPtrT> value) {
333     return Signed(value);
334   }
335 
ParameterToTagged(TNode<Smi> value)336   TNode<Smi> ParameterToTagged(TNode<Smi> value) { return value; }
337 
ParameterToTagged(TNode<IntPtrT> value)338   TNode<Smi> ParameterToTagged(TNode<IntPtrT> value) { return SmiTag(value); }
339 
340   template <typename TIndex>
341   TNode<TIndex> TaggedToParameter(TNode<Smi> value);
342 
ToParameterConstant(TNode<Smi> node,intptr_t * out)343   bool ToParameterConstant(TNode<Smi> node, intptr_t* out) {
344     Smi constant;
345     if (ToSmiConstant(node, &constant)) {
346       *out = static_cast<intptr_t>(constant.value());
347       return true;
348     }
349     return false;
350   }
351 
ToParameterConstant(TNode<IntPtrT> node,intptr_t * out)352   bool ToParameterConstant(TNode<IntPtrT> node, intptr_t* out) {
353     intptr_t constant;
354     if (ToIntPtrConstant(node, &constant)) {
355       *out = constant;
356       return true;
357     }
358     return false;
359   }
360 
361 #if defined(BINT_IS_SMI)
BIntToSmi(TNode<BInt> source)362   TNode<Smi> BIntToSmi(TNode<BInt> source) { return source; }
BIntToIntPtr(TNode<BInt> source)363   TNode<IntPtrT> BIntToIntPtr(TNode<BInt> source) {
364     return SmiToIntPtr(source);
365   }
SmiToBInt(TNode<Smi> source)366   TNode<BInt> SmiToBInt(TNode<Smi> source) { return source; }
IntPtrToBInt(TNode<IntPtrT> source)367   TNode<BInt> IntPtrToBInt(TNode<IntPtrT> source) {
368     return SmiFromIntPtr(source);
369   }
370 #elif defined(BINT_IS_INTPTR)
BIntToSmi(TNode<BInt> source)371   TNode<Smi> BIntToSmi(TNode<BInt> source) { return SmiFromIntPtr(source); }
BIntToIntPtr(TNode<BInt> source)372   TNode<IntPtrT> BIntToIntPtr(TNode<BInt> source) { return source; }
SmiToBInt(TNode<Smi> source)373   TNode<BInt> SmiToBInt(TNode<Smi> source) { return SmiToIntPtr(source); }
IntPtrToBInt(TNode<IntPtrT> source)374   TNode<BInt> IntPtrToBInt(TNode<IntPtrT> source) { return source; }
375 #else
376 #error Unknown architecture.
377 #endif
378 
379   TNode<IntPtrT> TaggedIndexToIntPtr(TNode<TaggedIndex> value);
380   TNode<TaggedIndex> IntPtrToTaggedIndex(TNode<IntPtrT> value);
381   // TODO(v8:10047): Get rid of these convertions eventually.
382   TNode<Smi> TaggedIndexToSmi(TNode<TaggedIndex> value);
383   TNode<TaggedIndex> SmiToTaggedIndex(TNode<Smi> value);
384 
385   // Pointer compression specific. Ensures that the upper 32 bits of a Smi
386   // contain the sign of a lower 32 bits so that the Smi can be directly used
387   // as an index in element offset computation.
388   TNode<Smi> NormalizeSmiIndex(TNode<Smi> smi_index);
389 
TaggedToSmi(TNode<Object> value,Label * fail)390   TNode<Smi> TaggedToSmi(TNode<Object> value, Label* fail) {
391     GotoIf(TaggedIsNotSmi(value), fail);
392     return UncheckedCast<Smi>(value);
393   }
394 
TaggedToPositiveSmi(TNode<Object> value,Label * fail)395   TNode<Smi> TaggedToPositiveSmi(TNode<Object> value, Label* fail) {
396     GotoIfNot(TaggedIsPositiveSmi(value), fail);
397     return UncheckedCast<Smi>(value);
398   }
399 
400   TNode<String> TaggedToDirectString(TNode<Object> value, Label* fail);
401 
TaggedToHeapObject(TNode<Object> value,Label * fail)402   TNode<HeapObject> TaggedToHeapObject(TNode<Object> value, Label* fail) {
403     GotoIf(TaggedIsSmi(value), fail);
404     return UncheckedCast<HeapObject>(value);
405   }
406 
Uint16Constant(uint16_t t)407   TNode<Uint16T> Uint16Constant(uint16_t t) {
408     return UncheckedCast<Uint16T>(Int32Constant(t));
409   }
410 
HeapObjectToJSDataView(TNode<HeapObject> heap_object,Label * fail)411   TNode<JSDataView> HeapObjectToJSDataView(TNode<HeapObject> heap_object,
412                                            Label* fail) {
413     GotoIfNot(IsJSDataView(heap_object), fail);
414     return CAST(heap_object);
415   }
416 
HeapObjectToJSProxy(TNode<HeapObject> heap_object,Label * fail)417   TNode<JSProxy> HeapObjectToJSProxy(TNode<HeapObject> heap_object,
418                                      Label* fail) {
419     GotoIfNot(IsJSProxy(heap_object), fail);
420     return CAST(heap_object);
421   }
422 
HeapObjectToJSStringIterator(TNode<HeapObject> heap_object,Label * fail)423   TNode<JSStringIterator> HeapObjectToJSStringIterator(
424       TNode<HeapObject> heap_object, Label* fail) {
425     GotoIfNot(IsJSStringIterator(heap_object), fail);
426     return CAST(heap_object);
427   }
428 
HeapObjectToCallable(TNode<HeapObject> heap_object,Label * fail)429   TNode<JSReceiver> HeapObjectToCallable(TNode<HeapObject> heap_object,
430                                          Label* fail) {
431     GotoIfNot(IsCallable(heap_object), fail);
432     return CAST(heap_object);
433   }
434 
HeapObjectToString(TNode<HeapObject> heap_object,Label * fail)435   TNode<String> HeapObjectToString(TNode<HeapObject> heap_object, Label* fail) {
436     GotoIfNot(IsString(heap_object), fail);
437     return CAST(heap_object);
438   }
439 
HeapObjectToConstructor(TNode<HeapObject> heap_object,Label * fail)440   TNode<JSReceiver> HeapObjectToConstructor(TNode<HeapObject> heap_object,
441                                             Label* fail) {
442     GotoIfNot(IsConstructor(heap_object), fail);
443     return CAST(heap_object);
444   }
445 
HeapObjectToJSFunctionWithPrototypeSlot(TNode<HeapObject> heap_object,Label * fail)446   TNode<JSFunction> HeapObjectToJSFunctionWithPrototypeSlot(
447       TNode<HeapObject> heap_object, Label* fail) {
448     GotoIfNot(IsJSFunctionWithPrototypeSlot(heap_object), fail);
449     return CAST(heap_object);
450   }
451 
452 #define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName)                    \
453   TNode<Smi> OpName(TNode<Smi> a, TNode<Smi> b) { return SmiOpName(a, b); } \
454   TNode<IntPtrT> OpName(TNode<IntPtrT> a, TNode<IntPtrT> b) {               \
455     return IntPtrOpName(a, b);                                              \
456   }                                                                         \
457   TNode<UintPtrT> OpName(TNode<UintPtrT> a, TNode<UintPtrT> b) {            \
458     return Unsigned(IntPtrOpName(Signed(a), Signed(b)));                    \
459   }                                                                         \
460   TNode<RawPtrT> OpName(TNode<RawPtrT> a, TNode<RawPtrT> b) {               \
461     return ReinterpretCast<RawPtrT>(IntPtrOpName(                           \
462         ReinterpretCast<IntPtrT>(a), ReinterpretCast<IntPtrT>(b)));         \
463   }
464   // TODO(v8:9708): Define BInt operations once all uses are ported.
PARAMETER_BINOP(IntPtrOrSmiAdd,IntPtrAdd,SmiAdd)465   PARAMETER_BINOP(IntPtrOrSmiAdd, IntPtrAdd, SmiAdd)
466   PARAMETER_BINOP(IntPtrOrSmiSub, IntPtrSub, SmiSub)
467 #undef PARAMETER_BINOP
468 
469 #define PARAMETER_BINOP(OpName, IntPtrOpName, SmiOpName)                      \
470   TNode<BoolT> OpName(TNode<Smi> a, TNode<Smi> b) { return SmiOpName(a, b); } \
471   TNode<BoolT> OpName(TNode<IntPtrT> a, TNode<IntPtrT> b) {                   \
472     return IntPtrOpName(a, b);                                                \
473   }                                                                           \
474   TNode<BoolT> OpName(TNode<UintPtrT> a, TNode<UintPtrT> b) {                 \
475     return IntPtrOpName(Signed(a), Signed(b));                                \
476   }                                                                           \
477   TNode<BoolT> OpName(TNode<RawPtrT> a, TNode<RawPtrT> b) {                   \
478     return IntPtrOpName(a, b);                                                \
479   }
480   // TODO(v8:9708): Define BInt operations once all uses are ported.
481   PARAMETER_BINOP(IntPtrOrSmiEqual, WordEqual, SmiEqual)
482   PARAMETER_BINOP(IntPtrOrSmiNotEqual, WordNotEqual, SmiNotEqual)
483   PARAMETER_BINOP(IntPtrOrSmiLessThanOrEqual, IntPtrLessThanOrEqual,
484                   SmiLessThanOrEqual)
485   PARAMETER_BINOP(IntPtrOrSmiGreaterThan, IntPtrGreaterThan, SmiGreaterThan)
486   PARAMETER_BINOP(UintPtrOrSmiLessThan, UintPtrLessThan, SmiBelow)
487   PARAMETER_BINOP(UintPtrOrSmiGreaterThanOrEqual, UintPtrGreaterThanOrEqual,
488                   SmiAboveOrEqual)
489 #undef PARAMETER_BINOP
490 
491   uintptr_t ConstexprUintPtrShl(uintptr_t a, int32_t b) { return a << b; }
ConstexprUintPtrShr(uintptr_t a,int32_t b)492   uintptr_t ConstexprUintPtrShr(uintptr_t a, int32_t b) { return a >> b; }
ConstexprIntPtrAdd(intptr_t a,intptr_t b)493   intptr_t ConstexprIntPtrAdd(intptr_t a, intptr_t b) { return a + b; }
ConstexprUintPtrAdd(uintptr_t a,uintptr_t b)494   uintptr_t ConstexprUintPtrAdd(uintptr_t a, uintptr_t b) { return a + b; }
ConstexprWordNot(intptr_t a)495   intptr_t ConstexprWordNot(intptr_t a) { return ~a; }
ConstexprWordNot(uintptr_t a)496   uintptr_t ConstexprWordNot(uintptr_t a) { return ~a; }
497 
TaggedEqual(TNode<AnyTaggedT> a,TNode<AnyTaggedT> b)498   TNode<BoolT> TaggedEqual(TNode<AnyTaggedT> a, TNode<AnyTaggedT> b) {
499     if (COMPRESS_POINTERS_BOOL) {
500       return Word32Equal(ReinterpretCast<Word32T>(a),
501                          ReinterpretCast<Word32T>(b));
502     } else {
503       return WordEqual(ReinterpretCast<WordT>(a), ReinterpretCast<WordT>(b));
504     }
505   }
506 
TaggedNotEqual(TNode<AnyTaggedT> a,TNode<AnyTaggedT> b)507   TNode<BoolT> TaggedNotEqual(TNode<AnyTaggedT> a, TNode<AnyTaggedT> b) {
508     return Word32BinaryNot(TaggedEqual(a, b));
509   }
510 
511   TNode<Smi> NoContextConstant();
512 
513 #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name)  \
514   TNode<std::remove_pointer<std::remove_reference<decltype(            \
515       std::declval<ReadOnlyRoots>().rootAccessorName())>::type>::type> \
516       name##Constant();
517   HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR)
518 #undef HEAP_CONSTANT_ACCESSOR
519 
520 #define HEAP_CONSTANT_ACCESSOR(rootIndexName, rootAccessorName, name) \
521   TNode<std::remove_pointer<std::remove_reference<decltype(           \
522       std::declval<Heap>().rootAccessorName())>::type>::type>         \
523       name##Constant();
524   HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_ACCESSOR)
525 #undef HEAP_CONSTANT_ACCESSOR
526 
527 #define HEAP_CONSTANT_TEST(rootIndexName, rootAccessorName, name) \
528   TNode<BoolT> Is##name(SloppyTNode<Object> value);               \
529   TNode<BoolT> IsNot##name(SloppyTNode<Object> value);
530   HEAP_IMMOVABLE_OBJECT_LIST(HEAP_CONSTANT_TEST)
531 #undef HEAP_CONSTANT_TEST
532 
533   TNode<BInt> BIntConstant(int value);
534 
535   template <typename TIndex>
536   TNode<TIndex> IntPtrOrSmiConstant(int value);
537 
538   bool TryGetIntPtrOrSmiConstantValue(TNode<Smi> maybe_constant, int* value);
539   bool TryGetIntPtrOrSmiConstantValue(TNode<IntPtrT> maybe_constant,
540                                       int* value);
541 
542   // Round the 32bits payload of the provided word up to the next power of two.
543   TNode<IntPtrT> IntPtrRoundUpToPowerOfTwo32(TNode<IntPtrT> value);
544   // Select the maximum of the two provided IntPtr values.
545   TNode<IntPtrT> IntPtrMax(SloppyTNode<IntPtrT> left,
546                            SloppyTNode<IntPtrT> right);
547   // Select the minimum of the two provided IntPtr values.
548   TNode<IntPtrT> IntPtrMin(SloppyTNode<IntPtrT> left,
549                            SloppyTNode<IntPtrT> right);
550   TNode<UintPtrT> UintPtrMin(TNode<UintPtrT> left, TNode<UintPtrT> right);
551 
552   // Float64 operations.
553   TNode<Float64T> Float64Ceil(SloppyTNode<Float64T> x);
554   TNode<Float64T> Float64Floor(SloppyTNode<Float64T> x);
555   TNode<Float64T> Float64Round(SloppyTNode<Float64T> x);
556   TNode<Float64T> Float64RoundToEven(SloppyTNode<Float64T> x);
557   TNode<Float64T> Float64Trunc(SloppyTNode<Float64T> x);
558   // Select the minimum of the two provided Number values.
559   TNode<Number> NumberMax(TNode<Number> left, TNode<Number> right);
560   // Select the minimum of the two provided Number values.
561   TNode<Number> NumberMin(TNode<Number> left, TNode<Number> right);
562 
563   // Returns true iff the given value fits into smi range and is >= 0.
564   TNode<BoolT> IsValidPositiveSmi(TNode<IntPtrT> value);
565 
566   // Tag an IntPtr as a Smi value.
567   TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value);
568   // Untag a Smi value as an IntPtr.
569   TNode<IntPtrT> SmiUntag(SloppyTNode<Smi> value);
570 
571   // Smi conversions.
572   TNode<Float64T> SmiToFloat64(SloppyTNode<Smi> value);
SmiFromIntPtr(SloppyTNode<IntPtrT> value)573   TNode<Smi> SmiFromIntPtr(SloppyTNode<IntPtrT> value) { return SmiTag(value); }
574   TNode<Smi> SmiFromInt32(SloppyTNode<Int32T> value);
575   TNode<Smi> SmiFromUint32(TNode<Uint32T> value);
SmiToIntPtr(SloppyTNode<Smi> value)576   TNode<IntPtrT> SmiToIntPtr(SloppyTNode<Smi> value) { return SmiUntag(value); }
577   TNode<Int32T> SmiToInt32(SloppyTNode<Smi> value);
578 
579   // Smi operations.
580 #define SMI_ARITHMETIC_BINOP(SmiOpName, IntPtrOpName, Int32OpName)          \
581   TNode<Smi> SmiOpName(TNode<Smi> a, TNode<Smi> b) {                        \
582     if (SmiValuesAre32Bits()) {                                             \
583       return BitcastWordToTaggedSigned(                                     \
584           IntPtrOpName(BitcastTaggedToWordForTagAndSmiBits(a),              \
585                        BitcastTaggedToWordForTagAndSmiBits(b)));            \
586     } else {                                                                \
587       DCHECK(SmiValuesAre31Bits());                                         \
588       return BitcastWordToTaggedSigned(ChangeInt32ToIntPtr(Int32OpName(     \
589           TruncateIntPtrToInt32(BitcastTaggedToWordForTagAndSmiBits(a)),    \
590           TruncateIntPtrToInt32(BitcastTaggedToWordForTagAndSmiBits(b))))); \
591     }                                                                       \
592   }
593   SMI_ARITHMETIC_BINOP(SmiAdd, IntPtrAdd, Int32Add)
594   SMI_ARITHMETIC_BINOP(SmiSub, IntPtrSub, Int32Sub)
595   SMI_ARITHMETIC_BINOP(SmiAnd, WordAnd, Word32And)
596   SMI_ARITHMETIC_BINOP(SmiOr, WordOr, Word32Or)
597 #undef SMI_ARITHMETIC_BINOP
598 
599   TNode<IntPtrT> TryIntPtrAdd(TNode<IntPtrT> a, TNode<IntPtrT> b,
600                               Label* if_overflow);
601   TNode<IntPtrT> TryIntPtrSub(TNode<IntPtrT> a, TNode<IntPtrT> b,
602                               Label* if_overflow);
603   TNode<Int32T> TryInt32Mul(TNode<Int32T> a, TNode<Int32T> b,
604                             Label* if_overflow);
605   TNode<Smi> TrySmiAdd(TNode<Smi> a, TNode<Smi> b, Label* if_overflow);
606   TNode<Smi> TrySmiSub(TNode<Smi> a, TNode<Smi> b, Label* if_overflow);
607   TNode<Smi> TrySmiAbs(TNode<Smi> a, Label* if_overflow);
608 
SmiShl(TNode<Smi> a,int shift)609   TNode<Smi> SmiShl(TNode<Smi> a, int shift) {
610     return BitcastWordToTaggedSigned(
611         WordShl(BitcastTaggedToWordForTagAndSmiBits(a), shift));
612   }
613 
SmiShr(TNode<Smi> a,int shift)614   TNode<Smi> SmiShr(TNode<Smi> a, int shift) {
615     if (kTaggedSize == kInt64Size) {
616       return BitcastWordToTaggedSigned(
617           WordAnd(WordShr(BitcastTaggedToWordForTagAndSmiBits(a), shift),
618                   BitcastTaggedToWordForTagAndSmiBits(SmiConstant(-1))));
619     } else {
620       // For pointer compressed Smis, we want to make sure that we truncate to
621       // int32 before shifting, to avoid the values of the top 32-bits from
622       // leaking into the sign bit of the smi.
623       return BitcastWordToTaggedSigned(WordAnd(
624           ChangeInt32ToIntPtr(Word32Shr(
625               TruncateWordToInt32(BitcastTaggedToWordForTagAndSmiBits(a)),
626               shift)),
627           BitcastTaggedToWordForTagAndSmiBits(SmiConstant(-1))));
628     }
629   }
630 
SmiSar(TNode<Smi> a,int shift)631   TNode<Smi> SmiSar(TNode<Smi> a, int shift) {
632     if (kTaggedSize == kInt64Size) {
633       return BitcastWordToTaggedSigned(
634           WordAnd(WordSar(BitcastTaggedToWordForTagAndSmiBits(a), shift),
635                   BitcastTaggedToWordForTagAndSmiBits(SmiConstant(-1))));
636     } else {
637       // For pointer compressed Smis, we want to make sure that we truncate to
638       // int32 before shifting, to avoid the values of the top 32-bits from
639       // changing the sign bit of the smi.
640       return BitcastWordToTaggedSigned(WordAnd(
641           ChangeInt32ToIntPtr(Word32Sar(
642               TruncateWordToInt32(BitcastTaggedToWordForTagAndSmiBits(a)),
643               shift)),
644           BitcastTaggedToWordForTagAndSmiBits(SmiConstant(-1))));
645     }
646   }
647 
WordOrSmiShr(TNode<Smi> a,int shift)648   TNode<Smi> WordOrSmiShr(TNode<Smi> a, int shift) { return SmiShr(a, shift); }
649 
WordOrSmiShr(TNode<IntPtrT> a,int shift)650   TNode<IntPtrT> WordOrSmiShr(TNode<IntPtrT> a, int shift) {
651     return WordShr(a, shift);
652   }
653 
654 #define SMI_COMPARISON_OP(SmiOpName, IntPtrOpName, Int32OpName)           \
655   TNode<BoolT> SmiOpName(TNode<Smi> a, TNode<Smi> b) {                    \
656     if (kTaggedSize == kInt64Size) {                                      \
657       return IntPtrOpName(BitcastTaggedToWordForTagAndSmiBits(a),         \
658                           BitcastTaggedToWordForTagAndSmiBits(b));        \
659     } else {                                                              \
660       DCHECK_EQ(kTaggedSize, kInt32Size);                                 \
661       DCHECK(SmiValuesAre31Bits());                                       \
662       return Int32OpName(                                                 \
663           TruncateIntPtrToInt32(BitcastTaggedToWordForTagAndSmiBits(a)),  \
664           TruncateIntPtrToInt32(BitcastTaggedToWordForTagAndSmiBits(b))); \
665     }                                                                     \
666   }
667   SMI_COMPARISON_OP(SmiEqual, WordEqual, Word32Equal)
668   SMI_COMPARISON_OP(SmiNotEqual, WordNotEqual, Word32NotEqual)
669   SMI_COMPARISON_OP(SmiAbove, UintPtrGreaterThan, Uint32GreaterThan)
670   SMI_COMPARISON_OP(SmiAboveOrEqual, UintPtrGreaterThanOrEqual,
671                     Uint32GreaterThanOrEqual)
672   SMI_COMPARISON_OP(SmiBelow, UintPtrLessThan, Uint32LessThan)
673   SMI_COMPARISON_OP(SmiLessThan, IntPtrLessThan, Int32LessThan)
674   SMI_COMPARISON_OP(SmiLessThanOrEqual, IntPtrLessThanOrEqual,
675                     Int32LessThanOrEqual)
676   SMI_COMPARISON_OP(SmiGreaterThan, IntPtrGreaterThan, Int32GreaterThan)
677   SMI_COMPARISON_OP(SmiGreaterThanOrEqual, IntPtrGreaterThanOrEqual,
678                     Int32GreaterThanOrEqual)
679 #undef SMI_COMPARISON_OP
680   TNode<Smi> SmiMax(TNode<Smi> a, TNode<Smi> b);
681   TNode<Smi> SmiMin(TNode<Smi> a, TNode<Smi> b);
682   // Computes a % b for Smi inputs a and b; result is not necessarily a Smi.
683   TNode<Number> SmiMod(TNode<Smi> a, TNode<Smi> b);
684   // Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
685   TNode<Number> SmiMul(TNode<Smi> a, TNode<Smi> b);
686   // Tries to compute dividend / divisor for Smi inputs; branching to bailout
687   // if the division needs to be performed as a floating point operation.
688   TNode<Smi> TrySmiDiv(TNode<Smi> dividend, TNode<Smi> divisor, Label* bailout);
689 
690   // Compares two Smis a and b as if they were converted to strings and then
691   // compared lexicographically. Returns:
692   // -1 iff x < y.
693   //  0 iff x == y.
694   //  1 iff x > y.
695   TNode<Smi> SmiLexicographicCompare(TNode<Smi> x, TNode<Smi> y);
696 
697 #ifdef BINT_IS_SMI
698 #define BINT_COMPARISON_OP(BIntOpName, SmiOpName, IntPtrOpName) \
699   TNode<BoolT> BIntOpName(TNode<BInt> a, TNode<BInt> b) {       \
700     return SmiOpName(a, b);                                     \
701   }
702 #else
703 #define BINT_COMPARISON_OP(BIntOpName, SmiOpName, IntPtrOpName) \
704   TNode<BoolT> BIntOpName(TNode<BInt> a, TNode<BInt> b) {       \
705     return IntPtrOpName(a, b);                                  \
706   }
707 #endif
708   BINT_COMPARISON_OP(BIntEqual, SmiEqual, WordEqual)
709   BINT_COMPARISON_OP(BIntNotEqual, SmiNotEqual, WordNotEqual)
710   BINT_COMPARISON_OP(BIntAbove, SmiAbove, UintPtrGreaterThan)
711   BINT_COMPARISON_OP(BIntAboveOrEqual, SmiAboveOrEqual,
712                      UintPtrGreaterThanOrEqual)
713   BINT_COMPARISON_OP(BIntBelow, SmiBelow, UintPtrLessThan)
714   BINT_COMPARISON_OP(BIntLessThan, SmiLessThan, IntPtrLessThan)
715   BINT_COMPARISON_OP(BIntLessThanOrEqual, SmiLessThanOrEqual,
716                      IntPtrLessThanOrEqual)
717   BINT_COMPARISON_OP(BIntGreaterThan, SmiGreaterThan, IntPtrGreaterThan)
718   BINT_COMPARISON_OP(BIntGreaterThanOrEqual, SmiGreaterThanOrEqual,
719                      IntPtrGreaterThanOrEqual)
720 #undef BINT_COMPARISON_OP
721 
722   // Smi | HeapNumber operations.
723   TNode<Number> NumberInc(TNode<Number> value);
724   TNode<Number> NumberDec(TNode<Number> value);
725   TNode<Number> NumberAdd(TNode<Number> a, TNode<Number> b);
726   TNode<Number> NumberSub(TNode<Number> a, TNode<Number> b);
727   void GotoIfNotNumber(TNode<Object> value, Label* is_not_number);
728   void GotoIfNumber(TNode<Object> value, Label* is_number);
SmiToNumber(TNode<Smi> v)729   TNode<Number> SmiToNumber(TNode<Smi> v) { return v; }
730 
731   TNode<Number> BitwiseOp(TNode<Word32T> left32, TNode<Word32T> right32,
732                           Operation bitwise_op);
733 
734   // Allocate an object of the given size.
735   TNode<HeapObject> AllocateInNewSpace(TNode<IntPtrT> size,
736                                        AllocationFlags flags = kNone);
737   TNode<HeapObject> AllocateInNewSpace(int size, AllocationFlags flags = kNone);
738   TNode<HeapObject> Allocate(TNode<IntPtrT> size,
739                              AllocationFlags flags = kNone);
740 
741   TNode<HeapObject> Allocate(int size, AllocationFlags flags = kNone);
742   TNode<HeapObject> InnerAllocate(TNode<HeapObject> previous, int offset);
743   TNode<HeapObject> InnerAllocate(TNode<HeapObject> previous,
744                                   TNode<IntPtrT> offset);
745 
746   TNode<BoolT> IsRegularHeapObjectSize(TNode<IntPtrT> size);
747 
748   using BranchGenerator = std::function<void(Label*, Label*)>;
749   template <typename T>
750   using NodeGenerator = std::function<TNode<T>()>;
751   using ExtraNode = std::pair<TNode<Object>, const char*>;
752 
753   void Assert(const BranchGenerator& branch, const char* message,
754               const char* file, int line,
755               std::initializer_list<ExtraNode> extra_nodes = {});
756   void Assert(const NodeGenerator<BoolT>& condition_body, const char* message,
757               const char* file, int line,
758               std::initializer_list<ExtraNode> extra_nodes = {});
759   void Assert(TNode<Word32T> condition_node, const char* message,
760               const char* file, int line,
761               std::initializer_list<ExtraNode> extra_nodes = {});
762   void Check(const BranchGenerator& branch, const char* message,
763              const char* file, int line,
764              std::initializer_list<ExtraNode> extra_nodes = {});
765   void Check(const NodeGenerator<BoolT>& condition_body, const char* message,
766              const char* file, int line,
767              std::initializer_list<ExtraNode> extra_nodes = {});
768   void Check(TNode<Word32T> condition_node, const char* message,
769              const char* file, int line,
770              std::initializer_list<ExtraNode> extra_nodes = {});
771   void FailAssert(const char* message,
772                   const std::vector<FileAndLine>& files_and_lines,
773                   std::initializer_list<ExtraNode> extra_nodes = {});
774 
775   void FastCheck(TNode<BoolT> condition);
776 
777   // The following Call wrappers call an object according to the semantics that
778   // one finds in the EcmaScript spec, operating on an Callable (e.g. a
779   // JSFunction or proxy) rather than a Code object.
780   template <class... TArgs>
Call(TNode<Context> context,TNode<Object> callable,TNode<JSReceiver> receiver,TArgs...args)781   TNode<Object> Call(TNode<Context> context, TNode<Object> callable,
782                      TNode<JSReceiver> receiver, TArgs... args) {
783     return UncheckedCast<Object>(CallJS(
784         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
785         context, callable, receiver, args...));
786   }
787   template <class... TArgs>
Call(TNode<Context> context,TNode<Object> callable,TNode<Object> receiver,TArgs...args)788   TNode<Object> Call(TNode<Context> context, TNode<Object> callable,
789                      TNode<Object> receiver, TArgs... args) {
790     if (IsUndefinedConstant(receiver) || IsNullConstant(receiver)) {
791       return UncheckedCast<Object>(CallJS(
792           CodeFactory::Call(isolate(), ConvertReceiverMode::kNullOrUndefined),
793           context, callable, receiver, args...));
794     }
795     return UncheckedCast<Object>(CallJS(CodeFactory::Call(isolate()), context,
796                                         callable, receiver, args...));
797   }
798 
799   TNode<Object> CallApiCallback(TNode<Object> context, TNode<RawPtrT> callback,
800                                 TNode<IntPtrT> argc, TNode<Object> data,
801                                 TNode<Object> holder, TNode<Object> receiver);
802 
803   TNode<Object> CallApiCallback(TNode<Object> context, TNode<RawPtrT> callback,
804                                 TNode<IntPtrT> argc, TNode<Object> data,
805                                 TNode<Object> holder, TNode<Object> receiver,
806                                 TNode<Object> value);
807 
808   TNode<Object> CallRuntimeNewArray(TNode<Context> context,
809                                     TNode<Object> receiver,
810                                     TNode<Object> length,
811                                     TNode<Object> new_target,
812                                     TNode<Object> allocation_site);
813 
814   void TailCallRuntimeNewArray(TNode<Context> context, TNode<Object> receiver,
815                                TNode<Object> length, TNode<Object> new_target,
816                                TNode<Object> allocation_site);
817 
818   template <class... TArgs>
ConstructWithTarget(TNode<Context> context,TNode<JSReceiver> target,TNode<JSReceiver> new_target,TArgs...args)819   TNode<JSReceiver> ConstructWithTarget(TNode<Context> context,
820                                         TNode<JSReceiver> target,
821                                         TNode<JSReceiver> new_target,
822                                         TArgs... args) {
823     return CAST(ConstructJSWithTarget(CodeFactory::Construct(isolate()),
824                                       context, target, new_target,
825                                       implicit_cast<TNode<Object>>(args)...));
826   }
827   template <class... TArgs>
Construct(TNode<Context> context,TNode<JSReceiver> new_target,TArgs...args)828   TNode<JSReceiver> Construct(TNode<Context> context,
829                               TNode<JSReceiver> new_target, TArgs... args) {
830     return ConstructWithTarget(context, new_target, new_target, args...);
831   }
832 
833   template <typename T>
Select(TNode<BoolT> condition,const NodeGenerator<T> & true_body,const NodeGenerator<T> & false_body)834   TNode<T> Select(TNode<BoolT> condition, const NodeGenerator<T>& true_body,
835                   const NodeGenerator<T>& false_body) {
836     TVARIABLE(T, value);
837     Label vtrue(this), vfalse(this), end(this);
838     Branch(condition, &vtrue, &vfalse);
839 
840     BIND(&vtrue);
841     {
842       value = true_body();
843       Goto(&end);
844     }
845     BIND(&vfalse);
846     {
847       value = false_body();
848       Goto(&end);
849     }
850 
851     BIND(&end);
852     return value.value();
853   }
854 
855   template <class A>
SelectConstant(TNode<BoolT> condition,TNode<A> true_value,TNode<A> false_value)856   TNode<A> SelectConstant(TNode<BoolT> condition, TNode<A> true_value,
857                           TNode<A> false_value) {
858     return Select<A>(
859         condition, [=] { return true_value; }, [=] { return false_value; });
860   }
861 
862   TNode<Int32T> SelectInt32Constant(TNode<BoolT> condition, int true_value,
863                                     int false_value);
864   TNode<IntPtrT> SelectIntPtrConstant(TNode<BoolT> condition, int true_value,
865                                       int false_value);
866   TNode<Oddball> SelectBooleanConstant(TNode<BoolT> condition);
867   TNode<Smi> SelectSmiConstant(TNode<BoolT> condition, Smi true_value,
868                                Smi false_value);
SelectSmiConstant(TNode<BoolT> condition,int true_value,Smi false_value)869   TNode<Smi> SelectSmiConstant(TNode<BoolT> condition, int true_value,
870                                Smi false_value) {
871     return SelectSmiConstant(condition, Smi::FromInt(true_value), false_value);
872   }
SelectSmiConstant(TNode<BoolT> condition,Smi true_value,int false_value)873   TNode<Smi> SelectSmiConstant(TNode<BoolT> condition, Smi true_value,
874                                int false_value) {
875     return SelectSmiConstant(condition, true_value, Smi::FromInt(false_value));
876   }
SelectSmiConstant(TNode<BoolT> condition,int true_value,int false_value)877   TNode<Smi> SelectSmiConstant(TNode<BoolT> condition, int true_value,
878                                int false_value) {
879     return SelectSmiConstant(condition, Smi::FromInt(true_value),
880                              Smi::FromInt(false_value));
881   }
882 
SingleCharacterStringConstant(char const * single_char)883   TNode<String> SingleCharacterStringConstant(char const* single_char) {
884     DCHECK_EQ(strlen(single_char), 1);
885     return HeapConstant(
886         isolate()->factory()->LookupSingleCharacterStringFromCode(
887             single_char[0]));
888   }
889 
890   TNode<Int32T> TruncateWordToInt32(SloppyTNode<WordT> value);
891   TNode<Int32T> TruncateIntPtrToInt32(SloppyTNode<IntPtrT> value);
892 
893   // Check a value for smi-ness
894   TNode<BoolT> TaggedIsSmi(TNode<MaybeObject> a);
895   TNode<BoolT> TaggedIsNotSmi(TNode<MaybeObject> a);
896 
897   // Check that the value is a non-negative smi.
898   TNode<BoolT> TaggedIsPositiveSmi(SloppyTNode<Object> a);
899   // Check that a word has a word-aligned address.
900   TNode<BoolT> WordIsAligned(SloppyTNode<WordT> word, size_t alignment);
901   TNode<BoolT> WordIsPowerOfTwo(SloppyTNode<IntPtrT> value);
902 
903   // Check if lower_limit <= value <= higher_limit.
904   template <typename U>
IsInRange(TNode<Word32T> value,U lower_limit,U higher_limit)905   TNode<BoolT> IsInRange(TNode<Word32T> value, U lower_limit, U higher_limit) {
906     DCHECK_LE(lower_limit, higher_limit);
907     STATIC_ASSERT(sizeof(U) <= kInt32Size);
908     return Uint32LessThanOrEqual(Int32Sub(value, Int32Constant(lower_limit)),
909                                  Int32Constant(higher_limit - lower_limit));
910   }
911 
IsInRange(TNode<WordT> value,intptr_t lower_limit,intptr_t higher_limit)912   TNode<BoolT> IsInRange(TNode<WordT> value, intptr_t lower_limit,
913                          intptr_t higher_limit) {
914     DCHECK_LE(lower_limit, higher_limit);
915     return UintPtrLessThanOrEqual(IntPtrSub(value, IntPtrConstant(lower_limit)),
916                                   IntPtrConstant(higher_limit - lower_limit));
917   }
918 
919 #if DEBUG
920   void Bind(Label* label, AssemblerDebugInfo debug_info);
921 #endif  // DEBUG
922   void Bind(Label* label);
923 
924   template <class... T>
Bind(compiler::CodeAssemblerParameterizedLabel<T...> * label,TNode<T> * ...phis)925   void Bind(compiler::CodeAssemblerParameterizedLabel<T...>* label,
926             TNode<T>*... phis) {
927     CodeAssembler::Bind(label, phis...);
928   }
929 
BranchIfSmiEqual(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)930   void BranchIfSmiEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true,
931                         Label* if_false) {
932     Branch(SmiEqual(a, b), if_true, if_false);
933   }
934 
BranchIfSmiLessThan(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)935   void BranchIfSmiLessThan(TNode<Smi> a, TNode<Smi> b, Label* if_true,
936                            Label* if_false) {
937     Branch(SmiLessThan(a, b), if_true, if_false);
938   }
939 
BranchIfSmiLessThanOrEqual(TNode<Smi> a,TNode<Smi> b,Label * if_true,Label * if_false)940   void BranchIfSmiLessThanOrEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true,
941                                   Label* if_false) {
942     Branch(SmiLessThanOrEqual(a, b), if_true, if_false);
943   }
944 
BranchIfFloat64IsNaN(TNode<Float64T> value,Label * if_true,Label * if_false)945   void BranchIfFloat64IsNaN(TNode<Float64T> value, Label* if_true,
946                             Label* if_false) {
947     Branch(Float64Equal(value, value), if_false, if_true);
948   }
949 
950   // Branches to {if_true} if ToBoolean applied to {value} yields true,
951   // otherwise goes to {if_false}.
952   void BranchIfToBooleanIsTrue(SloppyTNode<Object> value, Label* if_true,
953                                Label* if_false);
954 
955   // Branches to {if_false} if ToBoolean applied to {value} yields false,
956   // otherwise goes to {if_true}.
BranchIfToBooleanIsFalse(SloppyTNode<Object> value,Label * if_false,Label * if_true)957   void BranchIfToBooleanIsFalse(SloppyTNode<Object> value, Label* if_false,
958                                 Label* if_true) {
959     BranchIfToBooleanIsTrue(value, if_true, if_false);
960   }
961 
962   void BranchIfJSReceiver(SloppyTNode<Object> object, Label* if_true,
963                           Label* if_false);
964 
965   // Branches to {if_true} when --force-slow-path flag has been passed.
966   // It's used for testing to ensure that slow path implementation behave
967   // equivalent to corresponding fast paths (where applicable).
968   //
969   // Works only with V8_ENABLE_FORCE_SLOW_PATH compile time flag. Nop otherwise.
970   void GotoIfForceSlowPath(Label* if_true);
971 
972   //
973   // ExternalPointerT-related functionality.
974   //
975 
976   TNode<ExternalPointerT> ChangeUint32ToExternalPointer(TNode<Uint32T> value);
977   TNode<Uint32T> ChangeExternalPointerToUint32(TNode<ExternalPointerT> value);
978 
979   // Initialize an external pointer field in an object.
InitializeExternalPointerField(TNode<HeapObject> object,int offset)980   void InitializeExternalPointerField(TNode<HeapObject> object, int offset) {
981     InitializeExternalPointerField(object, IntPtrConstant(offset));
982   }
983   void InitializeExternalPointerField(TNode<HeapObject> object,
984                                       TNode<IntPtrT> offset);
985 
986   // Initialize an external pointer field in an object with given value.
InitializeExternalPointerField(TNode<HeapObject> object,int offset,TNode<RawPtrT> pointer,ExternalPointerTag tag)987   void InitializeExternalPointerField(TNode<HeapObject> object, int offset,
988                                       TNode<RawPtrT> pointer,
989                                       ExternalPointerTag tag) {
990     InitializeExternalPointerField(object, IntPtrConstant(offset), pointer,
991                                    tag);
992   }
993 
InitializeExternalPointerField(TNode<HeapObject> object,TNode<IntPtrT> offset,TNode<RawPtrT> pointer,ExternalPointerTag tag)994   void InitializeExternalPointerField(TNode<HeapObject> object,
995                                       TNode<IntPtrT> offset,
996                                       TNode<RawPtrT> pointer,
997                                       ExternalPointerTag tag) {
998     InitializeExternalPointerField(object, offset);
999     StoreExternalPointerToObject(object, offset, pointer, tag);
1000   }
1001 
1002   // Load an external pointer value from an object.
LoadExternalPointerFromObject(TNode<HeapObject> object,int offset,ExternalPointerTag tag)1003   TNode<RawPtrT> LoadExternalPointerFromObject(TNode<HeapObject> object,
1004                                                int offset,
1005                                                ExternalPointerTag tag) {
1006     return LoadExternalPointerFromObject(object, IntPtrConstant(offset), tag);
1007   }
1008 
1009   TNode<RawPtrT> LoadExternalPointerFromObject(TNode<HeapObject> object,
1010                                                TNode<IntPtrT> offset,
1011                                                ExternalPointerTag tag);
1012 
1013   // Store external object pointer to object.
StoreExternalPointerToObject(TNode<HeapObject> object,int offset,TNode<RawPtrT> pointer,ExternalPointerTag tag)1014   void StoreExternalPointerToObject(TNode<HeapObject> object, int offset,
1015                                     TNode<RawPtrT> pointer,
1016                                     ExternalPointerTag tag) {
1017     StoreExternalPointerToObject(object, IntPtrConstant(offset), pointer, tag);
1018   }
1019 
1020   void StoreExternalPointerToObject(TNode<HeapObject> object,
1021                                     TNode<IntPtrT> offset,
1022                                     TNode<RawPtrT> pointer,
1023                                     ExternalPointerTag tag);
1024 
LoadForeignForeignAddressPtr(TNode<Foreign> object)1025   TNode<RawPtrT> LoadForeignForeignAddressPtr(TNode<Foreign> object) {
1026     return LoadExternalPointerFromObject(object, Foreign::kForeignAddressOffset,
1027                                          kForeignForeignAddressTag);
1028   }
1029 
LoadExternalStringResourcePtr(TNode<ExternalString> object)1030   TNode<RawPtrT> LoadExternalStringResourcePtr(TNode<ExternalString> object) {
1031     return LoadExternalPointerFromObject(
1032         object, ExternalString::kResourceOffset, kExternalStringResourceTag);
1033   }
1034 
LoadExternalStringResourceDataPtr(TNode<ExternalString> object)1035   TNode<RawPtrT> LoadExternalStringResourceDataPtr(
1036       TNode<ExternalString> object) {
1037     return LoadExternalPointerFromObject(object,
1038                                          ExternalString::kResourceDataOffset,
1039                                          kExternalStringResourceDataTag);
1040   }
1041 
LoadJSTypedArrayExternalPointerPtr(TNode<JSTypedArray> holder)1042   TNode<RawPtrT> LoadJSTypedArrayExternalPointerPtr(
1043       TNode<JSTypedArray> holder) {
1044     return LoadExternalPointerFromObject(holder,
1045                                          JSTypedArray::kExternalPointerOffset,
1046                                          kTypedArrayExternalPointerTag);
1047   }
1048 
StoreJSTypedArrayExternalPointerPtr(TNode<JSTypedArray> holder,TNode<RawPtrT> value)1049   void StoreJSTypedArrayExternalPointerPtr(TNode<JSTypedArray> holder,
1050                                            TNode<RawPtrT> value) {
1051     StoreExternalPointerToObject(holder, JSTypedArray::kExternalPointerOffset,
1052                                  value, kTypedArrayExternalPointerTag);
1053   }
1054 
1055   // Load value from current parent frame by given offset in bytes.
1056   TNode<Object> LoadFromParentFrame(int offset);
1057 
1058   // Load an object pointer from a buffer that isn't in the heap.
LoadBufferObject(TNode<RawPtrT> buffer,int offset)1059   TNode<Object> LoadBufferObject(TNode<RawPtrT> buffer, int offset) {
1060     return LoadFullTagged(buffer, IntPtrConstant(offset));
1061   }
1062   template <typename T>
LoadBufferData(TNode<RawPtrT> buffer,int offset)1063   TNode<T> LoadBufferData(TNode<RawPtrT> buffer, int offset) {
1064     return UncheckedCast<T>(
1065         Load(MachineTypeOf<T>::value, buffer, IntPtrConstant(offset)));
1066   }
LoadBufferPointer(TNode<RawPtrT> buffer,int offset)1067   TNode<RawPtrT> LoadBufferPointer(TNode<RawPtrT> buffer, int offset) {
1068     return LoadBufferData<RawPtrT>(buffer, offset);
1069   }
LoadBufferSmi(TNode<RawPtrT> buffer,int offset)1070   TNode<Smi> LoadBufferSmi(TNode<RawPtrT> buffer, int offset) {
1071     return CAST(LoadBufferObject(buffer, offset));
1072   }
LoadBufferIntptr(TNode<RawPtrT> buffer,int offset)1073   TNode<IntPtrT> LoadBufferIntptr(TNode<RawPtrT> buffer, int offset) {
1074     return LoadBufferData<IntPtrT>(buffer, offset);
1075   }
1076   // Load a field from an object on the heap.
1077   template <class T, typename std::enable_if<
1078                          std::is_convertible<TNode<T>, TNode<Object>>::value,
1079                          int>::type = 0>
LoadObjectField(TNode<HeapObject> object,int offset)1080   TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) {
1081     return CAST(LoadFromObject(MachineTypeOf<T>::value, object,
1082                                IntPtrConstant(offset - kHeapObjectTag)));
1083   }
1084   template <class T, typename std::enable_if<
1085                          std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
1086                          int>::type = 0>
LoadObjectField(TNode<HeapObject> object,int offset)1087   TNode<T> LoadObjectField(TNode<HeapObject> object, int offset) {
1088     return UncheckedCast<T>(
1089         LoadFromObject(MachineTypeOf<T>::value, object,
1090                        IntPtrConstant(offset - kHeapObjectTag)));
1091   }
LoadObjectField(TNode<HeapObject> object,int offset)1092   TNode<Object> LoadObjectField(TNode<HeapObject> object, int offset) {
1093     return UncheckedCast<Object>(
1094         LoadFromObject(MachineType::AnyTagged(), object,
1095                        IntPtrConstant(offset - kHeapObjectTag)));
1096   }
LoadObjectField(TNode<HeapObject> object,TNode<IntPtrT> offset)1097   TNode<Object> LoadObjectField(TNode<HeapObject> object,
1098                                 TNode<IntPtrT> offset) {
1099     return UncheckedCast<Object>(
1100         LoadFromObject(MachineType::AnyTagged(), object,
1101                        IntPtrSub(offset, IntPtrConstant(kHeapObjectTag))));
1102   }
1103   template <class T, typename std::enable_if<
1104                          std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
1105                          int>::type = 0>
LoadObjectField(TNode<HeapObject> object,TNode<IntPtrT> offset)1106   TNode<T> LoadObjectField(TNode<HeapObject> object, TNode<IntPtrT> offset) {
1107     return UncheckedCast<T>(
1108         LoadFromObject(MachineTypeOf<T>::value, object,
1109                        IntPtrSub(offset, IntPtrConstant(kHeapObjectTag))));
1110   }
1111   // Load a SMI field and untag it.
1112   TNode<IntPtrT> LoadAndUntagObjectField(TNode<HeapObject> object, int offset);
1113   // Load a SMI field, untag it, and convert to Word32.
1114   TNode<Int32T> LoadAndUntagToWord32ObjectField(TNode<HeapObject> object,
1115                                                 int offset);
1116 
LoadMaybeWeakObjectField(TNode<HeapObject> object,int offset)1117   TNode<MaybeObject> LoadMaybeWeakObjectField(TNode<HeapObject> object,
1118                                               int offset) {
1119     return UncheckedCast<MaybeObject>(LoadObjectField(object, offset));
1120   }
1121 
LoadConstructorOrBackPointer(TNode<Map> map)1122   TNode<Object> LoadConstructorOrBackPointer(TNode<Map> map) {
1123     return LoadObjectField(map,
1124                            Map::kConstructorOrBackPointerOrNativeContextOffset);
1125   }
1126 
1127   // Reference is the CSA-equivalent of a Torque reference value,
1128   // representing an inner pointer into a HeapObject.
1129   // TODO(gsps): Remove in favor of flattened {Load,Store}Reference interface
1130   struct Reference {
1131     TNode<HeapObject> object;
1132     TNode<IntPtrT> offset;
1133 
FlattenReference1134     std::tuple<TNode<HeapObject>, TNode<IntPtrT>> Flatten() const {
1135       return std::make_tuple(object, offset);
1136     }
1137   };
1138 
1139   template <class T, typename std::enable_if<
1140                          std::is_convertible<TNode<T>, TNode<Object>>::value,
1141                          int>::type = 0>
LoadReference(Reference reference)1142   TNode<T> LoadReference(Reference reference) {
1143     TNode<IntPtrT> offset =
1144         IntPtrSub(reference.offset, IntPtrConstant(kHeapObjectTag));
1145     return CAST(
1146         LoadFromObject(MachineTypeOf<T>::value, reference.object, offset));
1147   }
1148   template <class T,
1149             typename std::enable_if<
1150                 std::is_convertible<TNode<T>, TNode<UntaggedT>>::value ||
1151                     std::is_same<T, MaybeObject>::value,
1152                 int>::type = 0>
LoadReference(Reference reference)1153   TNode<T> LoadReference(Reference reference) {
1154     TNode<IntPtrT> offset =
1155         IntPtrSub(reference.offset, IntPtrConstant(kHeapObjectTag));
1156     return UncheckedCast<T>(
1157         LoadFromObject(MachineTypeOf<T>::value, reference.object, offset));
1158   }
1159   template <class T, typename std::enable_if<
1160                          std::is_convertible<TNode<T>, TNode<Object>>::value ||
1161                              std::is_same<T, MaybeObject>::value,
1162                          int>::type = 0>
StoreReference(Reference reference,TNode<T> value)1163   void StoreReference(Reference reference, TNode<T> value) {
1164     MachineRepresentation rep = MachineRepresentationOf<T>::value;
1165     StoreToObjectWriteBarrier write_barrier = StoreToObjectWriteBarrier::kFull;
1166     if (std::is_same<T, Smi>::value) {
1167       write_barrier = StoreToObjectWriteBarrier::kNone;
1168     } else if (std::is_same<T, Map>::value) {
1169       write_barrier = StoreToObjectWriteBarrier::kMap;
1170     }
1171     TNode<IntPtrT> offset =
1172         IntPtrSub(reference.offset, IntPtrConstant(kHeapObjectTag));
1173     StoreToObject(rep, reference.object, offset, value, write_barrier);
1174   }
1175   template <class T, typename std::enable_if<
1176                          std::is_convertible<TNode<T>, TNode<UntaggedT>>::value,
1177                          int>::type = 0>
StoreReference(Reference reference,TNode<T> value)1178   void StoreReference(Reference reference, TNode<T> value) {
1179     TNode<IntPtrT> offset =
1180         IntPtrSub(reference.offset, IntPtrConstant(kHeapObjectTag));
1181     StoreToObject(MachineRepresentationOf<T>::value, reference.object, offset,
1182                   value, StoreToObjectWriteBarrier::kNone);
1183   }
1184 
1185   // Load the floating point value of a HeapNumber.
1186   TNode<Float64T> LoadHeapNumberValue(TNode<HeapObject> object);
1187   // Load the Map of an HeapObject.
1188   TNode<Map> LoadMap(TNode<HeapObject> object);
1189   // Load the instance type of an HeapObject.
1190   TNode<Uint16T> LoadInstanceType(TNode<HeapObject> object);
1191   // Compare the instance the type of the object against the provided one.
1192   TNode<BoolT> HasInstanceType(TNode<HeapObject> object, InstanceType type);
1193   TNode<BoolT> DoesntHaveInstanceType(TNode<HeapObject> object,
1194                                       InstanceType type);
1195   TNode<BoolT> TaggedDoesntHaveInstanceType(TNode<HeapObject> any_tagged,
1196                                             InstanceType type);
1197 
1198   TNode<Word32T> IsStringWrapperElementsKind(TNode<Map> map);
1199   void GotoIfMapHasSlowProperties(TNode<Map> map, Label* if_slow);
1200 
1201   // Load the properties backing store of a JSReceiver.
1202   TNode<HeapObject> LoadSlowProperties(TNode<JSReceiver> object);
1203   TNode<HeapObject> LoadFastProperties(TNode<JSReceiver> object);
1204   // Load the elements backing store of a JSObject.
LoadElements(TNode<JSObject> object)1205   TNode<FixedArrayBase> LoadElements(TNode<JSObject> object) {
1206     return LoadJSObjectElements(object);
1207   }
1208   // Load the length of a JSArray instance.
1209   TNode<Object> LoadJSArgumentsObjectLength(TNode<Context> context,
1210                                             TNode<JSArgumentsObject> array);
1211   // Load the length of a fast JSArray instance. Returns a positive Smi.
1212   TNode<Smi> LoadFastJSArrayLength(TNode<JSArray> array);
1213   // Load the length of a fixed array base instance.
1214   TNode<Smi> LoadFixedArrayBaseLength(TNode<FixedArrayBase> array);
1215   // Load the length of a fixed array base instance.
1216   TNode<IntPtrT> LoadAndUntagFixedArrayBaseLength(TNode<FixedArrayBase> array);
1217   // Load the length of a WeakFixedArray.
1218   TNode<Smi> LoadWeakFixedArrayLength(TNode<WeakFixedArray> array);
1219   TNode<IntPtrT> LoadAndUntagWeakFixedArrayLength(TNode<WeakFixedArray> array);
1220   // Load the number of descriptors in DescriptorArray.
1221   TNode<Int32T> LoadNumberOfDescriptors(TNode<DescriptorArray> array);
1222   // Load the number of own descriptors of a map.
1223   TNode<Int32T> LoadNumberOfOwnDescriptors(TNode<Map> map);
1224   // Load the bit field of a Map.
1225   TNode<Int32T> LoadMapBitField(TNode<Map> map);
1226   // Load bit field 2 of a map.
1227   TNode<Int32T> LoadMapBitField2(TNode<Map> map);
1228   // Load bit field 3 of a map.
1229   TNode<Uint32T> LoadMapBitField3(TNode<Map> map);
1230   // Load the instance type of a map.
1231   TNode<Uint16T> LoadMapInstanceType(TNode<Map> map);
1232   // Load the ElementsKind of a map.
1233   TNode<Int32T> LoadMapElementsKind(TNode<Map> map);
1234   TNode<Int32T> LoadElementsKind(TNode<HeapObject> object);
1235   // Load the instance descriptors of a map.
1236   TNode<DescriptorArray> LoadMapDescriptors(TNode<Map> map);
1237   // Load the prototype of a map.
1238   TNode<HeapObject> LoadMapPrototype(TNode<Map> map);
1239   // Load the instance size of a Map.
1240   TNode<IntPtrT> LoadMapInstanceSizeInWords(TNode<Map> map);
1241   // Load the inobject properties start of a Map (valid only for JSObjects).
1242   TNode<IntPtrT> LoadMapInobjectPropertiesStartInWords(TNode<Map> map);
1243   // Load the constructor function index of a Map (only for primitive maps).
1244   TNode<IntPtrT> LoadMapConstructorFunctionIndex(TNode<Map> map);
1245   // Load the constructor of a Map (equivalent to Map::GetConstructor()).
1246   TNode<Object> LoadMapConstructor(TNode<Map> map);
1247   // Load the EnumLength of a Map.
1248   TNode<WordT> LoadMapEnumLength(TNode<Map> map);
1249   // Load the back-pointer of a Map.
1250   TNode<Object> LoadMapBackPointer(TNode<Map> map);
1251   // Checks that |map| has only simple properties, returns bitfield3.
1252   TNode<Uint32T> EnsureOnlyHasSimpleProperties(TNode<Map> map,
1253                                                TNode<Int32T> instance_type,
1254                                                Label* bailout);
1255   // Load the identity hash of a JSRececiver.
1256   TNode<IntPtrT> LoadJSReceiverIdentityHash(SloppyTNode<Object> receiver,
1257                                             Label* if_no_hash = nullptr);
1258 
1259   // This is only used on a newly allocated PropertyArray which
1260   // doesn't have an existing hash.
1261   void InitializePropertyArrayLength(TNode<PropertyArray> property_array,
1262                                      TNode<IntPtrT> length);
1263 
1264   // Check if the map is set for slow properties.
1265   TNode<BoolT> IsDictionaryMap(TNode<Map> map);
1266 
1267   // Load the Name::hash() value of a name as an uint32 value.
1268   // If {if_hash_not_computed} label is specified then it also checks if
1269   // hash is actually computed.
1270   TNode<Uint32T> LoadNameHash(TNode<Name> name,
1271                               Label* if_hash_not_computed = nullptr);
1272   TNode<Uint32T> LoadNameHashAssumeComputed(TNode<Name> name);
1273 
1274   // Load length field of a String object as Smi value.
1275   TNode<Smi> LoadStringLengthAsSmi(TNode<String> string);
1276   // Load length field of a String object as intptr_t value.
1277   TNode<IntPtrT> LoadStringLengthAsWord(TNode<String> string);
1278   // Load length field of a String object as uint32_t value.
1279   TNode<Uint32T> LoadStringLengthAsWord32(TNode<String> string);
1280   // Load value field of a JSPrimitiveWrapper object.
1281   TNode<Object> LoadJSPrimitiveWrapperValue(TNode<JSPrimitiveWrapper> object);
1282 
1283   // Figures out whether the value of maybe_object is:
1284   // - a SMI (jump to "if_smi", "extracted" will be the SMI value)
1285   // - a cleared weak reference (jump to "if_cleared", "extracted" will be
1286   // untouched)
1287   // - a weak reference (jump to "if_weak", "extracted" will be the object
1288   // pointed to)
1289   // - a strong reference (jump to "if_strong", "extracted" will be the object
1290   // pointed to)
1291   void DispatchMaybeObject(TNode<MaybeObject> maybe_object, Label* if_smi,
1292                            Label* if_cleared, Label* if_weak, Label* if_strong,
1293                            TVariable<Object>* extracted);
1294   // See MaybeObject for semantics of these functions.
1295   TNode<BoolT> IsStrong(TNode<MaybeObject> value);
1296   TNode<HeapObject> GetHeapObjectIfStrong(TNode<MaybeObject> value,
1297                                           Label* if_not_strong);
1298 
1299   TNode<BoolT> IsWeakOrCleared(TNode<MaybeObject> value);
1300   TNode<BoolT> IsCleared(TNode<MaybeObject> value);
IsNotCleared(TNode<MaybeObject> value)1301   TNode<BoolT> IsNotCleared(TNode<MaybeObject> value) {
1302     return Word32BinaryNot(IsCleared(value));
1303   }
1304 
1305   // Removes the weak bit + asserts it was set.
1306   TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value);
1307 
1308   TNode<HeapObject> GetHeapObjectAssumeWeak(TNode<MaybeObject> value,
1309                                             Label* if_cleared);
1310 
1311   // Checks if |maybe_object| is a weak reference to given |heap_object|.
1312   // Works for both any tagged |maybe_object| values.
1313   TNode<BoolT> IsWeakReferenceTo(TNode<MaybeObject> maybe_object,
1314                                  TNode<HeapObject> heap_object);
1315   // Returns true if the |object| is a HeapObject and |maybe_object| is a weak
1316   // reference to |object|.
1317   // The |maybe_object| must not be a Smi.
1318   TNode<BoolT> IsWeakReferenceToObject(TNode<MaybeObject> maybe_object,
1319                                        TNode<Object> object);
1320 
1321   TNode<MaybeObject> MakeWeak(TNode<HeapObject> value);
1322 
1323   void FixedArrayBoundsCheck(TNode<FixedArrayBase> array, TNode<Smi> index,
1324                              int additional_offset);
1325 
1326   void FixedArrayBoundsCheck(TNode<FixedArrayBase> array, TNode<IntPtrT> index,
1327                              int additional_offset);
1328 
FixedArrayBoundsCheck(TNode<FixedArrayBase> array,TNode<UintPtrT> index,int additional_offset)1329   void FixedArrayBoundsCheck(TNode<FixedArrayBase> array, TNode<UintPtrT> index,
1330                              int additional_offset) {
1331     FixedArrayBoundsCheck(array, Signed(index), additional_offset);
1332   }
1333 
1334   // Array is any array-like type that has a fixed header followed by
1335   // tagged elements.
1336   template <typename Array>
1337   TNode<IntPtrT> LoadArrayLength(TNode<Array> array);
1338 
1339   // Array is any array-like type that has a fixed header followed by
1340   // tagged elements.
1341   template <typename Array, typename TIndex, typename TValue = MaybeObject>
1342   TNode<TValue> LoadArrayElement(
1343       TNode<Array> array, int array_header_size, TNode<TIndex> index,
1344       int additional_offset = 0,
1345       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe);
1346 
1347   template <typename TIndex>
1348   TNode<Object> LoadFixedArrayElement(
1349       TNode<FixedArray> object, TNode<TIndex> index, int additional_offset = 0,
1350       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe,
1351       CheckBounds check_bounds = CheckBounds::kAlways);
1352 
1353   // This doesn't emit a bounds-check. As part of the security-performance
1354   // tradeoff, only use it if it is performance critical.
1355   TNode<Object> UnsafeLoadFixedArrayElement(
1356       TNode<FixedArray> object, TNode<IntPtrT> index, int additional_offset = 0,
1357       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
1358     return LoadFixedArrayElement(object, index, additional_offset,
1359                                  needs_poisoning, CheckBounds::kDebugOnly);
1360   }
1361 
1362   TNode<Object> LoadFixedArrayElement(
1363       TNode<FixedArray> object, int index, int additional_offset = 0,
1364       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
1365     return LoadFixedArrayElement(object, IntPtrConstant(index),
1366                                  additional_offset, needs_poisoning);
1367   }
1368   // This doesn't emit a bounds-check. As part of the security-performance
1369   // tradeoff, only use it if it is performance critical.
1370   TNode<Object> UnsafeLoadFixedArrayElement(
1371       TNode<FixedArray> object, int index, int additional_offset = 0,
1372       LoadSensitivity needs_poisoning = LoadSensitivity::kSafe) {
1373     return LoadFixedArrayElement(object, IntPtrConstant(index),
1374                                  additional_offset, needs_poisoning,
1375                                  CheckBounds::kDebugOnly);
1376   }
1377 
1378   TNode<Object> LoadPropertyArrayElement(TNode<PropertyArray> object,
1379                                          SloppyTNode<IntPtrT> index);
1380   TNode<IntPtrT> LoadPropertyArrayLength(TNode<PropertyArray> object);
1381 
1382   // Load an element from an array and untag it and return it as Word32.
1383   // Array is any array-like type that has a fixed header followed by
1384   // tagged elements.
1385   template <typename Array>
1386   TNode<Int32T> LoadAndUntagToWord32ArrayElement(TNode<Array> array,
1387                                                  int array_header_size,
1388                                                  TNode<IntPtrT> index,
1389                                                  int additional_offset = 0);
1390 
1391   // Load an array element from a FixedArray, untag it and return it as Word32.
1392   TNode<Int32T> LoadAndUntagToWord32FixedArrayElement(
1393       TNode<FixedArray> object, TNode<IntPtrT> index,
1394       int additional_offset = 0);
1395 
1396   // Load an array element from a WeakFixedArray.
1397   TNode<MaybeObject> LoadWeakFixedArrayElement(TNode<WeakFixedArray> object,
1398                                                TNode<IntPtrT> index,
1399                                                int additional_offset = 0);
1400 
1401   // Load an array element from a FixedDoubleArray.
1402   TNode<Float64T> LoadFixedDoubleArrayElement(
1403       TNode<FixedDoubleArray> object, TNode<IntPtrT> index,
1404       Label* if_hole = nullptr,
1405       MachineType machine_type = MachineType::Float64());
1406 
1407   // Load an array element from a FixedArray, FixedDoubleArray or a
1408   // NumberDictionary (depending on the |elements_kind|) and return
1409   // it as a tagged value. Assumes that the |index| passed a length
1410   // check before. Bails out to |if_accessor| if the element that
1411   // was found is an accessor, or to |if_hole| if the element at
1412   // the given |index| is not found in |elements|.
1413   TNode<Object> LoadFixedArrayBaseElementAsTagged(
1414       TNode<FixedArrayBase> elements, TNode<IntPtrT> index,
1415       TNode<Int32T> elements_kind, Label* if_accessor, Label* if_hole);
1416 
1417   // Load a feedback slot from a FeedbackVector.
1418   template <typename TIndex>
1419   TNode<MaybeObject> LoadFeedbackVectorSlot(
1420       TNode<FeedbackVector> feedback_vector, TNode<TIndex> slot,
1421       int additional_offset = 0);
1422 
1423   TNode<IntPtrT> LoadFeedbackVectorLength(TNode<FeedbackVector>);
1424   TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array,
1425                                           TNode<IntPtrT> index,
1426                                           Label* if_hole = nullptr);
1427 
1428   TNode<BoolT> IsDoubleHole(TNode<Object> base, TNode<IntPtrT> offset);
1429   // Load Float64 value by |base| + |offset| address. If the value is a double
1430   // hole then jump to |if_hole|. If |machine_type| is None then only the hole
1431   // check is generated.
1432   TNode<Float64T> LoadDoubleWithHoleCheck(
1433       TNode<Object> base, TNode<IntPtrT> offset, Label* if_hole,
1434       MachineType machine_type = MachineType::Float64());
1435   TNode<Numeric> LoadFixedTypedArrayElementAsTagged(TNode<RawPtrT> data_pointer,
1436                                                     TNode<UintPtrT> index,
1437                                                     ElementsKind elements_kind);
1438   TNode<Numeric> LoadFixedTypedArrayElementAsTagged(
1439       TNode<RawPtrT> data_pointer, TNode<UintPtrT> index,
1440       TNode<Int32T> elements_kind);
1441   // Parts of the above, factored out for readability:
1442   TNode<BigInt> LoadFixedBigInt64ArrayElementAsTagged(
1443       SloppyTNode<RawPtrT> data_pointer, SloppyTNode<IntPtrT> offset);
1444   TNode<BigInt> LoadFixedBigUint64ArrayElementAsTagged(
1445       SloppyTNode<RawPtrT> data_pointer, SloppyTNode<IntPtrT> offset);
1446   // 64-bit platforms only:
1447   TNode<BigInt> BigIntFromInt64(TNode<IntPtrT> value);
1448   TNode<BigInt> BigIntFromUint64(TNode<UintPtrT> value);
1449   // 32-bit platforms only:
1450   TNode<BigInt> BigIntFromInt32Pair(TNode<IntPtrT> low, TNode<IntPtrT> high);
1451   TNode<BigInt> BigIntFromUint32Pair(TNode<UintPtrT> low, TNode<UintPtrT> high);
1452 
1453   // ScopeInfo:
1454   TNode<ScopeInfo> LoadScopeInfo(TNode<Context> context);
1455   TNode<BoolT> LoadScopeInfoHasExtensionField(TNode<ScopeInfo> scope_info);
1456 
1457   // Context manipulation:
1458   void StoreContextElementNoWriteBarrier(TNode<Context> context, int slot_index,
1459                                          SloppyTNode<Object> value);
1460   TNode<NativeContext> LoadNativeContext(TNode<Context> context);
1461   // Calling this is only valid if there's a module context in the chain.
1462   TNode<Context> LoadModuleContext(TNode<Context> context);
1463 
GotoIfContextElementEqual(SloppyTNode<Object> value,TNode<NativeContext> native_context,int slot_index,Label * if_equal)1464   void GotoIfContextElementEqual(SloppyTNode<Object> value,
1465                                  TNode<NativeContext> native_context,
1466                                  int slot_index, Label* if_equal) {
1467     GotoIf(TaggedEqual(value, LoadContextElement(native_context, slot_index)),
1468            if_equal);
1469   }
1470 
1471   // Loads the initial map of the the Object constructor.
1472   TNode<Map> LoadObjectFunctionInitialMap(TNode<NativeContext> native_context);
1473   TNode<Map> LoadSlowObjectWithNullPrototypeMap(
1474       TNode<NativeContext> native_context);
1475 
1476   TNode<Map> LoadJSArrayElementsMap(ElementsKind kind,
1477                                     TNode<NativeContext> native_context);
1478   TNode<Map> LoadJSArrayElementsMap(SloppyTNode<Int32T> kind,
1479                                     TNode<NativeContext> native_context);
1480 
1481   TNode<BoolT> IsJSFunctionWithPrototypeSlot(TNode<HeapObject> object);
1482   TNode<BoolT> IsGeneratorFunction(TNode<JSFunction> function);
1483   void BranchIfHasPrototypeProperty(TNode<JSFunction> function,
1484                                     TNode<Int32T> function_map_bit_field,
1485                                     Label* if_true, Label* if_false);
1486   void GotoIfPrototypeRequiresRuntimeLookup(TNode<JSFunction> function,
1487                                             TNode<Map> map, Label* runtime);
1488   // Load the "prototype" property of a JSFunction.
1489   TNode<HeapObject> LoadJSFunctionPrototype(TNode<JSFunction> function,
1490                                             Label* if_bailout);
1491 
1492   TNode<BytecodeArray> LoadSharedFunctionInfoBytecodeArray(
1493       TNode<SharedFunctionInfo> shared);
1494 
1495   void StoreObjectByteNoWriteBarrier(TNode<HeapObject> object, int offset,
1496                                      TNode<Word32T> value);
1497 
1498   // Store the floating point value of a HeapNumber.
1499   void StoreHeapNumberValue(SloppyTNode<HeapNumber> object,
1500                             SloppyTNode<Float64T> value);
1501   // Store a field to an object on the heap.
1502   void StoreObjectField(TNode<HeapObject> object, int offset,
1503                         TNode<Object> value);
1504   void StoreObjectField(TNode<HeapObject> object, TNode<IntPtrT> offset,
1505                         TNode<Object> value);
1506   template <class T>
StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object,SloppyTNode<IntPtrT> offset,TNode<T> value)1507   void StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object,
1508                                       SloppyTNode<IntPtrT> offset,
1509                                       TNode<T> value) {
1510     int const_offset;
1511     if (ToInt32Constant(offset, &const_offset)) {
1512       return StoreObjectFieldNoWriteBarrier<T>(object, const_offset, value);
1513     }
1514     StoreNoWriteBarrier(MachineRepresentationOf<T>::value, object,
1515                         IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)),
1516                         value);
1517   }
1518   template <class T>
StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object,int offset,TNode<T> value)1519   void StoreObjectFieldNoWriteBarrier(TNode<HeapObject> object, int offset,
1520                                       TNode<T> value) {
1521     if (CanBeTaggedPointer(MachineRepresentationOf<T>::value)) {
1522       OptimizedStoreFieldAssertNoWriteBarrier(MachineRepresentationOf<T>::value,
1523                                               object, offset, value);
1524     } else {
1525       OptimizedStoreFieldUnsafeNoWriteBarrier(MachineRepresentationOf<T>::value,
1526                                               object, offset, value);
1527     }
1528   }
1529 
1530   void UnsafeStoreObjectFieldNoWriteBarrier(TNode<HeapObject> object,
1531                                             int offset, TNode<Object> value);
1532 
1533   // Store the Map of an HeapObject.
1534   void StoreMap(TNode<HeapObject> object, TNode<Map> map);
1535   void StoreMapNoWriteBarrier(TNode<HeapObject> object,
1536                               RootIndex map_root_index);
1537   void StoreMapNoWriteBarrier(TNode<HeapObject> object, TNode<Map> map);
1538   void StoreObjectFieldRoot(TNode<HeapObject> object, int offset,
1539                             RootIndex root);
1540   // Store an array element to a FixedArray.
1541   void StoreFixedArrayElement(
1542       TNode<FixedArray> object, int index, SloppyTNode<Object> value,
1543       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
1544       CheckBounds check_bounds = CheckBounds::kAlways) {
1545     return StoreFixedArrayElement(object, IntPtrConstant(index), value,
1546                                   barrier_mode, 0, check_bounds);
1547   }
1548   // This doesn't emit a bounds-check. As part of the security-performance
1549   // tradeoff, only use it if it is performance critical.
1550   void UnsafeStoreFixedArrayElement(
1551       TNode<FixedArray> object, int index, TNode<Object> value,
1552       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
1553     return StoreFixedArrayElement(object, index, value, barrier_mode,
1554                                   CheckBounds::kDebugOnly);
1555   }
UnsafeStoreFixedArrayElement(TNode<FixedArray> object,int index,TNode<Smi> value)1556   void UnsafeStoreFixedArrayElement(TNode<FixedArray> object, int index,
1557                                     TNode<Smi> value) {
1558     return StoreFixedArrayElement(object, index, value,
1559                                   UNSAFE_SKIP_WRITE_BARRIER,
1560                                   CheckBounds::kDebugOnly);
1561   }
1562   void StoreFixedArrayElement(TNode<FixedArray> object, int index,
1563                               TNode<Smi> value,
1564                               CheckBounds check_bounds = CheckBounds::kAlways) {
1565     return StoreFixedArrayElement(object, IntPtrConstant(index), value,
1566                                   UNSAFE_SKIP_WRITE_BARRIER, 0, check_bounds);
1567   }
1568   template <typename TIndex>
1569   void StoreFixedArrayElement(
1570       TNode<FixedArray> array, TNode<TIndex> index, SloppyTNode<Object> value,
1571       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
1572       int additional_offset = 0,
1573       CheckBounds check_bounds = CheckBounds::kAlways) {
1574     // TODO(v8:9708): Do we want to keep both IntPtrT and UintPtrT variants?
1575     static_assert(std::is_same<TIndex, Smi>::value ||
1576                       std::is_same<TIndex, UintPtrT>::value ||
1577                       std::is_same<TIndex, IntPtrT>::value,
1578                   "Only Smi, UintPtrT or IntPtrT index is allowed");
1579     if (NeedsBoundsCheck(check_bounds)) {
1580       FixedArrayBoundsCheck(array, index, additional_offset);
1581     }
1582     StoreFixedArrayOrPropertyArrayElement(array, index, value, barrier_mode,
1583                                           additional_offset);
1584   }
1585   // This doesn't emit a bounds-check. As part of the security-performance
1586   // tradeoff, only use it if it is performance critical.
1587   void UnsafeStoreFixedArrayElement(
1588       TNode<FixedArray> array, TNode<IntPtrT> index, TNode<Object> value,
1589       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
1590       int additional_offset = 0) {
1591     return StoreFixedArrayElement(array, index, value, barrier_mode,
1592                                   additional_offset, CheckBounds::kDebugOnly);
1593   }
1594 
UnsafeStoreFixedArrayElement(TNode<FixedArray> array,TNode<IntPtrT> index,TNode<Smi> value,int additional_offset)1595   void UnsafeStoreFixedArrayElement(TNode<FixedArray> array,
1596                                     TNode<IntPtrT> index, TNode<Smi> value,
1597                                     int additional_offset) {
1598     return StoreFixedArrayElement(array, index, value,
1599                                   UNSAFE_SKIP_WRITE_BARRIER, additional_offset,
1600                                   CheckBounds::kDebugOnly);
1601   }
1602 
StorePropertyArrayElement(TNode<PropertyArray> array,TNode<IntPtrT> index,TNode<Object> value)1603   void StorePropertyArrayElement(TNode<PropertyArray> array,
1604                                  TNode<IntPtrT> index, TNode<Object> value) {
1605     StoreFixedArrayOrPropertyArrayElement(array, index, value,
1606                                           UPDATE_WRITE_BARRIER);
1607   }
1608 
1609   void StoreFixedArrayElement(
1610       TNode<FixedArray> array, TNode<Smi> index, TNode<Object> value,
1611       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
1612     StoreFixedArrayElement(array, index, value, barrier_mode, 0);
1613   }
1614   void StoreFixedArrayElement(
1615       TNode<FixedArray> array, TNode<IntPtrT> index, TNode<Smi> value,
1616       WriteBarrierMode barrier_mode = SKIP_WRITE_BARRIER,
1617       int additional_offset = 0) {
1618     DCHECK_EQ(SKIP_WRITE_BARRIER, barrier_mode);
1619     StoreFixedArrayElement(array, index, TNode<Object>{value},
1620                            UNSAFE_SKIP_WRITE_BARRIER, additional_offset);
1621   }
1622   void StoreFixedArrayElement(
1623       TNode<FixedArray> array, TNode<Smi> index, TNode<Smi> value,
1624       WriteBarrierMode barrier_mode = SKIP_WRITE_BARRIER,
1625       int additional_offset = 0) {
1626     DCHECK_EQ(SKIP_WRITE_BARRIER, barrier_mode);
1627     StoreFixedArrayElement(array, index, TNode<Object>{value},
1628                            UNSAFE_SKIP_WRITE_BARRIER, additional_offset);
1629   }
1630 
1631   template <typename TIndex>
1632   void StoreFixedDoubleArrayElement(
1633       TNode<FixedDoubleArray> object, TNode<TIndex> index,
1634       TNode<Float64T> value, CheckBounds check_bounds = CheckBounds::kAlways);
1635 
1636   void StoreDoubleHole(TNode<HeapObject> object, TNode<IntPtrT> offset);
1637   void StoreFixedDoubleArrayHole(TNode<FixedDoubleArray> array,
1638                                  TNode<IntPtrT> index);
1639   void StoreFeedbackVectorSlot(
1640       TNode<FeedbackVector> feedback_vector, TNode<UintPtrT> slot,
1641       TNode<AnyTaggedT> value,
1642       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
1643       int additional_offset = 0);
1644 
1645   // EnsureArrayPushable verifies that receiver with this map is:
1646   //   1. Is not a prototype.
1647   //   2. Is not a dictionary.
1648   //   3. Has a writeable length property.
1649   // It returns ElementsKind as a node for further division into cases.
1650   TNode<Int32T> EnsureArrayPushable(TNode<Context> context, TNode<Map> map,
1651                                     Label* bailout);
1652 
1653   void TryStoreArrayElement(ElementsKind kind, Label* bailout,
1654                             TNode<FixedArrayBase> elements, TNode<BInt> index,
1655                             TNode<Object> value);
1656   // Consumes args into the array, and returns tagged new length.
1657   TNode<Smi> BuildAppendJSArray(ElementsKind kind, TNode<JSArray> array,
1658                                 CodeStubArguments* args,
1659                                 TVariable<IntPtrT>* arg_index, Label* bailout);
1660   // Pushes value onto the end of array.
1661   void BuildAppendJSArray(ElementsKind kind, TNode<JSArray> array,
1662                           TNode<Object> value, Label* bailout);
1663 
1664   void StoreFieldsNoWriteBarrier(TNode<IntPtrT> start_address,
1665                                  TNode<IntPtrT> end_address,
1666                                  TNode<Object> value);
1667 
1668   // Marks the FixedArray copy-on-write without moving it.
1669   void MakeFixedArrayCOW(TNode<FixedArray> array);
1670 
1671   TNode<Cell> AllocateCellWithValue(
1672       TNode<Object> value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
1673   TNode<Cell> AllocateSmiCell(int value = 0) {
1674     return AllocateCellWithValue(SmiConstant(value), SKIP_WRITE_BARRIER);
1675   }
1676 
1677   TNode<Object> LoadCellValue(TNode<Cell> cell);
1678 
1679   void StoreCellValue(TNode<Cell> cell, TNode<Object> value,
1680                       WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
1681 
1682   // Allocate a HeapNumber without initializing its value.
1683   TNode<HeapNumber> AllocateHeapNumber();
1684   // Allocate a HeapNumber with a specific value.
1685   TNode<HeapNumber> AllocateHeapNumberWithValue(SloppyTNode<Float64T> value);
AllocateHeapNumberWithValue(double value)1686   TNode<HeapNumber> AllocateHeapNumberWithValue(double value) {
1687     return AllocateHeapNumberWithValue(Float64Constant(value));
1688   }
1689 
1690   // Allocate a BigInt with {length} digits. Sets the sign bit to {false}.
1691   // Does not initialize the digits.
1692   TNode<BigInt> AllocateBigInt(TNode<IntPtrT> length);
1693   // Like above, but allowing custom bitfield initialization.
1694   TNode<BigInt> AllocateRawBigInt(TNode<IntPtrT> length);
1695   void StoreBigIntBitfield(TNode<BigInt> bigint, TNode<Word32T> bitfield);
1696   void StoreBigIntDigit(TNode<BigInt> bigint, intptr_t digit_index,
1697                         TNode<UintPtrT> digit);
1698   void StoreBigIntDigit(TNode<BigInt> bigint, TNode<IntPtrT> digit_index,
1699                         TNode<UintPtrT> digit);
1700 
1701   TNode<Word32T> LoadBigIntBitfield(TNode<BigInt> bigint);
1702   TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint, intptr_t digit_index);
1703   TNode<UintPtrT> LoadBigIntDigit(TNode<BigInt> bigint,
1704                                   TNode<IntPtrT> digit_index);
1705 
1706   // Allocate a ByteArray with the given length.
1707   TNode<ByteArray> AllocateByteArray(TNode<UintPtrT> length,
1708                                      AllocationFlags flags = kNone);
1709 
1710   // Allocate a SeqOneByteString with the given length.
1711   TNode<String> AllocateSeqOneByteString(uint32_t length,
1712                                          AllocationFlags flags = kNone);
1713   using TorqueGeneratedExportedMacrosAssembler::AllocateSeqOneByteString;
1714 
1715   // Allocate a SeqTwoByteString with the given length.
1716   TNode<String> AllocateSeqTwoByteString(uint32_t length,
1717                                          AllocationFlags flags = kNone);
1718   using TorqueGeneratedExportedMacrosAssembler::AllocateSeqTwoByteString;
1719 
1720   // Allocate a SlicedOneByteString with the given length, parent and offset.
1721   // |length| and |offset| are expected to be tagged.
1722 
1723   TNode<String> AllocateSlicedOneByteString(TNode<Uint32T> length,
1724                                             TNode<String> parent,
1725                                             TNode<Smi> offset);
1726   // Allocate a SlicedTwoByteString with the given length, parent and offset.
1727   // |length| and |offset| are expected to be tagged.
1728   TNode<String> AllocateSlicedTwoByteString(TNode<Uint32T> length,
1729                                             TNode<String> parent,
1730                                             TNode<Smi> offset);
1731 
1732   TNode<NameDictionary> AllocateNameDictionary(int at_least_space_for);
1733   TNode<NameDictionary> AllocateNameDictionary(
1734       TNode<IntPtrT> at_least_space_for, AllocationFlags = kNone);
1735   TNode<NameDictionary> AllocateNameDictionaryWithCapacity(
1736       TNode<IntPtrT> capacity, AllocationFlags = kNone);
1737   TNode<NameDictionary> CopyNameDictionary(TNode<NameDictionary> dictionary,
1738                                            Label* large_object_fallback);
1739 
1740   template <typename CollectionType>
1741   TNode<CollectionType> AllocateOrderedHashTable();
1742 
1743   TNode<JSObject> AllocateJSObjectFromMap(
1744       TNode<Map> map,
1745       base::Optional<TNode<HeapObject>> properties = base::nullopt,
1746       base::Optional<TNode<FixedArray>> elements = base::nullopt,
1747       AllocationFlags flags = kNone,
1748       SlackTrackingMode slack_tracking_mode = kNoSlackTracking);
1749 
1750   void InitializeJSObjectFromMap(
1751       TNode<HeapObject> object, TNode<Map> map, TNode<IntPtrT> instance_size,
1752       base::Optional<TNode<HeapObject>> properties = base::nullopt,
1753       base::Optional<TNode<FixedArray>> elements = base::nullopt,
1754       SlackTrackingMode slack_tracking_mode = kNoSlackTracking);
1755 
1756   void InitializeJSObjectBodyWithSlackTracking(
1757       TNode<HeapObject> object, TNode<Map> map,
1758       SloppyTNode<IntPtrT> instance_size);
1759   void InitializeJSObjectBodyNoSlackTracking(
1760       TNode<HeapObject> object, TNode<Map> map,
1761       SloppyTNode<IntPtrT> instance_size,
1762       int start_offset = JSObject::kHeaderSize);
1763 
1764   TNode<BoolT> IsValidFastJSArrayCapacity(TNode<IntPtrT> capacity);
1765 
1766   //
1767   // Allocate and return a JSArray with initialized header fields and its
1768   // uninitialized elements.
1769   std::pair<TNode<JSArray>, TNode<FixedArrayBase>>
1770   AllocateUninitializedJSArrayWithElements(
1771       ElementsKind kind, TNode<Map> array_map, TNode<Smi> length,
1772       base::Optional<TNode<AllocationSite>> allocation_site,
1773       TNode<IntPtrT> capacity, AllocationFlags allocation_flags = kNone,
1774       int array_header_size = JSArray::kHeaderSize);
1775 
1776   // Allocate a JSArray and fill elements with the hole.
1777   TNode<JSArray> AllocateJSArray(
1778       ElementsKind kind, TNode<Map> array_map, TNode<IntPtrT> capacity,
1779       TNode<Smi> length, base::Optional<TNode<AllocationSite>> allocation_site,
1780       AllocationFlags allocation_flags = kNone);
1781   TNode<JSArray> AllocateJSArray(
1782       ElementsKind kind, TNode<Map> array_map, TNode<Smi> capacity,
1783       TNode<Smi> length, base::Optional<TNode<AllocationSite>> allocation_site,
1784       AllocationFlags allocation_flags = kNone) {
1785     return AllocateJSArray(kind, array_map, SmiUntag(capacity), length,
1786                            allocation_site, allocation_flags);
1787   }
1788   TNode<JSArray> AllocateJSArray(ElementsKind kind, TNode<Map> array_map,
1789                                  TNode<Smi> capacity, TNode<Smi> length,
1790                                  AllocationFlags allocation_flags = kNone) {
1791     return AllocateJSArray(kind, array_map, SmiUntag(capacity), length,
1792                            base::nullopt, allocation_flags);
1793   }
1794   TNode<JSArray> AllocateJSArray(ElementsKind kind, TNode<Map> array_map,
1795                                  TNode<IntPtrT> capacity, TNode<Smi> length,
1796                                  AllocationFlags allocation_flags = kNone) {
1797     return AllocateJSArray(kind, array_map, capacity, length, base::nullopt,
1798                            allocation_flags);
1799   }
1800 
1801   // Allocate a JSArray and initialize the header fields.
1802   TNode<JSArray> AllocateJSArray(
1803       TNode<Map> array_map, TNode<FixedArrayBase> elements, TNode<Smi> length,
1804       base::Optional<TNode<AllocationSite>> allocation_site = base::nullopt,
1805       int array_header_size = JSArray::kHeaderSize);
1806 
1807   enum class HoleConversionMode { kDontConvert, kConvertToUndefined };
1808   // Clone a fast JSArray |array| into a new fast JSArray.
1809   // |convert_holes| tells the function to convert holes into undefined or not.
1810   // If |convert_holes| is set to kConvertToUndefined, but the function did not
1811   // find any hole in |array|, the resulting array will have the same elements
1812   // kind as |array|. If the function did find a hole, it will convert holes in
1813   // |array| to undefined in the resulting array, who will now have
1814   // PACKED_ELEMENTS kind.
1815   // If |convert_holes| is set kDontConvert, holes are also copied to the
1816   // resulting array, who will have the same elements kind as |array|. The
1817   // function generates significantly less code in this case.
1818   TNode<JSArray> CloneFastJSArray(
1819       TNode<Context> context, TNode<JSArray> array,
1820       base::Optional<TNode<AllocationSite>> allocation_site = base::nullopt,
1821       HoleConversionMode convert_holes = HoleConversionMode::kDontConvert);
1822 
1823   TNode<JSArray> ExtractFastJSArray(TNode<Context> context,
1824                                     TNode<JSArray> array, TNode<BInt> begin,
1825                                     TNode<BInt> count);
1826 
1827   template <typename TIndex>
1828   TNode<FixedArrayBase> AllocateFixedArray(
1829       ElementsKind kind, TNode<TIndex> capacity, AllocationFlags flags = kNone,
1830       base::Optional<TNode<Map>> fixed_array_map = base::nullopt);
1831 
1832   TNode<NativeContext> GetCreationContext(TNode<JSReceiver> receiver,
1833                                           Label* if_bailout);
1834   TNode<Object> GetConstructor(TNode<Map> map);
1835 
1836   TNode<Map> GetInstanceTypeMap(InstanceType instance_type);
1837 
AllocateUninitializedFixedArray(intptr_t capacity)1838   TNode<FixedArray> AllocateUninitializedFixedArray(intptr_t capacity) {
1839     return UncheckedCast<FixedArray>(AllocateFixedArray(
1840         PACKED_ELEMENTS, IntPtrConstant(capacity), AllocationFlag::kNone));
1841   }
1842 
AllocateZeroedFixedArray(TNode<IntPtrT> capacity)1843   TNode<FixedArray> AllocateZeroedFixedArray(TNode<IntPtrT> capacity) {
1844     TNode<FixedArray> result = UncheckedCast<FixedArray>(
1845         AllocateFixedArray(PACKED_ELEMENTS, capacity,
1846                            AllocationFlag::kAllowLargeObjectAllocation));
1847     FillFixedArrayWithSmiZero(result, capacity);
1848     return result;
1849   }
1850 
AllocateZeroedFixedDoubleArray(TNode<IntPtrT> capacity)1851   TNode<FixedDoubleArray> AllocateZeroedFixedDoubleArray(
1852       TNode<IntPtrT> capacity) {
1853     TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
1854         AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity,
1855                            AllocationFlag::kAllowLargeObjectAllocation));
1856     FillFixedDoubleArrayWithZero(result, capacity);
1857     return result;
1858   }
1859 
AllocateFixedArrayWithHoles(TNode<IntPtrT> capacity,AllocationFlags flags)1860   TNode<FixedArray> AllocateFixedArrayWithHoles(TNode<IntPtrT> capacity,
1861                                                 AllocationFlags flags) {
1862     TNode<FixedArray> result = UncheckedCast<FixedArray>(
1863         AllocateFixedArray(PACKED_ELEMENTS, capacity, flags));
1864     FillFixedArrayWithValue(PACKED_ELEMENTS, result, IntPtrConstant(0),
1865                             capacity, RootIndex::kTheHoleValue);
1866     return result;
1867   }
1868 
AllocateFixedDoubleArrayWithHoles(TNode<IntPtrT> capacity,AllocationFlags flags)1869   TNode<FixedDoubleArray> AllocateFixedDoubleArrayWithHoles(
1870       TNode<IntPtrT> capacity, AllocationFlags flags) {
1871     TNode<FixedDoubleArray> result = UncheckedCast<FixedDoubleArray>(
1872         AllocateFixedArray(PACKED_DOUBLE_ELEMENTS, capacity, flags));
1873     FillFixedArrayWithValue(PACKED_DOUBLE_ELEMENTS, result, IntPtrConstant(0),
1874                             capacity, RootIndex::kTheHoleValue);
1875     return result;
1876   }
1877 
1878   TNode<PropertyArray> AllocatePropertyArray(TNode<IntPtrT> capacity);
1879 
1880   // TODO(v8:9722): Return type should be JSIteratorResult
1881   TNode<JSObject> AllocateJSIteratorResult(TNode<Context> context,
1882                                            SloppyTNode<Object> value,
1883                                            SloppyTNode<Oddball> done);
1884 
1885   // TODO(v8:9722): Return type should be JSIteratorResult
1886   TNode<JSObject> AllocateJSIteratorResultForEntry(TNode<Context> context,
1887                                                    TNode<Object> key,
1888                                                    SloppyTNode<Object> value);
1889 
1890   TNode<JSReceiver> ArraySpeciesCreate(TNode<Context> context,
1891                                        TNode<Object> originalArray,
1892                                        TNode<Number> len);
1893 
1894   template <typename TIndex>
1895   void FillFixedArrayWithValue(ElementsKind kind, TNode<FixedArrayBase> array,
1896                                TNode<TIndex> from_index, TNode<TIndex> to_index,
1897                                RootIndex value_root_index);
1898 
1899   // Uses memset to effectively initialize the given FixedArray with zeroes.
1900   void FillFixedArrayWithSmiZero(TNode<FixedArray> array,
1901                                  TNode<IntPtrT> length);
1902   void FillFixedDoubleArrayWithZero(TNode<FixedDoubleArray> array,
1903                                     TNode<IntPtrT> length);
1904 
1905   void FillPropertyArrayWithUndefined(TNode<PropertyArray> array,
1906                                       TNode<IntPtrT> from_index,
1907                                       TNode<IntPtrT> to_index);
1908 
1909   enum class DestroySource { kNo, kYes };
1910 
1911   // Increment the call count for a CALL_IC or construct call.
1912   // The call count is located at feedback_vector[slot_id + 1].
1913   void IncrementCallCount(TNode<FeedbackVector> feedback_vector,
1914                           TNode<UintPtrT> slot_id);
1915 
1916   // Specify DestroySource::kYes if {from_array} is being supplanted by
1917   // {to_array}. This offers a slight performance benefit by simply copying the
1918   // array word by word. The source may be destroyed at the end of this macro.
1919   //
1920   // Otherwise, specify DestroySource::kNo for operations where an Object is
1921   // being cloned, to ensure that mutable HeapNumbers are unique between the
1922   // source and cloned object.
1923   void CopyPropertyArrayValues(TNode<HeapObject> from_array,
1924                                TNode<PropertyArray> to_array,
1925                                TNode<IntPtrT> length,
1926                                WriteBarrierMode barrier_mode,
1927                                DestroySource destroy_source);
1928 
1929   // Copies all elements from |from_array| of |length| size to
1930   // |to_array| of the same size respecting the elements kind.
1931   template <typename TIndex>
1932   void CopyFixedArrayElements(
1933       ElementsKind kind, TNode<FixedArrayBase> from_array,
1934       TNode<FixedArrayBase> to_array, TNode<TIndex> length,
1935       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
1936     CopyFixedArrayElements(kind, from_array, kind, to_array,
1937                            IntPtrOrSmiConstant<TIndex>(0), length, length,
1938                            barrier_mode);
1939   }
1940 
1941   // Copies |element_count| elements from |from_array| starting from element
1942   // zero to |to_array| of |capacity| size respecting both array's elements
1943   // kinds.
1944   template <typename TIndex>
1945   void CopyFixedArrayElements(
1946       ElementsKind from_kind, TNode<FixedArrayBase> from_array,
1947       ElementsKind to_kind, TNode<FixedArrayBase> to_array,
1948       TNode<TIndex> element_count, TNode<TIndex> capacity,
1949       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER) {
1950     CopyFixedArrayElements(from_kind, from_array, to_kind, to_array,
1951                            IntPtrOrSmiConstant<TIndex>(0), element_count,
1952                            capacity, barrier_mode);
1953   }
1954 
1955   // Copies |element_count| elements from |from_array| starting from element
1956   // |first_element| to |to_array| of |capacity| size respecting both array's
1957   // elements kinds.
1958   // |convert_holes| tells the function whether to convert holes to undefined.
1959   // |var_holes_converted| can be used to signify that the conversion happened
1960   // (i.e. that there were holes). If |convert_holes_to_undefined| is
1961   // HoleConversionMode::kConvertToUndefined, then it must not be the case that
1962   // IsDoubleElementsKind(to_kind).
1963   template <typename TIndex>
1964   void CopyFixedArrayElements(
1965       ElementsKind from_kind, TNode<FixedArrayBase> from_array,
1966       ElementsKind to_kind, TNode<FixedArrayBase> to_array,
1967       TNode<TIndex> first_element, TNode<TIndex> element_count,
1968       TNode<TIndex> capacity,
1969       WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
1970       HoleConversionMode convert_holes = HoleConversionMode::kDontConvert,
1971       TVariable<BoolT>* var_holes_converted = nullptr);
1972 
1973   void JumpIfPointersFromHereAreInteresting(TNode<Object> object,
1974                                             Label* interesting);
1975 
1976   // Efficiently copy elements within a single array. The regions
1977   // [src_index, src_index + length) and [dst_index, dst_index + length)
1978   // can be overlapping.
1979   void MoveElements(ElementsKind kind, TNode<FixedArrayBase> elements,
1980                     TNode<IntPtrT> dst_index, TNode<IntPtrT> src_index,
1981                     TNode<IntPtrT> length);
1982 
1983   // Efficiently copy elements from one array to another. The ElementsKind
1984   // needs to be the same. Copy from src_elements at
1985   // [src_index, src_index + length) to dst_elements at
1986   // [dst_index, dst_index + length).
1987   // The function decides whether it can use memcpy. In case it cannot,
1988   // |write_barrier| can help it to skip write barrier. SKIP_WRITE_BARRIER is
1989   // only safe when copying to new space, or when copying to old space and the
1990   // array does not contain object pointers.
1991   void CopyElements(ElementsKind kind, TNode<FixedArrayBase> dst_elements,
1992                     TNode<IntPtrT> dst_index,
1993                     TNode<FixedArrayBase> src_elements,
1994                     TNode<IntPtrT> src_index, TNode<IntPtrT> length,
1995                     WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER);
1996 
1997   TNode<FixedArray> HeapObjectToFixedArray(TNode<HeapObject> base,
1998                                            Label* cast_fail);
1999 
HeapObjectToFixedDoubleArray(TNode<HeapObject> base,Label * cast_fail)2000   TNode<FixedDoubleArray> HeapObjectToFixedDoubleArray(TNode<HeapObject> base,
2001                                                        Label* cast_fail) {
2002     GotoIf(TaggedNotEqual(LoadMap(base), FixedDoubleArrayMapConstant()),
2003            cast_fail);
2004     return UncheckedCast<FixedDoubleArray>(base);
2005   }
2006 
ConvertElementsKindToInt(TNode<Int32T> elements_kind)2007   TNode<Int32T> ConvertElementsKindToInt(TNode<Int32T> elements_kind) {
2008     return UncheckedCast<Int32T>(elements_kind);
2009   }
2010 
2011   template <typename T>
ClassHasMapConstant()2012   bool ClassHasMapConstant() {
2013     return false;
2014   }
2015 
2016   template <typename T>
GetClassMapConstant()2017   TNode<Map> GetClassMapConstant() {
2018     UNREACHABLE();
2019     return TNode<Map>();
2020   }
2021 
2022   enum class ExtractFixedArrayFlag {
2023     kFixedArrays = 1,
2024     kFixedDoubleArrays = 2,
2025     kDontCopyCOW = 4,
2026     kNewSpaceAllocationOnly = 8,
2027     kAllFixedArrays = kFixedArrays | kFixedDoubleArrays,
2028     kAllFixedArraysDontCopyCOW = kAllFixedArrays | kDontCopyCOW
2029   };
2030 
2031   using ExtractFixedArrayFlags = base::Flags<ExtractFixedArrayFlag>;
2032 
2033   // Copy a portion of an existing FixedArray or FixedDoubleArray into a new
2034   // array, including special appropriate handling for empty arrays and COW
2035   // arrays. The result array will be of the same type as the original array.
2036   //
2037   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
2038   // elements.
2039   // * |first| is the starting element index to copy from, if nullptr is passed
2040   // then index zero is used by default.
2041   // * |count| is the number of elements to copy out of the source array
2042   // starting from and including the element indexed by |start|. If |count| is
2043   // nullptr, then all of the elements from |start| to the end of |source| are
2044   // copied.
2045   // * |capacity| determines the size of the allocated result array, with
2046   // |capacity| >= |count|. If |capacity| is nullptr, then |count| is used as
2047   // the destination array's capacity.
2048   // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both
2049   // are detected and copied. Although it's always correct to pass
2050   // kAllFixedArrays, the generated code is more compact and efficient if the
2051   // caller can specify whether only FixedArrays or FixedDoubleArrays will be
2052   // passed as the |source| parameter.
2053   // * |parameter_mode| determines the parameter mode of |first|, |count| and
2054   // |capacity|.
2055   // * If |var_holes_converted| is given, any holes will be converted to
2056   // undefined and the variable will be set according to whether or not there
2057   // were any hole.
2058   // * If |source_elements_kind| is given, the function will try to use the
2059   // runtime elements kind of source to make copy faster. More specifically, it
2060   // can skip write barriers.
2061   template <typename TIndex>
2062   TNode<FixedArrayBase> ExtractFixedArray(
2063       TNode<FixedArrayBase> source, base::Optional<TNode<TIndex>> first,
2064       base::Optional<TNode<TIndex>> count = base::nullopt,
2065       base::Optional<TNode<TIndex>> capacity = base::nullopt,
2066       ExtractFixedArrayFlags extract_flags =
2067           ExtractFixedArrayFlag::kAllFixedArrays,
2068       TVariable<BoolT>* var_holes_converted = nullptr,
2069       base::Optional<TNode<Int32T>> source_elements_kind = base::nullopt);
2070 
2071   // Copy a portion of an existing FixedArray or FixedDoubleArray into a new
2072   // FixedArray, including special appropriate handling for COW arrays.
2073   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
2074   // elements. |source| is assumed to be non-empty.
2075   // * |first| is the starting element index to copy from.
2076   // * |count| is the number of elements to copy out of the source array
2077   // starting from and including the element indexed by |start|.
2078   // * |capacity| determines the size of the allocated result array, with
2079   // |capacity| >= |count|.
2080   // * |source_map| is the map of the |source|.
2081   // * |from_kind| is the elements kind that is consistent with |source| being
2082   // a FixedArray or FixedDoubleArray. This function only cares about double vs.
2083   // non-double, so as to distinguish FixedDoubleArray vs. FixedArray. It does
2084   // not care about holeyness. For example, when |source| is a FixedArray,
2085   // PACKED/HOLEY_ELEMENTS can be used, but not PACKED_DOUBLE_ELEMENTS.
2086   // * |allocation_flags| and |extract_flags| influence how the target
2087   // FixedArray is allocated.
2088   // * |convert_holes| is used to signify that the target array should use
2089   // undefined in places of holes.
2090   // * If |convert_holes| is true and |var_holes_converted| not nullptr, then
2091   // |var_holes_converted| is used to signal whether any holes were found and
2092   // converted. The caller should use this information to decide which map is
2093   // compatible with the result array. For example, if the input was of
2094   // HOLEY_SMI_ELEMENTS kind, and a conversion took place, the result will be
2095   // compatible only with HOLEY_ELEMENTS and PACKED_ELEMENTS.
2096   template <typename TIndex>
2097   TNode<FixedArray> ExtractToFixedArray(
2098       TNode<FixedArrayBase> source, TNode<TIndex> first, TNode<TIndex> count,
2099       TNode<TIndex> capacity, TNode<Map> source_map, ElementsKind from_kind,
2100       AllocationFlags allocation_flags, ExtractFixedArrayFlags extract_flags,
2101       HoleConversionMode convert_holes,
2102       TVariable<BoolT>* var_holes_converted = nullptr,
2103       base::Optional<TNode<Int32T>> source_runtime_kind = base::nullopt);
2104 
2105   // Attempt to copy a FixedDoubleArray to another FixedDoubleArray. In the case
2106   // where the source array has a hole, produce a FixedArray instead where holes
2107   // are replaced with undefined.
2108   // * |source| is a FixedDoubleArray from which to copy elements.
2109   // * |first| is the starting element index to copy from.
2110   // * |count| is the number of elements to copy out of the source array
2111   // starting from and including the element indexed by |start|.
2112   // * |capacity| determines the size of the allocated result array, with
2113   // |capacity| >= |count|.
2114   // * |source_map| is the map of |source|. It will be used as the map of the
2115   // target array if the target can stay a FixedDoubleArray. Otherwise if the
2116   // target array needs to be a FixedArray, the FixedArrayMap will be used.
2117   // * |var_holes_converted| is used to signal whether a FixedAray
2118   // is produced or not.
2119   // * |allocation_flags| and |extract_flags| influence how the target array is
2120   // allocated.
2121   template <typename TIndex>
2122   TNode<FixedArrayBase> ExtractFixedDoubleArrayFillingHoles(
2123       TNode<FixedArrayBase> source, TNode<TIndex> first, TNode<TIndex> count,
2124       TNode<TIndex> capacity, TNode<Map> source_map,
2125       TVariable<BoolT>* var_holes_converted, AllocationFlags allocation_flags,
2126       ExtractFixedArrayFlags extract_flags);
2127 
2128   // Copy the entire contents of a FixedArray or FixedDoubleArray to a new
2129   // array, including special appropriate handling for empty arrays and COW
2130   // arrays.
2131   //
2132   // * |source| is either a FixedArray or FixedDoubleArray from which to copy
2133   // elements.
2134   // * |extract_flags| determines whether FixedArrays, FixedDoubleArrays or both
2135   // are detected and copied. Although it's always correct to pass
2136   // kAllFixedArrays, the generated code is more compact and efficient if the
2137   // caller can specify whether only FixedArrays or FixedDoubleArrays will be
2138   // passed as the |source| parameter.
2139   TNode<FixedArrayBase> CloneFixedArray(
2140       TNode<FixedArrayBase> source,
2141       ExtractFixedArrayFlags flags =
2142           ExtractFixedArrayFlag::kAllFixedArraysDontCopyCOW);
2143 
2144   // Loads an element from |array| of |from_kind| elements by given |offset|
2145   // (NOTE: not index!), does a hole check if |if_hole| is provided and
2146   // converts the value so that it becomes ready for storing to array of
2147   // |to_kind| elements.
2148   Node* LoadElementAndPrepareForStore(TNode<FixedArrayBase> array,
2149                                       TNode<IntPtrT> offset,
2150                                       ElementsKind from_kind,
2151                                       ElementsKind to_kind, Label* if_hole);
2152 
2153   template <typename TIndex>
2154   TNode<TIndex> CalculateNewElementsCapacity(TNode<TIndex> old_capacity);
2155 
2156   // Tries to grow the |elements| array of given |object| to store the |key|
2157   // or bails out if the growing gap is too big. Returns new elements.
2158   TNode<FixedArrayBase> TryGrowElementsCapacity(TNode<HeapObject> object,
2159                                                 TNode<FixedArrayBase> elements,
2160                                                 ElementsKind kind,
2161                                                 TNode<Smi> key, Label* bailout);
2162 
2163   // Tries to grow the |capacity|-length |elements| array of given |object|
2164   // to store the |key| or bails out if the growing gap is too big. Returns
2165   // new elements.
2166   template <typename TIndex>
2167   TNode<FixedArrayBase> TryGrowElementsCapacity(TNode<HeapObject> object,
2168                                                 TNode<FixedArrayBase> elements,
2169                                                 ElementsKind kind,
2170                                                 TNode<TIndex> key,
2171                                                 TNode<TIndex> capacity,
2172                                                 Label* bailout);
2173 
2174   // Grows elements capacity of given object. Returns new elements.
2175   template <typename TIndex>
2176   TNode<FixedArrayBase> GrowElementsCapacity(
2177       TNode<HeapObject> object, TNode<FixedArrayBase> elements,
2178       ElementsKind from_kind, ElementsKind to_kind, TNode<TIndex> capacity,
2179       TNode<TIndex> new_capacity, Label* bailout);
2180 
2181   // Given a need to grow by |growth|, allocate an appropriate new capacity
2182   // if necessary, and return a new elements FixedArray object. Label |bailout|
2183   // is followed for allocation failure.
2184   void PossiblyGrowElementsCapacity(ElementsKind kind, TNode<HeapObject> array,
2185                                     TNode<BInt> length,
2186                                     TVariable<FixedArrayBase>* var_elements,
2187                                     TNode<BInt> growth, Label* bailout);
2188 
2189   // Allocation site manipulation
2190   void InitializeAllocationMemento(TNode<HeapObject> base,
2191                                    TNode<IntPtrT> base_allocation_size,
2192                                    TNode<AllocationSite> allocation_site);
2193 
2194   TNode<Float64T> TryTaggedToFloat64(TNode<Object> value,
2195                                      Label* if_valueisnotnumber);
2196   TNode<Float64T> TruncateTaggedToFloat64(TNode<Context> context,
2197                                           SloppyTNode<Object> value);
2198   TNode<Word32T> TruncateTaggedToWord32(TNode<Context> context,
2199                                         SloppyTNode<Object> value);
2200   void TaggedToWord32OrBigInt(TNode<Context> context, TNode<Object> value,
2201                               Label* if_number, TVariable<Word32T>* var_word32,
2202                               Label* if_bigint,
2203                               TVariable<BigInt>* var_maybe_bigint);
2204   void TaggedToWord32OrBigIntWithFeedback(TNode<Context> context,
2205                                           TNode<Object> value, Label* if_number,
2206                                           TVariable<Word32T>* var_word32,
2207                                           Label* if_bigint,
2208                                           TVariable<BigInt>* var_maybe_bigint,
2209                                           TVariable<Smi>* var_feedback);
2210 
2211   TNode<Int32T> TruncateNumberToWord32(TNode<Number> value);
2212   // Truncate the floating point value of a HeapNumber to an Int32.
2213   TNode<Int32T> TruncateHeapNumberValueToWord32(TNode<HeapNumber> object);
2214 
2215   // Conversions.
2216   void TryHeapNumberToSmi(TNode<HeapNumber> number, TVariable<Smi>* output,
2217                           Label* if_smi);
2218   void TryFloat32ToSmi(TNode<Float32T> number, TVariable<Smi>* output,
2219                        Label* if_smi);
2220   void TryFloat64ToSmi(TNode<Float64T> number, TVariable<Smi>* output,
2221                        Label* if_smi);
2222   TNode<Number> ChangeFloat32ToTagged(TNode<Float32T> value);
2223   TNode<Number> ChangeFloat64ToTagged(SloppyTNode<Float64T> value);
2224   TNode<Number> ChangeInt32ToTagged(SloppyTNode<Int32T> value);
2225   TNode<Number> ChangeUint32ToTagged(SloppyTNode<Uint32T> value);
2226   TNode<Number> ChangeUintPtrToTagged(TNode<UintPtrT> value);
2227   TNode<Uint32T> ChangeNumberToUint32(TNode<Number> value);
2228   TNode<Float64T> ChangeNumberToFloat64(TNode<Number> value);
2229 
2230   TNode<Int32T> ChangeTaggedNonSmiToInt32(TNode<Context> context,
2231                                           TNode<HeapObject> input);
2232   TNode<Float64T> ChangeTaggedToFloat64(TNode<Context> context,
2233                                         TNode<Object> input);
2234 
2235   void TaggedToNumeric(TNode<Context> context, TNode<Object> value,
2236                        TVariable<Numeric>* var_numeric);
2237   void TaggedToNumericWithFeedback(TNode<Context> context, TNode<Object> value,
2238                                    TVariable<Numeric>* var_numeric,
2239                                    TVariable<Smi>* var_feedback);
2240 
2241   TNode<WordT> TimesSystemPointerSize(SloppyTNode<WordT> value);
TimesSystemPointerSize(TNode<IntPtrT> value)2242   TNode<IntPtrT> TimesSystemPointerSize(TNode<IntPtrT> value) {
2243     return Signed(TimesSystemPointerSize(implicit_cast<TNode<WordT>>(value)));
2244   }
TimesSystemPointerSize(TNode<UintPtrT> value)2245   TNode<UintPtrT> TimesSystemPointerSize(TNode<UintPtrT> value) {
2246     return Unsigned(TimesSystemPointerSize(implicit_cast<TNode<WordT>>(value)));
2247   }
2248 
2249   TNode<WordT> TimesTaggedSize(SloppyTNode<WordT> value);
TimesTaggedSize(TNode<IntPtrT> value)2250   TNode<IntPtrT> TimesTaggedSize(TNode<IntPtrT> value) {
2251     return Signed(TimesTaggedSize(implicit_cast<TNode<WordT>>(value)));
2252   }
TimesTaggedSize(TNode<UintPtrT> value)2253   TNode<UintPtrT> TimesTaggedSize(TNode<UintPtrT> value) {
2254     return Unsigned(TimesTaggedSize(implicit_cast<TNode<WordT>>(value)));
2255   }
2256 
2257   TNode<WordT> TimesDoubleSize(SloppyTNode<WordT> value);
TimesDoubleSize(TNode<UintPtrT> value)2258   TNode<UintPtrT> TimesDoubleSize(TNode<UintPtrT> value) {
2259     return Unsigned(TimesDoubleSize(implicit_cast<TNode<WordT>>(value)));
2260   }
TimesDoubleSize(TNode<IntPtrT> value)2261   TNode<IntPtrT> TimesDoubleSize(TNode<IntPtrT> value) {
2262     return Signed(TimesDoubleSize(implicit_cast<TNode<WordT>>(value)));
2263   }
2264 
2265   // Type conversions.
2266   // Throws a TypeError for {method_name} if {value} is not coercible to Object,
2267   // or returns the {value} converted to a String otherwise.
2268   TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
2269                              TNode<String> method_name);
ToThisString(TNode<Context> context,TNode<Object> value,char const * method_name)2270   TNode<String> ToThisString(TNode<Context> context, TNode<Object> value,
2271                              char const* method_name) {
2272     return ToThisString(context, value, StringConstant(method_name));
2273   }
2274 
2275   // Throws a TypeError for {method_name} if {value} is neither of the given
2276   // {primitive_type} nor a JSPrimitiveWrapper wrapping a value of
2277   // {primitive_type}, or returns the {value} (or wrapped value) otherwise.
2278   TNode<Object> ToThisValue(TNode<Context> context, TNode<Object> value,
2279                             PrimitiveType primitive_type,
2280                             char const* method_name);
2281 
2282   // Throws a TypeError for {method_name} if {value} is not of the given
2283   // instance type.
2284   void ThrowIfNotInstanceType(TNode<Context> context, TNode<Object> value,
2285                               InstanceType instance_type,
2286                               char const* method_name);
2287   // Throws a TypeError for {method_name} if {value} is not a JSReceiver.
2288   void ThrowIfNotJSReceiver(TNode<Context> context, TNode<Object> value,
2289                             MessageTemplate msg_template,
2290                             const char* method_name);
2291   void ThrowIfNotCallable(TNode<Context> context, TNode<Object> value,
2292                           const char* method_name);
2293 
2294   void ThrowRangeError(TNode<Context> context, MessageTemplate message,
2295                        base::Optional<TNode<Object>> arg0 = base::nullopt,
2296                        base::Optional<TNode<Object>> arg1 = base::nullopt,
2297                        base::Optional<TNode<Object>> arg2 = base::nullopt);
2298   void ThrowTypeError(TNode<Context> context, MessageTemplate message,
2299                       char const* arg0 = nullptr, char const* arg1 = nullptr);
2300   void ThrowTypeError(TNode<Context> context, MessageTemplate message,
2301                       base::Optional<TNode<Object>> arg0,
2302                       base::Optional<TNode<Object>> arg1 = base::nullopt,
2303                       base::Optional<TNode<Object>> arg2 = base::nullopt);
2304 
2305   // Type checks.
2306   // Check whether the map is for an object with special properties, such as a
2307   // JSProxy or an object with interceptors.
2308   TNode<BoolT> InstanceTypeEqual(SloppyTNode<Int32T> instance_type, int type);
2309   TNode<BoolT> IsNoElementsProtectorCellInvalid();
2310   TNode<BoolT> IsArrayIteratorProtectorCellInvalid();
2311   TNode<BoolT> IsBigIntInstanceType(SloppyTNode<Int32T> instance_type);
2312   TNode<BoolT> IsBigInt(TNode<HeapObject> object);
2313   TNode<BoolT> IsBoolean(TNode<HeapObject> object);
2314   TNode<BoolT> IsCallableMap(TNode<Map> map);
2315   TNode<BoolT> IsCallable(TNode<HeapObject> object);
2316   TNode<BoolT> TaggedIsCallable(TNode<Object> object);
2317   TNode<BoolT> IsConsStringInstanceType(SloppyTNode<Int32T> instance_type);
2318   TNode<BoolT> IsConstructorMap(TNode<Map> map);
2319   TNode<BoolT> IsConstructor(TNode<HeapObject> object);
2320   TNode<BoolT> IsDeprecatedMap(TNode<Map> map);
2321   TNode<BoolT> IsNameDictionary(TNode<HeapObject> object);
2322   TNode<BoolT> IsGlobalDictionary(TNode<HeapObject> object);
2323   TNode<BoolT> IsExtensibleMap(TNode<Map> map);
2324   TNode<BoolT> IsExtensibleNonPrototypeMap(TNode<Map> map);
2325   TNode<BoolT> IsExternalStringInstanceType(SloppyTNode<Int32T> instance_type);
2326   TNode<BoolT> IsFixedArray(TNode<HeapObject> object);
2327   TNode<BoolT> IsFixedArraySubclass(TNode<HeapObject> object);
2328   TNode<BoolT> IsFixedArrayWithKind(TNode<HeapObject> object,
2329                                     ElementsKind kind);
2330   TNode<BoolT> IsFixedArrayWithKindOrEmpty(TNode<FixedArrayBase> object,
2331                                            ElementsKind kind);
2332   TNode<BoolT> IsFunctionWithPrototypeSlotMap(TNode<Map> map);
2333   TNode<BoolT> IsHashTable(TNode<HeapObject> object);
2334   TNode<BoolT> IsEphemeronHashTable(TNode<HeapObject> object);
2335   TNode<BoolT> IsHeapNumberInstanceType(SloppyTNode<Int32T> instance_type);
2336   TNode<BoolT> IsOddball(TNode<HeapObject> object);
2337   TNode<BoolT> IsOddballInstanceType(SloppyTNode<Int32T> instance_type);
2338   TNode<BoolT> IsIndirectStringInstanceType(SloppyTNode<Int32T> instance_type);
2339   TNode<BoolT> IsJSArrayBuffer(TNode<HeapObject> object);
2340   TNode<BoolT> IsJSDataView(TNode<HeapObject> object);
2341   TNode<BoolT> IsJSArrayInstanceType(SloppyTNode<Int32T> instance_type);
2342   TNode<BoolT> IsJSArrayMap(TNode<Map> map);
2343   TNode<BoolT> IsJSArray(TNode<HeapObject> object);
2344   TNode<BoolT> IsJSArrayIterator(TNode<HeapObject> object);
2345   TNode<BoolT> IsJSAsyncGeneratorObject(TNode<HeapObject> object);
2346   TNode<BoolT> IsJSFunctionInstanceType(SloppyTNode<Int32T> instance_type);
2347   TNode<BoolT> IsJSFunctionMap(TNode<Map> map);
2348   TNode<BoolT> IsJSFunction(TNode<HeapObject> object);
2349   TNode<BoolT> IsJSBoundFunction(TNode<HeapObject> object);
2350   TNode<BoolT> IsJSGeneratorObject(TNode<HeapObject> object);
2351   TNode<BoolT> IsJSGlobalProxyInstanceType(SloppyTNode<Int32T> instance_type);
2352   TNode<BoolT> IsJSGlobalProxyMap(TNode<Map> map);
2353   TNode<BoolT> IsJSGlobalProxy(TNode<HeapObject> object);
2354   TNode<BoolT> IsJSObjectInstanceType(SloppyTNode<Int32T> instance_type);
2355   TNode<BoolT> IsJSObjectMap(TNode<Map> map);
2356   TNode<BoolT> IsJSObject(TNode<HeapObject> object);
2357   TNode<BoolT> IsJSFinalizationRegistryMap(TNode<Map> map);
2358   TNode<BoolT> IsJSFinalizationRegistry(TNode<HeapObject> object);
2359   TNode<BoolT> IsJSPromiseMap(TNode<Map> map);
2360   TNode<BoolT> IsJSPromise(TNode<HeapObject> object);
2361   TNode<BoolT> IsJSProxy(TNode<HeapObject> object);
2362   TNode<BoolT> IsJSStringIterator(TNode<HeapObject> object);
2363   TNode<BoolT> IsJSRegExpStringIterator(TNode<HeapObject> object);
2364   TNode<BoolT> IsJSReceiverInstanceType(SloppyTNode<Int32T> instance_type);
2365   TNode<BoolT> IsJSReceiverMap(TNode<Map> map);
2366   TNode<BoolT> IsJSReceiver(TNode<HeapObject> object);
2367   TNode<BoolT> IsJSRegExp(TNode<HeapObject> object);
2368   TNode<BoolT> IsJSTypedArrayInstanceType(SloppyTNode<Int32T> instance_type);
2369   TNode<BoolT> IsJSTypedArrayMap(TNode<Map> map);
2370   TNode<BoolT> IsJSTypedArray(TNode<HeapObject> object);
2371   TNode<BoolT> IsJSGeneratorMap(TNode<Map> map);
2372   TNode<BoolT> IsJSPrimitiveWrapperInstanceType(
2373       SloppyTNode<Int32T> instance_type);
2374   TNode<BoolT> IsJSPrimitiveWrapperMap(TNode<Map> map);
2375   TNode<BoolT> IsJSPrimitiveWrapper(TNode<HeapObject> object);
2376   TNode<BoolT> IsMap(TNode<HeapObject> object);
2377   TNode<BoolT> IsName(TNode<HeapObject> object);
2378   TNode<BoolT> IsNameInstanceType(SloppyTNode<Int32T> instance_type);
2379   TNode<BoolT> IsNullOrJSReceiver(TNode<HeapObject> object);
2380   TNode<BoolT> IsNullOrUndefined(SloppyTNode<Object> object);
2381   TNode<BoolT> IsNumberDictionary(TNode<HeapObject> object);
2382   TNode<BoolT> IsOneByteStringInstanceType(TNode<Int32T> instance_type);
2383   TNode<BoolT> IsSeqOneByteStringInstanceType(TNode<Int32T> instance_type);
2384   TNode<BoolT> IsPrimitiveInstanceType(SloppyTNode<Int32T> instance_type);
2385   TNode<BoolT> IsPrivateName(SloppyTNode<Symbol> symbol);
2386   TNode<BoolT> IsPropertyArray(TNode<HeapObject> object);
2387   TNode<BoolT> IsPropertyCell(TNode<HeapObject> object);
2388   TNode<BoolT> IsPromiseReactionJobTask(TNode<HeapObject> object);
2389   TNode<BoolT> IsPrototypeInitialArrayPrototype(TNode<Context> context,
2390                                                 TNode<Map> map);
2391   TNode<BoolT> IsPrototypeTypedArrayPrototype(TNode<Context> context,
2392                                               TNode<Map> map);
2393 
2394   TNode<BoolT> IsFastAliasedArgumentsMap(TNode<Context> context,
2395                                          TNode<Map> map);
2396   TNode<BoolT> IsSlowAliasedArgumentsMap(TNode<Context> context,
2397                                          TNode<Map> map);
2398   TNode<BoolT> IsSloppyArgumentsMap(TNode<Context> context, TNode<Map> map);
2399   TNode<BoolT> IsStrictArgumentsMap(TNode<Context> context, TNode<Map> map);
2400 
2401   TNode<BoolT> IsSequentialStringInstanceType(
2402       SloppyTNode<Int32T> instance_type);
2403   TNode<BoolT> IsUncachedExternalStringInstanceType(
2404       SloppyTNode<Int32T> instance_type);
2405   TNode<BoolT> IsSpecialReceiverInstanceType(TNode<Int32T> instance_type);
2406   TNode<BoolT> IsCustomElementsReceiverInstanceType(
2407       TNode<Int32T> instance_type);
2408   TNode<BoolT> IsSpecialReceiverMap(TNode<Map> map);
2409   TNode<BoolT> IsStringInstanceType(SloppyTNode<Int32T> instance_type);
2410   TNode<BoolT> IsString(TNode<HeapObject> object);
2411   TNode<BoolT> IsSeqOneByteString(TNode<HeapObject> object);
2412 
2413   TNode<BoolT> IsSymbolInstanceType(SloppyTNode<Int32T> instance_type);
2414   TNode<BoolT> IsInternalizedStringInstanceType(TNode<Int32T> instance_type);
2415   TNode<BoolT> IsUniqueName(TNode<HeapObject> object);
2416   TNode<BoolT> IsUniqueNameNoIndex(TNode<HeapObject> object);
2417   TNode<BoolT> IsUniqueNameNoCachedIndex(TNode<HeapObject> object);
2418   TNode<BoolT> IsUndetectableMap(TNode<Map> map);
2419   TNode<BoolT> IsNotWeakFixedArraySubclass(TNode<HeapObject> object);
2420   TNode<BoolT> IsZeroOrContext(SloppyTNode<Object> object);
2421 
2422   TNode<BoolT> IsPromiseResolveProtectorCellInvalid();
2423   TNode<BoolT> IsPromiseThenProtectorCellInvalid();
2424   TNode<BoolT> IsArraySpeciesProtectorCellInvalid();
2425   TNode<BoolT> IsTypedArraySpeciesProtectorCellInvalid();
2426   TNode<BoolT> IsRegExpSpeciesProtectorCellInvalid();
2427   TNode<BoolT> IsPromiseSpeciesProtectorCellInvalid();
2428 
IsMockArrayBufferAllocatorFlag()2429   TNode<BoolT> IsMockArrayBufferAllocatorFlag() {
2430     TNode<Word32T> flag_value = UncheckedCast<Word32T>(Load(
2431         MachineType::Uint8(),
2432         ExternalConstant(
2433             ExternalReference::address_of_mock_arraybuffer_allocator_flag())));
2434     return Word32NotEqual(Word32And(flag_value, Int32Constant(0xFF)),
2435                           Int32Constant(0));
2436   }
2437 
2438   // True iff |object| is a Smi or a HeapNumber or a BigInt.
2439   TNode<BoolT> IsNumeric(SloppyTNode<Object> object);
2440 
2441   // True iff |number| is either a Smi, or a HeapNumber whose value is not
2442   // within Smi range.
2443   TNode<BoolT> IsNumberNormalized(TNode<Number> number);
2444   TNode<BoolT> IsNumberPositive(TNode<Number> number);
2445   TNode<BoolT> IsHeapNumberPositive(TNode<HeapNumber> number);
2446 
2447   // True iff {number} is non-negative and less or equal than 2**53-1.
2448   TNode<BoolT> IsNumberNonNegativeSafeInteger(TNode<Number> number);
2449 
2450   // True iff {number} represents an integer value.
2451   TNode<BoolT> IsInteger(TNode<Object> number);
2452   TNode<BoolT> IsInteger(TNode<HeapNumber> number);
2453 
2454   // True iff abs({number}) <= 2**53 -1
2455   TNode<BoolT> IsSafeInteger(TNode<Object> number);
2456   TNode<BoolT> IsSafeInteger(TNode<HeapNumber> number);
2457 
2458   // True iff {number} represents a valid uint32t value.
2459   TNode<BoolT> IsHeapNumberUint32(TNode<HeapNumber> number);
2460 
2461   // True iff {number} is a positive number and a valid array index in the range
2462   // [0, 2^32-1).
2463   TNode<BoolT> IsNumberArrayIndex(TNode<Number> number);
2464 
2465   template <typename TIndex>
2466   TNode<BoolT> FixedArraySizeDoesntFitInNewSpace(TNode<TIndex> element_count,
2467                                                  int base_size);
2468 
IsMetaMap(TNode<HeapObject> o)2469   TNode<BoolT> IsMetaMap(TNode<HeapObject> o) { return IsMapMap(o); }
2470 
2471   // ElementsKind helpers:
ElementsKindEqual(TNode<Int32T> a,TNode<Int32T> b)2472   TNode<BoolT> ElementsKindEqual(TNode<Int32T> a, TNode<Int32T> b) {
2473     return Word32Equal(a, b);
2474   }
ElementsKindEqual(ElementsKind a,ElementsKind b)2475   bool ElementsKindEqual(ElementsKind a, ElementsKind b) { return a == b; }
2476   TNode<BoolT> IsFastElementsKind(TNode<Int32T> elements_kind);
IsFastElementsKind(ElementsKind kind)2477   bool IsFastElementsKind(ElementsKind kind) {
2478     return v8::internal::IsFastElementsKind(kind);
2479   }
2480   TNode<BoolT> IsFastOrNonExtensibleOrSealedElementsKind(
2481       TNode<Int32T> elements_kind);
2482 
IsDictionaryElementsKind(TNode<Int32T> elements_kind)2483   TNode<BoolT> IsDictionaryElementsKind(TNode<Int32T> elements_kind) {
2484     return ElementsKindEqual(elements_kind, Int32Constant(DICTIONARY_ELEMENTS));
2485   }
2486   TNode<BoolT> IsDoubleElementsKind(TNode<Int32T> elements_kind);
IsDoubleElementsKind(ElementsKind kind)2487   bool IsDoubleElementsKind(ElementsKind kind) {
2488     return v8::internal::IsDoubleElementsKind(kind);
2489   }
2490   TNode<BoolT> IsFastSmiOrTaggedElementsKind(TNode<Int32T> elements_kind);
2491   TNode<BoolT> IsFastSmiElementsKind(SloppyTNode<Int32T> elements_kind);
2492   TNode<BoolT> IsHoleyFastElementsKind(TNode<Int32T> elements_kind);
2493   TNode<BoolT> IsHoleyFastElementsKindForRead(TNode<Int32T> elements_kind);
2494   TNode<BoolT> IsElementsKindGreaterThan(TNode<Int32T> target_kind,
2495                                          ElementsKind reference_kind);
2496   TNode<BoolT> IsElementsKindLessThanOrEqual(TNode<Int32T> target_kind,
2497                                              ElementsKind reference_kind);
2498   // Check if lower_reference_kind <= target_kind <= higher_reference_kind.
IsElementsKindInRange(TNode<Int32T> target_kind,ElementsKind lower_reference_kind,ElementsKind higher_reference_kind)2499   TNode<BoolT> IsElementsKindInRange(TNode<Int32T> target_kind,
2500                                      ElementsKind lower_reference_kind,
2501                                      ElementsKind higher_reference_kind) {
2502     return IsInRange(target_kind, lower_reference_kind, higher_reference_kind);
2503   }
2504 
2505   // String helpers.
2506   // Load a character from a String (might flatten a ConsString).
2507   TNode<Int32T> StringCharCodeAt(TNode<String> string, TNode<UintPtrT> index);
2508   // Return the single character string with only {code}.
2509   TNode<String> StringFromSingleCharCode(TNode<Int32T> code);
2510 
2511   // Type conversion helpers.
2512   enum class BigIntHandling { kConvertToNumber, kThrow };
2513   // Convert a String to a Number.
2514   TNode<Number> StringToNumber(TNode<String> input);
2515   // Convert a Number to a String.
2516   TNode<String> NumberToString(TNode<Number> input);
2517   TNode<String> NumberToString(TNode<Number> input, Label* bailout);
2518 
2519   // Convert a Non-Number object to a Number.
2520   TNode<Number> NonNumberToNumber(
2521       TNode<Context> context, TNode<HeapObject> input,
2522       BigIntHandling bigint_handling = BigIntHandling::kThrow);
2523   // Convert a Non-Number object to a Numeric.
2524   TNode<Numeric> NonNumberToNumeric(TNode<Context> context,
2525                                     TNode<HeapObject> input);
2526   // Convert any object to a Number.
2527   // Conforms to ES#sec-tonumber if {bigint_handling} == kThrow.
2528   // With {bigint_handling} == kConvertToNumber, matches behavior of
2529   // tc39.github.io/proposal-bigint/#sec-number-constructor-number-value.
2530   TNode<Number> ToNumber(
2531       TNode<Context> context, SloppyTNode<Object> input,
2532       BigIntHandling bigint_handling = BigIntHandling::kThrow);
2533   TNode<Number> ToNumber_Inline(TNode<Context> context,
2534                                 SloppyTNode<Object> input);
2535   // Convert any plain primitive to a Number. No need to handle BigInts since
2536   // they are not plain primitives.
2537   TNode<Number> PlainPrimitiveToNumber(TNode<Object> input);
2538 
2539   // Try to convert an object to a BigInt. Throws on failure (e.g. for Numbers).
2540   // https://tc39.github.io/proposal-bigint/#sec-to-bigint
2541   TNode<BigInt> ToBigInt(TNode<Context> context, TNode<Object> input);
2542 
2543   // Converts |input| to one of 2^32 integer values in the range 0 through
2544   // 2^32-1, inclusive.
2545   // ES#sec-touint32
2546   TNode<Number> ToUint32(TNode<Context> context, SloppyTNode<Object> input);
2547 
2548   // Convert any object to a String.
2549   TNode<String> ToString_Inline(TNode<Context> context,
2550                                 SloppyTNode<Object> input);
2551 
2552   TNode<JSReceiver> ToObject(TNode<Context> context, SloppyTNode<Object> input);
2553 
2554   // Same as ToObject but avoids the Builtin call if |input| is already a
2555   // JSReceiver.
2556   TNode<JSReceiver> ToObject_Inline(TNode<Context> context,
2557                                     TNode<Object> input);
2558 
2559   // ES6 7.1.15 ToLength, but with inlined fast path.
2560   TNode<Number> ToLength_Inline(TNode<Context> context,
2561                                 SloppyTNode<Object> input);
2562 
2563   TNode<Object> OrdinaryToPrimitive(TNode<Context> context, TNode<Object> input,
2564                                     OrdinaryToPrimitiveHint hint);
2565 
2566   // Returns a node that contains a decoded (unsigned!) value of a bit
2567   // field |BitField| in |word32|. Returns result as an uint32 node.
2568   template <typename BitField>
DecodeWord32(TNode<Word32T> word32)2569   TNode<Uint32T> DecodeWord32(TNode<Word32T> word32) {
2570     return DecodeWord32(word32, BitField::kShift, BitField::kMask);
2571   }
2572 
2573   // Returns a node that contains a decoded (unsigned!) value of a bit
2574   // field |BitField| in |word|. Returns result as a word-size node.
2575   template <typename BitField>
DecodeWord(SloppyTNode<WordT> word)2576   TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word) {
2577     return DecodeWord(word, BitField::kShift, BitField::kMask);
2578   }
2579 
2580   // Returns a node that contains a decoded (unsigned!) value of a bit
2581   // field |BitField| in |word32|. Returns result as a word-size node.
2582   template <typename BitField>
DecodeWordFromWord32(TNode<Word32T> word32)2583   TNode<UintPtrT> DecodeWordFromWord32(TNode<Word32T> word32) {
2584     return DecodeWord<BitField>(ChangeUint32ToWord(word32));
2585   }
2586 
2587   // Returns a node that contains a decoded (unsigned!) value of a bit
2588   // field |BitField| in |word|. Returns result as an uint32 node.
2589   template <typename BitField>
DecodeWord32FromWord(SloppyTNode<WordT> word)2590   TNode<Uint32T> DecodeWord32FromWord(SloppyTNode<WordT> word) {
2591     return UncheckedCast<Uint32T>(
2592         TruncateIntPtrToInt32(Signed(DecodeWord<BitField>(word))));
2593   }
2594 
2595   // Decodes an unsigned (!) value from |word32| to an uint32 node.
2596   TNode<Uint32T> DecodeWord32(TNode<Word32T> word32, uint32_t shift,
2597                               uint32_t mask);
2598 
2599   // Decodes an unsigned (!) value from |word| to a word-size node.
2600   TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift,
2601                              uintptr_t mask);
2602 
2603   // Returns a node that contains the updated values of a |BitField|.
2604   template <typename BitField>
2605   TNode<Word32T> UpdateWord32(TNode<Word32T> word, TNode<Uint32T> value,
2606                               bool starts_as_zero = false) {
2607     return UpdateWord32(word, value, BitField::kShift, BitField::kMask,
2608                         starts_as_zero);
2609   }
2610 
2611   // Returns a node that contains the updated values of a |BitField|.
2612   template <typename BitField>
2613   TNode<WordT> UpdateWord(TNode<WordT> word, TNode<UintPtrT> value,
2614                           bool starts_as_zero = false) {
2615     return UpdateWord(word, value, BitField::kShift, BitField::kMask,
2616                       starts_as_zero);
2617   }
2618 
2619   // Returns a node that contains the updated values of a |BitField|.
2620   template <typename BitField>
2621   TNode<Word32T> UpdateWordInWord32(TNode<Word32T> word, TNode<UintPtrT> value,
2622                                     bool starts_as_zero = false) {
2623     return UncheckedCast<Uint32T>(
2624         TruncateIntPtrToInt32(Signed(UpdateWord<BitField>(
2625             ChangeUint32ToWord(word), value, starts_as_zero))));
2626   }
2627 
2628   // Returns a node that contains the updated values of a |BitField|.
2629   template <typename BitField>
2630   TNode<WordT> UpdateWord32InWord(TNode<WordT> word, TNode<Uint32T> value,
2631                                   bool starts_as_zero = false) {
2632     return UpdateWord<BitField>(word, ChangeUint32ToWord(value),
2633                                 starts_as_zero);
2634   }
2635 
2636   // Returns a node that contains the updated {value} inside {word} starting
2637   // at {shift} and fitting in {mask}.
2638   TNode<Word32T> UpdateWord32(TNode<Word32T> word, TNode<Uint32T> value,
2639                               uint32_t shift, uint32_t mask,
2640                               bool starts_as_zero = false);
2641 
2642   // Returns a node that contains the updated {value} inside {word} starting
2643   // at {shift} and fitting in {mask}.
2644   TNode<WordT> UpdateWord(TNode<WordT> word, TNode<UintPtrT> value,
2645                           uint32_t shift, uintptr_t mask,
2646                           bool starts_as_zero = false);
2647 
2648   // Returns true if any of the |T|'s bits in given |word32| are set.
2649   template <typename T>
IsSetWord32(TNode<Word32T> word32)2650   TNode<BoolT> IsSetWord32(TNode<Word32T> word32) {
2651     return IsSetWord32(word32, T::kMask);
2652   }
2653 
2654   // Returns true if any of the mask's bits in given |word32| are set.
IsSetWord32(TNode<Word32T> word32,uint32_t mask)2655   TNode<BoolT> IsSetWord32(TNode<Word32T> word32, uint32_t mask) {
2656     return Word32NotEqual(Word32And(word32, Int32Constant(mask)),
2657                           Int32Constant(0));
2658   }
2659 
2660   // Returns true if none of the mask's bits in given |word32| are set.
IsNotSetWord32(TNode<Word32T> word32,uint32_t mask)2661   TNode<BoolT> IsNotSetWord32(TNode<Word32T> word32, uint32_t mask) {
2662     return Word32Equal(Word32And(word32, Int32Constant(mask)),
2663                        Int32Constant(0));
2664   }
2665 
2666   // Returns true if all of the mask's bits in a given |word32| are set.
IsAllSetWord32(TNode<Word32T> word32,uint32_t mask)2667   TNode<BoolT> IsAllSetWord32(TNode<Word32T> word32, uint32_t mask) {
2668     TNode<Int32T> const_mask = Int32Constant(mask);
2669     return Word32Equal(Word32And(word32, const_mask), const_mask);
2670   }
2671 
2672   // Returns true if the bit field |BitField| in |word32| is equal to a given.
2673   // constant |value|. Avoids a shift compared to using DecodeWord32.
2674   template <typename BitField>
IsEqualInWord32(TNode<Word32T> word32,typename BitField::FieldType value)2675   TNode<BoolT> IsEqualInWord32(TNode<Word32T> word32,
2676                                typename BitField::FieldType value) {
2677     TNode<Word32T> masked_word32 =
2678         Word32And(word32, Int32Constant(BitField::kMask));
2679     return Word32Equal(masked_word32, Int32Constant(BitField::encode(value)));
2680   }
2681 
2682   // Returns true if any of the |T|'s bits in given |word| are set.
2683   template <typename T>
IsSetWord(SloppyTNode<WordT> word)2684   TNode<BoolT> IsSetWord(SloppyTNode<WordT> word) {
2685     return IsSetWord(word, T::kMask);
2686   }
2687 
2688   // Returns true if any of the mask's bits in given |word| are set.
IsSetWord(SloppyTNode<WordT> word,uint32_t mask)2689   TNode<BoolT> IsSetWord(SloppyTNode<WordT> word, uint32_t mask) {
2690     return WordNotEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
2691   }
2692 
2693   // Returns true if any of the mask's bit are set in the given Smi.
2694   // Smi-encoding of the mask is performed implicitly!
IsSetSmi(SloppyTNode<Smi> smi,int untagged_mask)2695   TNode<BoolT> IsSetSmi(SloppyTNode<Smi> smi, int untagged_mask) {
2696     intptr_t mask_word = bit_cast<intptr_t>(Smi::FromInt(untagged_mask));
2697     return WordNotEqual(WordAnd(BitcastTaggedToWordForTagAndSmiBits(smi),
2698                                 IntPtrConstant(mask_word)),
2699                         IntPtrConstant(0));
2700   }
2701 
2702   // Returns true if all of the |T|'s bits in given |word32| are clear.
2703   template <typename T>
IsClearWord32(TNode<Word32T> word32)2704   TNode<BoolT> IsClearWord32(TNode<Word32T> word32) {
2705     return IsClearWord32(word32, T::kMask);
2706   }
2707 
2708   // Returns true if all of the mask's bits in given |word32| are clear.
IsClearWord32(TNode<Word32T> word32,uint32_t mask)2709   TNode<BoolT> IsClearWord32(TNode<Word32T> word32, uint32_t mask) {
2710     return Word32Equal(Word32And(word32, Int32Constant(mask)),
2711                        Int32Constant(0));
2712   }
2713 
2714   // Returns true if all of the |T|'s bits in given |word| are clear.
2715   template <typename T>
IsClearWord(SloppyTNode<WordT> word)2716   TNode<BoolT> IsClearWord(SloppyTNode<WordT> word) {
2717     return IsClearWord(word, T::kMask);
2718   }
2719 
2720   // Returns true if all of the mask's bits in given |word| are clear.
IsClearWord(SloppyTNode<WordT> word,uint32_t mask)2721   TNode<BoolT> IsClearWord(SloppyTNode<WordT> word, uint32_t mask) {
2722     return IntPtrEqual(WordAnd(word, IntPtrConstant(mask)), IntPtrConstant(0));
2723   }
2724 
2725   void SetCounter(StatsCounter* counter, int value);
2726   void IncrementCounter(StatsCounter* counter, int delta);
2727   void DecrementCounter(StatsCounter* counter, int delta);
2728 
2729   template <typename TIndex>
2730   void Increment(TVariable<TIndex>* variable, int value = 1);
2731 
2732   template <typename TIndex>
2733   void Decrement(TVariable<TIndex>* variable, int value = 1) {
2734     Increment(variable, -value);
2735   }
2736 
2737   // Generates "if (false) goto label" code. Useful for marking a label as
2738   // "live" to avoid assertion failures during graph building. In the resulting
2739   // code this check will be eliminated.
2740   void Use(Label* label);
2741 
2742   // Various building blocks for stubs doing property lookups.
2743 
2744   // |if_notinternalized| is optional; |if_bailout| will be used by default.
2745   // Note: If |key| does not yet have a hash, |if_notinternalized| will be taken
2746   // even if |key| is an array index. |if_keyisunique| will never
2747   // be taken for array indices.
2748   void TryToName(SloppyTNode<Object> key, Label* if_keyisindex,
2749                  TVariable<IntPtrT>* var_index, Label* if_keyisunique,
2750                  TVariable<Name>* var_unique, Label* if_bailout,
2751                  Label* if_notinternalized = nullptr);
2752 
2753   // Performs a hash computation and string table lookup for the given string,
2754   // and jumps to:
2755   // - |if_index| if the string is an array index like "123"; |var_index|
2756   //              will contain the intptr representation of that index.
2757   // - |if_internalized| if the string exists in the string table; the
2758   //                     internalized version will be in |var_internalized|.
2759   // - |if_not_internalized| if the string is not in the string table (but
2760   //                         does not add it).
2761   // - |if_bailout| for unsupported cases (e.g. uncachable array index).
2762   void TryInternalizeString(TNode<String> string, Label* if_index,
2763                             TVariable<IntPtrT>* var_index,
2764                             Label* if_internalized,
2765                             TVariable<Name>* var_internalized,
2766                             Label* if_not_internalized, Label* if_bailout);
2767 
2768   // Calculates array index for given dictionary entry and entry field.
2769   // See Dictionary::EntryToIndex().
2770   template <typename Dictionary>
2771   TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry, int field_index);
2772   template <typename Dictionary>
EntryToIndex(TNode<IntPtrT> entry)2773   TNode<IntPtrT> EntryToIndex(TNode<IntPtrT> entry) {
2774     return EntryToIndex<Dictionary>(entry, Dictionary::kEntryKeyIndex);
2775   }
2776 
2777   // Loads the details for the entry with the given key_index.
2778   // Returns an untagged int32.
2779   template <class ContainerType>
LoadDetailsByKeyIndex(TNode<ContainerType> container,TNode<IntPtrT> key_index)2780   TNode<Uint32T> LoadDetailsByKeyIndex(TNode<ContainerType> container,
2781                                        TNode<IntPtrT> key_index) {
2782     static_assert(!std::is_same<ContainerType, DescriptorArray>::value,
2783                   "Use the non-templatized version for DescriptorArray");
2784     const int kKeyToDetailsOffset =
2785         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
2786         kTaggedSize;
2787     return Unsigned(LoadAndUntagToWord32FixedArrayElement(container, key_index,
2788                                                           kKeyToDetailsOffset));
2789   }
2790 
2791   // Loads the value for the entry with the given key_index.
2792   // Returns a tagged value.
2793   template <class ContainerType>
LoadValueByKeyIndex(TNode<ContainerType> container,TNode<IntPtrT> key_index)2794   TNode<Object> LoadValueByKeyIndex(TNode<ContainerType> container,
2795                                     TNode<IntPtrT> key_index) {
2796     static_assert(!std::is_same<ContainerType, DescriptorArray>::value,
2797                   "Use the non-templatized version for DescriptorArray");
2798     const int kKeyToValueOffset =
2799         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
2800         kTaggedSize;
2801     return LoadFixedArrayElement(container, key_index, kKeyToValueOffset);
2802   }
2803 
2804   // Stores the details for the entry with the given key_index.
2805   // |details| must be a Smi.
2806   template <class ContainerType>
StoreDetailsByKeyIndex(TNode<ContainerType> container,TNode<IntPtrT> key_index,TNode<Smi> details)2807   void StoreDetailsByKeyIndex(TNode<ContainerType> container,
2808                               TNode<IntPtrT> key_index, TNode<Smi> details) {
2809     const int kKeyToDetailsOffset =
2810         (ContainerType::kEntryDetailsIndex - ContainerType::kEntryKeyIndex) *
2811         kTaggedSize;
2812     StoreFixedArrayElement(container, key_index, details, SKIP_WRITE_BARRIER,
2813                            kKeyToDetailsOffset);
2814   }
2815 
2816   // Stores the value for the entry with the given key_index.
2817   template <class ContainerType>
2818   void StoreValueByKeyIndex(
2819       TNode<ContainerType> container, TNode<IntPtrT> key_index,
2820       TNode<Object> value,
2821       WriteBarrierMode write_barrier = UPDATE_WRITE_BARRIER) {
2822     const int kKeyToValueOffset =
2823         (ContainerType::kEntryValueIndex - ContainerType::kEntryKeyIndex) *
2824         kTaggedSize;
2825     StoreFixedArrayElement(container, key_index, value, write_barrier,
2826                            kKeyToValueOffset);
2827   }
2828 
2829   // Calculate a valid size for the a hash table.
2830   TNode<IntPtrT> HashTableComputeCapacity(TNode<IntPtrT> at_least_space_for);
2831 
2832   template <class Dictionary>
GetNumberOfElements(TNode<Dictionary> dictionary)2833   TNode<Smi> GetNumberOfElements(TNode<Dictionary> dictionary) {
2834     return CAST(
2835         LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex));
2836   }
2837 
GetNumberDictionaryNumberOfElements(TNode<NumberDictionary> dictionary)2838   TNode<Smi> GetNumberDictionaryNumberOfElements(
2839       TNode<NumberDictionary> dictionary) {
2840     return GetNumberOfElements<NumberDictionary>(dictionary);
2841   }
2842 
2843   template <class Dictionary>
SetNumberOfElements(TNode<Dictionary> dictionary,TNode<Smi> num_elements_smi)2844   void SetNumberOfElements(TNode<Dictionary> dictionary,
2845                            TNode<Smi> num_elements_smi) {
2846     StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex,
2847                            num_elements_smi, SKIP_WRITE_BARRIER);
2848   }
2849 
2850   template <class Dictionary>
GetNumberOfDeletedElements(TNode<Dictionary> dictionary)2851   TNode<Smi> GetNumberOfDeletedElements(TNode<Dictionary> dictionary) {
2852     return CAST(LoadFixedArrayElement(
2853         dictionary, Dictionary::kNumberOfDeletedElementsIndex));
2854   }
2855 
2856   template <class Dictionary>
SetNumberOfDeletedElements(TNode<Dictionary> dictionary,TNode<Smi> num_deleted_smi)2857   void SetNumberOfDeletedElements(TNode<Dictionary> dictionary,
2858                                   TNode<Smi> num_deleted_smi) {
2859     StoreFixedArrayElement(dictionary,
2860                            Dictionary::kNumberOfDeletedElementsIndex,
2861                            num_deleted_smi, SKIP_WRITE_BARRIER);
2862   }
2863 
2864   template <class Dictionary>
GetCapacity(TNode<Dictionary> dictionary)2865   TNode<Smi> GetCapacity(TNode<Dictionary> dictionary) {
2866     return CAST(
2867         UnsafeLoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex));
2868   }
2869 
2870   template <class Dictionary>
GetNextEnumerationIndex(TNode<Dictionary> dictionary)2871   TNode<Smi> GetNextEnumerationIndex(TNode<Dictionary> dictionary) {
2872     return CAST(LoadFixedArrayElement(dictionary,
2873                                       Dictionary::kNextEnumerationIndexIndex));
2874   }
2875 
2876   template <class Dictionary>
SetNextEnumerationIndex(TNode<Dictionary> dictionary,TNode<Smi> next_enum_index_smi)2877   void SetNextEnumerationIndex(TNode<Dictionary> dictionary,
2878                                TNode<Smi> next_enum_index_smi) {
2879     StoreFixedArrayElement(dictionary, Dictionary::kNextEnumerationIndexIndex,
2880                            next_enum_index_smi, SKIP_WRITE_BARRIER);
2881   }
2882 
2883   // Looks up an entry in a NameDictionaryBase successor. If the entry is found
2884   // control goes to {if_found} and {var_name_index} contains an index of the
2885   // key field of the entry found. If the key is not found control goes to
2886   // {if_not_found}.
2887   enum LookupMode { kFindExisting, kFindInsertionIndex };
2888 
2889   template <typename Dictionary>
2890   TNode<HeapObject> LoadName(TNode<HeapObject> key);
2891 
2892   template <typename Dictionary>
2893   void NameDictionaryLookup(TNode<Dictionary> dictionary,
2894                             TNode<Name> unique_name, Label* if_found,
2895                             TVariable<IntPtrT>* var_name_index,
2896                             Label* if_not_found,
2897                             LookupMode mode = kFindExisting);
2898 
2899   TNode<Word32T> ComputeSeededHash(TNode<IntPtrT> key);
2900 
2901   void NumberDictionaryLookup(TNode<NumberDictionary> dictionary,
2902                               TNode<IntPtrT> intptr_index, Label* if_found,
2903                               TVariable<IntPtrT>* var_entry,
2904                               Label* if_not_found);
2905 
2906   TNode<Object> BasicLoadNumberDictionaryElement(
2907       TNode<NumberDictionary> dictionary, TNode<IntPtrT> intptr_index,
2908       Label* not_data, Label* if_hole);
2909 
2910   template <class Dictionary>
2911   void FindInsertionEntry(TNode<Dictionary> dictionary, TNode<Name> key,
2912                           TVariable<IntPtrT>* var_key_index);
2913 
2914   template <class Dictionary>
2915   void InsertEntry(TNode<Dictionary> dictionary, TNode<Name> key,
2916                    TNode<Object> value, TNode<IntPtrT> index,
2917                    TNode<Smi> enum_index);
2918 
2919   template <class Dictionary>
2920   void Add(TNode<Dictionary> dictionary, TNode<Name> key, TNode<Object> value,
2921            Label* bailout);
2922 
2923   // Tries to check if {object} has own {unique_name} property.
2924   void TryHasOwnProperty(TNode<HeapObject> object, TNode<Map> map,
2925                          TNode<Int32T> instance_type, TNode<Name> unique_name,
2926                          Label* if_found, Label* if_not_found,
2927                          Label* if_bailout);
2928 
2929   // Operating mode for TryGetOwnProperty and CallGetterIfAccessor
2930   // kReturnAccessorPair is used when we're only getting the property descriptor
2931   enum GetOwnPropertyMode { kCallJSGetter, kReturnAccessorPair };
2932   // Tries to get {object}'s own {unique_name} property value. If the property
2933   // is an accessor then it also calls a getter. If the property is a double
2934   // field it re-wraps value in an immutable heap number. {unique_name} must be
2935   // a unique name (Symbol or InternalizedString) that is not an array index.
2936   void TryGetOwnProperty(TNode<Context> context, TNode<Object> receiver,
2937                          TNode<JSReceiver> object, TNode<Map> map,
2938                          TNode<Int32T> instance_type, TNode<Name> unique_name,
2939                          Label* if_found_value, TVariable<Object>* var_value,
2940                          Label* if_not_found, Label* if_bailout);
2941   void TryGetOwnProperty(TNode<Context> context, TNode<Object> receiver,
2942                          TNode<JSReceiver> object, TNode<Map> map,
2943                          TNode<Int32T> instance_type, TNode<Name> unique_name,
2944                          Label* if_found_value, TVariable<Object>* var_value,
2945                          TVariable<Uint32T>* var_details,
2946                          TVariable<Object>* var_raw_value, Label* if_not_found,
2947                          Label* if_bailout, GetOwnPropertyMode mode);
2948 
GetProperty(TNode<Context> context,SloppyTNode<Object> receiver,Handle<Name> name)2949   TNode<Object> GetProperty(TNode<Context> context,
2950                             SloppyTNode<Object> receiver, Handle<Name> name) {
2951     return GetProperty(context, receiver, HeapConstant(name));
2952   }
2953 
GetProperty(TNode<Context> context,SloppyTNode<Object> receiver,SloppyTNode<Object> name)2954   TNode<Object> GetProperty(TNode<Context> context,
2955                             SloppyTNode<Object> receiver,
2956                             SloppyTNode<Object> name) {
2957     return CallBuiltin(Builtins::kGetProperty, context, receiver, name);
2958   }
2959 
SetPropertyStrict(TNode<Context> context,TNode<Object> receiver,TNode<Object> key,TNode<Object> value)2960   TNode<Object> SetPropertyStrict(TNode<Context> context,
2961                                   TNode<Object> receiver, TNode<Object> key,
2962                                   TNode<Object> value) {
2963     return CallBuiltin(Builtins::kSetProperty, context, receiver, key, value);
2964   }
2965 
SetPropertyInLiteral(TNode<Context> context,TNode<JSObject> receiver,TNode<Object> key,TNode<Object> value)2966   TNode<Object> SetPropertyInLiteral(TNode<Context> context,
2967                                      TNode<JSObject> receiver,
2968                                      TNode<Object> key, TNode<Object> value) {
2969     return CallBuiltin(Builtins::kSetPropertyInLiteral, context, receiver, key,
2970                        value);
2971   }
2972 
2973   TNode<Object> GetMethod(TNode<Context> context, TNode<Object> object,
2974                           Handle<Name> name, Label* if_null_or_undefined);
2975 
2976   TNode<Object> GetIteratorMethod(TNode<Context> context,
2977                                   TNode<HeapObject> heap_obj,
2978                                   Label* if_iteratorundefined);
2979 
2980   template <class... TArgs>
CallBuiltin(Builtins::Name id,SloppyTNode<Object> context,TArgs...args)2981   TNode<Object> CallBuiltin(Builtins::Name id, SloppyTNode<Object> context,
2982                             TArgs... args) {
2983     return CallStub<Object>(Builtins::CallableFor(isolate(), id), context,
2984                             args...);
2985   }
2986 
2987   template <class... TArgs>
TailCallBuiltin(Builtins::Name id,SloppyTNode<Object> context,TArgs...args)2988   void TailCallBuiltin(Builtins::Name id, SloppyTNode<Object> context,
2989                        TArgs... args) {
2990     return TailCallStub(Builtins::CallableFor(isolate(), id), context, args...);
2991   }
2992 
2993   void LoadPropertyFromFastObject(TNode<HeapObject> object, TNode<Map> map,
2994                                   TNode<DescriptorArray> descriptors,
2995                                   TNode<IntPtrT> name_index,
2996                                   TVariable<Uint32T>* var_details,
2997                                   TVariable<Object>* var_value);
2998 
2999   void LoadPropertyFromFastObject(TNode<HeapObject> object, TNode<Map> map,
3000                                   TNode<DescriptorArray> descriptors,
3001                                   TNode<IntPtrT> name_index, TNode<Uint32T>,
3002                                   TVariable<Object>* var_value);
3003 
3004   void LoadPropertyFromNameDictionary(TNode<NameDictionary> dictionary,
3005                                       TNode<IntPtrT> name_index,
3006                                       TVariable<Uint32T>* var_details,
3007                                       TVariable<Object>* var_value);
3008   void LoadPropertyFromGlobalDictionary(TNode<GlobalDictionary> dictionary,
3009                                         TNode<IntPtrT> name_index,
3010                                         TVariable<Uint32T>* var_details,
3011                                         TVariable<Object>* var_value,
3012                                         Label* if_deleted);
3013 
3014   // Generic property lookup generator. If the {object} is fast and
3015   // {unique_name} property is found then the control goes to {if_found_fast}
3016   // label and {var_meta_storage} and {var_name_index} will contain
3017   // DescriptorArray and an index of the descriptor's name respectively.
3018   // If the {object} is slow or global then the control goes to {if_found_dict}
3019   // or {if_found_global} and the {var_meta_storage} and {var_name_index} will
3020   // contain a dictionary and an index of the key field of the found entry.
3021   // If property is not found or given lookup is not supported then
3022   // the control goes to {if_not_found} or {if_bailout} respectively.
3023   //
3024   // Note: this code does not check if the global dictionary points to deleted
3025   // entry! This has to be done by the caller.
3026   void TryLookupProperty(TNode<HeapObject> object, TNode<Map> map,
3027                          SloppyTNode<Int32T> instance_type,
3028                          TNode<Name> unique_name, Label* if_found_fast,
3029                          Label* if_found_dict, Label* if_found_global,
3030                          TVariable<HeapObject>* var_meta_storage,
3031                          TVariable<IntPtrT>* var_name_index,
3032                          Label* if_not_found, Label* if_bailout);
3033 
3034   // This is a building block for TryLookupProperty() above. Supports only
3035   // non-special fast and dictionary objects.
3036   void TryLookupPropertyInSimpleObject(TNode<JSObject> object, TNode<Map> map,
3037                                        TNode<Name> unique_name,
3038                                        Label* if_found_fast,
3039                                        Label* if_found_dict,
3040                                        TVariable<HeapObject>* var_meta_storage,
3041                                        TVariable<IntPtrT>* var_name_index,
3042                                        Label* if_not_found);
3043 
3044   // This method jumps to if_found if the element is known to exist. To
3045   // if_absent if it's known to not exist. To if_not_found if the prototype
3046   // chain needs to be checked. And if_bailout if the lookup is unsupported.
3047   void TryLookupElement(TNode<HeapObject> object, TNode<Map> map,
3048                         SloppyTNode<Int32T> instance_type,
3049                         SloppyTNode<IntPtrT> intptr_index, Label* if_found,
3050                         Label* if_absent, Label* if_not_found,
3051                         Label* if_bailout);
3052 
3053   // For integer indexed exotic cases, check if the given string cannot be a
3054   // special index. If we are not sure that the given string is not a special
3055   // index with a simple check, return False. Note that "False" return value
3056   // does not mean that the name_string is a special index in the current
3057   // implementation.
3058   void BranchIfMaybeSpecialIndex(TNode<String> name_string,
3059                                  Label* if_maybe_special_index,
3060                                  Label* if_not_special_index);
3061 
3062   // This is a type of a lookup property in holder generator function. The {key}
3063   // is guaranteed to be an unique name.
3064   using LookupPropertyInHolder = std::function<void(
3065       TNode<HeapObject> receiver, TNode<HeapObject> holder, TNode<Map> map,
3066       TNode<Int32T> instance_type, TNode<Name> key, Label* next_holder,
3067       Label* if_bailout)>;
3068 
3069   // This is a type of a lookup element in holder generator function. The {key}
3070   // is an Int32 index.
3071   using LookupElementInHolder = std::function<void(
3072       TNode<HeapObject> receiver, TNode<HeapObject> holder, TNode<Map> map,
3073       TNode<Int32T> instance_type, TNode<IntPtrT> key, Label* next_holder,
3074       Label* if_bailout)>;
3075 
3076   // Generic property prototype chain lookup generator.
3077   // For properties it generates lookup using given {lookup_property_in_holder}
3078   // and for elements it uses {lookup_element_in_holder}.
3079   // Upon reaching the end of prototype chain the control goes to {if_end}.
3080   // If it can't handle the case {receiver}/{key} case then the control goes
3081   // to {if_bailout}.
3082   // If {if_proxy} is nullptr, proxies go to if_bailout.
3083   void TryPrototypeChainLookup(
3084       TNode<Object> receiver, TNode<Object> object, TNode<Object> key,
3085       const LookupPropertyInHolder& lookup_property_in_holder,
3086       const LookupElementInHolder& lookup_element_in_holder, Label* if_end,
3087       Label* if_bailout, Label* if_proxy);
3088 
3089   // Instanceof helpers.
3090   // Returns true if {object} has {prototype} somewhere in it's prototype
3091   // chain, otherwise false is returned. Might cause arbitrary side effects
3092   // due to [[GetPrototypeOf]] invocations.
3093   TNode<Oddball> HasInPrototypeChain(TNode<Context> context,
3094                                      TNode<HeapObject> object,
3095                                      TNode<Object> prototype);
3096   // ES6 section 7.3.19 OrdinaryHasInstance (C, O)
3097   TNode<Oddball> OrdinaryHasInstance(TNode<Context> context,
3098                                      TNode<Object> callable,
3099                                      TNode<Object> object);
3100 
3101   // Load type feedback vector from the stub caller's frame.
3102   TNode<FeedbackVector> LoadFeedbackVectorForStub();
3103 
3104   // Load the value from closure's feedback cell.
3105   TNode<HeapObject> LoadFeedbackCellValue(TNode<JSFunction> closure);
3106 
3107   // Load the object from feedback vector cell for the given closure.
3108   // The returned object could be undefined if the closure does not have
3109   // a feedback vector associated with it.
3110   TNode<HeapObject> LoadFeedbackVector(TNode<JSFunction> closure);
3111 
3112   // Load the ClosureFeedbackCellArray that contains the feedback cells
3113   // used when creating closures from this function. This array could be
3114   // directly hanging off the FeedbackCell when there is no feedback vector
3115   // or available from the feedback vector's header.
3116   TNode<ClosureFeedbackCellArray> LoadClosureFeedbackArray(
3117       TNode<JSFunction> closure);
3118 
3119   // Update the type feedback vector.
3120   void UpdateFeedback(TNode<Smi> feedback,
3121                       TNode<HeapObject> maybe_feedback_vector,
3122                       TNode<UintPtrT> slot_id);
3123 
3124   // Report that there was a feedback update, performing any tasks that should
3125   // be done after a feedback update.
3126   void ReportFeedbackUpdate(TNode<FeedbackVector> feedback_vector,
3127                             SloppyTNode<UintPtrT> slot_id, const char* reason);
3128 
3129   // Combine the new feedback with the existing_feedback. Do nothing if
3130   // existing_feedback is nullptr.
3131   void CombineFeedback(TVariable<Smi>* existing_feedback, int feedback);
3132   void CombineFeedback(TVariable<Smi>* existing_feedback, TNode<Smi> feedback);
3133 
3134   // Overwrite the existing feedback with new_feedback. Do nothing if
3135   // existing_feedback is nullptr.
3136   void OverwriteFeedback(TVariable<Smi>* existing_feedback, int new_feedback);
3137 
3138   // Check if a property name might require protector invalidation when it is
3139   // used for a property store or deletion.
3140   void CheckForAssociatedProtector(TNode<Name> name, Label* if_protector);
3141 
3142   TNode<Map> LoadReceiverMap(SloppyTNode<Object> receiver);
3143 
3144   // Loads script context from the script context table.
3145   TNode<Context> LoadScriptContext(TNode<Context> context,
3146                                    TNode<IntPtrT> context_index);
3147 
3148   TNode<Uint8T> Int32ToUint8Clamped(TNode<Int32T> int32_value);
3149   TNode<Uint8T> Float64ToUint8Clamped(TNode<Float64T> float64_value);
3150 
3151   Node* PrepareValueForWriteToTypedArray(TNode<Object> input,
3152                                          ElementsKind elements_kind,
3153                                          TNode<Context> context);
3154 
3155   template <typename T>
3156   TNode<T> PrepareValueForWriteToTypedArray(TNode<Object> input,
3157                                             ElementsKind elements_kind,
3158                                             TNode<Context> context);
3159 
3160   // Store value to an elements array with given elements kind.
3161   // TODO(turbofan): For BIGINT64_ELEMENTS and BIGUINT64_ELEMENTS
3162   // we pass {value} as BigInt object instead of int64_t. We should
3163   // teach TurboFan to handle int64_t on 32-bit platforms eventually.
3164   template <typename TIndex>
3165   void StoreElement(TNode<RawPtrT> elements, ElementsKind kind,
3166                     TNode<TIndex> index, Node* value);
3167 
3168   // Implements the BigInt part of
3169   // https://tc39.github.io/proposal-bigint/#sec-numbertorawbytes,
3170   // including truncation to 64 bits (i.e. modulo 2^64).
3171   // {var_high} is only used on 32-bit platforms.
3172   void BigIntToRawBytes(TNode<BigInt> bigint, TVariable<UintPtrT>* var_low,
3173                         TVariable<UintPtrT>* var_high);
3174 
3175   void EmitElementStore(TNode<JSObject> object, TNode<Object> key,
3176                         TNode<Object> value, ElementsKind elements_kind,
3177                         KeyedAccessStoreMode store_mode, Label* bailout,
3178                         TNode<Context> context,
3179                         TVariable<Object>* maybe_converted_value = nullptr);
3180 
3181   TNode<FixedArrayBase> CheckForCapacityGrow(
3182       TNode<JSObject> object, TNode<FixedArrayBase> elements, ElementsKind kind,
3183       TNode<UintPtrT> length, TNode<IntPtrT> key, Label* bailout);
3184 
3185   TNode<FixedArrayBase> CopyElementsOnWrite(TNode<HeapObject> object,
3186                                             TNode<FixedArrayBase> elements,
3187                                             ElementsKind kind,
3188                                             TNode<IntPtrT> length,
3189                                             Label* bailout);
3190 
3191   void TransitionElementsKind(TNode<JSObject> object, TNode<Map> map,
3192                               ElementsKind from_kind, ElementsKind to_kind,
3193                               Label* bailout);
3194 
3195   void TrapAllocationMemento(TNode<JSObject> object, Label* memento_found);
3196 
3197   TNode<IntPtrT> PageFromAddress(TNode<IntPtrT> address);
3198 
3199   // Store a weak in-place reference into the FeedbackVector.
3200   TNode<MaybeObject> StoreWeakReferenceInFeedbackVector(
3201       TNode<FeedbackVector> feedback_vector, TNode<UintPtrT> slot,
3202       TNode<HeapObject> value, int additional_offset = 0);
3203 
3204   // Create a new AllocationSite and install it into a feedback vector.
3205   TNode<AllocationSite> CreateAllocationSiteInFeedbackVector(
3206       TNode<FeedbackVector> feedback_vector, TNode<UintPtrT> slot);
3207 
3208   TNode<BoolT> HasBoilerplate(TNode<Object> maybe_literal_site);
3209   TNode<Smi> LoadTransitionInfo(TNode<AllocationSite> allocation_site);
3210   TNode<JSObject> LoadBoilerplate(TNode<AllocationSite> allocation_site);
3211   TNode<Int32T> LoadElementsKind(TNode<AllocationSite> allocation_site);
3212 
3213   enum class IndexAdvanceMode { kPre, kPost };
3214 
3215   template <typename TIndex>
3216   using FastLoopBody = std::function<void(TNode<TIndex> index)>;
3217 
3218   template <typename TIndex>
3219   TNode<TIndex> BuildFastLoop(
3220       const VariableList& var_list, TNode<TIndex> start_index,
3221       TNode<TIndex> end_index, const FastLoopBody<TIndex>& body, int increment,
3222       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre);
3223 
3224   template <typename TIndex>
3225   TNode<TIndex> BuildFastLoop(
3226       TNode<TIndex> start_index, TNode<TIndex> end_index,
3227       const FastLoopBody<TIndex>& body, int increment,
3228       IndexAdvanceMode advance_mode = IndexAdvanceMode::kPre) {
3229     return BuildFastLoop(VariableList(0, zone()), start_index, end_index, body,
3230                          increment, advance_mode);
3231   }
3232 
3233   enum class ForEachDirection { kForward, kReverse };
3234 
3235   using FastArrayForEachBody =
3236       std::function<void(TNode<HeapObject> array, TNode<IntPtrT> offset)>;
3237 
3238   template <typename TIndex>
3239   void BuildFastArrayForEach(
3240       TNode<UnionT<UnionT<FixedArray, PropertyArray>, HeapObject>> array,
3241       ElementsKind kind, TNode<TIndex> first_element_inclusive,
3242       TNode<TIndex> last_element_exclusive, const FastArrayForEachBody& body,
3243       ForEachDirection direction = ForEachDirection::kReverse);
3244 
3245   template <typename TIndex>
GetArrayAllocationSize(TNode<TIndex> element_count,ElementsKind kind,int header_size)3246   TNode<IntPtrT> GetArrayAllocationSize(TNode<TIndex> element_count,
3247                                         ElementsKind kind, int header_size) {
3248     return ElementOffsetFromIndex(element_count, kind, header_size);
3249   }
3250 
3251   template <typename TIndex>
GetFixedArrayAllocationSize(TNode<TIndex> element_count,ElementsKind kind)3252   TNode<IntPtrT> GetFixedArrayAllocationSize(TNode<TIndex> element_count,
3253                                              ElementsKind kind) {
3254     return GetArrayAllocationSize(element_count, kind, FixedArray::kHeaderSize);
3255   }
3256 
GetPropertyArrayAllocationSize(TNode<IntPtrT> element_count)3257   TNode<IntPtrT> GetPropertyArrayAllocationSize(TNode<IntPtrT> element_count) {
3258     return GetArrayAllocationSize(element_count, PACKED_ELEMENTS,
3259                                   PropertyArray::kHeaderSize);
3260   }
3261 
3262   template <typename TIndex>
3263   void GotoIfFixedArraySizeDoesntFitInNewSpace(TNode<TIndex> element_count,
3264                                                Label* doesnt_fit,
3265                                                int base_size);
3266 
3267   void InitializeFieldsWithRoot(TNode<HeapObject> object,
3268                                 TNode<IntPtrT> start_offset,
3269                                 TNode<IntPtrT> end_offset, RootIndex root);
3270 
3271   TNode<Oddball> RelationalComparison(
3272       Operation op, TNode<Object> left, TNode<Object> right,
3273       TNode<Context> context, TVariable<Smi>* var_type_feedback = nullptr);
3274 
3275   void BranchIfNumberRelationalComparison(Operation op, TNode<Number> left,
3276                                           TNode<Number> right, Label* if_true,
3277                                           Label* if_false);
3278 
BranchIfNumberEqual(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3279   void BranchIfNumberEqual(TNode<Number> left, TNode<Number> right,
3280                            Label* if_true, Label* if_false) {
3281     BranchIfNumberRelationalComparison(Operation::kEqual, left, right, if_true,
3282                                        if_false);
3283   }
3284 
BranchIfNumberNotEqual(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3285   void BranchIfNumberNotEqual(TNode<Number> left, TNode<Number> right,
3286                               Label* if_true, Label* if_false) {
3287     BranchIfNumberEqual(left, right, if_false, if_true);
3288   }
3289 
BranchIfNumberLessThan(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3290   void BranchIfNumberLessThan(TNode<Number> left, TNode<Number> right,
3291                               Label* if_true, Label* if_false) {
3292     BranchIfNumberRelationalComparison(Operation::kLessThan, left, right,
3293                                        if_true, if_false);
3294   }
3295 
BranchIfNumberLessThanOrEqual(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3296   void BranchIfNumberLessThanOrEqual(TNode<Number> left, TNode<Number> right,
3297                                      Label* if_true, Label* if_false) {
3298     BranchIfNumberRelationalComparison(Operation::kLessThanOrEqual, left, right,
3299                                        if_true, if_false);
3300   }
3301 
BranchIfNumberGreaterThan(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3302   void BranchIfNumberGreaterThan(TNode<Number> left, TNode<Number> right,
3303                                  Label* if_true, Label* if_false) {
3304     BranchIfNumberRelationalComparison(Operation::kGreaterThan, left, right,
3305                                        if_true, if_false);
3306   }
3307 
BranchIfNumberGreaterThanOrEqual(TNode<Number> left,TNode<Number> right,Label * if_true,Label * if_false)3308   void BranchIfNumberGreaterThanOrEqual(TNode<Number> left, TNode<Number> right,
3309                                         Label* if_true, Label* if_false) {
3310     BranchIfNumberRelationalComparison(Operation::kGreaterThanOrEqual, left,
3311                                        right, if_true, if_false);
3312   }
3313 
BranchIfAccessorPair(TNode<Object> value,Label * if_accessor_pair,Label * if_not_accessor_pair)3314   void BranchIfAccessorPair(TNode<Object> value, Label* if_accessor_pair,
3315                             Label* if_not_accessor_pair) {
3316     GotoIf(TaggedIsSmi(value), if_not_accessor_pair);
3317     Branch(IsAccessorPair(CAST(value)), if_accessor_pair, if_not_accessor_pair);
3318   }
3319 
3320   void GotoIfNumberGreaterThanOrEqual(TNode<Number> left, TNode<Number> right,
3321                                       Label* if_false);
3322 
3323   TNode<Oddball> Equal(SloppyTNode<Object> lhs, SloppyTNode<Object> rhs,
3324                        TNode<Context> context,
3325                        TVariable<Smi>* var_type_feedback = nullptr);
3326 
3327   TNode<Oddball> StrictEqual(SloppyTNode<Object> lhs, SloppyTNode<Object> rhs,
3328                              TVariable<Smi>* var_type_feedback = nullptr);
3329 
3330   // ECMA#sec-samevalue
3331   // Similar to StrictEqual except that NaNs are treated as equal and minus zero
3332   // differs from positive zero.
3333   enum class SameValueMode { kNumbersOnly, kFull };
3334   void BranchIfSameValue(SloppyTNode<Object> lhs, SloppyTNode<Object> rhs,
3335                          Label* if_true, Label* if_false,
3336                          SameValueMode mode = SameValueMode::kFull);
3337   // A part of BranchIfSameValue() that handles two double values.
3338   // Treats NaN == NaN and +0 != -0.
3339   void BranchIfSameNumberValue(TNode<Float64T> lhs_value,
3340                                TNode<Float64T> rhs_value, Label* if_true,
3341                                Label* if_false);
3342 
3343   enum HasPropertyLookupMode { kHasProperty, kForInHasProperty };
3344 
3345   TNode<Oddball> HasProperty(TNode<Context> context, SloppyTNode<Object> object,
3346                              SloppyTNode<Object> key,
3347                              HasPropertyLookupMode mode);
3348 
3349   // Due to naming conflict with the builtin function namespace.
HasProperty_Inline(TNode<Context> context,TNode<JSReceiver> object,TNode<Object> key)3350   TNode<Oddball> HasProperty_Inline(TNode<Context> context,
3351                                     TNode<JSReceiver> object,
3352                                     TNode<Object> key) {
3353     return HasProperty(context, object, key,
3354                        HasPropertyLookupMode::kHasProperty);
3355   }
3356 
3357   void ForInPrepare(TNode<HeapObject> enumerator, TNode<UintPtrT> slot,
3358                     TNode<HeapObject> maybe_feedback_vector,
3359                     TNode<FixedArray>* cache_array_out,
3360                     TNode<Smi>* cache_length_out);
3361   // Returns {cache_array} and {cache_length} in a fixed array of length 2.
3362   // TODO(jgruber): Tuple2 would be a slightly better fit as the return type,
3363   // but FixedArray has better support and there are no effective drawbacks to
3364   // using it instead of Tuple2 in practice.
3365   TNode<FixedArray> ForInPrepareForTorque(
3366       TNode<HeapObject> enumerator, TNode<UintPtrT> slot,
3367       TNode<HeapObject> maybe_feedback_vector);
3368 
3369   TNode<String> Typeof(SloppyTNode<Object> value);
3370 
3371   TNode<HeapObject> GetSuperConstructor(TNode<JSFunction> active_function);
3372 
3373   TNode<JSReceiver> SpeciesConstructor(TNode<Context> context,
3374                                        SloppyTNode<Object> object,
3375                                        TNode<JSReceiver> default_constructor);
3376 
3377   TNode<Oddball> InstanceOf(TNode<Object> object, TNode<Object> callable,
3378                             TNode<Context> context);
3379 
3380   // Debug helpers
3381   TNode<BoolT> IsDebugActive();
3382 
3383   // JSArrayBuffer helpers
3384   TNode<RawPtrT> LoadJSArrayBufferBackingStorePtr(
3385       TNode<JSArrayBuffer> array_buffer);
3386   void ThrowIfArrayBufferIsDetached(TNode<Context> context,
3387                                     TNode<JSArrayBuffer> array_buffer,
3388                                     const char* method_name);
3389 
3390   // JSArrayBufferView helpers
3391   TNode<JSArrayBuffer> LoadJSArrayBufferViewBuffer(
3392       TNode<JSArrayBufferView> array_buffer_view);
3393   TNode<UintPtrT> LoadJSArrayBufferViewByteLength(
3394       TNode<JSArrayBufferView> array_buffer_view);
3395   TNode<UintPtrT> LoadJSArrayBufferViewByteOffset(
3396       TNode<JSArrayBufferView> array_buffer_view);
3397   void ThrowIfArrayBufferViewBufferIsDetached(
3398       TNode<Context> context, TNode<JSArrayBufferView> array_buffer_view,
3399       const char* method_name);
3400 
3401   // JSTypedArray helpers
3402   TNode<UintPtrT> LoadJSTypedArrayLength(TNode<JSTypedArray> typed_array);
3403   TNode<RawPtrT> LoadJSTypedArrayDataPtr(TNode<JSTypedArray> typed_array);
3404   TNode<JSArrayBuffer> GetTypedArrayBuffer(TNode<Context> context,
3405                                            TNode<JSTypedArray> array);
3406 
3407   template <typename TIndex>
3408   TNode<IntPtrT> ElementOffsetFromIndex(TNode<TIndex> index, ElementsKind kind,
3409                                         int base_size = 0);
3410 
3411   // Check that a field offset is within the bounds of the an object.
3412   TNode<BoolT> IsOffsetInBounds(SloppyTNode<IntPtrT> offset,
3413                                 SloppyTNode<IntPtrT> length, int header_size,
3414                                 ElementsKind kind = HOLEY_ELEMENTS);
3415 
3416   // Load a builtin's code from the builtin array in the isolate.
3417   TNode<Code> LoadBuiltin(TNode<Smi> builtin_id);
3418 
3419   // Figure out the SFI's code object using its data field.
3420   // If |if_compile_lazy| is provided then the execution will go to the given
3421   // label in case of an CompileLazy code object.
3422   TNode<Code> GetSharedFunctionInfoCode(TNode<SharedFunctionInfo> shared_info,
3423                                         Label* if_compile_lazy = nullptr);
3424 
3425   TNode<JSFunction> AllocateFunctionWithMapAndContext(
3426       TNode<Map> map, TNode<SharedFunctionInfo> shared_info,
3427       TNode<Context> context);
3428 
3429   // Promise helpers
3430   TNode<BoolT> IsPromiseHookEnabled();
3431   TNode<BoolT> HasAsyncEventDelegate();
3432   TNode<BoolT> IsPromiseHookEnabledOrHasAsyncEventDelegate();
3433   TNode<BoolT> IsPromiseHookEnabledOrDebugIsActiveOrHasAsyncEventDelegate();
3434 
3435   // for..in helpers
3436   void CheckPrototypeEnumCache(TNode<JSReceiver> receiver,
3437                                TNode<Map> receiver_map, Label* if_fast,
3438                                Label* if_slow);
3439   TNode<Map> CheckEnumCache(TNode<JSReceiver> receiver, Label* if_empty,
3440                             Label* if_runtime);
3441 
3442   TNode<Object> GetArgumentValue(TorqueStructArguments args,
3443                                  TNode<IntPtrT> index);
3444 
3445   TorqueStructArguments GetFrameArguments(TNode<RawPtrT> frame,
3446                                           TNode<IntPtrT> argc);
3447 
3448   // Support for printf-style debugging
3449   void Print(const char* s);
3450   void Print(const char* prefix, TNode<MaybeObject> tagged_value);
Print(TNode<MaybeObject> tagged_value)3451   void Print(TNode<MaybeObject> tagged_value) {
3452     return Print(nullptr, tagged_value);
3453   }
3454 
3455   template <class... TArgs>
MakeTypeError(MessageTemplate message,TNode<Context> context,TArgs...args)3456   TNode<HeapObject> MakeTypeError(MessageTemplate message,
3457                                   TNode<Context> context, TArgs... args) {
3458     STATIC_ASSERT(sizeof...(TArgs) <= 3);
3459     return CAST(CallRuntime(Runtime::kNewTypeError, context,
3460                             SmiConstant(message), args...));
3461   }
3462 
Abort(AbortReason reason)3463   void Abort(AbortReason reason) {
3464     CallRuntime(Runtime::kAbort, NoContextConstant(), SmiConstant(reason));
3465     Unreachable();
3466   }
3467 
ConstexprBoolNot(bool value)3468   bool ConstexprBoolNot(bool value) { return !value; }
3469 
ConstexprInt31Equal(int31_t a,int31_t b)3470   bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; }
ConstexprInt31NotEqual(int31_t a,int31_t b)3471   bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; }
ConstexprInt31GreaterThanEqual(int31_t a,int31_t b)3472   bool ConstexprInt31GreaterThanEqual(int31_t a, int31_t b) { return a >= b; }
ConstexprUint32Equal(uint32_t a,uint32_t b)3473   bool ConstexprUint32Equal(uint32_t a, uint32_t b) { return a == b; }
ConstexprUint32NotEqual(uint32_t a,uint32_t b)3474   bool ConstexprUint32NotEqual(uint32_t a, uint32_t b) { return a != b; }
ConstexprInt32Equal(int32_t a,int32_t b)3475   bool ConstexprInt32Equal(int32_t a, int32_t b) { return a == b; }
ConstexprInt32NotEqual(int32_t a,int32_t b)3476   bool ConstexprInt32NotEqual(int32_t a, int32_t b) { return a != b; }
ConstexprInt32GreaterThanEqual(int32_t a,int32_t b)3477   bool ConstexprInt32GreaterThanEqual(int32_t a, int32_t b) { return a >= b; }
ConstexprUint32Add(uint32_t a,uint32_t b)3478   uint32_t ConstexprUint32Add(uint32_t a, uint32_t b) { return a + b; }
ConstexprUint32Sub(uint32_t a,uint32_t b)3479   int32_t ConstexprUint32Sub(uint32_t a, uint32_t b) { return a - b; }
ConstexprInt31Add(int31_t a,int31_t b)3480   int31_t ConstexprInt31Add(int31_t a, int31_t b) {
3481     int32_t val;
3482     CHECK(!base::bits::SignedAddOverflow32(a, b, &val));
3483     return val;
3484   }
ConstexprInt31Mul(int31_t a,int31_t b)3485   int31_t ConstexprInt31Mul(int31_t a, int31_t b) {
3486     int32_t val;
3487     CHECK(!base::bits::SignedMulOverflow32(a, b, &val));
3488     return val;
3489   }
3490 
ConstexprWord32Or(int32_t a,int32_t b)3491   int32_t ConstexprWord32Or(int32_t a, int32_t b) { return a | b; }
3492 
ConstexprUintPtrLessThan(uintptr_t a,uintptr_t b)3493   bool ConstexprUintPtrLessThan(uintptr_t a, uintptr_t b) { return a < b; }
3494 
3495   // CSA does not support 64-bit types on 32-bit platforms so as a workaround
3496   // the kMaxSafeIntegerUint64 is defined as uintptr and allowed to be used only
3497   // inside if constexpr (Is64()) i.e. on 64-bit architectures.
MaxSafeIntegerUintPtr()3498   static uintptr_t MaxSafeIntegerUintPtr() {
3499 #if defined(V8_HOST_ARCH_64_BIT)
3500     // This ifdef is required to avoid build issues on 32-bit MSVC which
3501     // complains about static_cast<uintptr_t>(kMaxSafeIntegerUint64).
3502     return kMaxSafeIntegerUint64;
3503 #else
3504     UNREACHABLE();
3505 #endif
3506   }
3507 
3508   void PerformStackCheck(TNode<Context> context);
3509 
3510   void SetPropertyLength(TNode<Context> context, TNode<Object> array,
3511                          TNode<Number> length);
3512 
3513   // Implements DescriptorArray::Search().
3514   void DescriptorLookup(TNode<Name> unique_name,
3515                         TNode<DescriptorArray> descriptors,
3516                         TNode<Uint32T> bitfield3, Label* if_found,
3517                         TVariable<IntPtrT>* var_name_index,
3518                         Label* if_not_found);
3519 
3520   // Implements TransitionArray::SearchName() - searches for first transition
3521   // entry with given name (note that there could be multiple entries with
3522   // the same name).
3523   void TransitionLookup(TNode<Name> unique_name,
3524                         TNode<TransitionArray> transitions, Label* if_found,
3525                         TVariable<IntPtrT>* var_name_index,
3526                         Label* if_not_found);
3527 
3528   // Implements generic search procedure like i::Search<Array>().
3529   template <typename Array>
3530   void Lookup(TNode<Name> unique_name, TNode<Array> array,
3531               TNode<Uint32T> number_of_valid_entries, Label* if_found,
3532               TVariable<IntPtrT>* var_name_index, Label* if_not_found);
3533 
3534   // Implements generic linear search procedure like i::LinearSearch<Array>().
3535   template <typename Array>
3536   void LookupLinear(TNode<Name> unique_name, TNode<Array> array,
3537                     TNode<Uint32T> number_of_valid_entries, Label* if_found,
3538                     TVariable<IntPtrT>* var_name_index, Label* if_not_found);
3539 
3540   // Implements generic binary search procedure like i::BinarySearch<Array>().
3541   template <typename Array>
3542   void LookupBinary(TNode<Name> unique_name, TNode<Array> array,
3543                     TNode<Uint32T> number_of_valid_entries, Label* if_found,
3544                     TVariable<IntPtrT>* var_name_index, Label* if_not_found);
3545 
3546   // Converts [Descriptor/Transition]Array entry number to a fixed array index.
3547   template <typename Array>
3548   TNode<IntPtrT> EntryIndexToIndex(TNode<Uint32T> entry_index);
3549 
3550   // Implements [Descriptor/Transition]Array::ToKeyIndex.
3551   template <typename Array>
3552   TNode<IntPtrT> ToKeyIndex(TNode<Uint32T> entry_index);
3553 
3554   // Implements [Descriptor/Transition]Array::GetKey.
3555   template <typename Array>
3556   TNode<Name> GetKey(TNode<Array> array, TNode<Uint32T> entry_index);
3557 
3558   // Implements DescriptorArray::GetDetails.
3559   TNode<Uint32T> DescriptorArrayGetDetails(TNode<DescriptorArray> descriptors,
3560                                            TNode<Uint32T> descriptor_number);
3561 
3562   using ForEachDescriptorBodyFunction =
3563       std::function<void(TNode<IntPtrT> descriptor_key_index)>;
3564 
3565   // Descriptor array accessors based on key_index, which is equal to
3566   // DescriptorArray::ToKeyIndex(descriptor).
3567   TNode<Name> LoadKeyByKeyIndex(TNode<DescriptorArray> container,
3568                                 TNode<IntPtrT> key_index);
3569   TNode<Uint32T> LoadDetailsByKeyIndex(TNode<DescriptorArray> container,
3570                                        TNode<IntPtrT> key_index);
3571   TNode<Object> LoadValueByKeyIndex(TNode<DescriptorArray> container,
3572                                     TNode<IntPtrT> key_index);
3573   TNode<MaybeObject> LoadFieldTypeByKeyIndex(TNode<DescriptorArray> container,
3574                                              TNode<IntPtrT> key_index);
3575 
3576   TNode<IntPtrT> DescriptorEntryToIndex(TNode<IntPtrT> descriptor);
3577 
3578   // Descriptor array accessors based on descriptor.
3579   TNode<Name> LoadKeyByDescriptorEntry(TNode<DescriptorArray> descriptors,
3580                                        TNode<IntPtrT> descriptor);
3581   TNode<Name> LoadKeyByDescriptorEntry(TNode<DescriptorArray> descriptors,
3582                                        int descriptor);
3583   TNode<Uint32T> LoadDetailsByDescriptorEntry(
3584       TNode<DescriptorArray> descriptors, TNode<IntPtrT> descriptor);
3585   TNode<Uint32T> LoadDetailsByDescriptorEntry(
3586       TNode<DescriptorArray> descriptors, int descriptor);
3587   TNode<Object> LoadValueByDescriptorEntry(TNode<DescriptorArray> descriptors,
3588                                            int descriptor);
3589   TNode<MaybeObject> LoadFieldTypeByDescriptorEntry(
3590       TNode<DescriptorArray> descriptors, TNode<IntPtrT> descriptor);
3591 
3592   using ForEachKeyValueFunction =
3593       std::function<void(TNode<Name> key, TNode<Object> value)>;
3594 
3595   enum ForEachEnumerationMode {
3596     // String and then Symbol properties according to the spec
3597     // ES#sec-object.assign
3598     kEnumerationOrder,
3599     // Order of property addition
3600     kPropertyAdditionOrder,
3601   };
3602 
3603   // For each JSObject property (in DescriptorArray order), check if the key is
3604   // enumerable, and if so, load the value from the receiver and evaluate the
3605   // closure.
3606   void ForEachEnumerableOwnProperty(TNode<Context> context, TNode<Map> map,
3607                                     TNode<JSObject> object,
3608                                     ForEachEnumerationMode mode,
3609                                     const ForEachKeyValueFunction& body,
3610                                     Label* bailout);
3611 
3612   TNode<Object> CallGetterIfAccessor(TNode<Object> value,
3613                                      TNode<HeapObject> holder,
3614                                      TNode<Uint32T> details,
3615                                      TNode<Context> context,
3616                                      TNode<Object> receiver, Label* if_bailout,
3617                                      GetOwnPropertyMode mode = kCallJSGetter);
3618 
3619   TNode<IntPtrT> TryToIntptr(SloppyTNode<Object> key, Label* if_not_intptr,
3620                              TVariable<Int32T>* var_instance_type = nullptr);
3621 
3622   TNode<JSArray> ArrayCreate(TNode<Context> context, TNode<Number> length);
3623 
3624   // Allocate a clone of a mutable primitive, if {object} is a mutable
3625   // HeapNumber.
3626   TNode<Object> CloneIfMutablePrimitive(TNode<Object> object);
3627 
3628   TNode<Smi> RefillMathRandom(TNode<NativeContext> native_context);
3629 
3630   void RemoveFinalizationRegistryCellFromUnregisterTokenMap(
3631       TNode<JSFinalizationRegistry> finalization_registry,
3632       TNode<WeakCell> weak_cell);
3633 
FeedbackIteratorSizeFor(int number_of_entries)3634   TNode<IntPtrT> FeedbackIteratorSizeFor(int number_of_entries) {
3635     return IntPtrConstant(FeedbackIterator::SizeFor(number_of_entries));
3636   }
3637 
FeedbackIteratorMapIndexForEntry(int entry)3638   TNode<IntPtrT> FeedbackIteratorMapIndexForEntry(int entry) {
3639     return IntPtrConstant(FeedbackIterator::MapIndexForEntry(entry));
3640   }
3641 
FeedbackIteratorHandlerIndexForEntry(int entry)3642   TNode<IntPtrT> FeedbackIteratorHandlerIndexForEntry(int entry) {
3643     return IntPtrConstant(FeedbackIterator::HandlerIndexForEntry(entry));
3644   }
3645 
3646  private:
3647   friend class CodeStubArguments;
3648 
3649   void HandleBreakOnNode();
3650 
3651   TNode<HeapObject> AllocateRawDoubleAligned(TNode<IntPtrT> size_in_bytes,
3652                                              AllocationFlags flags,
3653                                              TNode<RawPtrT> top_address,
3654                                              TNode<RawPtrT> limit_address);
3655   TNode<HeapObject> AllocateRawUnaligned(TNode<IntPtrT> size_in_bytes,
3656                                          AllocationFlags flags,
3657                                          TNode<RawPtrT> top_address,
3658                                          TNode<RawPtrT> limit_address);
3659   TNode<HeapObject> AllocateRaw(TNode<IntPtrT> size_in_bytes,
3660                                 AllocationFlags flags,
3661                                 TNode<RawPtrT> top_address,
3662                                 TNode<RawPtrT> limit_address);
3663 
3664   // Allocate and return a JSArray of given total size in bytes with header
3665   // fields initialized.
3666   TNode<JSArray> AllocateUninitializedJSArray(
3667       TNode<Map> array_map, TNode<Smi> length,
3668       base::Optional<TNode<AllocationSite>> allocation_site,
3669       TNode<IntPtrT> size_in_bytes);
3670 
SmiShiftBitsConstant()3671   TNode<IntPtrT> SmiShiftBitsConstant() {
3672     return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
3673   }
SmiShiftBitsConstant32()3674   TNode<Int32T> SmiShiftBitsConstant32() {
3675     return Int32Constant(kSmiShiftSize + kSmiTagSize);
3676   }
3677 
3678   TNode<String> AllocateSlicedString(RootIndex map_root_index,
3679                                      TNode<Uint32T> length,
3680                                      TNode<String> parent, TNode<Smi> offset);
3681 
3682   // Implements [Descriptor/Transition]Array::number_of_entries.
3683   template <typename Array>
3684   TNode<Uint32T> NumberOfEntries(TNode<Array> array);
3685 
3686   // Implements [Descriptor/Transition]Array::GetSortedKeyIndex.
3687   template <typename Array>
3688   TNode<Uint32T> GetSortedKeyIndex(TNode<Array> descriptors,
3689                                    TNode<Uint32T> entry_index);
3690 
3691   TNode<Smi> CollectFeedbackForString(SloppyTNode<Int32T> instance_type);
3692   void GenerateEqual_Same(SloppyTNode<Object> value, Label* if_equal,
3693                           Label* if_notequal,
3694                           TVariable<Smi>* var_type_feedback = nullptr);
3695 
3696   static const int kElementLoopUnrollThreshold = 8;
3697 
3698   // {convert_bigint} is only meaningful when {mode} == kToNumber.
3699   TNode<Numeric> NonNumberToNumberOrNumeric(
3700       TNode<Context> context, TNode<HeapObject> input, Object::Conversion mode,
3701       BigIntHandling bigint_handling = BigIntHandling::kThrow);
3702 
3703   void TaggedToNumeric(TNode<Context> context, TNode<Object> value,
3704                        TVariable<Numeric>* var_numeric,
3705                        TVariable<Smi>* var_feedback);
3706 
3707   template <Object::Conversion conversion>
3708   void TaggedToWord32OrBigIntImpl(TNode<Context> context, TNode<Object> value,
3709                                   Label* if_number,
3710                                   TVariable<Word32T>* var_word32,
3711                                   Label* if_bigint = nullptr,
3712                                   TVariable<BigInt>* var_maybe_bigint = nullptr,
3713                                   TVariable<Smi>* var_feedback = nullptr);
3714 
3715   // Low-level accessors for Descriptor arrays.
3716   template <typename T>
3717   TNode<T> LoadDescriptorArrayElement(TNode<DescriptorArray> object,
3718                                       TNode<IntPtrT> index,
3719                                       int additional_offset);
3720 
3721   // Hide LoadRoot for subclasses of CodeStubAssembler. If you get an error
3722   // complaining about this method, don't make it public, add your root to
3723   // HEAP_(IM)MUTABLE_IMMOVABLE_OBJECT_LIST instead. If you *really* need
3724   // LoadRoot, use CodeAssembler::LoadRoot.
LoadRoot(RootIndex root_index)3725   TNode<Object> LoadRoot(RootIndex root_index) {
3726     return CodeAssembler::LoadRoot(root_index);
3727   }
3728 
3729   template <typename TIndex>
3730   void StoreFixedArrayOrPropertyArrayElement(
3731       TNode<UnionT<FixedArray, PropertyArray>> array, TNode<TIndex> index,
3732       TNode<Object> value, WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
3733       int additional_offset = 0);
3734 
3735   // Store value to an elements array with given elements kind.
3736   // TODO(turbofan): For BIGINT64_ELEMENTS and BIGUINT64_ELEMENTS
3737   // we pass {value} as BigInt object instead of int64_t. We should
3738   // teach TurboFan to handle int64_t on 32-bit platforms eventually.
3739   // TODO(solanes): This method can go away and simplify into only one version
3740   // of StoreElement once we have "if constexpr" available to use.
3741   template <typename TArray, typename TIndex>
3742   void StoreElementBigIntOrTypedArray(TNode<TArray> elements, ElementsKind kind,
3743                                       TNode<TIndex> index, Node* value);
3744 
3745   template <typename TIndex>
3746   void StoreElement(TNode<FixedArrayBase> elements, ElementsKind kind,
3747                     TNode<TIndex> index, Node* value);
3748 
3749   // Converts {input} to a number if {input} is a plain primitve (i.e. String or
3750   // Oddball) and stores the result in {var_result}. Otherwise, it bails out to
3751   // {if_bailout}.
3752   void TryPlainPrimitiveNonNumberToNumber(TNode<HeapObject> input,
3753                                           TVariable<Number>* var_result,
3754                                           Label* if_bailout);
3755 };
3756 
3757 class V8_EXPORT_PRIVATE CodeStubArguments {
3758  public:
3759   using Node = compiler::Node;
3760 
3761   // |argc| specifies the number of arguments passed to the builtin excluding
3762   // the receiver. The arguments include the receiver.
CodeStubArguments(CodeStubAssembler * assembler,TNode<IntPtrT> argc)3763   CodeStubArguments(CodeStubAssembler* assembler, TNode<IntPtrT> argc)
3764       : CodeStubArguments(assembler, argc, TNode<RawPtrT>()) {}
CodeStubArguments(CodeStubAssembler * assembler,TNode<Int32T> argc)3765   CodeStubArguments(CodeStubAssembler* assembler, TNode<Int32T> argc)
3766       : CodeStubArguments(assembler, assembler->ChangeInt32ToIntPtr(argc)) {}
3767   CodeStubArguments(CodeStubAssembler* assembler, TNode<IntPtrT> argc,
3768                     TNode<RawPtrT> fp);
3769 
3770   // Used by Torque to construct arguments based on a Torque-defined
3771   // struct of values.
CodeStubArguments(CodeStubAssembler * assembler,TorqueStructArguments torque_arguments)3772   CodeStubArguments(CodeStubAssembler* assembler,
3773                     TorqueStructArguments torque_arguments)
3774       : assembler_(assembler),
3775         argc_(torque_arguments.length),
3776         base_(torque_arguments.base),
3777         fp_(torque_arguments.frame) {}
3778 
3779   TNode<Object> GetReceiver() const;
3780   // Replaces receiver argument on the expression stack. Should be used only
3781   // for manipulating arguments in trampoline builtins before tail calling
3782   // further with passing all the JS arguments as is.
3783   void SetReceiver(TNode<Object> object) const;
3784 
3785   // Computes address of the index'th argument.
3786   TNode<RawPtrT> AtIndexPtr(TNode<IntPtrT> index) const;
3787 
3788   // |index| is zero-based and does not include the receiver
3789   TNode<Object> AtIndex(TNode<IntPtrT> index) const;
3790   TNode<Object> AtIndex(int index) const;
3791 
GetLength()3792   TNode<IntPtrT> GetLength() const { return argc_; }
3793 
GetTorqueArguments()3794   TorqueStructArguments GetTorqueArguments() const {
3795     return TorqueStructArguments{fp_, base_, argc_};
3796   }
3797 
3798   TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index,
3799                                          TNode<Object> default_value);
GetOptionalArgumentValue(TNode<IntPtrT> index)3800   TNode<Object> GetOptionalArgumentValue(TNode<IntPtrT> index) {
3801     return GetOptionalArgumentValue(index, assembler_->UndefinedConstant());
3802   }
GetOptionalArgumentValue(int index)3803   TNode<Object> GetOptionalArgumentValue(int index) {
3804     return GetOptionalArgumentValue(assembler_->IntPtrConstant(index));
3805   }
3806 
3807   // Iteration doesn't include the receiver. |first| and |last| are zero-based.
3808   using ForEachBodyFunction = std::function<void(TNode<Object> arg)>;
3809   void ForEach(const ForEachBodyFunction& body, TNode<IntPtrT> first = {},
3810                TNode<IntPtrT> last = {}) const {
3811     CodeStubAssembler::VariableList list(0, assembler_->zone());
3812     ForEach(list, body, first, last);
3813   }
3814   void ForEach(const CodeStubAssembler::VariableList& vars,
3815                const ForEachBodyFunction& body, TNode<IntPtrT> first = {},
3816                TNode<IntPtrT> last = {}) const;
3817 
3818   void PopAndReturn(TNode<Object> value);
3819 
3820  private:
3821   CodeStubAssembler* assembler_;
3822   TNode<IntPtrT> argc_;
3823   TNode<RawPtrT> base_;
3824   TNode<RawPtrT> fp_;
3825 };
3826 
3827 class ToDirectStringAssembler : public CodeStubAssembler {
3828  private:
3829   enum StringPointerKind { PTR_TO_DATA, PTR_TO_STRING };
3830 
3831  public:
3832   enum Flag {
3833     kDontUnpackSlicedStrings = 1 << 0,
3834   };
3835   using Flags = base::Flags<Flag>;
3836 
3837   ToDirectStringAssembler(compiler::CodeAssemblerState* state,
3838                           TNode<String> string, Flags flags = Flags());
3839 
3840   // Converts flat cons, thin, and sliced strings and returns the direct
3841   // string. The result can be either a sequential or external string.
3842   // Jumps to if_bailout if the string if the string is indirect and cannot
3843   // be unpacked.
3844   TNode<String> TryToDirect(Label* if_bailout);
3845 
3846   // Returns a pointer to the beginning of the string data.
3847   // Jumps to if_bailout if the external string cannot be unpacked.
PointerToData(Label * if_bailout)3848   TNode<RawPtrT> PointerToData(Label* if_bailout) {
3849     return TryToSequential(PTR_TO_DATA, if_bailout);
3850   }
3851 
3852   // Returns a pointer that, offset-wise, looks like a String.
3853   // Jumps to if_bailout if the external string cannot be unpacked.
PointerToString(Label * if_bailout)3854   TNode<RawPtrT> PointerToString(Label* if_bailout) {
3855     return TryToSequential(PTR_TO_STRING, if_bailout);
3856   }
3857 
string()3858   TNode<String> string() { return var_string_.value(); }
instance_type()3859   TNode<Int32T> instance_type() { return var_instance_type_.value(); }
offset()3860   TNode<IntPtrT> offset() { return var_offset_.value(); }
is_external()3861   TNode<Word32T> is_external() { return var_is_external_.value(); }
3862 
3863  private:
3864   TNode<RawPtrT> TryToSequential(StringPointerKind ptr_kind, Label* if_bailout);
3865 
3866   TVariable<String> var_string_;
3867   TVariable<Int32T> var_instance_type_;
3868   // TODO(v8:9880): Use UintPtrT here.
3869   TVariable<IntPtrT> var_offset_;
3870   TVariable<Word32T> var_is_external_;
3871 
3872   const Flags flags_;
3873 };
3874 
3875 // Performs checks on a given prototype (e.g. map identity, property
3876 // verification), intended for use in fast path checks.
3877 class PrototypeCheckAssembler : public CodeStubAssembler {
3878  public:
3879   enum Flag {
3880     kCheckPrototypePropertyConstness = 1 << 0,
3881     kCheckPrototypePropertyIdentity = 1 << 1,
3882     kCheckFull =
3883         kCheckPrototypePropertyConstness | kCheckPrototypePropertyIdentity,
3884   };
3885   using Flags = base::Flags<Flag>;
3886 
3887   // A tuple describing a relevant property. It contains the descriptor index of
3888   // the property (within the descriptor array), the property's expected name
3889   // (stored as a root), and the property's expected value (stored on the native
3890   // context).
3891   struct DescriptorIndexNameValue {
3892     int descriptor_index;
3893     RootIndex name_root_index;
3894     int expected_value_context_index;
3895   };
3896 
3897   PrototypeCheckAssembler(compiler::CodeAssemblerState* state, Flags flags,
3898                           TNode<NativeContext> native_context,
3899                           TNode<Map> initial_prototype_map,
3900                           Vector<DescriptorIndexNameValue> properties);
3901 
3902   void CheckAndBranch(TNode<HeapObject> prototype, Label* if_unmodified,
3903                       Label* if_modified);
3904 
3905  private:
3906   const Flags flags_;
3907   const TNode<NativeContext> native_context_;
3908   const TNode<Map> initial_prototype_map_;
3909   const Vector<DescriptorIndexNameValue> properties_;
3910 };
3911 
3912 DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags)
3913 
3914 #define CLASS_MAP_CONSTANT_ADAPTER(V, rootIndexName, rootAccessorName,     \
3915                                    class_name)                             \
3916   template <>                                                              \
3917   inline bool CodeStubAssembler::ClassHasMapConstant<class_name>() {       \
3918     return true;                                                           \
3919   }                                                                        \
3920   template <>                                                              \
3921   inline TNode<Map> CodeStubAssembler::GetClassMapConstant<class_name>() { \
3922     return class_name##MapConstant();                                      \
3923   }
3924 
3925 UNIQUE_INSTANCE_TYPE_MAP_LIST_GENERATOR(CLASS_MAP_CONSTANT_ADAPTER, _)
3926 
3927 }  // namespace internal
3928 }  // namespace v8
3929 #endif  // V8_CODEGEN_CODE_STUB_ASSEMBLER_H_
3930