v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-iterator-gen.cc
Go to the documentation of this file.
1// Copyright 2017 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
6
7#include <optional>
8
17
18namespace v8 {
19namespace internal {
20
22
23using IteratorRecord = TorqueStructIteratorRecord;
24
26 TNode<Context> context, TNode<JSAny> object) {
27 return GetProperty(context, object, factory()->iterator_symbol());
28}
29
35
37 TNode<JSAny> object,
39 Label if_not_callable(this, Label::kDeferred), if_callable(this);
40 GotoIf(TaggedIsSmi(method), &if_not_callable);
41 Branch(IsCallable(CAST(method)), &if_callable, &if_not_callable);
42
43 BIND(&if_not_callable);
44 CallRuntime(Runtime::kThrowIteratorError, context, object);
46
47 BIND(&if_callable);
48 {
49 TNode<JSAny> iterator = Call(context, method, object);
50
51 Label get_next(this), if_notobject(this, Label::kDeferred);
52 GotoIf(TaggedIsSmi(iterator), &if_notobject);
53 Branch(JSAnyIsNotPrimitive(CAST(iterator)), &get_next, &if_notobject);
54
55 BIND(&if_notobject);
56 CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context);
58
59 BIND(&get_next);
60 TNode<JSAny> next =
61 GetProperty(context, iterator, factory()->next_string());
63 }
64}
65
67 TNode<Context> context, const IteratorRecord& iterator, Label* if_done,
68 std::optional<TNode<Map>> fast_iterator_result_map) {
69 DCHECK_NOT_NULL(if_done);
70 // 1. a. Let result be ? Invoke(iterator, "next", « »).
71 TNode<JSAny> result = Call(context, iterator.next, iterator.object);
72
73 // 3. If Type(result) is not Object, throw a TypeError exception.
74 Label if_notobject(this, Label::kDeferred), return_result(this);
75 GotoIf(TaggedIsSmi(result), &if_notobject);
76 TNode<JSAnyNotSmi> heap_object_result = CAST(result);
77 TNode<Map> result_map = LoadMap(heap_object_result);
78 GotoIfNot(JSAnyIsNotPrimitiveMap(result_map), &if_notobject);
79
80 // IteratorComplete
81 // 2. Return ToBoolean(? Get(iterResult, "done")).
82 IteratorComplete(context, heap_object_result, if_done,
83 fast_iterator_result_map);
84 Goto(&return_result);
85
86 BIND(&if_notobject);
87 CallRuntime(Runtime::kThrowIteratorResultNotAnObject, context, result);
89
90 BIND(&return_result);
91 return CAST(heap_object_result);
92}
93
95 TNode<Context> context, const TNode<JSAnyNotSmi> iterator, Label* if_done,
96 std::optional<TNode<Map>> fast_iterator_result_map) {
97 DCHECK_NOT_NULL(if_done);
98
99 Label return_result(this);
100
101 TNode<Map> result_map = LoadMap(iterator);
102
103 if (fast_iterator_result_map) {
104 // Fast iterator result case:
105 Label if_generic(this);
106
107 // 4. Return result.
108 GotoIfNot(TaggedEqual(result_map, *fast_iterator_result_map), &if_generic);
109
110 // 2. Return ToBoolean(? Get(iterResult, "done")).
111 TNode<Object> done =
112 LoadObjectField(iterator, JSIteratorResult::kDoneOffset);
113 BranchIfToBooleanIsTrue(done, if_done, &return_result);
114
115 BIND(&if_generic);
116 }
117
118 // Generic iterator result case:
119 {
120 // 2. Return ToBoolean(? Get(iterResult, "done")).
121 TNode<JSAny> done =
122 GetProperty(context, iterator, factory()->done_string());
123 BranchIfToBooleanIsTrue(done, if_done, &return_result);
124 }
125
126 BIND(&return_result);
127}
128
131 std::optional<TNode<Map>> fast_iterator_result_map) {
132 Label exit(this);
133 TVARIABLE(JSAny, var_value);
134 if (fast_iterator_result_map) {
135 // Fast iterator result case:
136 Label if_generic(this);
138 GotoIfNot(TaggedEqual(map, *fast_iterator_result_map), &if_generic);
139 var_value = CAST(LoadObjectField(result, JSIteratorResult::kValueOffset));
140 Goto(&exit);
141
142 BIND(&if_generic);
143 }
144
145 // Generic iterator result case:
146 var_value = GetProperty(context, result, factory()->value_string());
147 Goto(&exit);
148
149 BIND(&exit);
150 return var_value.value();
151}
152
154 TNode<Context> context, TNode<JSAny> iterable,
155 std::function<void(TNode<Object>)> func,
156 std::initializer_list<compiler::CodeAssemblerVariable*> merged_variables) {
157 Iterate(context, iterable, GetIteratorMethod(context, iterable), func,
158 merged_variables);
159}
160
162 TNode<Context> context, TNode<JSAny> iterable, TNode<Object> iterable_fn,
163 std::function<void(TNode<Object>)> func,
164 std::initializer_list<compiler::CodeAssemblerVariable*> merged_variables) {
165 Label done(this);
166
167 IteratorRecord iterator_record = GetIterator(context, iterable, iterable_fn);
168
169 Label if_exception(this, Label::kDeferred);
170 TVARIABLE(Object, var_exception);
171
172 Label loop_start(this, merged_variables);
173 Goto(&loop_start);
174
175 BIND(&loop_start);
176 {
177 TNode<JSReceiver> next = IteratorStep(context, iterator_record, &done);
178 TNode<Object> next_value = IteratorValue(context, next);
179
180 {
181 compiler::ScopedExceptionHandler handler(this, &if_exception,
182 &var_exception);
183 func(next_value);
184 }
185
186 Goto(&loop_start);
187 }
188
189 BIND(&if_exception);
190 {
192 SetPendingMessage(TheHoleConstant());
193 IteratorCloseOnException(context, iterator_record.object);
194 CallRuntime(Runtime::kReThrowWithMessage, context, var_exception.value(),
195 message);
196 Unreachable();
197 }
198
199 BIND(&done);
200}
201
203 TNode<Context> context, TNode<JSAny> iterable, TNode<Object> iterator_fn) {
204 GrowableFixedArray values(state());
205 FillFixedArrayFromIterable(context, iterable, iterator_fn, &values);
206 return values.ToJSArray(context);
207}
208
210 TNode<Context> context, TNode<JSAny> iterable, TNode<Object> iterator_fn) {
211 GrowableFixedArray values(state());
212 FillFixedArrayFromIterable(context, iterable, iterator_fn, &values);
213 TNode<FixedArray> new_array = values.ToFixedArray();
214 return new_array;
215}
216
218 TNode<Context> context, TNode<JSAny> iterable, TNode<Object> iterator_fn,
219 GrowableFixedArray* values) {
220 // 1. Let iteratorRecord be ? GetIterator(items, method) (handled by Iterate).
221
222 // 2. Let values be a new empty List.
223
224 // The GrowableFixedArray has already been created. It's ok if we do this step
225 // out of order, since creating an empty List is not observable.
226
227 // 3. Let next be true. (handled by Iterate)
228 // 4. Repeat, while next is not false (handled by Iterate)
229 Iterate(context, iterable, iterator_fn,
230 [&values](TNode<Object> value) {
231 // Handled by Iterate:
232 // a. Set next to ? IteratorStep(iteratorRecord).
233 // b. If next is not false, then
234 // i. Let nextValue be ? IteratorValue(next).
235
236 // ii. Append nextValue to the end of the List values.
237 values->Push(value);
238 },
239 {values->var_array(), values->var_capacity(), values->var_length()});
240}
241
243 auto context = Parameter<Context>(Descriptor::kContext);
244 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
245 auto iterator_fn = Parameter<Object>(Descriptor::kIteratorFn);
246
247 Return(IterableToList(context, iterable, iterator_fn));
248}
249
250TF_BUILTIN(IterableToFixedArray, IteratorBuiltinsAssembler) {
251 auto context = Parameter<Context>(Descriptor::kContext);
252 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
253 auto iterator_fn = Parameter<Object>(Descriptor::kIteratorFn);
254
255 Return(IterableToFixedArray(context, iterable, iterator_fn));
256}
257
258#if V8_ENABLE_WEBASSEMBLY
259TF_BUILTIN(IterableToFixedArrayForWasm, IteratorBuiltinsAssembler) {
260 auto context = Parameter<Context>(Descriptor::kContext);
261 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
262 auto expected_length = Parameter<Smi>(Descriptor::kExpectedLength);
263
264 TNode<Object> iterator_fn = GetIteratorMethod(context, iterable);
265 GrowableFixedArray values(state());
266
267 Label done(this);
268
269 FillFixedArrayFromIterable(context, iterable, iterator_fn, &values);
270
271 GotoIf(WordEqual(PositiveSmiUntag(expected_length),
272 values.var_length()->value()),
273 &done);
274 Return(CallRuntime(
275 Runtime::kThrowTypeError, context,
276 SmiConstant(MessageTemplate::kWasmTrapMultiReturnLengthMismatch)));
277
278 BIND(&done);
279 Return(values.var_array()->value());
280}
281#endif // V8_ENABLE_WEBASSEMBLY
282
284 TNode<Context> context, TNode<JSAny> iterable) {
285 Label done(this);
287 // 1. If iterable is undefined, then
288 // a. Return a new empty List.
289 GotoIf(IsUndefined(iterable), &done);
290
291 // 2. Let iteratorRecord be ? GetIterator(items) (handled by Iterate).
292
293 // 3. Let list be a new empty List.
294
295 // 4. Let next be true (handled by Iterate).
296 // 5. Repeat, while next is not false (handled by Iterate).
297 Iterate(
298 context, iterable,
299 [&](TNode<Object> next_value) {
300 // Handled by Iterate:
301 // a. Set next to ? IteratorStep(iteratorRecord).
302 // b. If next is not false, then
303 // i. Let nextValue be ? IteratorValue(next).
304
305 // ii. If Type(nextValue) is not String, then
306 Label if_isnotstringtype(this, Label::kDeferred), loop_body_end(this);
307 GotoIf(TaggedIsSmi(next_value), &if_isnotstringtype);
308 TNode<Uint16T> next_value_type = LoadInstanceType(CAST(next_value));
309 GotoIfNot(IsStringInstanceType(next_value_type), &if_isnotstringtype);
310
311 // iii. Append nextValue to the end of the List list.
312 list.Push(next_value);
313
314 Goto(&loop_body_end);
315
316 // 5.b.ii
317 BIND(&if_isnotstringtype);
318 {
319 // 1. Let error be ThrowCompletion(a newly created TypeError object).
320
321 CallRuntime(Runtime::kThrowTypeError, context,
322 SmiConstant(MessageTemplate::kIterableYieldedNonString),
323 next_value);
324 // 2. Return ? IteratorClose(iteratorRecord, error). (handled by
325 // Iterate).
326 Unreachable();
327 }
328
329 BIND(&loop_body_end);
330 },
331 {list.var_array(), list.var_length(), list.var_capacity()});
332 Goto(&done);
333
334 BIND(&done);
335 // 6. Return list.
336 return list.ToFixedArray();
337}
338
339TF_BUILTIN(StringListFromIterable, IteratorBuiltinsAssembler) {
340 auto context = Parameter<Context>(Descriptor::kContext);
341 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
342
343 Return(StringListFromIterable(context, iterable));
344}
345
346TF_BUILTIN(StringFixedArrayFromIterable, IteratorBuiltinsAssembler) {
347 auto context = Parameter<Context>(Descriptor::kContext);
348 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
349
350 Return(StringListFromIterable(context, iterable));
351}
352
353// This builtin always returns a new JSArray and is thus safe to use even in the
354// presence of code that may call back into user-JS. This builtin will take the
355// fast path if the iterable is a fast array and the Array prototype and the
356// Symbol.iterator is untouched. The fast path skips the iterator and copies the
357// backing store to the new array. Note that if the array has holes, the holes
358// will be copied to the new array, which is inconsistent with the behavior of
359// an actual iteration, where holes should be replaced with undefined (if the
360// prototype has no elements). To maintain the correct behavior for holey
361// arrays, use the builtins IterableToList or IterableToListWithSymbolLookup or
362// IterableToListConvertHoles.
363TF_BUILTIN(IterableToListMayPreserveHoles, IteratorBuiltinsAssembler) {
364 auto context = Parameter<Context>(Descriptor::kContext);
365 auto iterable = Parameter<Object>(Descriptor::kIterable);
366 auto iterator_fn = Parameter<Object>(Descriptor::kIteratorFn);
367
368 Label slow_path(this);
369
370 GotoIfNot(IsFastJSArrayWithNoCustomIteration(context, iterable), &slow_path);
371
372 // The fast path will copy holes to the new array.
373 TailCallBuiltin(Builtin::kCloneFastJSArray, context, iterable);
374
375 BIND(&slow_path);
376 TailCallBuiltin(Builtin::kIterableToList, context, iterable, iterator_fn);
377}
378
379// This builtin always returns a new JSArray and is thus safe to use even in the
380// presence of code that may call back into user-JS. This builtin will take the
381// fast path if the iterable is a fast array and the Array prototype and the
382// Symbol.iterator is untouched. The fast path skips the iterator and copies the
383// backing store to the new array. Note that if the array has holes, the holes
384// will be converted to undefined values in the new array (unlike
385// IterableToListMayPreserveHoles builtin).
386TF_BUILTIN(IterableToListConvertHoles, IteratorBuiltinsAssembler) {
387 auto context = Parameter<Context>(Descriptor::kContext);
388 auto iterable = Parameter<Object>(Descriptor::kIterable);
389 auto iterator_fn = Parameter<Object>(Descriptor::kIteratorFn);
390
391 Label slow_path(this);
392
393 GotoIfNot(IsFastJSArrayWithNoCustomIteration(context, iterable), &slow_path);
394
395 // The fast path will convert holes to undefined values in the new array.
396 TailCallBuiltin(Builtin::kCloneFastJSArrayFillingHoles, context, iterable);
397
398 BIND(&slow_path);
399 TailCallBuiltin(Builtin::kIterableToList, context, iterable, iterator_fn);
400}
401
403 TNode<Context> context, TNode<JSAny> iterable,
404 TVariable<JSArray>* var_result, Label* slow) {
405 Label done(this), check_string(this), check_map(this), check_set(this);
406
407 // Always call the `next()` builtins when the debugger is
408 // active, to ensure we capture side-effects correctly.
409 GotoIf(IsDebugActive(), slow);
410
411 GotoIfNot(
412 Word32Or(IsFastJSArrayWithNoCustomIteration(context, iterable),
413 IsFastJSArrayForReadWithNoCustomIteration(context, iterable)),
414 &check_string);
415
416 // Fast path for fast JSArray.
417 *var_result = CAST(
418 CallBuiltin(Builtin::kCloneFastJSArrayFillingHoles, context, iterable));
419 Goto(&done);
420
421 BIND(&check_string);
422 {
423 Label string_maybe_fast_call(this);
424 StringBuiltinsAssembler string_assembler(state());
426 iterable, context, &string_maybe_fast_call, &check_map);
427
428 BIND(&string_maybe_fast_call);
429 const TNode<Uint32T> length = LoadStringLengthAsWord32(CAST(iterable));
430 // Use string length as conservative approximation of number of codepoints.
431 GotoIf(
432 Uint32GreaterThan(length, Uint32Constant(JSArray::kMaxFastArrayLength)),
433 slow);
434 *var_result = CAST(CallBuiltin(Builtin::kStringToList, context, iterable));
435 Goto(&done);
436 }
437
438 BIND(&check_map);
439 {
440 Label map_fast_call(this);
442 state(), iterable, context, &map_fast_call, &check_set);
443
444 BIND(&map_fast_call);
445 *var_result =
446 CAST(CallBuiltin(Builtin::kMapIteratorToList, context, iterable));
447 Goto(&done);
448 }
449
450 BIND(&check_set);
451 {
452 Label set_fast_call(this);
454 &set_fast_call, slow);
455
456 BIND(&set_fast_call);
457 *var_result =
458 CAST(CallBuiltin(Builtin::kSetOrSetIteratorToList, context, iterable));
459 Goto(&done);
460 }
461
462 BIND(&done);
463}
464
466 TNode<Context> context, TNode<JSAny> iterable, Label* slow) {
467 TVARIABLE(JSArray, var_fast_result);
468 FastIterableToList(context, iterable, &var_fast_result, slow);
469 return var_fast_result.value();
470}
471
472// This builtin loads the property Symbol.iterator as the iterator, and has fast
473// paths for fast arrays, for primitive strings, for sets and set iterators, and
474// for map iterators. These fast paths will only be taken if Symbol.iterator and
475// the Iterator prototype are not modified in a way that changes the original
476// iteration behavior.
477// * In case of fast holey arrays, holes will be converted to undefined to
478// reflect iteration semantics. Note that replacement by undefined is only
479// correct when the NoElements protector is valid.
480// * In case of map/set iterators, there is an additional requirement that the
481// iterator is not partially consumed. To be spec-compliant, after spreading
482// the iterator is set to be exhausted.
483TF_BUILTIN(IterableToListWithSymbolLookup, IteratorBuiltinsAssembler) {
484 auto context = Parameter<Context>(Descriptor::kContext);
485 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
486
487 Label slow_path(this);
488
489 GotoIfForceSlowPath(&slow_path);
490
491 TVARIABLE(JSArray, var_result);
492 FastIterableToList(context, iterable, &var_result, &slow_path);
493 Return(var_result.value());
494
495 BIND(&slow_path);
496 {
497 TNode<Object> iterator_fn = GetIteratorMethod(context, iterable);
498 TailCallBuiltin(Builtin::kIterableToList, context, iterable, iterator_fn);
499 }
500}
501
502TF_BUILTIN(GetIteratorWithFeedbackLazyDeoptContinuation,
504 auto context = Parameter<Context>(Descriptor::kContext);
505 auto receiver = Parameter<Object>(Descriptor::kReceiver);
506 // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it.
507 auto call_slot_smi = Parameter<Smi>(Descriptor::kCallSlot);
508 auto feedback = Parameter<FeedbackVector>(Descriptor::kFeedback);
509 auto iterator_method = Parameter<Object>(Descriptor::kResult);
510
511 // Note, that the builtin also expects the call_slot as a Smi.
513 CallBuiltin(Builtin::kCallIteratorWithFeedback, context, receiver,
514 iterator_method, call_slot_smi, feedback);
515 Return(result);
516}
517
518TF_BUILTIN(CallIteratorWithFeedbackLazyDeoptContinuation,
520 TNode<Context> context = Parameter<Context>(Descriptor::kContext);
521 TNode<Object> iterator = Parameter<Object>(Descriptor::kArgument);
522
523 ThrowIfNotJSReceiver(context, iterator,
524 MessageTemplate::kSymbolIteratorInvalid, "");
525 Return(iterator);
526}
527
528// This builtin creates a FixedArray based on an Iterable and doesn't have a
529// fast path for anything.
530TF_BUILTIN(IterableToFixedArrayWithSymbolLookupSlow,
532 auto context = Parameter<Context>(Descriptor::kContext);
533 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
534
535 TNode<Object> iterator_fn = GetIteratorMethod(context, iterable);
536 TailCallBuiltin(Builtin::kIterableToFixedArray, context, iterable,
537 iterator_fn);
538}
539
541
542} // namespace internal
543} // namespace v8
#define BIND(label)
#define TVARIABLE(...)
#define TF_BUILTIN(Name, AssemblerBase)
void SetPendingMessage(TNode< Union< Hole, JSMessageObject > > message)
TNode< JSAny > GetProperty(TNode< Context > context, TNode< JSAny > receiver, Handle< Name > name)
TNode< BoolT > TaggedEqual(TNode< AnyTaggedT > a, TNode< AnyTaggedT > b)
TNode< T > LoadObjectField(TNode< HeapObject > object, int offset)
TNode< BoolT > JSAnyIsNotPrimitiveMap(TNode< Map > map)
TNode< JSAny > Call(TNode< Context > context, TNode< TCallable > callable, ConvertReceiverMode mode, TNode< JSAny > receiver, TArgs... args)
TNode< Uint16T > LoadInstanceType(TNode< HeapObject > object)
TNode< BoolT > TaggedIsSmi(TNode< MaybeObject > a)
TNode< Map > LoadMap(TNode< HeapObject > object)
TNode< Uint32T > LoadStringLengthAsWord32(TNode< String > string)
TNode< Union< Hole, JSMessageObject > > GetPendingMessage()
void BranchIfToBooleanIsTrue(TNode< Object > value, Label *if_true, Label *if_false)
TNode< BoolT > IsStringInstanceType(TNode< Int32T > instance_type)
TNode< BoolT > IsCallable(TNode< HeapObject > object)
TNode< BoolT > JSAnyIsNotPrimitive(TNode< HeapObject > object)
TVariable< FixedArray > * var_array()
void Push(const TNode< Object > value)
TNode< JSReceiver > IteratorStep(TNode< Context > context, const IteratorRecord &iterator, Label *if_done, std::optional< TNode< Map > > fast_iterator_result_map=std::nullopt)
void Iterate(TNode< Context > context, TNode< JSAny > iterable, std::function< void(TNode< Object >)> func, std::initializer_list< compiler::CodeAssemblerVariable * > merged_variables={})
TNode< JSArray > IterableToList(TNode< Context > context, TNode< JSAny > iterable, TNode< Object > iterator_fn)
void FastIterableToList(TNode< Context > context, TNode< JSAny > iterable, TVariable< JSArray > *var_result, Label *slow)
TNode< FixedArray > IterableToFixedArray(TNode< Context > context, TNode< JSAny > iterable, TNode< Object > iterator_fn)
void IteratorComplete(TNode< Context > context, const TNode< JSAnyNotSmi > iterator, Label *if_done, std::optional< TNode< Map > > fast_iterator_result_map=std::nullopt)
TNode< JSAny > IteratorValue(TNode< Context > context, TNode< JSReceiver > result, std::optional< TNode< Map > > fast_iterator_result_map=std::nullopt)
void FillFixedArrayFromIterable(TNode< Context > context, TNode< JSAny > iterable, TNode< Object > iterator_fn, GrowableFixedArray *values)
TNode< JSAny > GetIteratorMethod(TNode< Context > context, TNode< JSAny >)
TNode< FixedArray > StringListFromIterable(TNode< Context > context, TNode< JSAny > iterable)
IteratorRecord GetIterator(TNode< Context > context, TNode< JSAny > object)
static constexpr uint32_t kMaxFastArrayLength
Definition js-array.h:136
void BranchIfStringPrimitiveWithNoCustomIteration(TNode< Object > object, TNode< Context > context, Label *if_true, Label *if_false)
static TNode UncheckedCast(compiler::Node *node)
Definition tnode.h:413
void GotoIfNot(TNode< IntegralT > condition, Label *false_label, GotoHint goto_hint=GotoHint::kNone)
TNode< Smi > SmiConstant(Tagged< Smi > value)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
TNode< Int32T > Word32Or(TNode< Int32T > left, TNode< Int32T > right)
TNode< Uint32T > Uint32Constant(uint32_t value)
TNode< T > CallRuntime(Runtime::FunctionId function, TNode< Object > context, TArgs... args)
TNode< T > CallBuiltin(Builtin id, TNode< Object > context, TArgs... args)
void Branch(TNode< IntegralT > condition, Label *true_label, Label *false_label, BranchHint branch_hint=BranchHint::kNone)
#define CAST(x)
TNode< Object > receiver
ZoneVector< RpoNumber > & result
MovableLabel handler
LiftoffAssembler::CacheState state
void BranchIfIterableWithOriginalKeyOrValueMapIterator(compiler::CodeAssemblerState *state, TNode< Object > iterable, TNode< Context > context, compiler::CodeAssemblerLabel *if_true, compiler::CodeAssemblerLabel *if_false)
void BranchIfIterableWithOriginalValueSetIterator(compiler::CodeAssemblerState *state, TNode< Object > iterable, TNode< Context > context, compiler::CodeAssemblerLabel *if_true, compiler::CodeAssemblerLabel *if_false)
TorqueStructIteratorRecord IteratorRecord
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
Symbol method