Line data Source code
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 :
5 : #include "src/builtins/builtins-utils-gen.h"
6 : #include "src/builtins/builtins.h"
7 : #include "src/code-stub-assembler.h"
8 :
9 : namespace v8 {
10 : namespace internal {
11 :
12 : // -----------------------------------------------------------------------------
13 : // ES6 section 20.3 Date Objects
14 :
15 : class DateBuiltinsAssembler : public CodeStubAssembler {
16 : public:
17 : explicit DateBuiltinsAssembler(compiler::CodeAssemblerState* state)
18 1064 : : CodeStubAssembler(state) {}
19 :
20 : protected:
21 : void Generate_DatePrototype_GetField(Node* context, Node* receiver,
22 : int field_index);
23 : };
24 :
25 1064 : void DateBuiltinsAssembler::Generate_DatePrototype_GetField(Node* context,
26 : Node* receiver,
27 : int field_index) {
28 1064 : Label receiver_not_date(this, Label::kDeferred);
29 :
30 2128 : GotoIf(TaggedIsSmi(receiver), &receiver_not_date);
31 2128 : Node* receiver_instance_type = LoadInstanceType(receiver);
32 1064 : GotoIfNot(InstanceTypeEqual(receiver_instance_type, JS_DATE_TYPE),
33 2128 : &receiver_not_date);
34 :
35 : // Load the specified date field, falling back to the runtime as necessary.
36 1064 : if (field_index == JSDate::kDateValue) {
37 112 : Return(LoadObjectField(receiver, JSDate::kValueOffset));
38 : } else {
39 952 : if (field_index < JSDate::kFirstUncachedField) {
40 : Label stamp_mismatch(this, Label::kDeferred);
41 : Node* date_cache_stamp = Load(
42 : MachineType::AnyTagged(),
43 784 : ExternalConstant(ExternalReference::date_cache_stamp(isolate())));
44 :
45 : Node* cache_stamp = LoadObjectField(receiver, JSDate::kCacheStampOffset);
46 784 : GotoIf(WordNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch);
47 : Return(LoadObjectField(receiver,
48 784 : JSDate::kValueOffset + field_index * kTaggedSize));
49 :
50 392 : BIND(&stamp_mismatch);
51 : }
52 :
53 1904 : Node* field_index_smi = SmiConstant(field_index);
54 : Node* function =
55 1904 : ExternalConstant(ExternalReference::get_date_field_function());
56 : Node* result = CallCFunction2(
57 : MachineType::AnyTagged(), MachineType::AnyTagged(),
58 952 : MachineType::AnyTagged(), function, receiver, field_index_smi);
59 952 : Return(result);
60 : }
61 :
62 : // Raise a TypeError if the receiver is not a date.
63 1064 : BIND(&receiver_not_date);
64 1064 : { ThrowTypeError(context, MessageTemplate::kNotDateObject); }
65 1064 : }
66 :
67 224 : TF_BUILTIN(DatePrototypeGetDate, DateBuiltinsAssembler) {
68 : Node* context = Parameter(Descriptor::kContext);
69 : Node* receiver = Parameter(Descriptor::kReceiver);
70 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDay);
71 56 : }
72 :
73 224 : TF_BUILTIN(DatePrototypeGetDay, DateBuiltinsAssembler) {
74 : Node* context = Parameter(Descriptor::kContext);
75 : Node* receiver = Parameter(Descriptor::kReceiver);
76 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekday);
77 56 : }
78 :
79 224 : TF_BUILTIN(DatePrototypeGetFullYear, DateBuiltinsAssembler) {
80 : Node* context = Parameter(Descriptor::kContext);
81 : Node* receiver = Parameter(Descriptor::kReceiver);
82 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kYear);
83 56 : }
84 :
85 224 : TF_BUILTIN(DatePrototypeGetHours, DateBuiltinsAssembler) {
86 : Node* context = Parameter(Descriptor::kContext);
87 : Node* receiver = Parameter(Descriptor::kReceiver);
88 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kHour);
89 56 : }
90 :
91 224 : TF_BUILTIN(DatePrototypeGetMilliseconds, DateBuiltinsAssembler) {
92 : Node* context = Parameter(Descriptor::kContext);
93 : Node* receiver = Parameter(Descriptor::kReceiver);
94 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecond);
95 56 : }
96 :
97 224 : TF_BUILTIN(DatePrototypeGetMinutes, DateBuiltinsAssembler) {
98 : Node* context = Parameter(Descriptor::kContext);
99 : Node* receiver = Parameter(Descriptor::kReceiver);
100 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMinute);
101 56 : }
102 :
103 224 : TF_BUILTIN(DatePrototypeGetMonth, DateBuiltinsAssembler) {
104 : Node* context = Parameter(Descriptor::kContext);
105 : Node* receiver = Parameter(Descriptor::kReceiver);
106 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMonth);
107 56 : }
108 :
109 224 : TF_BUILTIN(DatePrototypeGetSeconds, DateBuiltinsAssembler) {
110 : Node* context = Parameter(Descriptor::kContext);
111 : Node* receiver = Parameter(Descriptor::kReceiver);
112 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kSecond);
113 56 : }
114 :
115 224 : TF_BUILTIN(DatePrototypeGetTime, DateBuiltinsAssembler) {
116 : Node* context = Parameter(Descriptor::kContext);
117 : Node* receiver = Parameter(Descriptor::kReceiver);
118 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDateValue);
119 56 : }
120 :
121 224 : TF_BUILTIN(DatePrototypeGetTimezoneOffset, DateBuiltinsAssembler) {
122 : Node* context = Parameter(Descriptor::kContext);
123 : Node* receiver = Parameter(Descriptor::kReceiver);
124 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kTimezoneOffset);
125 56 : }
126 :
127 224 : TF_BUILTIN(DatePrototypeGetUTCDate, DateBuiltinsAssembler) {
128 : Node* context = Parameter(Descriptor::kContext);
129 : Node* receiver = Parameter(Descriptor::kReceiver);
130 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDayUTC);
131 56 : }
132 :
133 224 : TF_BUILTIN(DatePrototypeGetUTCDay, DateBuiltinsAssembler) {
134 : Node* context = Parameter(Descriptor::kContext);
135 : Node* receiver = Parameter(Descriptor::kReceiver);
136 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekdayUTC);
137 56 : }
138 :
139 224 : TF_BUILTIN(DatePrototypeGetUTCFullYear, DateBuiltinsAssembler) {
140 : Node* context = Parameter(Descriptor::kContext);
141 : Node* receiver = Parameter(Descriptor::kReceiver);
142 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kYearUTC);
143 56 : }
144 :
145 224 : TF_BUILTIN(DatePrototypeGetUTCHours, DateBuiltinsAssembler) {
146 : Node* context = Parameter(Descriptor::kContext);
147 : Node* receiver = Parameter(Descriptor::kReceiver);
148 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kHourUTC);
149 56 : }
150 :
151 224 : TF_BUILTIN(DatePrototypeGetUTCMilliseconds, DateBuiltinsAssembler) {
152 : Node* context = Parameter(Descriptor::kContext);
153 : Node* receiver = Parameter(Descriptor::kReceiver);
154 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecondUTC);
155 56 : }
156 :
157 224 : TF_BUILTIN(DatePrototypeGetUTCMinutes, DateBuiltinsAssembler) {
158 : Node* context = Parameter(Descriptor::kContext);
159 : Node* receiver = Parameter(Descriptor::kReceiver);
160 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMinuteUTC);
161 56 : }
162 :
163 224 : TF_BUILTIN(DatePrototypeGetUTCMonth, DateBuiltinsAssembler) {
164 : Node* context = Parameter(Descriptor::kContext);
165 : Node* receiver = Parameter(Descriptor::kReceiver);
166 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMonthUTC);
167 56 : }
168 :
169 224 : TF_BUILTIN(DatePrototypeGetUTCSeconds, DateBuiltinsAssembler) {
170 : Node* context = Parameter(Descriptor::kContext);
171 : Node* receiver = Parameter(Descriptor::kReceiver);
172 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kSecondUTC);
173 56 : }
174 :
175 224 : TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) {
176 : Node* context = Parameter(Descriptor::kContext);
177 : Node* receiver = Parameter(Descriptor::kReceiver);
178 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDateValue);
179 56 : }
180 :
181 168 : TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) {
182 : Node* context = Parameter(Descriptor::kContext);
183 : Node* receiver = Parameter(Descriptor::kReceiver);
184 : Node* hint = Parameter(Descriptor::kHint);
185 :
186 : // Check if the {receiver} is actually a JSReceiver.
187 : Label receiver_is_invalid(this, Label::kDeferred);
188 112 : GotoIf(TaggedIsSmi(receiver), &receiver_is_invalid);
189 112 : GotoIfNot(IsJSReceiver(receiver), &receiver_is_invalid);
190 :
191 : // Dispatch to the appropriate OrdinaryToPrimitive builtin.
192 56 : Label hint_is_number(this), hint_is_string(this),
193 56 : hint_is_invalid(this, Label::kDeferred);
194 :
195 : // Fast cases for internalized strings.
196 112 : Node* number_string = LoadRoot(RootIndex::knumber_string);
197 112 : GotoIf(WordEqual(hint, number_string), &hint_is_number);
198 112 : Node* default_string = LoadRoot(RootIndex::kdefault_string);
199 112 : GotoIf(WordEqual(hint, default_string), &hint_is_string);
200 112 : Node* string_string = LoadRoot(RootIndex::kstring_string);
201 112 : GotoIf(WordEqual(hint, string_string), &hint_is_string);
202 :
203 : // Slow-case with actual string comparisons.
204 112 : GotoIf(TaggedIsSmi(hint), &hint_is_invalid);
205 112 : GotoIfNot(IsString(hint), &hint_is_invalid);
206 : GotoIf(WordEqual(
207 : CallBuiltin(Builtins::kStringEqual, context, hint, number_string),
208 168 : TrueConstant()),
209 56 : &hint_is_number);
210 : GotoIf(WordEqual(
211 : CallBuiltin(Builtins::kStringEqual, context, hint, default_string),
212 168 : TrueConstant()),
213 56 : &hint_is_string);
214 : GotoIf(WordEqual(
215 : CallBuiltin(Builtins::kStringEqual, context, hint, string_string),
216 168 : TrueConstant()),
217 56 : &hint_is_string);
218 56 : Goto(&hint_is_invalid);
219 :
220 : // Use the OrdinaryToPrimitive builtin to convert to a Number.
221 56 : BIND(&hint_is_number);
222 : {
223 : Callable callable = CodeFactory::OrdinaryToPrimitive(
224 56 : isolate(), OrdinaryToPrimitiveHint::kNumber);
225 112 : Node* result = CallStub(callable, context, receiver);
226 56 : Return(result);
227 : }
228 :
229 : // Use the OrdinaryToPrimitive builtin to convert to a String.
230 56 : BIND(&hint_is_string);
231 : {
232 : Callable callable = CodeFactory::OrdinaryToPrimitive(
233 56 : isolate(), OrdinaryToPrimitiveHint::kString);
234 112 : Node* result = CallStub(callable, context, receiver);
235 56 : Return(result);
236 : }
237 :
238 : // Raise a TypeError if the {hint} is invalid.
239 56 : BIND(&hint_is_invalid);
240 56 : { ThrowTypeError(context, MessageTemplate::kInvalidHint, hint); }
241 :
242 : // Raise a TypeError if the {receiver} is not a JSReceiver instance.
243 56 : BIND(&receiver_is_invalid);
244 : {
245 : ThrowTypeError(context, MessageTemplate::kIncompatibleMethodReceiver,
246 : StringConstant("Date.prototype [ @@toPrimitive ]"),
247 112 : receiver);
248 56 : }
249 56 : }
250 :
251 : } // namespace internal
252 94089 : } // namespace v8
|