• 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/ecma_string-inl.h"
22 #include "ecmascript/global_dictionary-inl.h"
23 #include "ecmascript/global_env.h"
24 #include "ecmascript/interpreter/interpreter.h"
25 #include "ecmascript/js_function.h"
26 #include "ecmascript/js_proxy.h"
27 #include "ecmascript/js_tagged_value-inl.h"
28 #include "ecmascript/object_factory-inl.h"
29 #include "ecmascript/object_fast_operator-inl.h"
30 #include "ecmascript/runtime_call_id.h"
31 
32 namespace panda::ecmascript {
33 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
34 #define CHECK_IS_ON_PROTOTYPE_CHAIN(receiver, holder) \
35     if (UNLIKELY((receiver) != (holder))) {           \
36         return JSTaggedValue::Hole();                 \
37     }
38 
FastMul(JSTaggedValue left,JSTaggedValue right)39 JSTaggedValue FastRuntimeStub::FastMul(JSTaggedValue left, JSTaggedValue right)
40 {
41     if (left.IsNumber() && right.IsNumber()) {
42         return JSTaggedValue(left.GetNumber() * right.GetNumber());
43     }
44 
45     return JSTaggedValue::Hole();
46 }
47 
FastDiv(JSTaggedValue left,JSTaggedValue right)48 JSTaggedValue FastRuntimeStub::FastDiv(JSTaggedValue left, JSTaggedValue right)
49 {
50     if (left.IsNumber() && right.IsNumber()) {
51         double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
52         double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
53         if (UNLIKELY(dRight == 0.0)) {
54             if (dLeft == 0.0 || std::isnan(dLeft)) {
55                 return JSTaggedValue(base::NAN_VALUE);
56             }
57             uint64_t flagBit = ((base::bit_cast<uint64_t>(dLeft)) ^ (base::bit_cast<uint64_t>(dRight))) &
58                                base::DOUBLE_SIGN_MASK;
59             return JSTaggedValue(base::bit_cast<double>(
60                 flagBit ^ (base::bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
61         }
62         return JSTaggedValue(dLeft / dRight);
63     }
64     return JSTaggedValue::Hole();
65 }
66 
FastMod(JSTaggedValue left,JSTaggedValue right)67 JSTaggedValue FastRuntimeStub::FastMod(JSTaggedValue left, JSTaggedValue right)
68 {
69     if (right.IsInt() && left.IsInt()) {
70         int iRight = right.GetInt();
71         int iLeft = left.GetInt();
72         if (iRight > 0 && iLeft > 0) {
73             return JSTaggedValue(iLeft % iRight);
74         }
75     }
76     if (left.IsNumber() && right.IsNumber()) {
77         double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
78         double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
79         if (dRight == 0.0 || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
80             return JSTaggedValue(base::NAN_VALUE);
81         }
82         if (dLeft == 0.0 || std::isinf(dRight)) {
83             return JSTaggedValue(dLeft);
84         }
85         return JSTaggedValue(std::fmod(dLeft, dRight));
86     }
87     return JSTaggedValue::Hole();
88 }
89 
FastEqual(JSTaggedValue left,JSTaggedValue right)90 JSTaggedValue FastRuntimeStub::FastEqual(JSTaggedValue left, JSTaggedValue right)
91 {
92     if (left == right) {
93         if (UNLIKELY(left.IsDouble())) {
94             return JSTaggedValue(!std::isnan(left.GetDouble()));
95         }
96         return JSTaggedValue::True();
97     }
98     if (left.IsNumber()) {
99         if (left.IsInt() && right.IsInt()) {
100             return JSTaggedValue::False();
101         }
102     }
103     if (right.IsUndefinedOrNull()) {
104         if (left.IsUndefinedOrNull()) {
105             return JSTaggedValue::True();
106         }
107         return JSTaggedValue::False();
108     }
109     if (left.IsUndefinedOrNull()) {
110         return JSTaggedValue::False();
111     }
112     if (left.IsBoolean()) {
113         if (right.IsSpecial()) {
114             return JSTaggedValue::False();
115         }
116     }
117     if (left.IsBigInt() && right.IsBigInt()) {
118         return JSTaggedValue(BigInt::Equal(left, right));
119     }
120     return JSTaggedValue::Hole();
121 }
122 
FastStrictEqual(JSThread * thread,JSTaggedValue left,JSTaggedValue right)123 JSTaggedValue FastRuntimeStub::FastStrictEqual(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
124 {
125     if (left.IsNumber()) {
126         if (right.IsNumber()) {
127             double dLeft = left.IsInt() ? left.GetInt() : left.GetDouble();
128             double dRight = right.IsInt() ? right.GetInt() : right.GetDouble();
129             return JSTaggedValue::StrictNumberEquals(dLeft, dRight) ? JSTaggedValue::True() : JSTaggedValue::False();
130         }
131         return JSTaggedValue::False();
132     }
133     if (right.IsNumber()) {
134         return JSTaggedValue::False();
135     }
136     if (left == right) {
137         return JSTaggedValue::True();
138     }
139     if (left.IsString() && right.IsString()) {
140         auto leftStr = static_cast<EcmaString *>(left.GetTaggedObject());
141         auto rightStr = static_cast<EcmaString *>(right.GetTaggedObject());
142         if (EcmaStringAccessor(leftStr).IsFlat(thread) && EcmaStringAccessor(rightStr).IsFlat(thread)) {
143             return EcmaStringAccessor::StringsAreEqual(thread,
144                                                        static_cast<EcmaString *>(left.GetTaggedObject()),
145                                                        static_cast<EcmaString *>(right.GetTaggedObject())) ?
146                 JSTaggedValue::True() : JSTaggedValue::False();
147         }
148         return JSTaggedValue::Hole();
149     }
150     if (left.IsBigInt()) {
151         if (right.IsBigInt()) {
152             return BigInt::Equal(left, right) ? JSTaggedValue::True() : JSTaggedValue::False();
153         }
154         return JSTaggedValue::False();
155     }
156     if (right.IsBigInt()) {
157         return JSTaggedValue::False();
158     }
159     return JSTaggedValue::False();
160 }
161 
CallGetter(JSThread * thread,JSTaggedValue receiver,JSTaggedValue holder,JSTaggedValue value)162 JSTaggedValue FastRuntimeStub::CallGetter(JSThread *thread, JSTaggedValue receiver, JSTaggedValue holder,
163                                           JSTaggedValue value)
164 {
165     return ObjectFastOperator::CallGetter(thread, receiver, holder, value);
166 }
167 
CallSetter(JSThread * thread,JSTaggedValue receiver,JSTaggedValue value,JSTaggedValue accessorValue)168 JSTaggedValue FastRuntimeStub::CallSetter(JSThread *thread, JSTaggedValue receiver, JSTaggedValue value,
169                                           JSTaggedValue accessorValue)
170 {
171     return ObjectFastOperator::CallSetter(thread, receiver, value, accessorValue);
172 }
173 
174 template<ObjectFastOperator::Status status>
GetPropertyByIndex(JSThread * thread,JSTaggedValue receiver,uint32_t index)175 JSTaggedValue FastRuntimeStub::GetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index)
176 {
177     return ObjectFastOperator::GetPropertyByIndex<status>(thread, receiver, index);
178 }
179 
180 template<ObjectFastOperator::Status status>
GetPropertyByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)181 JSTaggedValue FastRuntimeStub::GetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
182 {
183     return ObjectFastOperator::GetPropertyByValue<status>(thread, receiver, key);
184 }
185 
186 template<ObjectFastOperator::Status status>
GetPropertyByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)187 JSTaggedValue FastRuntimeStub::GetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
188 {
189     return ObjectFastOperator::GetPropertyByName<status>(thread, receiver, key);
190 }
191 
192 template<ObjectFastOperator::Status status>
SetPropertyByName(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value)193 JSTaggedValue FastRuntimeStub::SetPropertyByName(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
194                                                  JSTaggedValue value)
195 {
196     [[maybe_unused]] EcmaHandleScope handleScope(thread);
197     return ObjectFastOperator::SetPropertyByName<status>(thread, receiver, key, value);
198 }
199 
200 template<ObjectFastOperator::Status status>
SetPropertyByIndex(JSThread * thread,JSTaggedValue receiver,uint32_t index,JSTaggedValue value)201 JSTaggedValue FastRuntimeStub::SetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index,
202                                                   JSTaggedValue value)
203 {
204     [[maybe_unused]] EcmaHandleScope handleScope(thread);
205     return ObjectFastOperator::SetPropertyByIndex<status>(thread, receiver, index, value);
206 }
207 
208 template<ObjectFastOperator::Status status>
SetPropertyByValue(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key,JSTaggedValue value)209 JSTaggedValue FastRuntimeStub::SetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key,
210                                                   JSTaggedValue value)
211 {
212     [[maybe_unused]] EcmaHandleScope handleScope(thread);
213     return ObjectFastOperator::SetPropertyByValue<status>(thread, receiver, key, value);
214 }
215 
GetGlobalOwnProperty(JSThread * thread,JSTaggedValue receiver,JSTaggedValue key)216 JSTaggedValue FastRuntimeStub::GetGlobalOwnProperty(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key)
217 {
218     JSObject *obj = JSObject::Cast(receiver);
219     TaggedArray *properties = TaggedArray::Cast(obj->GetProperties(thread).GetTaggedObject());
220     GlobalDictionary *dict = GlobalDictionary::Cast(properties);
221     int entry = dict->FindEntry(thread, key);
222     if (entry != -1) {
223         auto value = dict->GetValue(thread, entry);
224         if (UNLIKELY(value.IsAccessor())) {
225             return CallGetter(thread, receiver, receiver, value);
226         }
227         ASSERT(!value.IsAccessor());
228         return value;
229     }
230     return JSTaggedValue::Hole();
231 }
232 
FastTypeOf(JSThread * thread,JSTaggedValue obj)233 JSTaggedValue FastRuntimeStub::FastTypeOf(JSThread *thread, JSTaggedValue obj)
234 {
235     INTERPRETER_TRACE(thread, FastTypeOf);
236     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
237     switch (obj.GetRawData()) {
238         case JSTaggedValue::VALUE_TRUE:
239         case JSTaggedValue::VALUE_FALSE:
240             return globalConst->GetBooleanString();
241         case JSTaggedValue::VALUE_NULL:
242             return globalConst->GetObjectString();
243         case JSTaggedValue::VALUE_UNDEFINED:
244             return globalConst->GetUndefinedString();
245         default:
246             if (obj.IsHeapObject()) {
247                 if (obj.IsString()) {
248                     return globalConst->GetStringString();
249                 }
250                 if (obj.IsSymbol()) {
251                     return globalConst->GetSymbolString();
252                 }
253                 if (obj.IsCallable()) {
254                     return globalConst->GetFunctionString();
255                 }
256                 if (obj.IsBigInt()) {
257                     return globalConst->GetBigIntString();
258                 }
259                 if (obj.IsNativeModuleFailureInfo()) {
260                     return globalConst->GetNativeModuleFailureInfoString();
261                 }
262                 return globalConst->GetObjectString();
263             }
264             if (obj.IsNumber()) {
265                 return globalConst->GetNumberString();
266             }
267     }
268     return globalConst->GetUndefinedString();
269 }
270 
NewLexicalEnv(JSThread * thread,ObjectFactory * factory,uint16_t numVars)271 JSTaggedValue FastRuntimeStub::NewLexicalEnv(JSThread *thread, ObjectFactory *factory, uint16_t numVars)
272 {
273     INTERPRETER_TRACE(thread, NewLexicalEnv);
274     [[maybe_unused]] EcmaHandleScope handleScope(thread);
275     LexicalEnv *newEnv = factory->InlineNewLexicalEnv(numVars);
276     if (UNLIKELY(newEnv == nullptr)) {
277         return JSTaggedValue::Hole();
278     }
279     JSTaggedValue currentEnv = thread->GetCurrentLexenv();
280     // currentEnv is LexicalEnv/GlobalEnv for normal function, and is SFunctionEnv for SharedFunction.
281     JSTaggedValue globalEnv = BaseEnv::Cast(currentEnv.GetTaggedObject())->GetGlobalEnv(thread);
282     if LIKELY(!globalEnv.IsHole()) {
283         newEnv->SetGlobalEnv(thread, globalEnv);
284     } else {
285         newEnv->SetGlobalEnv(thread, thread->GetGlueGlobalEnv());
286     }
287     newEnv->SetParentEnv(thread, currentEnv);
288     return JSTaggedValue(newEnv);
289 }
290 
NewThisObject(JSThread * thread,JSTaggedValue ctor,JSTaggedValue newTarget,InterpretedFrame * state)291 JSTaggedValue FastRuntimeStub::NewThisObject(JSThread *thread, JSTaggedValue ctor, JSTaggedValue newTarget,
292                                              InterpretedFrame *state)
293 {
294     [[maybe_unused]] EcmaHandleScope handleScope(thread);
295     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
296 
297     JSHandle<JSFunction> ctorHandle(thread, ctor);
298     JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
299     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(ctorHandle, newTargetHandle);
300     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
301 
302     Method *method = Method::Cast(ctorHandle->GetMethod(thread).GetTaggedObject());
303     state->function = ctorHandle.GetTaggedValue();
304     state->constpool = method->GetConstantPool(thread);
305     state->profileTypeInfo = ctorHandle->GetProfileTypeInfo(thread);
306     state->env = ctorHandle->GetLexicalEnv(thread);
307 
308     return obj.GetTaggedValue();
309 }
310 }  // namespace panda::ecmascript
311 #endif  // ECMASCRIPT_INTERPRETER_FAST_RUNTIME_STUB_INL_H
312