v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-date-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
9
10namespace v8 {
11namespace internal {
12
14
15// -----------------------------------------------------------------------------
16// ES6 section 20.3 Date Objects
17
28
31 Label ok(this), receiver_not_date(this, Label::kDeferred);
32
33 GotoIf(TaggedIsSmi(receiver), &receiver_not_date);
34 TNode<Uint16T> receiver_instance_type = LoadInstanceType(CAST(receiver));
35 Branch(InstanceTypeEqual(receiver_instance_type, JS_DATE_TYPE), &ok,
36 &receiver_not_date);
37
38 // Raise a TypeError if the receiver is not a date.
39 BIND(&receiver_not_date);
40 { ThrowTypeError(context, MessageTemplate::kNotDateObject); }
41
42 BIND(&ok);
43}
44
46 TNode<Context> context, TNode<Object> receiver, int field_index) {
48
49 TNode<JSDate> date_receiver = CAST(receiver);
50 // Load the specified date field, falling back to the runtime as necessary.
51 if (field_index < JSDate::kFirstUncachedField) {
52 Label stamp_mismatch(this, Label::kDeferred);
53 TNode<Object> date_cache_stamp = Load<Object>(
54 ExternalConstant(ExternalReference::date_cache_stamp(isolate())));
55
56 TNode<Object> cache_stamp =
57 LoadObjectField(date_receiver, JSDate::kCacheStampOffset);
58 GotoIf(TaggedNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch);
59 Return(LoadObjectField(date_receiver,
60 JSDate::kYearOffset + field_index * kTaggedSize));
61
62 BIND(&stamp_mismatch);
63 }
64
65 TNode<ExternalReference> isolate_ptr =
67 TNode<Smi> field_index_smi = SmiConstant(field_index);
69 ExternalConstant(ExternalReference::get_date_field_function());
72 std::make_pair(MachineType::Pointer(), isolate_ptr),
73 std::make_pair(MachineType::AnyTagged(), date_receiver),
74 std::make_pair(MachineType::AnyTagged(), field_index_smi)));
76}
77
78TF_BUILTIN(DatePrototypeGetDate, DateBuiltinsAssembler) {
79 auto context = Parameter<Context>(Descriptor::kContext);
80 auto receiver = Parameter<Object>(Descriptor::kReceiver);
81 Generate_DatePrototype_GetField(context, receiver, JSDate::kDay);
82}
83
84TF_BUILTIN(DatePrototypeGetDay, DateBuiltinsAssembler) {
85 auto context = Parameter<Context>(Descriptor::kContext);
86 auto receiver = Parameter<Object>(Descriptor::kReceiver);
87 Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekday);
88}
89
90TF_BUILTIN(DatePrototypeGetFullYear, DateBuiltinsAssembler) {
91 auto context = Parameter<Context>(Descriptor::kContext);
92 auto receiver = Parameter<Object>(Descriptor::kReceiver);
93 Generate_DatePrototype_GetField(context, receiver, JSDate::kYear);
94}
95
96TF_BUILTIN(DatePrototypeGetHours, DateBuiltinsAssembler) {
97 auto context = Parameter<Context>(Descriptor::kContext);
98 auto receiver = Parameter<Object>(Descriptor::kReceiver);
99 Generate_DatePrototype_GetField(context, receiver, JSDate::kHour);
100}
101
102TF_BUILTIN(DatePrototypeGetMilliseconds, DateBuiltinsAssembler) {
103 auto context = Parameter<Context>(Descriptor::kContext);
104 auto receiver = Parameter<Object>(Descriptor::kReceiver);
105 Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecond);
106}
107
108TF_BUILTIN(DatePrototypeGetMinutes, DateBuiltinsAssembler) {
109 auto context = Parameter<Context>(Descriptor::kContext);
110 auto receiver = Parameter<Object>(Descriptor::kReceiver);
111 Generate_DatePrototype_GetField(context, receiver, JSDate::kMinute);
112}
113
114TF_BUILTIN(DatePrototypeGetMonth, DateBuiltinsAssembler) {
115 auto context = Parameter<Context>(Descriptor::kContext);
116 auto receiver = Parameter<Object>(Descriptor::kReceiver);
117 Generate_DatePrototype_GetField(context, receiver, JSDate::kMonth);
118}
119
120TF_BUILTIN(DatePrototypeGetSeconds, DateBuiltinsAssembler) {
121 auto context = Parameter<Context>(Descriptor::kContext);
122 auto receiver = Parameter<Object>(Descriptor::kReceiver);
123 Generate_DatePrototype_GetField(context, receiver, JSDate::kSecond);
124}
125
126TF_BUILTIN(DatePrototypeGetTime, DateBuiltinsAssembler) {
127 auto context = Parameter<Context>(Descriptor::kContext);
128 auto receiver = Parameter<Object>(Descriptor::kReceiver);
129 Generate_IsDateCheck(context, receiver);
130 TNode<JSDate> date_receiver = CAST(receiver);
131 Return(ChangeFloat64ToTagged(
132 LoadObjectField<Float64T>(date_receiver, JSDate::kValueOffset)));
133}
134
135TF_BUILTIN(DatePrototypeGetTimezoneOffset, DateBuiltinsAssembler) {
136 auto context = Parameter<Context>(Descriptor::kContext);
137 auto receiver = Parameter<Object>(Descriptor::kReceiver);
138 Generate_DatePrototype_GetField(context, receiver, JSDate::kTimezoneOffset);
139}
140
141TF_BUILTIN(DatePrototypeGetUTCDate, DateBuiltinsAssembler) {
142 auto context = Parameter<Context>(Descriptor::kContext);
143 auto receiver = Parameter<Object>(Descriptor::kReceiver);
144 Generate_DatePrototype_GetField(context, receiver, JSDate::kDayUTC);
145}
146
147TF_BUILTIN(DatePrototypeGetUTCDay, DateBuiltinsAssembler) {
148 auto context = Parameter<Context>(Descriptor::kContext);
149 auto receiver = Parameter<Object>(Descriptor::kReceiver);
150 Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekdayUTC);
151}
152
153TF_BUILTIN(DatePrototypeGetUTCFullYear, DateBuiltinsAssembler) {
154 auto context = Parameter<Context>(Descriptor::kContext);
155 auto receiver = Parameter<Object>(Descriptor::kReceiver);
156 Generate_DatePrototype_GetField(context, receiver, JSDate::kYearUTC);
157}
158
159TF_BUILTIN(DatePrototypeGetUTCHours, DateBuiltinsAssembler) {
160 auto context = Parameter<Context>(Descriptor::kContext);
161 auto receiver = Parameter<Object>(Descriptor::kReceiver);
162 Generate_DatePrototype_GetField(context, receiver, JSDate::kHourUTC);
163}
164
165TF_BUILTIN(DatePrototypeGetUTCMilliseconds, DateBuiltinsAssembler) {
166 auto context = Parameter<Context>(Descriptor::kContext);
167 auto receiver = Parameter<Object>(Descriptor::kReceiver);
168 Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecondUTC);
169}
170
171TF_BUILTIN(DatePrototypeGetUTCMinutes, DateBuiltinsAssembler) {
172 auto context = Parameter<Context>(Descriptor::kContext);
173 auto receiver = Parameter<Object>(Descriptor::kReceiver);
174 Generate_DatePrototype_GetField(context, receiver, JSDate::kMinuteUTC);
175}
176
177TF_BUILTIN(DatePrototypeGetUTCMonth, DateBuiltinsAssembler) {
178 auto context = Parameter<Context>(Descriptor::kContext);
179 auto receiver = Parameter<Object>(Descriptor::kReceiver);
180 Generate_DatePrototype_GetField(context, receiver, JSDate::kMonthUTC);
181}
182
183TF_BUILTIN(DatePrototypeGetUTCSeconds, DateBuiltinsAssembler) {
184 auto context = Parameter<Context>(Descriptor::kContext);
185 auto receiver = Parameter<Object>(Descriptor::kReceiver);
186 Generate_DatePrototype_GetField(context, receiver, JSDate::kSecondUTC);
187}
188
189TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) {
190 auto context = Parameter<Context>(Descriptor::kContext);
191 auto receiver = Parameter<Object>(Descriptor::kReceiver);
192 Generate_IsDateCheck(context, receiver);
193 TNode<JSDate> date_receiver = CAST(receiver);
194 Return(ChangeFloat64ToTagged(
195 LoadObjectField<Float64T>(date_receiver, JSDate::kValueOffset)));
196}
197
198TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) {
199 auto context = Parameter<Context>(Descriptor::kContext);
200 auto receiver = Parameter<Object>(Descriptor::kReceiver);
201 auto hint = Parameter<Object>(Descriptor::kHint);
202
203 // Check if the {receiver} is actually a JSReceiver.
204 Label receiver_is_invalid(this, Label::kDeferred);
205 GotoIf(TaggedIsSmi(receiver), &receiver_is_invalid);
206 GotoIfNot(JSAnyIsNotPrimitive(CAST(receiver)), &receiver_is_invalid);
207
208 // Dispatch to the appropriate OrdinaryToPrimitive builtin.
209 Label hint_is_number(this), hint_is_string(this),
210 hint_is_invalid(this, Label::kDeferred);
211
212 // Fast cases for internalized strings.
213 TNode<String> number_string = NumberStringConstant();
214 GotoIf(TaggedEqual(hint, number_string), &hint_is_number);
215 TNode<String> default_string = DefaultStringConstant();
216 GotoIf(TaggedEqual(hint, default_string), &hint_is_string);
217 TNode<String> string_string = StringStringConstant();
218 GotoIf(TaggedEqual(hint, string_string), &hint_is_string);
219
220 // Slow-case with actual string comparisons.
221 GotoIf(TaggedIsSmi(hint), &hint_is_invalid);
222 GotoIfNot(IsString(CAST(hint)), &hint_is_invalid);
223
224 TNode<IntPtrT> hint_length = LoadStringLengthAsWord(CAST(hint));
225 GotoIfStringEqual(CAST(hint), hint_length, number_string, &hint_is_number);
226 GotoIfStringEqual(CAST(hint), hint_length, default_string, &hint_is_string);
227 GotoIfStringEqual(CAST(hint), hint_length, string_string, &hint_is_string);
228 Goto(&hint_is_invalid);
229
230 // Use the OrdinaryToPrimitive builtin to convert to a Number.
231 BIND(&hint_is_number);
232 {
233 Builtin builtin =
235 TNode<Object> result = CallBuiltin(builtin, context, receiver);
236 Return(result);
237 }
238
239 // Use the OrdinaryToPrimitive builtin to convert to a String.
240 BIND(&hint_is_string);
241 {
242 Builtin builtin =
244 TNode<Object> result = CallBuiltin(builtin, context, receiver);
245 Return(result);
246 }
247
248 // Raise a TypeError if the {hint} is invalid.
249 BIND(&hint_is_invalid);
250 { ThrowTypeError(context, MessageTemplate::kInvalidHint, hint); }
251
252 // Raise a TypeError if the {receiver} is not a JSReceiver instance.
253 BIND(&receiver_is_invalid);
254 {
255 ThrowTypeError(context, MessageTemplate::kIncompatibleMethodReceiver,
256 StringConstant("Date.prototype [ @@toPrimitive ]"),
257 receiver);
258 }
259}
260
262
263} // namespace internal
264} // namespace v8
#define BIND(label)
#define TF_BUILTIN(Name, AssemblerBase)
static constexpr Builtin OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint)
TNode< BoolT > InstanceTypeEqual(TNode< Int32T > instance_type, int type)
void ThrowTypeError(TNode< Context > context, MessageTemplate message, char const *arg0=nullptr, char const *arg1=nullptr)
TNode< T > LoadObjectField(TNode< HeapObject > object, int offset)
TNode< BoolT > TaggedNotEqual(TNode< AnyTaggedT > a, TNode< AnyTaggedT > b)
TNode< Uint16T > LoadInstanceType(TNode< HeapObject > object)
TNode< BoolT > TaggedIsSmi(TNode< MaybeObject > a)
DateBuiltinsAssembler(compiler::CodeAssemblerState *state)
void Generate_DatePrototype_GetField(TNode< Context > context, TNode< Object > receiver, int field_index)
void Generate_IsDateCheck(TNode< Context > context, TNode< Object > receiver)
static V8_EXPORT_PRIVATE ExternalReference isolate_address()
static constexpr MachineType Pointer()
static constexpr MachineType AnyTagged()
void Return(TNode< Object > value)
TNode< Smi > SmiConstant(Tagged< Smi > value)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
Node * Load(MachineType type, Node *base)
TNode< ExternalReference > ExternalConstant(ExternalReference address)
Node * CallCFunction(Node *function, std::optional< MachineType > return_type, CArgs... cargs)
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
constexpr int kTaggedSize
Definition globals.h:542