• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /**
3  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "plugins/ets/runtime/ets_class_linker_extension.h"
18 #include "plugins/ets/runtime/ets_stubs-inl.h"
19 #include "plugins/ets/runtime/types/ets_box_primitive.h"
20 #include "plugins/ets/runtime/types/ets_bigint.h"
21 
22 namespace ark::ets {
23 
24 template <typename T>
GetBoxedNumericValue(EtsClassLinkerExtension * ext,EtsObject * obj)25 static std::optional<T> GetBoxedNumericValue(EtsClassLinkerExtension *ext, EtsObject *obj)
26 {
27     auto *cls = obj->GetClass()->GetRuntimeClass();
28 
29     auto const getValue = [obj](auto typeId) {
30         using Type = typename decltype(typeId)::type;
31         return static_cast<T>(EtsBoxPrimitive<Type>::FromCoreType(obj)->GetValue());
32     };
33 
34     if (cls == ext->GetBoxDoubleClass()) {
35         return getValue(helpers::TypeIdentity<EtsDouble>());
36     }
37     if (cls == ext->GetBoxIntClass()) {
38         return getValue(helpers::TypeIdentity<EtsInt>());
39     }
40 
41     if (cls == ext->GetBoxByteClass()) {
42         return getValue(helpers::TypeIdentity<EtsByte>());
43     }
44     if (cls == ext->GetBoxShortClass()) {
45         return getValue(helpers::TypeIdentity<EtsShort>());
46     }
47     if (cls == ext->GetBoxLongClass()) {
48         return getValue(helpers::TypeIdentity<EtsLong>());
49     }
50     if (cls == ext->GetBoxFloatClass()) {
51         return getValue(helpers::TypeIdentity<EtsFloat>());
52     }
53     return std::nullopt;
54 }
55 
EtsBigIntEquality(EtsBigInt * obj1,EtsBigInt * obj2)56 static bool EtsBigIntEquality(EtsBigInt *obj1, EtsBigInt *obj2)
57 {
58     auto bytes1 = obj1->GetBytes();
59     auto bytes2 = obj2->GetBytes();
60     ASSERT(bytes1 != nullptr && bytes2 != nullptr);
61 
62     auto size1 = bytes1->GetActualLength();
63     auto size2 = bytes2->GetActualLength();
64     ASSERT(size1 != 0 && size2 != 0);
65     auto data1 = bytes1->GetData();
66     auto data2 = bytes2->GetData();
67     ASSERT(data1 != nullptr && data2 != nullptr);
68     ASSERT(data1->GetLength() >= size1 && data2->GetLength() >= size2);
69 
70     auto const readElem = [](auto *arr, uint32_t i) { return arr->Get(i)->GetValue(); };
71 
72     if (size1 != size2) {
73         return false;
74     }
75 
76     // start with check of MSD, which is sign.
77     for (int i = size1 - 1; i >= 0; --i) {
78         if (readElem(data1, i) != readElem(data2, i)) {
79             return false;
80         }
81     }
82     return true;
83 }
84 
85 template <typename BoxedType>
CompareBoxedPrimitive(EtsObject * obj1,EtsObject * obj2)86 static bool CompareBoxedPrimitive(EtsObject *obj1, EtsObject *obj2)
87 {
88     return EtsBoxPrimitive<BoxedType>::FromCoreType(obj1)->GetValue() ==
89            EtsBoxPrimitive<BoxedType>::FromCoreType(obj2)->GetValue();
90 }
91 
EtsValueTypedEquals(EtsCoroutine * coro,EtsObject * obj1,EtsObject * obj2)92 bool EtsValueTypedEquals(EtsCoroutine *coro, EtsObject *obj1, EtsObject *obj2)
93 {
94     auto ecls1 = obj1->GetClass();
95     auto ecls2 = obj2->GetClass();
96     auto cls1 = ecls1->GetRuntimeClass();
97     auto cls2 = ecls2->GetRuntimeClass();
98     ASSERT(ecls1->IsValueTyped() && ecls1->IsValueTyped());
99 
100     auto ext = coro->GetPandaVM()->GetClassLinker()->GetEtsClassLinkerExtension();
101 
102     if (cls1->IsStringClass()) {
103         return cls2->IsStringClass() &&
104                coretypes::String::Cast(obj1->GetCoreType())->Compare(coretypes::String::Cast(obj2->GetCoreType())) == 0;
105     }
106     if (cls1 == ext->GetBoxBooleanClass()) {
107         return cls2 == ext->GetBoxBooleanClass() && CompareBoxedPrimitive<EtsBoolean>(obj1, obj2);
108     }
109     if (cls1 == ext->GetBoxCharClass()) {
110         return cls2 == ext->GetBoxCharClass() && CompareBoxedPrimitive<EtsChar>(obj1, obj2);
111     }
112     if (UNLIKELY(cls1 == ext->GetBigIntClass())) {
113         return cls2 == ext->GetBigIntClass() &&
114                EtsBigIntEquality(EtsBigInt::FromEtsObject(obj1), EtsBigInt::FromEtsObject(obj2));
115     }
116     if (cls1 == ext->GetBoxLongClass() && cls2 == ext->GetBoxLongClass()) {
117         return CompareBoxedPrimitive<EtsLong>(obj1, obj2);
118     }
119     if (auto num1 = GetBoxedNumericValue<EtsDouble>(ext, obj1); num1.has_value()) {
120         auto num2 = GetBoxedNumericValue<EtsDouble>(ext, obj2);
121         return num2.has_value() && num2.value() == num1.value();
122     }
123     UNREACHABLE();
124 }
125 
126 }  // namespace ark::ets
127