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