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 1064 : 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 2128 : 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 2128 : GotoIfNot(InstanceTypeEqual(receiver_instance_type, JS_DATE_TYPE),
33 1064 : &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 392 : 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 392 : 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 = CallCFunction(
57 : function, MachineType::AnyTagged(),
58 : std::make_pair(MachineType::AnyTagged(), receiver),
59 952 : std::make_pair(MachineType::AnyTagged(), field_index_smi));
60 952 : Return(result);
61 : }
62 :
63 : // Raise a TypeError if the receiver is not a date.
64 1064 : BIND(&receiver_not_date);
65 1064 : { ThrowTypeError(context, MessageTemplate::kNotDateObject); }
66 1064 : }
67 :
68 224 : TF_BUILTIN(DatePrototypeGetDate, DateBuiltinsAssembler) {
69 : Node* context = Parameter(Descriptor::kContext);
70 : Node* receiver = Parameter(Descriptor::kReceiver);
71 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDay);
72 56 : }
73 :
74 224 : TF_BUILTIN(DatePrototypeGetDay, DateBuiltinsAssembler) {
75 : Node* context = Parameter(Descriptor::kContext);
76 : Node* receiver = Parameter(Descriptor::kReceiver);
77 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekday);
78 56 : }
79 :
80 224 : TF_BUILTIN(DatePrototypeGetFullYear, DateBuiltinsAssembler) {
81 : Node* context = Parameter(Descriptor::kContext);
82 : Node* receiver = Parameter(Descriptor::kReceiver);
83 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kYear);
84 56 : }
85 :
86 224 : TF_BUILTIN(DatePrototypeGetHours, DateBuiltinsAssembler) {
87 : Node* context = Parameter(Descriptor::kContext);
88 : Node* receiver = Parameter(Descriptor::kReceiver);
89 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kHour);
90 56 : }
91 :
92 224 : TF_BUILTIN(DatePrototypeGetMilliseconds, DateBuiltinsAssembler) {
93 : Node* context = Parameter(Descriptor::kContext);
94 : Node* receiver = Parameter(Descriptor::kReceiver);
95 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecond);
96 56 : }
97 :
98 224 : TF_BUILTIN(DatePrototypeGetMinutes, DateBuiltinsAssembler) {
99 : Node* context = Parameter(Descriptor::kContext);
100 : Node* receiver = Parameter(Descriptor::kReceiver);
101 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMinute);
102 56 : }
103 :
104 224 : TF_BUILTIN(DatePrototypeGetMonth, DateBuiltinsAssembler) {
105 : Node* context = Parameter(Descriptor::kContext);
106 : Node* receiver = Parameter(Descriptor::kReceiver);
107 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMonth);
108 56 : }
109 :
110 224 : TF_BUILTIN(DatePrototypeGetSeconds, DateBuiltinsAssembler) {
111 : Node* context = Parameter(Descriptor::kContext);
112 : Node* receiver = Parameter(Descriptor::kReceiver);
113 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kSecond);
114 56 : }
115 :
116 224 : TF_BUILTIN(DatePrototypeGetTime, DateBuiltinsAssembler) {
117 : Node* context = Parameter(Descriptor::kContext);
118 : Node* receiver = Parameter(Descriptor::kReceiver);
119 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDateValue);
120 56 : }
121 :
122 224 : TF_BUILTIN(DatePrototypeGetTimezoneOffset, DateBuiltinsAssembler) {
123 : Node* context = Parameter(Descriptor::kContext);
124 : Node* receiver = Parameter(Descriptor::kReceiver);
125 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kTimezoneOffset);
126 56 : }
127 :
128 224 : TF_BUILTIN(DatePrototypeGetUTCDate, DateBuiltinsAssembler) {
129 : Node* context = Parameter(Descriptor::kContext);
130 : Node* receiver = Parameter(Descriptor::kReceiver);
131 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDayUTC);
132 56 : }
133 :
134 224 : TF_BUILTIN(DatePrototypeGetUTCDay, DateBuiltinsAssembler) {
135 : Node* context = Parameter(Descriptor::kContext);
136 : Node* receiver = Parameter(Descriptor::kReceiver);
137 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kWeekdayUTC);
138 56 : }
139 :
140 224 : TF_BUILTIN(DatePrototypeGetUTCFullYear, DateBuiltinsAssembler) {
141 : Node* context = Parameter(Descriptor::kContext);
142 : Node* receiver = Parameter(Descriptor::kReceiver);
143 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kYearUTC);
144 56 : }
145 :
146 224 : TF_BUILTIN(DatePrototypeGetUTCHours, DateBuiltinsAssembler) {
147 : Node* context = Parameter(Descriptor::kContext);
148 : Node* receiver = Parameter(Descriptor::kReceiver);
149 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kHourUTC);
150 56 : }
151 :
152 224 : TF_BUILTIN(DatePrototypeGetUTCMilliseconds, DateBuiltinsAssembler) {
153 : Node* context = Parameter(Descriptor::kContext);
154 : Node* receiver = Parameter(Descriptor::kReceiver);
155 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMillisecondUTC);
156 56 : }
157 :
158 224 : TF_BUILTIN(DatePrototypeGetUTCMinutes, DateBuiltinsAssembler) {
159 : Node* context = Parameter(Descriptor::kContext);
160 : Node* receiver = Parameter(Descriptor::kReceiver);
161 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMinuteUTC);
162 56 : }
163 :
164 224 : TF_BUILTIN(DatePrototypeGetUTCMonth, DateBuiltinsAssembler) {
165 : Node* context = Parameter(Descriptor::kContext);
166 : Node* receiver = Parameter(Descriptor::kReceiver);
167 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kMonthUTC);
168 56 : }
169 :
170 224 : TF_BUILTIN(DatePrototypeGetUTCSeconds, DateBuiltinsAssembler) {
171 : Node* context = Parameter(Descriptor::kContext);
172 : Node* receiver = Parameter(Descriptor::kReceiver);
173 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kSecondUTC);
174 56 : }
175 :
176 224 : TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) {
177 : Node* context = Parameter(Descriptor::kContext);
178 : Node* receiver = Parameter(Descriptor::kReceiver);
179 56 : Generate_DatePrototype_GetField(context, receiver, JSDate::kDateValue);
180 56 : }
181 :
182 168 : TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) {
183 : Node* context = Parameter(Descriptor::kContext);
184 : Node* receiver = Parameter(Descriptor::kReceiver);
185 : Node* hint = Parameter(Descriptor::kHint);
186 :
187 : // Check if the {receiver} is actually a JSReceiver.
188 56 : Label receiver_is_invalid(this, Label::kDeferred);
189 112 : GotoIf(TaggedIsSmi(receiver), &receiver_is_invalid);
190 112 : GotoIfNot(IsJSReceiver(receiver), &receiver_is_invalid);
191 :
192 : // Dispatch to the appropriate OrdinaryToPrimitive builtin.
193 56 : Label hint_is_number(this), hint_is_string(this),
194 56 : hint_is_invalid(this, Label::kDeferred);
195 :
196 : // Fast cases for internalized strings.
197 112 : Node* number_string = LoadRoot(RootIndex::knumber_string);
198 112 : GotoIf(WordEqual(hint, number_string), &hint_is_number);
199 112 : Node* default_string = LoadRoot(RootIndex::kdefault_string);
200 112 : GotoIf(WordEqual(hint, default_string), &hint_is_string);
201 112 : Node* string_string = LoadRoot(RootIndex::kstring_string);
202 112 : GotoIf(WordEqual(hint, string_string), &hint_is_string);
203 :
204 : // Slow-case with actual string comparisons.
205 112 : GotoIf(TaggedIsSmi(hint), &hint_is_invalid);
206 112 : GotoIfNot(IsString(hint), &hint_is_invalid);
207 56 : GotoIf(WordEqual(
208 : CallBuiltin(Builtins::kStringEqual, context, hint, number_string),
209 168 : TrueConstant()),
210 56 : &hint_is_number);
211 56 : GotoIf(WordEqual(
212 : CallBuiltin(Builtins::kStringEqual, context, hint, default_string),
213 168 : TrueConstant()),
214 56 : &hint_is_string);
215 56 : GotoIf(WordEqual(
216 : CallBuiltin(Builtins::kStringEqual, context, hint, string_string),
217 168 : TrueConstant()),
218 56 : &hint_is_string);
219 56 : Goto(&hint_is_invalid);
220 :
221 : // Use the OrdinaryToPrimitive builtin to convert to a Number.
222 56 : BIND(&hint_is_number);
223 : {
224 : Callable callable = CodeFactory::OrdinaryToPrimitive(
225 56 : isolate(), OrdinaryToPrimitiveHint::kNumber);
226 112 : Node* result = CallStub(callable, context, receiver);
227 56 : Return(result);
228 : }
229 :
230 : // Use the OrdinaryToPrimitive builtin to convert to a String.
231 56 : BIND(&hint_is_string);
232 : {
233 : Callable callable = CodeFactory::OrdinaryToPrimitive(
234 56 : isolate(), OrdinaryToPrimitiveHint::kString);
235 112 : Node* result = CallStub(callable, context, receiver);
236 56 : Return(result);
237 : }
238 :
239 : // Raise a TypeError if the {hint} is invalid.
240 56 : BIND(&hint_is_invalid);
241 56 : { ThrowTypeError(context, MessageTemplate::kInvalidHint, hint); }
242 :
243 : // Raise a TypeError if the {receiver} is not a JSReceiver instance.
244 56 : BIND(&receiver_is_invalid);
245 : {
246 : ThrowTypeError(context, MessageTemplate::kIncompatibleMethodReceiver,
247 112 : StringConstant("Date.prototype [ @@toPrimitive ]"),
248 56 : receiver);
249 : }
250 56 : }
251 :
252 : } // namespace internal
253 59480 : } // namespace v8
|