OLD | NEW |
(Empty) | |
| 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 : CodeStubAssembler(state) {} |
| 19 |
| 20 protected: |
| 21 void Generate_DatePrototype_GetField(int field_index); |
| 22 }; |
| 23 |
| 24 void DateBuiltinsAssembler::Generate_DatePrototype_GetField(int field_index) { |
| 25 Node* receiver = Parameter(0); |
| 26 Node* context = Parameter(3); |
| 27 |
| 28 Label receiver_not_date(this, Label::kDeferred); |
| 29 |
| 30 GotoIf(TaggedIsSmi(receiver), &receiver_not_date); |
| 31 Node* receiver_instance_type = LoadInstanceType(receiver); |
| 32 GotoIf(Word32NotEqual(receiver_instance_type, Int32Constant(JS_DATE_TYPE)), |
| 33 &receiver_not_date); |
| 34 |
| 35 // Load the specified date field, falling back to the runtime as necessary. |
| 36 if (field_index == JSDate::kDateValue) { |
| 37 Return(LoadObjectField(receiver, JSDate::kValueOffset)); |
| 38 } else { |
| 39 if (field_index < JSDate::kFirstUncachedField) { |
| 40 Label stamp_mismatch(this, Label::kDeferred); |
| 41 Node* date_cache_stamp = Load( |
| 42 MachineType::AnyTagged(), |
| 43 ExternalConstant(ExternalReference::date_cache_stamp(isolate()))); |
| 44 |
| 45 Node* cache_stamp = LoadObjectField(receiver, JSDate::kCacheStampOffset); |
| 46 GotoIf(WordNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch); |
| 47 Return(LoadObjectField( |
| 48 receiver, JSDate::kValueOffset + field_index * kPointerSize)); |
| 49 |
| 50 Bind(&stamp_mismatch); |
| 51 } |
| 52 |
| 53 Node* field_index_smi = SmiConstant(Smi::FromInt(field_index)); |
| 54 Node* function = |
| 55 ExternalConstant(ExternalReference::get_date_field_function(isolate())); |
| 56 Node* result = CallCFunction2( |
| 57 MachineType::AnyTagged(), MachineType::AnyTagged(), |
| 58 MachineType::AnyTagged(), function, receiver, field_index_smi); |
| 59 Return(result); |
| 60 } |
| 61 |
| 62 // Raise a TypeError if the receiver is not a date. |
| 63 Bind(&receiver_not_date); |
| 64 { |
| 65 CallRuntime(Runtime::kThrowNotDateError, context); |
| 66 Unreachable(); |
| 67 } |
| 68 } |
| 69 |
| 70 TF_BUILTIN(DatePrototypeGetDate, DateBuiltinsAssembler) { |
| 71 Generate_DatePrototype_GetField(JSDate::kDay); |
| 72 } |
| 73 |
| 74 TF_BUILTIN(DatePrototypeGetDay, DateBuiltinsAssembler) { |
| 75 Generate_DatePrototype_GetField(JSDate::kWeekday); |
| 76 } |
| 77 |
| 78 TF_BUILTIN(DatePrototypeGetFullYear, DateBuiltinsAssembler) { |
| 79 Generate_DatePrototype_GetField(JSDate::kYear); |
| 80 } |
| 81 |
| 82 TF_BUILTIN(DatePrototypeGetHours, DateBuiltinsAssembler) { |
| 83 Generate_DatePrototype_GetField(JSDate::kHour); |
| 84 } |
| 85 |
| 86 TF_BUILTIN(DatePrototypeGetMilliseconds, DateBuiltinsAssembler) { |
| 87 Generate_DatePrototype_GetField(JSDate::kMillisecond); |
| 88 } |
| 89 |
| 90 TF_BUILTIN(DatePrototypeGetMinutes, DateBuiltinsAssembler) { |
| 91 Generate_DatePrototype_GetField(JSDate::kMinute); |
| 92 } |
| 93 |
| 94 TF_BUILTIN(DatePrototypeGetMonth, DateBuiltinsAssembler) { |
| 95 Generate_DatePrototype_GetField(JSDate::kMonth); |
| 96 } |
| 97 |
| 98 TF_BUILTIN(DatePrototypeGetSeconds, DateBuiltinsAssembler) { |
| 99 Generate_DatePrototype_GetField(JSDate::kSecond); |
| 100 } |
| 101 |
| 102 TF_BUILTIN(DatePrototypeGetTime, DateBuiltinsAssembler) { |
| 103 Generate_DatePrototype_GetField(JSDate::kDateValue); |
| 104 } |
| 105 |
| 106 TF_BUILTIN(DatePrototypeGetTimezoneOffset, DateBuiltinsAssembler) { |
| 107 Generate_DatePrototype_GetField(JSDate::kTimezoneOffset); |
| 108 } |
| 109 |
| 110 TF_BUILTIN(DatePrototypeGetUTCDate, DateBuiltinsAssembler) { |
| 111 Generate_DatePrototype_GetField(JSDate::kDayUTC); |
| 112 } |
| 113 |
| 114 TF_BUILTIN(DatePrototypeGetUTCDay, DateBuiltinsAssembler) { |
| 115 Generate_DatePrototype_GetField(JSDate::kWeekdayUTC); |
| 116 } |
| 117 |
| 118 TF_BUILTIN(DatePrototypeGetUTCFullYear, DateBuiltinsAssembler) { |
| 119 Generate_DatePrototype_GetField(JSDate::kYearUTC); |
| 120 } |
| 121 |
| 122 TF_BUILTIN(DatePrototypeGetUTCHours, DateBuiltinsAssembler) { |
| 123 Generate_DatePrototype_GetField(JSDate::kHourUTC); |
| 124 } |
| 125 |
| 126 TF_BUILTIN(DatePrototypeGetUTCMilliseconds, DateBuiltinsAssembler) { |
| 127 Generate_DatePrototype_GetField(JSDate::kMillisecondUTC); |
| 128 } |
| 129 |
| 130 TF_BUILTIN(DatePrototypeGetUTCMinutes, DateBuiltinsAssembler) { |
| 131 Generate_DatePrototype_GetField(JSDate::kMinuteUTC); |
| 132 } |
| 133 |
| 134 TF_BUILTIN(DatePrototypeGetUTCMonth, DateBuiltinsAssembler) { |
| 135 Generate_DatePrototype_GetField(JSDate::kMonthUTC); |
| 136 } |
| 137 |
| 138 TF_BUILTIN(DatePrototypeGetUTCSeconds, DateBuiltinsAssembler) { |
| 139 Generate_DatePrototype_GetField(JSDate::kSecondUTC); |
| 140 } |
| 141 |
| 142 TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) { |
| 143 Generate_DatePrototype_GetField(JSDate::kDateValue); |
| 144 } |
| 145 |
| 146 TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { |
| 147 Node* receiver = Parameter(0); |
| 148 Node* hint = Parameter(1); |
| 149 Node* context = Parameter(4); |
| 150 |
| 151 // Check if the {receiver} is actually a JSReceiver. |
| 152 Label receiver_is_invalid(this, Label::kDeferred); |
| 153 GotoIf(TaggedIsSmi(receiver), &receiver_is_invalid); |
| 154 GotoIfNot(IsJSReceiver(receiver), &receiver_is_invalid); |
| 155 |
| 156 // Dispatch to the appropriate OrdinaryToPrimitive builtin. |
| 157 Label hint_is_number(this), hint_is_string(this), |
| 158 hint_is_invalid(this, Label::kDeferred); |
| 159 |
| 160 // Fast cases for internalized strings. |
| 161 Node* number_string = LoadRoot(Heap::knumber_stringRootIndex); |
| 162 GotoIf(WordEqual(hint, number_string), &hint_is_number); |
| 163 Node* default_string = LoadRoot(Heap::kdefault_stringRootIndex); |
| 164 GotoIf(WordEqual(hint, default_string), &hint_is_string); |
| 165 Node* string_string = LoadRoot(Heap::kstring_stringRootIndex); |
| 166 GotoIf(WordEqual(hint, string_string), &hint_is_string); |
| 167 |
| 168 // Slow-case with actual string comparisons. |
| 169 Callable string_equal = CodeFactory::StringEqual(isolate()); |
| 170 GotoIf(TaggedIsSmi(hint), &hint_is_invalid); |
| 171 GotoIfNot(IsString(hint), &hint_is_invalid); |
| 172 GotoIf(WordEqual(CallStub(string_equal, context, hint, number_string), |
| 173 TrueConstant()), |
| 174 &hint_is_number); |
| 175 GotoIf(WordEqual(CallStub(string_equal, context, hint, default_string), |
| 176 TrueConstant()), |
| 177 &hint_is_string); |
| 178 GotoIf(WordEqual(CallStub(string_equal, context, hint, string_string), |
| 179 TrueConstant()), |
| 180 &hint_is_string); |
| 181 Goto(&hint_is_invalid); |
| 182 |
| 183 // Use the OrdinaryToPrimitive builtin to convert to a Number. |
| 184 Bind(&hint_is_number); |
| 185 { |
| 186 Callable callable = CodeFactory::OrdinaryToPrimitive( |
| 187 isolate(), OrdinaryToPrimitiveHint::kNumber); |
| 188 Node* result = CallStub(callable, context, receiver); |
| 189 Return(result); |
| 190 } |
| 191 |
| 192 // Use the OrdinaryToPrimitive builtin to convert to a String. |
| 193 Bind(&hint_is_string); |
| 194 { |
| 195 Callable callable = CodeFactory::OrdinaryToPrimitive( |
| 196 isolate(), OrdinaryToPrimitiveHint::kString); |
| 197 Node* result = CallStub(callable, context, receiver); |
| 198 Return(result); |
| 199 } |
| 200 |
| 201 // Raise a TypeError if the {hint} is invalid. |
| 202 Bind(&hint_is_invalid); |
| 203 { |
| 204 CallRuntime(Runtime::kThrowInvalidHint, context, hint); |
| 205 Unreachable(); |
| 206 } |
| 207 |
| 208 // Raise a TypeError if the {receiver} is not a JSReceiver instance. |
| 209 Bind(&receiver_is_invalid); |
| 210 { |
| 211 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, |
| 212 HeapConstant(factory()->NewStringFromAsciiChecked( |
| 213 "Date.prototype [ @@toPrimitive ]", TENURED)), |
| 214 receiver); |
| 215 Unreachable(); |
| 216 } |
| 217 } |
| 218 |
| 219 } // namespace internal |
| 220 } // namespace v8 |
OLD | NEW |