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 |