v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-temporal-gen.cc
Go to the documentation of this file.
1// Copyright 2021 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
11#include "src/objects/objects.h"
12
13namespace v8 {
14namespace internal {
15
17
19 public:
22
23 // Step 3 and later of #sec-temporal.calendar.prototype.fields
26 TNode<JSAny> iterable);
27
28 // For the use inside Temporal GetPossibleInstantFor
30 TNode<Context> context, TNode<JSAny> iterable);
31};
32
33// Step 3 and later of
34// #sec-temporal.calendar.prototype.fields
37 TNode<JSAny> iterable) {
38 Label done(this), add_fields(this, Label::kDeferred);
39 // 4. Let iteratorRecord be ? GetIterator(items).
40
41 // 5. Let fieldNames be a new empty List.
42 GrowableFixedArray field_names(state());
43
44 // 6. Repeat, while next is not false,
45 Iterate(
46 context, iterable,
47 [&](TNode<Object> next_value) {
48 // Handled by Iterate:
49 // a. Set next to ? IteratorStep(iteratorRecord).
50 // b. If next is not false, then
51 // i. Let nextValue be ? IteratorValue(next).
52
53 // ii. If Type(nextValue) is not String, then
54 Label if_isnotstringtype(this, Label::kDeferred),
55 if_rangeerror(this, Label::kDeferred), loop_body_end(this);
56 GotoIf(TaggedIsSmi(next_value), &if_isnotstringtype);
57 TNode<Uint16T> next_value_type = LoadInstanceType(CAST(next_value));
58 GotoIfNot(IsStringInstanceType(next_value_type), &if_isnotstringtype);
59
60 // Step iii and iv see IsInvalidTemporalCalendarField
61 // TODO(ftang) Optimize this and remove the runtime call by keeping a
62 // bitfield of "fields seen so far" and doing the string comparisons +
63 // bitfield access directly here.
64 GotoIf(IsTrue(CallRuntime(Runtime::kIsInvalidTemporalCalendarField,
65 context, next_value,
66 field_names.ToFixedArray())),
67 &if_rangeerror);
68
69 // v. Append nextValue to the end of the List fieldNames.
70 field_names.Push(next_value);
71
72 Goto(&loop_body_end);
73
74 // 6.b.ii
75 BIND(&if_isnotstringtype);
76 {
77 // 1. Let completion be ThrowCompletion(a newly created TypeError
78 // object).
79
80 CallRuntime(Runtime::kThrowTypeError, context,
81 SmiConstant(MessageTemplate::kIterableYieldedNonString),
82 next_value);
83 // 2. Return ? IteratorClose(iteratorRecord, completion). (handled by
84 // Iterate).
86 }
87
88 // 6.b.ii
89 BIND(&if_rangeerror);
90 {
91 // 1. Let completion be ThrowCompletion(a newly created RangeError
92 // object).
93
94 CallRuntime(Runtime::kThrowRangeError, context,
95 SmiConstant(MessageTemplate::kInvalidTimeValue),
96 next_value);
97 // 2. Return ? IteratorClose(iteratorRecord, completion). (handled by
98 // Iterate).
100 }
101 BIND(&loop_body_end);
102 },
103 {field_names.var_array(), field_names.var_length(),
104 field_names.var_capacity()});
105 {
106 // Step 7 and 8 of
107 // of #sup-temporal.calendar.prototype.fields.
108 // Notice this spec text is in the Chapter 15 of the #sup part not #sec
109 // part.
110 // 7. If calendar.[[Identifier]] is "iso8601", then
112 calendar, JSTemporalCalendar::kFlagsOffset);
113 // calendar is "iso8601" while the index of calendar is 0
114 const TNode<IntPtrT> index = Signed(
116 Branch(IntPtrEqual(index, IntPtrConstant(0)), &done, &add_fields);
117 BIND(&add_fields);
118 {
119 // Step 8.a. Let result be the result of implementation-defined processing
120 // of fieldNames and calendar.[[Identifier]]. We just always add "era" and
121 // "eraYear" for other calendar.
122
123 TNode<String> era_string = StringConstant("era");
124 field_names.Push(era_string);
125 TNode<String> eraYear_string = StringConstant("eraYear");
126 field_names.Push(eraYear_string);
127 }
128 Goto(&done);
129 }
130 BIND(&done);
131 return field_names.ToJSArray(context);
132}
133
134// #sec-iterabletolistoftype
137 TNode<Context> context, TNode<JSAny> iterable) {
139 Label done(this);
140 // 1. If iterable is undefined, then
141 // a. Return a new empty List.
142 GotoIf(IsUndefined(iterable), &done);
143
144 // 2. Let iteratorRecord be ? GetIterator(items) (handled by Iterate).
145
146 // 3. Let list be a new empty List.
147
148 // 3. Let next be true. (handled by Iterate).
149 // 4. Repeat, while next is not false (handled by Iterate).
150 Iterate(context, iterable,
151 [&](TNode<Object> next_value) {
152 // Handled by Iterate:
153 // a. Set next to ? IteratorStep(iteratorRecord).
154 // b. If next is not false, then
155 // i. Let nextValue be ? IteratorValue(next).
156
157 // ii. If Type(nextValue) is not Object or nextValue does not have
158 // an [[InitializedTemporalInstant]] internal slot
159 Label if_isnottemporalinstant(this, Label::kDeferred),
160 loop_body_end(this);
161 GotoIf(TaggedIsSmi(next_value), &if_isnottemporalinstant);
162 TNode<Uint16T> next_value_type = LoadInstanceType(CAST(next_value));
164 &if_isnottemporalinstant);
165
166 // iii. Append nextValue to the end of the List list.
167 list.Push(next_value);
168 Goto(&loop_body_end);
169
170 // 5.b.ii
171 BIND(&if_isnottemporalinstant);
172 {
173 // 1. Let error be ThrowCompletion(a newly created TypeError
174 // object).
176 Runtime::kThrowTypeError, context,
177 SmiConstant(MessageTemplate::kIterableYieldedNonString),
178 next_value);
179
180 // 2. Return ? IteratorClose(iteratorRecord, error). (handled by
181 // Iterate).
182 Unreachable();
183 }
184
185 BIND(&loop_body_end);
186 },
187 {list.var_array(), list.var_length(), list.var_capacity()});
188
189 Goto(&done);
190
191 BIND(&done);
192 return list.ToFixedArray();
193}
194
195TF_BUILTIN(TemporalInstantFixedArrayFromIterable, TemporalBuiltinsAssembler) {
196 auto context = Parameter<Context>(Descriptor::kContext);
197 auto iterable = Parameter<JSAny>(Descriptor::kIterable);
198
199 Return(TemporalInstantFixedArrayFromIterable(context, iterable));
200}
201
202// #sec-temporal.calendar.prototype.fields
203TF_BUILTIN(TemporalCalendarPrototypeFields, TemporalBuiltinsAssembler) {
204 auto context = Parameter<Context>(Descriptor::kContext);
205 auto argc = UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount);
206
207 CodeStubArguments args(this, argc);
208
209 // 1. Let calendar be this value.
210 TNode<JSAny> receiver = args.GetReceiver();
211
212 // 2. Perform ? RequireInternalSlot(calendar,
213 // [[InitializedTemporalCalendar]]).
214 ThrowIfNotInstanceType(context, receiver, JS_TEMPORAL_CALENDAR_TYPE,
215 "Temporal.Calendar.prototype.fields");
217
218 // Step 3 and later is inside CalendarFieldsArrayFromIterable
219 TNode<JSAny> iterable = args.GetOptionalArgumentValue(0);
220 Return(CalendarFieldsArrayFromIterable(context, calendar, iterable));
221}
222
224
225} // namespace internal
226} // namespace v8
#define BIND(label)
#define TF_BUILTIN(Name, AssemblerBase)
TNode< BoolT > IsTemporalInstantInstanceType(TNode< Int32T > instance_type)
TNode< Int32T > LoadAndUntagToWord32ObjectField(TNode< HeapObject > object, int offset)
TNode< Uint16T > LoadInstanceType(TNode< HeapObject > object)
TNode< BoolT > TaggedIsSmi(TNode< MaybeObject > a)
TNode< BoolT > IsStringInstanceType(TNode< Int32T > instance_type)
TNode< UintPtrT > DecodeWordFromWord32(TNode< Word32T > word32)
TNode< JSArray > ToJSArray(const TNode< Context > context)
TVariable< FixedArray > * var_array()
void Push(const TNode< Object > value)
void Iterate(TNode< Context > context, TNode< JSAny > iterable, std::function< void(TNode< Object >)> func, std::initializer_list< compiler::CodeAssemblerVariable * > merged_variables={})
TNode< JSArray > CalendarFieldsArrayFromIterable(TNode< Context > context, TNode< JSTemporalCalendar > calendar, TNode< JSAny > iterable)
TNode< FixedArray > TemporalInstantFixedArrayFromIterable(TNode< Context > context, TNode< JSAny > iterable)
TemporalBuiltinsAssembler(compiler::CodeAssemblerState *state)
TNode< Int32T > Signed(TNode< Word32T > x)
TNode< IntPtrT > IntPtrConstant(intptr_t value)
void GotoIfNot(TNode< IntegralT > condition, Label *false_label, GotoHint goto_hint=GotoHint::kNone)
TNode< String > StringConstant(const char *str)
TNode< Smi > SmiConstant(Tagged< Smi > value)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
TNode< BoolT > IntPtrEqual(TNode< WordT > left, TNode< WordT > right)
TNode< T > CallRuntime(Runtime::FunctionId function, TNode< Object > context, TArgs... args)
void Branch(TNode< IntegralT > condition, Label *true_label, Label *false_label, BranchHint branch_hint=BranchHint::kNone)
#define CAST(x)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Object > receiver
DirectHandle< Object > calendar