| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
| 9 #include "src/conversions.h" | 9 #include "src/conversions.h" |
| 10 #include "src/counters.h" | 10 #include "src/counters.h" |
| 11 #include "src/dateparser-inl.h" | 11 #include "src/dateparser-inl.h" |
| 12 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 // ----------------------------------------------------------------------------- | 17 // ----------------------------------------------------------------------------- |
| 18 // ES6 section 20.3 Date Objects | 18 // ES6 section 20.3 Date Objects |
| 19 | 19 |
| 20 class DateBuiltinsAssembler : public CodeStubAssembler { | |
| 21 public: | |
| 22 explicit DateBuiltinsAssembler(compiler::CodeAssemblerState* state) | |
| 23 : CodeStubAssembler(state) {} | |
| 24 | |
| 25 protected: | |
| 26 void Generate_DatePrototype_GetField(int field_index); | |
| 27 }; | |
| 28 | |
| 29 namespace { | 20 namespace { |
| 30 | 21 |
| 31 // ES6 section 20.3.1.1 Time Values and Time Range | 22 // ES6 section 20.3.1.1 Time Values and Time Range |
| 32 const double kMinYear = -1000000.0; | 23 const double kMinYear = -1000000.0; |
| 33 const double kMaxYear = -kMinYear; | 24 const double kMaxYear = -kMinYear; |
| 34 const double kMinMonth = -10000000.0; | 25 const double kMinMonth = -10000000.0; |
| 35 const double kMaxMonth = -kMinMonth; | 26 const double kMaxMonth = -kMinMonth; |
| 36 | 27 |
| 37 // 20.3.1.2 Day Number and Time within Day | 28 // 20.3.1.2 Day Number and Time within Day |
| 38 const double kMsPerDay = 86400000.0; | 29 const double kMsPerDay = 86400000.0; |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 Object::GetProperty(receiver_obj, name)); | 888 Object::GetProperty(receiver_obj, name)); |
| 898 if (!function->IsCallable()) { | 889 if (!function->IsCallable()) { |
| 899 THROW_NEW_ERROR_RETURN_FAILURE( | 890 THROW_NEW_ERROR_RETURN_FAILURE( |
| 900 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); | 891 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); |
| 901 } | 892 } |
| 902 RETURN_RESULT_OR_FAILURE( | 893 RETURN_RESULT_OR_FAILURE( |
| 903 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL)); | 894 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL)); |
| 904 } | 895 } |
| 905 } | 896 } |
| 906 | 897 |
| 907 void DateBuiltinsAssembler::Generate_DatePrototype_GetField(int field_index) { | |
| 908 Node* receiver = Parameter(0); | |
| 909 Node* context = Parameter(3); | |
| 910 | |
| 911 Label receiver_not_date(this, Label::kDeferred); | |
| 912 | |
| 913 GotoIf(TaggedIsSmi(receiver), &receiver_not_date); | |
| 914 Node* receiver_instance_type = LoadInstanceType(receiver); | |
| 915 GotoIf(Word32NotEqual(receiver_instance_type, Int32Constant(JS_DATE_TYPE)), | |
| 916 &receiver_not_date); | |
| 917 | |
| 918 // Load the specified date field, falling back to the runtime as necessary. | |
| 919 if (field_index == JSDate::kDateValue) { | |
| 920 Return(LoadObjectField(receiver, JSDate::kValueOffset)); | |
| 921 } else { | |
| 922 if (field_index < JSDate::kFirstUncachedField) { | |
| 923 Label stamp_mismatch(this, Label::kDeferred); | |
| 924 Node* date_cache_stamp = Load( | |
| 925 MachineType::AnyTagged(), | |
| 926 ExternalConstant(ExternalReference::date_cache_stamp(isolate()))); | |
| 927 | |
| 928 Node* cache_stamp = LoadObjectField(receiver, JSDate::kCacheStampOffset); | |
| 929 GotoIf(WordNotEqual(date_cache_stamp, cache_stamp), &stamp_mismatch); | |
| 930 Return(LoadObjectField( | |
| 931 receiver, JSDate::kValueOffset + field_index * kPointerSize)); | |
| 932 | |
| 933 Bind(&stamp_mismatch); | |
| 934 } | |
| 935 | |
| 936 Node* field_index_smi = SmiConstant(Smi::FromInt(field_index)); | |
| 937 Node* function = | |
| 938 ExternalConstant(ExternalReference::get_date_field_function(isolate())); | |
| 939 Node* result = CallCFunction2( | |
| 940 MachineType::AnyTagged(), MachineType::AnyTagged(), | |
| 941 MachineType::AnyTagged(), function, receiver, field_index_smi); | |
| 942 Return(result); | |
| 943 } | |
| 944 | |
| 945 // Raise a TypeError if the receiver is not a date. | |
| 946 Bind(&receiver_not_date); | |
| 947 { | |
| 948 CallRuntime(Runtime::kThrowNotDateError, context); | |
| 949 Unreachable(); | |
| 950 } | |
| 951 } | |
| 952 | |
| 953 TF_BUILTIN(DatePrototypeGetDate, DateBuiltinsAssembler) { | |
| 954 Generate_DatePrototype_GetField(JSDate::kDay); | |
| 955 } | |
| 956 | |
| 957 TF_BUILTIN(DatePrototypeGetDay, DateBuiltinsAssembler) { | |
| 958 Generate_DatePrototype_GetField(JSDate::kWeekday); | |
| 959 } | |
| 960 | |
| 961 TF_BUILTIN(DatePrototypeGetFullYear, DateBuiltinsAssembler) { | |
| 962 Generate_DatePrototype_GetField(JSDate::kYear); | |
| 963 } | |
| 964 | |
| 965 TF_BUILTIN(DatePrototypeGetHours, DateBuiltinsAssembler) { | |
| 966 Generate_DatePrototype_GetField(JSDate::kHour); | |
| 967 } | |
| 968 | |
| 969 TF_BUILTIN(DatePrototypeGetMilliseconds, DateBuiltinsAssembler) { | |
| 970 Generate_DatePrototype_GetField(JSDate::kMillisecond); | |
| 971 } | |
| 972 | |
| 973 TF_BUILTIN(DatePrototypeGetMinutes, DateBuiltinsAssembler) { | |
| 974 Generate_DatePrototype_GetField(JSDate::kMinute); | |
| 975 } | |
| 976 | |
| 977 TF_BUILTIN(DatePrototypeGetMonth, DateBuiltinsAssembler) { | |
| 978 Generate_DatePrototype_GetField(JSDate::kMonth); | |
| 979 } | |
| 980 | |
| 981 TF_BUILTIN(DatePrototypeGetSeconds, DateBuiltinsAssembler) { | |
| 982 Generate_DatePrototype_GetField(JSDate::kSecond); | |
| 983 } | |
| 984 | |
| 985 TF_BUILTIN(DatePrototypeGetTime, DateBuiltinsAssembler) { | |
| 986 Generate_DatePrototype_GetField(JSDate::kDateValue); | |
| 987 } | |
| 988 | |
| 989 TF_BUILTIN(DatePrototypeGetTimezoneOffset, DateBuiltinsAssembler) { | |
| 990 Generate_DatePrototype_GetField(JSDate::kTimezoneOffset); | |
| 991 } | |
| 992 | |
| 993 TF_BUILTIN(DatePrototypeGetUTCDate, DateBuiltinsAssembler) { | |
| 994 Generate_DatePrototype_GetField(JSDate::kDayUTC); | |
| 995 } | |
| 996 | |
| 997 TF_BUILTIN(DatePrototypeGetUTCDay, DateBuiltinsAssembler) { | |
| 998 Generate_DatePrototype_GetField(JSDate::kWeekdayUTC); | |
| 999 } | |
| 1000 | |
| 1001 TF_BUILTIN(DatePrototypeGetUTCFullYear, DateBuiltinsAssembler) { | |
| 1002 Generate_DatePrototype_GetField(JSDate::kYearUTC); | |
| 1003 } | |
| 1004 | |
| 1005 TF_BUILTIN(DatePrototypeGetUTCHours, DateBuiltinsAssembler) { | |
| 1006 Generate_DatePrototype_GetField(JSDate::kHourUTC); | |
| 1007 } | |
| 1008 | |
| 1009 TF_BUILTIN(DatePrototypeGetUTCMilliseconds, DateBuiltinsAssembler) { | |
| 1010 Generate_DatePrototype_GetField(JSDate::kMillisecondUTC); | |
| 1011 } | |
| 1012 | |
| 1013 TF_BUILTIN(DatePrototypeGetUTCMinutes, DateBuiltinsAssembler) { | |
| 1014 Generate_DatePrototype_GetField(JSDate::kMinuteUTC); | |
| 1015 } | |
| 1016 | |
| 1017 TF_BUILTIN(DatePrototypeGetUTCMonth, DateBuiltinsAssembler) { | |
| 1018 Generate_DatePrototype_GetField(JSDate::kMonthUTC); | |
| 1019 } | |
| 1020 | |
| 1021 TF_BUILTIN(DatePrototypeGetUTCSeconds, DateBuiltinsAssembler) { | |
| 1022 Generate_DatePrototype_GetField(JSDate::kSecondUTC); | |
| 1023 } | |
| 1024 | |
| 1025 TF_BUILTIN(DatePrototypeValueOf, DateBuiltinsAssembler) { | |
| 1026 Generate_DatePrototype_GetField(JSDate::kDateValue); | |
| 1027 } | |
| 1028 | |
| 1029 TF_BUILTIN(DatePrototypeToPrimitive, CodeStubAssembler) { | |
| 1030 Node* receiver = Parameter(0); | |
| 1031 Node* hint = Parameter(1); | |
| 1032 Node* context = Parameter(4); | |
| 1033 | |
| 1034 // Check if the {receiver} is actually a JSReceiver. | |
| 1035 Label receiver_is_invalid(this, Label::kDeferred); | |
| 1036 GotoIf(TaggedIsSmi(receiver), &receiver_is_invalid); | |
| 1037 GotoIfNot(IsJSReceiver(receiver), &receiver_is_invalid); | |
| 1038 | |
| 1039 // Dispatch to the appropriate OrdinaryToPrimitive builtin. | |
| 1040 Label hint_is_number(this), hint_is_string(this), | |
| 1041 hint_is_invalid(this, Label::kDeferred); | |
| 1042 | |
| 1043 // Fast cases for internalized strings. | |
| 1044 Node* number_string = LoadRoot(Heap::knumber_stringRootIndex); | |
| 1045 GotoIf(WordEqual(hint, number_string), &hint_is_number); | |
| 1046 Node* default_string = LoadRoot(Heap::kdefault_stringRootIndex); | |
| 1047 GotoIf(WordEqual(hint, default_string), &hint_is_string); | |
| 1048 Node* string_string = LoadRoot(Heap::kstring_stringRootIndex); | |
| 1049 GotoIf(WordEqual(hint, string_string), &hint_is_string); | |
| 1050 | |
| 1051 // Slow-case with actual string comparisons. | |
| 1052 Callable string_equal = CodeFactory::StringEqual(isolate()); | |
| 1053 GotoIf(TaggedIsSmi(hint), &hint_is_invalid); | |
| 1054 GotoIfNot(IsString(hint), &hint_is_invalid); | |
| 1055 GotoIf(WordEqual(CallStub(string_equal, context, hint, number_string), | |
| 1056 TrueConstant()), | |
| 1057 &hint_is_number); | |
| 1058 GotoIf(WordEqual(CallStub(string_equal, context, hint, default_string), | |
| 1059 TrueConstant()), | |
| 1060 &hint_is_string); | |
| 1061 GotoIf(WordEqual(CallStub(string_equal, context, hint, string_string), | |
| 1062 TrueConstant()), | |
| 1063 &hint_is_string); | |
| 1064 Goto(&hint_is_invalid); | |
| 1065 | |
| 1066 // Use the OrdinaryToPrimitive builtin to convert to a Number. | |
| 1067 Bind(&hint_is_number); | |
| 1068 { | |
| 1069 Callable callable = CodeFactory::OrdinaryToPrimitive( | |
| 1070 isolate(), OrdinaryToPrimitiveHint::kNumber); | |
| 1071 Node* result = CallStub(callable, context, receiver); | |
| 1072 Return(result); | |
| 1073 } | |
| 1074 | |
| 1075 // Use the OrdinaryToPrimitive builtin to convert to a String. | |
| 1076 Bind(&hint_is_string); | |
| 1077 { | |
| 1078 Callable callable = CodeFactory::OrdinaryToPrimitive( | |
| 1079 isolate(), OrdinaryToPrimitiveHint::kString); | |
| 1080 Node* result = CallStub(callable, context, receiver); | |
| 1081 Return(result); | |
| 1082 } | |
| 1083 | |
| 1084 // Raise a TypeError if the {hint} is invalid. | |
| 1085 Bind(&hint_is_invalid); | |
| 1086 { | |
| 1087 CallRuntime(Runtime::kThrowInvalidHint, context, hint); | |
| 1088 Unreachable(); | |
| 1089 } | |
| 1090 | |
| 1091 // Raise a TypeError if the {receiver} is not a JSReceiver instance. | |
| 1092 Bind(&receiver_is_invalid); | |
| 1093 { | |
| 1094 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, | |
| 1095 HeapConstant(factory()->NewStringFromAsciiChecked( | |
| 1096 "Date.prototype [ @@toPrimitive ]", TENURED)), | |
| 1097 receiver); | |
| 1098 Unreachable(); | |
| 1099 } | |
| 1100 } | |
| 1101 | |
| 1102 } // namespace internal | 898 } // namespace internal |
| 1103 } // namespace v8 | 899 } // namespace v8 |
| OLD | NEW |