• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_INL_H
17 #define ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_INL_H
18 
19 #include "ecmascript/interpreter/fast_runtime_stub.h"
20 
21 #include "ecmascript/global_dictionary-inl.h"
22 #include "ecmascript/global_env.h"
23 #include "ecmascript/interpreter/interpreter.h"
24 #include "ecmascript/js_function.h"
25 #include "ecmascript/js_proxy.h"
26 #include "ecmascript/js_tagged_value-inl.h"
27 #include "ecmascript/object_factory-inl.h"
28 #include "ecmascript/object_fast_operator-inl.h"
29 #include "ecmascript/runtime_call_id.h"
30 
31 namespace panda::ecmascript {
32 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
33 #define CHECK_IS_ON_PROTOTYPE_CHAIN(receiver, holder) \
34     if (UNLIKELY((receiver) != (holder))) {           \
35         return JSTaggedValue::Hole();                 \
36     }
37 
FastMul(JSTaggedValue left,JSTaggedValue right)38 JSTaggedValue FastRuntimeStub::FastMul(JSTaggedValue left, JSTaggedValue right)
39 {
40     if (left.IsNumber() && right.IsNumber()) {
41         return JSTaggedValue(left.GetNumber() * right.GetNumber());
42     }
43 
44     return JSTaggedValue::Hole();
45 }
46 
FastDiv(JSTaggedValue left,JSTaggedValue right)47 JSTaggedValue FastRuntimeStub::FastDiv(JSTaggedValue left, JSTaggedValue right)
48 {
49     if (left.IsNumber() && right.IsNumber()) {
50         double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
51         double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
52         if (UNLIKELY(dRight == 0.0)) {
53             if (dLeft == 0.0 || std::isnan(dLeft)) {
54                 return JSTaggedValue(base::NAN_VALUE);
55             }
56             uint64_t flagBit = ((bit_cast<uint64_t>(dLeft)) ^ (bit_cast<uint64_t>(dRight))) & base::DOUBLE_SIGN_MASK;
57             return JSTaggedValue(bit_cast<double>(flagBit ^ (bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
58         }
59         return JSTaggedValue(dLeft / dRight);
60     }
61     return JSTaggedValue::Hole();
62 }
63 
FastMod(JSTaggedValue left,JSTaggedValue right)64 JSTaggedValue FastRuntimeStub::FastMod(JSTaggedValue left, JSTaggedValue right)
65 {
66     if (right.IsInt() && left.IsInt()) {
67         int iRight = right.GetInt();
68         int iLeft = left.GetInt();
69         if (iRight > 0 && iLeft > 0) {
70             return JSTaggedValue(iLeft % iRight);
71         }
72     }
73     if (left.IsNumber() && right.IsNumber()) {
74         double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
75         double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
76         if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
77             return JSTaggedValue(base::NAN_VALUE);
78         }
79         if (dLeft == 0.0 || std::isinf(dRight)) {
80             return JSTaggedValue(dLeft);
81         }
82         return JSTaggedValue(std::fmod(dLeft, dRight));
83     }
84     return JSTaggedValue::Hole();
85 }
86 
FastEqual(JSTaggedValue left,JSTaggedValue right)87 JSTaggedValue FastRuntimeStub::FastEqual(JSTaggedValue left, JSTaggedValue right)
88 {
89     if (left == right) {
90         if (UNLIKELY(left.IsDouble())) {
91             return JSTaggedValue(!std::isnan(left.GetDouble()));
92         }
93         return JSTaggedValue::True();
94     }
95     if (left.IsNumber()) {
96         if (left.IsInt() && right.IsInt()) {
97             return JSTaggedValue::False();
98         }
99     }
100     if (right.IsUndefinedOrNull()) {
101         if (left.IsHeapObject()) {
102             return JSTaggedValue::False();
103         }
104         if (left.IsUndefinedOrNull()) {
105             return JSTaggedValue::True();
106         }
107     }
108     if (left.IsBoolean()) {
109         if (right.IsSpecial()) {
110             return JSTaggedValue::False();
111         }
112     }
113     if (left.IsBigInt() && right.IsBigInt()) {
114         return JSTaggedValue(BigInt::Equal(left, right));
115     }
116     return JSTaggedValue::Hole();
117 }
118 
FastStrictEqual(JSTaggedValue left,JSTaggedValue right)119 bool FastRuntimeStub::FastStrictEqual(JSTaggedValue left, JSTaggedValue right)
120 {
121     if (left.IsNumber()) {
122         if (right.IsNumber()) {
123             double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
124             double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
125             return JSTaggedValue::StrictNumberEquals(dLeft, dRight);
126         }
127         return false;
128     }
129     if (right.IsNumber()) {
130         return false;
131     }
132     if (left == right) {
133         return true;
134     }
135     if (left.IsString() && right.IsString()) {
136         return EcmaStringAccessor::StringsAreEqual(static_cast<EcmaString *>(left.GetTaggedObject()),
137                                                    static_cast<EcmaString *>(right.GetTaggedObject()));
138     }
139     if (left.IsBigInt()) {
140         if (right.IsBigInt()) {
141             return BigInt::Equal(left, right);
142         }
143         return false;
144     }
145     if (right.IsBigInt()) {
146         return false;
147     }
148     return false;
149 }
150 
CallGetter(JSThread * thread,JSTaggedValue receiver,JSTaggedValue holder,JSTaggedValue value)151 JSTaggedValue FastRuntimeStub::CallGetter(JSThread *thread, JSTaggedValue receiver, JSTaggedValue holder,
152                                           JSTaggedValue value)
153 {
154     return ObjectFastOperator::CallGetter(thread, receiver, holder, value);
155 }
156 
CallSetter(JSThread * thread,JSTaggedValue receiver,JSTaggedValue value,JSTaggedValue accessorValue)157 JSTaggedValue FastRuntimeStub::CallSetter(JSThread *thread, JSTaggedValue receiver, JSTaggedValue value,
158                                           JSTaggedValue accessorValue)
159 {
160     return ObjectFastOperator::CallSetter(thread, receiver, value, accessorValue);
161 }
162 
163 template<bool UseOwn>
GetPropertyByIndex(JSThread * thread,JSTaggedValue receiver,uint32_t index)164 JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index)
165 {
166     return ObjectFastOperator::GetPropertyByIndex<UseOwn>(thread, receiver, index);
167 }
168 
169 template<bool UseOwn>
GetPropertyByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)170 JSTaggedValue FastRuntimeStub::GetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
171 {
172     return ObjectFastOperator::GetPropertyByValue<UseOwn>(thread, receiver, key);
173 }
174 
175 template<bool UseOwn>
GetPropertyByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)176 JSTaggedValue FastRuntimeStub::GetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
177 {
178     return ObjectFastOperator::GetPropertyByName<UseOwn>(thread, receiver, key);
179 }
180 
181 template<bool UseOwn>
SetPropertyByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value)182 JSTaggedValue FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
183                                                  JSTaggedValue value)
184 {
185     return ObjectFastOperator::SetPropertyByName<UseOwn>(thread, receiver, key, value);
186 }
187 
188 template<bool UseOwn>
SetPropertyByIndex(JSThread * thread,JSTaggedValue receiver,uint32_t index,JSTaggedValue value)189 JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index,
190                                                   JSTaggedValue value)
191 {
192     return ObjectFastOperator::SetPropertyByIndex<UseOwn>(thread, receiver, index, value);
193 }
194 
195 template<bool UseOwn>
SetPropertyByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value)196 JSTaggedValue FastRuntimeStub::SetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
197                                                   JSTaggedValue value)
198 {
199     return ObjectFastOperator::SetPropertyByValue<UseOwn>(thread, receiver, key, value);
200 }
201 
GetGlobalOwnProperty(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)202 JSTaggedValue FastRuntimeStub::GetGlobalOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
203 {
204     JSObject *obj = JSObject::Cast(receiver);
205     TaggedArray *properties = TaggedArray::Cast(obj->GetProperties().GetTaggedObject());
206     GlobalDictionary *dict = GlobalDictionary::Cast(properties);
207     int entry = dict->FindEntry(key);
208     if (entry != -1) {
209         auto value = dict->GetValue(entry);
210         if (UNLIKELY(value.IsAccessor())) {
211             return CallGetter(thread, receiver, receiver, value);
212         }
213         ASSERT(!value.IsAccessor());
214         return value;
215     }
216     return JSTaggedValue::Hole();
217 }
218 
FastTypeOf(JSThread * thread,JSTaggedValue obj)219 JSTaggedValue FastRuntimeStub::FastTypeOf(JSThread *thread, JSTaggedValue obj)
220 {
221     INTERPRETER_TRACE(thread, FastTypeOf);
222     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
223     switch (obj.GetRawData()) {
224         case JSTaggedValue::VALUE_TRUE:
225         case JSTaggedValue::VALUE_FALSE:
226             return globalConst->GetBooleanString();
227         case JSTaggedValue::VALUE_NULL:
228             return globalConst->GetObjectString();
229         case JSTaggedValue::VALUE_UNDEFINED:
230             return globalConst->GetUndefinedString();
231         default:
232             if (obj.IsHeapObject()) {
233                 if (obj.IsString()) {
234                     return globalConst->GetStringString();
235                 }
236                 if (obj.IsSymbol()) {
237                     return globalConst->GetSymbolString();
238                 }
239                 if (obj.IsCallable()) {
240                     return globalConst->GetFunctionString();
241                 }
242                 if (obj.IsBigInt()) {
243                     return globalConst->GetBigIntString();
244                 }
245                 return globalConst->GetObjectString();
246             }
247             if (obj.IsNumber()) {
248                 return globalConst->GetNumberString();
249             }
250     }
251     return globalConst->GetUndefinedString();
252 }
253 
NewLexicalEnv(JSThread * thread,ObjectFactory * factory,uint16_t numVars)254 JSTaggedValue FastRuntimeStub::NewLexicalEnv(JSThread *thread, ObjectFactory *factory, uint16_t numVars)
255 {
256     INTERPRETER_TRACE(thread, NewLexicalEnv);
257     [[maybe_unused]] EcmaHandleScope handleScope(thread);
258     LexicalEnv *newEnv = factory->InlineNewLexicalEnv(numVars);
259     if (UNLIKELY(newEnv == nullptr)) {
260         return JSTaggedValue::Hole();
261     }
262     JSTaggedValue currentLexenv = thread->GetCurrentLexenv();
263     newEnv->SetParentEnv(thread, currentLexenv);
264     newEnv->SetScopeInfo(thread, JSTaggedValue::Hole());
265     return JSTaggedValue(newEnv);
266 }
267 
NewThisObject(JSThread * thread,JSTaggedValue ctor,JSTaggedValue newTarget,InterpretedFrame * state)268 JSTaggedValue FastRuntimeStub::NewThisObject(JSThread *thread, JSTaggedValue ctor, JSTaggedValue newTarget,
269                                              InterpretedFrame *state)
270 {
271     [[maybe_unused]] EcmaHandleScope handleScope(thread);
272     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
273 
274     JSHandle<JSFunction> ctorHandle(thread, ctor);
275     JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
276     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(ctorHandle, newTargetHandle);
277     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
278 
279     Method *method = Method::Cast(ctorHandle->GetMethod().GetTaggedObject());
280     state->function = ctorHandle.GetTaggedValue();
281     state->constpool = method->GetConstantPool();
282     state->profileTypeInfo = method->GetProfileTypeInfo();
283     state->env = ctorHandle->GetLexicalEnv();
284 
285     return obj.GetTaggedValue();
286 }
287 }  // namespace panda::ecmascript
288 #endif  // ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_INL_H
289