• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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_STUBS_RUNTIME_STUBS_INL_H
17 #define ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
18 
19 #include "ecmascript/ecma_macros.h"
20 #include "ecmascript/js_tagged_value.h"
21 #include "ecmascript/stubs/runtime_stubs.h"
22 
23 #include "ecmascript/base/array_helper.h"
24 #include "ecmascript/builtins/builtins_regexp.h"
25 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
26 #include "ecmascript/debugger/js_debugger_manager.h"
27 #include "ecmascript/ecma_string_table.h"
28 #include "ecmascript/global_dictionary-inl.h"
29 #include "ecmascript/global_env.h"
30 #include "ecmascript/ic/profile_type_info.h"
31 #include "ecmascript/interpreter/frame_handler.h"
32 #include "ecmascript/interpreter/interpreter.h"
33 #include "ecmascript/jobs/micro_job_queue.h"
34 #include "ecmascript/js_arguments.h"
35 #include "ecmascript/js_async_function.h"
36 #include "ecmascript/js_async_generator_object.h"
37 #include "ecmascript/js_bigint.h"
38 #include "ecmascript/js_for_in_iterator.h"
39 #include "ecmascript/js_generator_object.h"
40 #include "ecmascript/js_iterator.h"
41 #include "ecmascript/js_promise.h"
42 #include "ecmascript/jspandafile/class_info_extractor.h"
43 #include "ecmascript/jspandafile/literal_data_extractor.h"
44 #include "ecmascript/jspandafile/program_object.h"
45 #include "ecmascript/jspandafile/scope_info_extractor.h"
46 #include "ecmascript/message_string.h"
47 #include "ecmascript/module/js_module_manager.h"
48 #include "ecmascript/module/js_module_source_text.h"
49 #include "ecmascript/module/module_value_accessor.h"
50 #include "ecmascript/object_factory-inl.h"
51 #include "ecmascript/patch/quick_fix_helper.h"
52 #include "ecmascript/platform/file.h"
53 #include "ecmascript/runtime.h"
54 #include "ecmascript/stackmap/llvm/llvm_stackmap_parser.h"
55 #include "ecmascript/sendable_env.h"
56 #include "ecmascript/template_string.h"
57 
58 namespace panda::ecmascript {
59 using ArrayHelper = base::ArrayHelper;
RuntimeInc(JSThread * thread,const JSHandle<JSTaggedValue> & value)60 JSTaggedValue RuntimeStubs::RuntimeInc(JSThread *thread, const JSHandle<JSTaggedValue> &value)
61 {
62     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
63     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
64     if (inputVal->IsBigInt()) {
65         JSHandle<BigInt> bigValue(inputVal);
66         return BigInt::BigintAddOne(thread, bigValue).GetTaggedValue();
67     }
68     JSTaggedNumber number(inputVal.GetTaggedValue());
69     return JSTaggedValue(++number);
70 }
71 
RuntimeDec(JSThread * thread,const JSHandle<JSTaggedValue> & value)72 JSTaggedValue RuntimeStubs::RuntimeDec(JSThread *thread, const JSHandle<JSTaggedValue> &value)
73 {
74     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
75     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
76     if (inputVal->IsBigInt()) {
77         JSHandle<BigInt> bigValue(inputVal);
78         return BigInt::BigintSubOne(thread, bigValue).GetTaggedValue();
79     }
80     JSTaggedNumber number(inputVal.GetTaggedValue());
81     return JSTaggedValue(--number);
82 }
83 
RuntimeExp(JSThread * thread,JSTaggedValue base,JSTaggedValue exponent)84 JSTaggedValue RuntimeStubs::RuntimeExp(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent)
85 {
86     JSHandle<JSTaggedValue> baseTag(thread, base);
87     JSHandle<JSTaggedValue> exponentTag(thread, exponent);
88     JSHandle<JSTaggedValue> valBase = JSTaggedValue::ToNumeric(thread, baseTag);
89     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
90     JSHandle<JSTaggedValue> valExponent = JSTaggedValue::ToNumeric(thread, exponentTag);
91     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
92     if (valBase->IsBigInt() || valExponent->IsBigInt()) {
93         if (valBase->IsBigInt() && valExponent->IsBigInt()) {
94             JSHandle<BigInt> bigBaseVale(valBase);
95             JSHandle<BigInt> bigExponentValue(valExponent);
96             return BigInt::Exponentiate(thread, bigBaseVale, bigExponentValue).GetTaggedValue();
97         }
98         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot mix BigInt and other types, use explicit conversions",
99                                     JSTaggedValue::Exception());
100     }
101     double doubleBase = valBase->GetNumber();
102     double doubleExponent = valExponent->GetNumber();
103     if ((std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) || std::isnan(doubleExponent)) {
104         return JSTaggedValue(base::NAN_VALUE);
105     }
106     if (((doubleBase == 0) &&
107         ((base::bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
108         std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
109         base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == (doubleExponent / 2)) {  // 2: half
110         if (doubleExponent > 0) {
111             return JSTaggedValue(-0.0);
112         }
113         if (doubleExponent < 0) {
114             return JSTaggedValue(-base::POSITIVE_INFINITY);
115         }
116     }
117     return JSTaggedValue(std::pow(doubleBase, doubleExponent));
118 }
119 
RuntimeIsIn(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & obj)120 JSTaggedValue RuntimeStubs::RuntimeIsIn(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
121                                         const JSHandle<JSTaggedValue> &obj)
122 {
123     if (!obj->IsECMAObject()) {
124         return RuntimeThrowTypeError(thread, "Cannot use 'in' operator in Non-Object");
125     }
126     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
127     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
128     bool ret = JSTaggedValue::HasProperty(thread, obj, propKey);
129     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
130     return JSTaggedValue(ret);
131 }
132 
RuntimeInstanceof(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & target)133 JSTaggedValue RuntimeStubs::RuntimeInstanceof(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
134                                               const JSHandle<JSTaggedValue> &target)
135 {
136     bool ret = JSObject::InstanceOf(thread, obj, target);
137     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
138     return JSTaggedValue(ret);
139 }
140 
RuntimeInstanceofByHandler(JSThread * thread,JSHandle<JSTaggedValue> target,JSHandle<JSTaggedValue> object,JSHandle<JSTaggedValue> instOfHandler)141 JSTaggedValue RuntimeStubs::RuntimeInstanceofByHandler(JSThread *thread, JSHandle<JSTaggedValue> target,
142                                                        JSHandle<JSTaggedValue> object,
143                                                        JSHandle<JSTaggedValue> instOfHandler)
144 {
145     // 3. ReturnIfAbrupt(instOfHandler).
146     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
147     // 4. If instOfHandler is not undefined, then
148     if (!instOfHandler->IsUndefined()) {
149         // a. Return ! ToBoolean(? Call(instOfHandler, target, «object»)).
150         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
151         JSTaggedValue function = env->GetTaggedHasInstanceFunction();
152         JSTaggedValue instOf = instOfHandler.GetTaggedValue();
153         // slowpath
154         if (function != instOf) {
155             JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
156             EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, instOfHandler, target,
157                                                                             undefined, 1);
158             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
159             info->SetCallArg(object.GetTaggedValue());
160             JSTaggedValue tagged = JSFunction::Call(info);
161 
162             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
163             return tagged;
164         }
165     }
166     // 5. If IsCallable(target) is false, throw a TypeError exception.
167     if (!target->IsCallable()) {
168         THROW_TYPE_ERROR_AND_RETURN(thread, "InstanceOf error when target is not Callable", JSTaggedValue::Exception());
169     }
170     // fastpath
171     // 6. Return ? OrdinaryHasInstance(target, object).
172     bool res = JSFunction::OrdinaryHasInstance(thread, target, object);
173     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
174     return JSTaggedValue(res);
175 }
176 
RuntimeCreateGeneratorObj(JSThread * thread,const JSHandle<JSTaggedValue> & genFunc)177 JSTaggedValue RuntimeStubs::RuntimeCreateGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc)
178 {
179     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
180     JSHandle<JSGeneratorObject> obj = factory->NewJSGeneratorObject(genFunc);
181     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
182     context->SetGeneratorObject(thread, obj.GetTaggedValue());
183 
184     // change state to SUSPENDED_START
185     obj->SetGeneratorState(JSGeneratorState::SUSPENDED_START);
186     obj->SetGeneratorContext(thread, context);
187 
188     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
189     return obj.GetTaggedValue();
190 }
191 
RuntimeCreateAsyncGeneratorObj(JSThread * thread,const JSHandle<JSTaggedValue> & genFunc)192 JSTaggedValue RuntimeStubs::RuntimeCreateAsyncGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc)
193 {
194     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
195     JSHandle<JSAsyncGeneratorObject> obj = factory->NewJSAsyncGeneratorObject(genFunc);
196     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
197     context->SetGeneratorObject(thread, obj.GetTaggedValue());
198 
199     // change state to SUSPENDED_START
200     obj->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_START);
201     obj->SetGeneratorContext(thread, context);
202 
203     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
204     return obj.GetTaggedValue();
205 }
206 
RuntimeGetTemplateObject(JSThread * thread,const JSHandle<JSTaggedValue> & literal)207 JSTaggedValue RuntimeStubs::RuntimeGetTemplateObject(JSThread *thread, const JSHandle<JSTaggedValue> &literal)
208 {
209     JSHandle<JSTaggedValue> templateObj = TemplateString::GetTemplateObject(thread, literal);
210     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
211     return templateObj.GetTaggedValue();
212 }
213 
RuntimeGetNextPropName(JSThread * thread,const JSHandle<JSTaggedValue> & iter)214 JSTaggedValue RuntimeStubs::RuntimeGetNextPropName(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
215 {
216     ASSERT(iter->IsForinIterator());
217     JSTaggedValue res = JSForInIterator::NextInternal(thread, JSHandle<JSForInIterator>::Cast(iter));
218     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
219     return res;
220 }
221 
RuntimeIterNext(JSThread * thread,const JSHandle<JSTaggedValue> & iter)222 JSTaggedValue RuntimeStubs::RuntimeIterNext(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
223 {
224     JSHandle<JSTaggedValue> resultObj = JSIterator::IteratorNext(thread, iter);
225     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
226     return resultObj.GetTaggedValue();
227 }
228 
RuntimeCloseIterator(JSThread * thread,const JSHandle<JSTaggedValue> & iter)229 JSTaggedValue RuntimeStubs::RuntimeCloseIterator(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
230 {
231     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
232     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
233 
234     JSHandle<JSTaggedValue> record;
235     if (thread->HasPendingException()) {
236         record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(
237             CompletionRecordType::THROW, JSHandle<JSTaggedValue>(thread, thread->GetException())));
238     } else {
239         JSHandle<JSTaggedValue> undefinedVal = globalConst->GetHandledUndefined();
240         record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(CompletionRecordType::NORMAL, undefinedVal));
241     }
242     JSHandle<JSTaggedValue> result = JSIterator::IteratorClose(thread, iter, record);
243     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
244     if (result->IsCompletionRecord()) {
245         return CompletionRecord::Cast(result->GetTaggedObject())->GetValue(thread);
246     }
247     return result.GetTaggedValue();
248 }
249 
RuntimeSuperCallSpread(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,const JSHandle<JSTaggedValue> & array)250 JSTaggedValue RuntimeStubs::RuntimeSuperCallSpread(JSThread *thread, const JSHandle<JSTaggedValue> &func,
251                                                    const JSHandle<JSTaggedValue> &newTarget,
252                                                    const JSHandle<JSTaggedValue> &array)
253 {
254     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
255     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
256     if (!superFunc->IsJSFunction()) {
257         THROW_TYPE_ERROR_AND_RETURN(thread, "Super constructor is not JSFunction", JSTaggedValue::Exception());
258     }
259 
260     JSHandle<TaggedArray> argv(thread, RuntimeGetCallSpreadArgs(thread, array));
261     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
262     const uint32_t argsLength = argv->GetLength();
263     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
264     EcmaRuntimeCallInfo *info =
265         EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, argsLength);
266     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
267     info->SetCallArg(argsLength, argv);
268     JSTaggedValue result = JSFunction::Construct(info);
269     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
270 
271     return result;
272 }
273 
RuntimeOptSuperCallSpread(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,const JSHandle<JSTaggedValue> & taggedArray)274 JSTaggedValue RuntimeStubs::RuntimeOptSuperCallSpread(JSThread *thread, const JSHandle<JSTaggedValue> &func,
275                                                       const JSHandle<JSTaggedValue> &newTarget,
276                                                       const JSHandle<JSTaggedValue> &taggedArray)
277 {
278     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
279     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
280     if (!superFunc->IsJSFunction()) {
281         THROW_TYPE_ERROR_AND_RETURN(thread, "Super constructor is not JSFunction", JSTaggedValue::Exception());
282     }
283 
284     JSHandle<TaggedArray> argv(thread, taggedArray.GetTaggedValue());
285     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
286     const uint32_t argsLength = argv->GetLength();
287     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
288     EcmaRuntimeCallInfo *info =
289         EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, argsLength);
290     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
291     info->SetCallArg(argsLength, argv);
292     JSTaggedValue result = JSFunction::Construct(info);
293     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
294 
295     return result;
296 }
297 
RuntimeSuperCallForwardAllArgs(JSThread * thread,JSTaggedType * sp,const JSHandle<JSTaggedValue> & superFunc,const JSHandle<JSTaggedValue> & newTarget,uint32_t restNumArgs,uint32_t startIdx)298 JSTaggedValue RuntimeStubs::RuntimeSuperCallForwardAllArgs(JSThread *thread, JSTaggedType *sp,
299                                                            const JSHandle<JSTaggedValue> &superFunc,
300                                                            const JSHandle<JSTaggedValue> &newTarget,
301                                                            uint32_t restNumArgs, uint32_t startIdx)
302 {
303     if (!superFunc->IsConstructor()) {
304         THROW_TYPE_ERROR_AND_RETURN(thread, "Super constructor is not a constructor", JSTaggedValue::Exception());
305     }
306 
307     // prepare callinfo
308     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
309     EcmaRuntimeCallInfo *info =
310         EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, restNumArgs);
311     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
312     // set args for callinfo
313     for (uint32_t i = 0; i < restNumArgs; ++i) {
314         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
315         info->SetCallArg(i, JSTaggedValue(sp[startIdx + i]));
316     }
317     // execute super ctor with call info
318     JSTaggedValue res = JSFunction::Construct(info);
319     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
320     return res;
321 }
322 
RuntimeDelObjProp(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop)323 JSTaggedValue RuntimeStubs::RuntimeDelObjProp(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
324                                               const JSHandle<JSTaggedValue> &prop)
325 {
326     JSHandle<JSTaggedValue> jsObj(JSTaggedValue::ToObject(thread, obj));
327     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
328     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
329     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
330     bool ret = JSTaggedValue::DeletePropertyOrThrow(thread, jsObj, propKey);
331     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
332     return JSTaggedValue(ret);
333 }
334 
RuntimeNewObjApply(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & array)335 JSTaggedValue RuntimeStubs::RuntimeNewObjApply(JSThread *thread, const JSHandle<JSTaggedValue> &func,
336                                                const JSHandle<JSTaggedValue> &array)
337 {
338     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
339     if (!array->IsJSArray()) {
340         return RuntimeThrowTypeError(thread, "Cannot Newobjspread");
341     }
342 
343     uint32_t length = JSHandle<JSArray>::Cast(array)->GetArrayLength();
344     JSHandle<TaggedArray> argsArray = factory->NewTaggedArray(length);
345     for (uint32_t i = 0; i < length; ++i) {
346         auto prop = JSTaggedValue::GetProperty(thread, array, i).GetValue();
347         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
348         argsArray->Set(thread, i, prop);
349         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
350     }
351     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
352     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, func, length);
353     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
354     info->SetCallArg(length, argsArray);
355     return NewObject(info);
356 }
357 
RuntimeCreateIterResultObj(JSThread * thread,const JSHandle<JSTaggedValue> & value,JSTaggedValue flag)358 JSTaggedValue RuntimeStubs::RuntimeCreateIterResultObj(JSThread *thread, const JSHandle<JSTaggedValue> &value,
359                                                        JSTaggedValue flag)
360 {
361     ASSERT(flag.IsBoolean());
362     bool done = flag.IsTrue();
363     JSHandle<JSObject> iter = JSIterator::CreateIterResultObject(thread, value, done);
364     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
365     return iter.GetTaggedValue();
366 }
367 
RuntimeAsyncFunctionAwaitUncaught(JSThread * thread,const JSHandle<JSTaggedValue> & asyncFuncObj,const JSHandle<JSTaggedValue> & value)368 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionAwaitUncaught(JSThread *thread,
369                                                               const JSHandle<JSTaggedValue> &asyncFuncObj,
370                                                               const JSHandle<JSTaggedValue> &value)
371 {
372     JSAsyncFunction::AsyncFunctionAwait(thread, asyncFuncObj, value);
373     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
374     if (asyncFuncObj->IsAsyncGeneratorObject()) {
375         JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, asyncFuncObj);
376         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
377         JSHandle<JSAsyncGeneratorObject> generator = JSHandle<JSAsyncGeneratorObject>::Cast(obj);
378         JSHandle<TaggedQueue> queue(thread, generator->GetAsyncGeneratorQueue(thread));
379         if (queue->Empty(thread)) {
380             return JSTaggedValue::Undefined();
381         }
382         JSHandle<AsyncGeneratorRequest> next(thread, queue->Front(thread));
383         JSHandle<PromiseCapability> completion(thread, next->GetCapability(thread));
384         JSHandle<JSPromise> promise(thread, completion->GetPromise(thread));
385         return promise.GetTaggedValue();
386     }
387     JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(asyncFuncObj);
388     JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise(thread));
389 
390     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
391     return promise.GetTaggedValue();
392 }
393 
RuntimeAsyncFunctionResolveOrReject(JSThread * thread,const JSHandle<JSTaggedValue> & asyncFuncObj,const JSHandle<JSTaggedValue> & value,bool is_resolve)394 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionResolveOrReject(JSThread *thread,
395     const JSHandle<JSTaggedValue> &asyncFuncObj, const JSHandle<JSTaggedValue> &value, bool is_resolve)
396 {
397     JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(asyncFuncObj);
398     JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise(thread));
399 
400     if (thread->GetEcmaVM()->GetJSOptions().EnablePendingCheak()) {
401         thread->GetEcmaVM()->RemoveAsyncStackTrace(promise);
402     }
403     // ActivePromise
404     JSHandle<ResolvingFunctionsRecord> reactions = JSPromise::CreateResolvingFunctions(thread, promise);
405     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
406     JSHandle<JSTaggedValue> thisArg = globalConst->GetHandledUndefined();
407     JSHandle<JSTaggedValue> activeFunc;
408     if (is_resolve) {
409         activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetResolveFunction(thread));
410     } else {
411         activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetRejectFunction(thread));
412     }
413     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
414     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, activeFunc, thisArg, undefined, 1);
415     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
416     info->SetCallArg(value.GetTaggedValue());
417     [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
418 
419     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
420     return promise.GetTaggedValue();
421 }
422 
RuntimeAsyncGeneratorResolve(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value,JSTaggedValue flag)423 JSTaggedValue RuntimeStubs::RuntimeAsyncGeneratorResolve(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
424                                                          JSHandle<JSTaggedValue> value, JSTaggedValue flag)
425 {
426     [[maybe_unused]] EcmaHandleScope handleScope(thread);
427 
428     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
429     JSHandle<JSTaggedValue> valueHandle(value);
430     JSHandle<GeneratorContext> genContextHandle(thread, asyncGeneratorObjHandle->GetGeneratorContext(thread));
431     // save stack, should copy cur_frame, function execute over will free cur_frame
432     SaveFrameToContext(thread, genContextHandle);
433 
434     ASSERT(flag.IsBoolean());
435     bool done = flag.IsTrue();
436 
437     return JSAsyncGeneratorObject::AsyncGeneratorResolve(thread, asyncGeneratorObjHandle, valueHandle, done);
438 }
439 
RuntimeAsyncGeneratorReject(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value)440 JSTaggedValue RuntimeStubs::RuntimeAsyncGeneratorReject(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
441                                                         JSHandle<JSTaggedValue> value)
442 {
443     [[maybe_unused]] EcmaHandleScope handleScope(thread);
444 
445     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
446     JSHandle<JSTaggedValue> valueHandle(value);
447 
448     return JSAsyncGeneratorObject::AsyncGeneratorReject(thread, asyncGeneratorObjHandle, valueHandle);
449 }
450 
RuntimeCopyDataProperties(JSThread * thread,const JSHandle<JSTaggedValue> & dst,const JSHandle<JSTaggedValue> & src)451 JSTaggedValue RuntimeStubs::RuntimeCopyDataProperties(JSThread *thread, const JSHandle<JSTaggedValue> &dst,
452                                                       const JSHandle<JSTaggedValue> &src)
453 {
454     if (!src->IsNull() && !src->IsUndefined()) {
455         // 2. Let from be ! ToObject(source).
456         JSHandle<JSTaggedValue> from(JSTaggedValue::ToObject(thread, src));
457         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
458         JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, from);
459         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
460 
461         JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
462         uint32_t keysLen = keys->GetLength();
463         for (uint32_t i = 0; i < keysLen; i++) {
464             PropertyDescriptor desc(thread);
465             key.Update(keys->Get(thread, i));
466             bool success = JSTaggedValue::GetOwnProperty(thread, from, key, desc);
467             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
468 
469             if (success && desc.IsEnumerable()) {
470                 desc.SetWritable(true);
471                 desc.SetConfigurable(true);
472                 JSTaggedValue::DefineOwnProperty(thread, dst, key, desc);
473                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
474             }
475         }
476     }
477     return dst.GetTaggedValue();
478 }
479 
RuntimeStArraySpread(JSThread * thread,const JSHandle<JSTaggedValue> & dst,JSTaggedValue index,const JSHandle<JSTaggedValue> & src)480 JSTaggedValue RuntimeStubs::RuntimeStArraySpread(JSThread *thread, const JSHandle<JSTaggedValue> &dst,
481                                                  JSTaggedValue index, const JSHandle<JSTaggedValue> &src)
482 {
483     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
484     JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
485     ASSERT(dst->IsJSArray());
486     if (dst->IsJSArray()) {
487         if (src->IsNull() || src->IsUndefined()) {
488             THROW_TYPE_ERROR_AND_RETURN(thread, "src is not iterable", JSTaggedValue::Exception());
489         }
490     } else {
491         THROW_TYPE_ERROR_AND_RETURN(thread, "dst is not iterable", JSTaggedValue::Exception());
492     }
493     if (src->IsString()) {
494         JSHandle<EcmaString> srcString = JSTaggedValue::ToString(thread, src);
495         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
496         JSHandle<EcmaString> srcFlat = JSHandle<EcmaString>(thread,
497             EcmaStringAccessor::Flatten(thread->GetEcmaVM(), srcString));
498         uint32_t dstLen = static_cast<uint32_t>(index.GetInt());
499         uint32_t strLen = EcmaStringAccessor(srcFlat).GetLength();
500         for (uint32_t i = 0; i < strLen; i++) {
501             uint16_t res = EcmaStringAccessor(srcFlat).Get<false>(thread, i);
502             JSHandle<JSTaggedValue> strValue(factory->NewFromUtf16Literal(&res, 1));
503             JSTaggedValue::SetProperty(thread, dst, dstLen + i, strValue, true);
504             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
505         }
506         JSHandle<JSTaggedValue> length(thread, JSTaggedValue(dstLen + strLen));
507         if (strLen == 0U) {
508             JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
509             JSTaggedValue::SetProperty(thread, dst, lengthKey, length);
510         }
511         return length.GetTaggedValue();
512     }
513 
514     if (index.GetInt() == 0 && src->IsStableJSArray(thread)) {
515         JSHandle<TaggedArray> srcElements(thread, JSHandle<JSObject>::Cast(src)->GetElements(thread));
516         uint32_t length = JSHandle<JSArray>::Cast(src)->GetArrayLength();
517         JSHandle<TaggedArray> dstElements = factory->NewTaggedArray(length);
518         JSHandle<JSArray> dstArray = JSHandle<JSArray>::Cast(dst);
519         dstArray->SetElements(thread, dstElements);
520         dstArray->SetArrayLength(thread, length);
521         JSHandle<JSObject> srcObj(src);
522         JSHandle<JSObject> dstObj(dst);
523         ElementAccessor::CopyJSArrayObject(thread, srcObj, dstObj, length);
524         for (uint32_t i = 0; i < length; i++) {
525             JSHandle<JSTaggedValue> reg(thread, ElementAccessor::Get(thread, srcObj, i));
526             if (reg->IsHole()) {
527                 JSHandle<JSTaggedValue> reg2(thread, JSArray::FastGetPropertyByValue(thread, src, i).GetTaggedValue());
528                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
529                 if (reg2->IsHole()) {
530                     ElementAccessor::Set(thread, dstObj, i, undefinedHandle, true);
531                 } else {
532                     ElementAccessor::Set(thread, dstObj, i, reg2, true);
533                 }
534             } else {
535                 ElementAccessor::Set(thread, dstObj, i, reg, true);
536             }
537         }
538         return JSTaggedValue(length);
539     }
540 
541     JSHandle<JSTaggedValue> iter;
542     auto globalConst = thread->GlobalConstants();
543     if (src->IsJSArrayIterator() || src->IsJSMapIterator() || src->IsJSSetIterator() ||
544         src->IsIterator()) {
545         iter = src;
546     } else if (src->IsJSArray()) {
547         JSHandle<JSTaggedValue> valuesStr = globalConst->GetHandledValuesString();
548         JSHandle<JSTaggedValue> valuesMethod = JSObject::GetMethod(thread, src, valuesStr);
549         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
550         iter = JSIterator::GetIterator(thread, src, valuesMethod);
551         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
552     } else {
553         iter = JSIterator::GetIterator(thread, src);
554         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
555     }
556 
557     JSMutableHandle<JSTaggedValue> indexHandle(thread, index);
558     JSHandle<JSTaggedValue> valueStr = globalConst->GetHandledValueString();
559     PropertyDescriptor desc(thread);
560     JSHandle<JSTaggedValue> iterResult;
561     uint32_t srcLen = 0U;
562     do {
563         iterResult = JSIterator::IteratorStep(thread, iter);
564         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
565         if (iterResult->IsFalse()) {
566             break;
567         }
568         bool success = JSTaggedValue::GetOwnProperty(thread, iterResult, valueStr, desc);
569         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
570         if (success && desc.IsEnumerable()) {
571             JSTaggedValue::DefineOwnProperty(thread, dst, indexHandle, desc);
572             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
573             int tmp = indexHandle->GetInt();
574             indexHandle.Update(JSTaggedValue(tmp + 1));
575             ++srcLen;
576         }
577     } while (true);
578     if (srcLen == 0U) {
579         JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
580         JSTaggedValue::SetProperty(thread, dst, lengthKey, indexHandle);
581     }
582     return indexHandle.GetTaggedValue();
583 }
584 
RuntimeGetIteratorNext(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & method)585 JSTaggedValue RuntimeStubs::RuntimeGetIteratorNext(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
586                                                    const JSHandle<JSTaggedValue> &method)
587 {
588     ASSERT(method->IsCallable());
589     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
590     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, obj, undefined, 0);
591     JSTaggedValue ret = JSFunction::Call(info);
592     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
593     if (!ret.IsECMAObject()) {
594         return RuntimeThrowTypeError(thread, "the Iterator is not an ecmaobject.");
595     }
596     return ret;
597 }
598 
RuntimeSetObjectWithProto(JSThread * thread,const JSHandle<JSTaggedValue> & proto,const JSHandle<JSObject> & obj)599 JSTaggedValue RuntimeStubs::RuntimeSetObjectWithProto(JSThread *thread, const JSHandle<JSTaggedValue> &proto,
600                                                       const JSHandle<JSObject> &obj)
601 {
602     if (!proto->IsECMAObject() && !proto->IsNull()) {
603         return JSTaggedValue::False();
604     }
605     if (UNLIKELY(proto->IsJSShared())) {
606         THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetProtoWithSendable), JSTaggedValue::Exception());
607     }
608     JSObject::SetPrototype(thread, obj, proto, true);
609     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
610     return JSTaggedValue::True();
611 }
612 
RuntimeLdObjByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,bool callGetter,JSTaggedValue receiver)613 JSTaggedValue RuntimeStubs::RuntimeLdObjByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
614                                                 const JSHandle<JSTaggedValue> &prop, bool callGetter,
615                                                 JSTaggedValue receiver)
616 {
617     // Ecma Spec 2015 12.3.2.1
618     // 7. Let bv be RequireObjectCoercible(baseValue).
619     // 8. ReturnIfAbrupt(bv).
620     JSHandle<JSTaggedValue> object =
621         JSTaggedValue::RequireObjectCoercible(thread, obj, "Cannot load property of null or undefined");
622     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
623 
624     JSTaggedValue res;
625     if (callGetter) {
626         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), object);
627         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
628     } else {
629         JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
630         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
631         res = JSTaggedValue::GetProperty(thread, object, propKey).GetValue().GetTaggedValue();
632     }
633     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
634     return res;
635 }
636 
RuntimeStObjByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)637 JSTaggedValue RuntimeStubs::RuntimeStObjByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
638                                                 const JSHandle<JSTaggedValue> &prop,
639                                                 const JSHandle<JSTaggedValue> &value)
640 {
641     // Ecma Spec 2015 12.3.2.1
642     // 7. Let bv be RequireObjectCoercible(baseValue).
643     // 8. ReturnIfAbrupt(bv).
644     JSHandle<JSTaggedValue> object =
645         JSTaggedValue::RequireObjectCoercible(thread, obj, "Cannot store property of null or undefined");
646     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
647 
648     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, prop));
649     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
650     // strict mode is true
651     JSTaggedValue::SetProperty(thread, object, propKey, value, true);
652     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
653     return JSTaggedValue::True();
654 }
655 
RuntimeStOwnByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)656 JSTaggedValue RuntimeStubs::RuntimeStOwnByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
657                                                 const JSHandle<JSTaggedValue> &key,
658                                                 const JSHandle<JSTaggedValue> &value)
659 {
660     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
661 
662     if (obj->IsClassConstructor() && JSTaggedValue::SameValue(thread, key, globalConst->GetHandledPrototypeString())) {
663         return RuntimeThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
664     }
665 
666     // property in class is non-enumerable
667     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
668 
669     PropertyDescriptor desc(thread, value, true, enumerable, true);
670     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, key);
671     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
672     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, propKey, desc);
673     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
674     if (!ret) {
675         return RuntimeThrowTypeError(thread, "StOwnByValue failed");
676     }
677     return JSTaggedValue::True();
678 }
679 
RuntimeLdSuperByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,JSTaggedValue thisFunc)680 JSTaggedValue RuntimeStubs::RuntimeLdSuperByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
681                                                   const JSHandle<JSTaggedValue> &key, JSTaggedValue thisFunc)
682 {
683     ASSERT(thisFunc.IsJSFunction());
684     // get Homeobject form function
685     JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject(thread));
686     JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
687     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
688     JSTaggedValue::RequireObjectCoercible(thread, superBase);
689     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
690     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, key));
691     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
692 
693     JSTaggedValue res = JSTaggedValue::GetProperty(thread, superBase, propKey, obj).GetValue().GetTaggedValue();
694     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
695     return res;
696 }
697 
RuntimeStSuperByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value,JSTaggedValue thisFunc)698 JSTaggedValue RuntimeStubs::RuntimeStSuperByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
699                                                   const JSHandle<JSTaggedValue> &key,
700                                                   const JSHandle<JSTaggedValue> &value, JSTaggedValue thisFunc)
701 {
702     ASSERT(thisFunc.IsJSFunction());
703     // get Homeobject form function
704     JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject(thread));
705     JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
706     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
707     JSTaggedValue::RequireObjectCoercible(thread, superBase);
708     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
709     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, key));
710     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
711 
712     // check may_throw is false?
713     JSTaggedValue::SetProperty(thread, superBase, propKey, value, obj, true);
714     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
715     return JSTaggedValue::True();
716 }
717 
RuntimeLdObjByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,uint32_t idx,bool callGetter,JSTaggedValue receiver)718 JSTaggedValue RuntimeStubs::RuntimeLdObjByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
719                                                 uint32_t idx, bool callGetter, JSTaggedValue receiver)
720 {
721     JSTaggedValue res;
722     if (callGetter) {
723         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), obj);
724     } else {
725         res = JSTaggedValue::GetProperty(thread, obj, idx).GetValue().GetTaggedValue();
726     }
727     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
728     return res;
729 }
730 
RuntimeLdObjByName(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,bool callGetter,JSTaggedValue receiver)731 JSTaggedValue RuntimeStubs::RuntimeLdObjByName(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop,
732                                                bool callGetter, JSTaggedValue receiver)
733 {
734     JSHandle<JSTaggedValue> objHandle(thread, obj);
735     JSTaggedValue res;
736     if (callGetter) {
737         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), objHandle);
738     } else {
739         JSHandle<JSTaggedValue> propHandle(thread, prop);
740         res = JSTaggedValue::GetProperty(thread, objHandle, propHandle).GetValue().GetTaggedValue();
741     }
742     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
743     return res;
744 }
745 
RuntimeStObjByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)746 JSTaggedValue RuntimeStubs::RuntimeStObjByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
747                                                const JSHandle<JSTaggedValue> &prop,
748                                                const JSHandle<JSTaggedValue> &value)
749 {
750     JSTaggedValue::SetProperty(thread, obj, prop, value, true);
751     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
752     return JSTaggedValue::True();
753 }
754 
RuntimeStObjByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,uint32_t idx,const JSHandle<JSTaggedValue> & value)755 JSTaggedValue RuntimeStubs::RuntimeStObjByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
756                                                 uint32_t idx, const JSHandle<JSTaggedValue> &value)
757 {
758     JSTaggedValue::SetProperty(thread, obj, idx, value, true);
759     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
760     return JSTaggedValue::True();
761 }
762 
RuntimeStOwnByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & idx,const JSHandle<JSTaggedValue> & value)763 JSTaggedValue RuntimeStubs::RuntimeStOwnByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
764                                                 const JSHandle<JSTaggedValue> &idx,
765                                                 const JSHandle<JSTaggedValue> &value)
766 {
767     // property in class is non-enumerable
768     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
769 
770     PropertyDescriptor desc(thread, value, true, enumerable, true);
771     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, idx, desc);
772     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
773     if (!ret) {
774         return RuntimeThrowTypeError(thread, "SetOwnByIndex failed");
775     }
776     return JSTaggedValue::True();
777 }
778 
RuntimeStGlobalRecord(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value,bool isConst)779 JSTaggedValue RuntimeStubs::RuntimeStGlobalRecord(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
780                                                   const JSHandle<JSTaggedValue> &value, bool isConst)
781 {
782     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
783     if (thread->GetEcmaVM()->GetJSOptions().IsEnableLoweringBuiltin()) {
784         BuiltinIndex& builtinIndex = BuiltinIndex::GetInstance();
785         auto index = builtinIndex.GetBuiltinIndex(thread, prop.GetTaggedValue());
786         if (index != BuiltinIndex::NOT_FOUND) {
787             auto box = factory->NewPropertyBox(JSHandle<JSTaggedValue>(thread, JSTaggedValue::Hole()));
788             thread->GetBuiltinEntriesPointer()->ClearByIndex(index, box.GetTaggedValue());
789         }
790     }
791 
792     EcmaVM *vm = thread->GetEcmaVM();
793     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
794     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
795 
796     // cross files global record name binding judgment
797     int entry = dict->FindEntry(thread, prop.GetTaggedValue());
798     if (entry != -1) {
799         std::string message = "Duplicate identifier \"";
800         message.append(EcmaStringAccessor(JSTaggedValue::ToString(thread, prop)).ToStdString(thread));
801         message.append("\"");
802         LOG_ECMA(ERROR) << message;
803         return RuntimeThrowSyntaxError(thread, "Duplicate identifier");
804     }
805 
806     PropertyAttributes attributes;
807     if (isConst) {
808         attributes.SetIsConstProps(true);
809     }
810     JSHandle<GlobalDictionary> dictHandle(thread, dict);
811     JSHandle<PropertyBox> box = factory->NewPropertyBox(value);
812     PropertyBoxType boxType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT;
813     attributes.SetBoxType(boxType);
814 
815     dict = *GlobalDictionary::PutIfAbsent(thread, dictHandle, prop, JSHandle<JSTaggedValue>(box), attributes);
816     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
817     env->SetGlobalRecord(thread, JSTaggedValue(dict));
818     return JSTaggedValue::True();
819 }
820 
RuntimeNeg(JSThread * thread,const JSHandle<JSTaggedValue> & value)821 JSTaggedValue RuntimeStubs::RuntimeNeg(JSThread *thread, const JSHandle<JSTaggedValue> &value)
822 {
823     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
824     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
825     if (inputVal->IsBigInt()) {
826         JSHandle<BigInt> bigValue(inputVal);
827         return BigInt::UnaryMinus(thread, bigValue).GetTaggedValue();
828     }
829     JSTaggedNumber number(inputVal.GetTaggedValue());
830     if (number.IsInt()) {
831         int32_t intValue = number.GetInt();
832         if (intValue == 0) {
833             return JSTaggedValue(-0.0);
834         }
835         if (intValue == INT32_MIN) {
836             return JSTaggedValue(-static_cast<double>(INT32_MIN));
837         }
838         return JSTaggedValue(-intValue);
839     }
840     if (number.IsDouble()) {
841         return JSTaggedValue(-number.GetDouble());
842     }
843     LOG_ECMA(FATAL) << "this branch is unreachable";
844     UNREACHABLE();
845 }
846 
RuntimeNot(JSThread * thread,const JSHandle<JSTaggedValue> & value)847 JSTaggedValue RuntimeStubs::RuntimeNot(JSThread *thread, const JSHandle<JSTaggedValue> &value)
848 {
849     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
850     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
851     if (inputVal->IsBigInt()) {
852         JSHandle<BigInt> bigValue(inputVal);
853         return BigInt::BitwiseNOT(thread, bigValue).GetTaggedValue();
854     }
855     int32_t number = JSTaggedValue::ToInt32(thread, inputVal);
856     return JSTaggedValue(~number); // NOLINT(hicpp-signed-bitwise)
857 }
858 
RuntimeResolveClass(JSThread * thread,const JSHandle<JSFunction> & ctor,const JSHandle<TaggedArray> & literal,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv)859 JSTaggedValue RuntimeStubs::RuntimeResolveClass(JSThread *thread, const JSHandle<JSFunction> &ctor,
860                                                 const JSHandle<TaggedArray> &literal,
861                                                 const JSHandle<JSTaggedValue> &base,
862                                                 const JSHandle<JSTaggedValue> &lexenv)
863 {
864     ASSERT(ctor.GetTaggedValue().IsClassConstructor());
865 
866     FrameHandler frameHandler(thread);
867     JSTaggedValue currentFunc = frameHandler.GetFunction();
868     JSHandle<JSTaggedValue> ecmaModule(thread, JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule(thread));
869 
870     RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(ctor), base);
871     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
872 
873     uint32_t literalBufferLength = literal->GetLength();
874     ASSERT(literalBufferLength > 0);
875 
876     // only traverse the value of key-value pair
877     for (uint32_t index = 1; index < literalBufferLength - 1; index += 2) {  // 2: key-value pair
878         JSTaggedValue value = literal->Get(thread, index);
879         if (LIKELY(value.IsJSFunction())) {
880             JSFunction *func = JSFunction::Cast(value.GetTaggedObject());
881             func->SetLexicalEnv(thread, lexenv.GetTaggedValue());
882             func->SetModule(thread, ecmaModule);
883         }
884     }
885 
886     return ctor.GetTaggedValue();
887 }
888 
RuntimeCloneClassFromTemplate(JSThread * thread,const JSHandle<JSFunction> & ctor,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv)889 JSTaggedValue RuntimeStubs::RuntimeCloneClassFromTemplate(JSThread *thread, const JSHandle<JSFunction> &ctor,
890                                                           const JSHandle<JSTaggedValue> &base,
891                                                           const JSHandle<JSTaggedValue> &lexenv)
892 {
893     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
894     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
895 
896     ASSERT(ctor.GetTaggedValue().IsClassConstructor());
897     JSHandle<JSObject> clsPrototype(thread, ctor->GetFunctionPrototype(thread));
898 
899     bool canShareHClass = false;
900     JSHandle<JSFunction> cloneClass = factory->CloneClassCtor(ctor, lexenv, canShareHClass);
901     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
902     JSHandle<JSObject> cloneClassPrototype = factory->CloneObjectLiteral(JSHandle<JSObject>(clsPrototype), lexenv,
903                                                                          canShareHClass);
904     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
905 
906     // After clone both, reset "constructor" and "prototype" properties.
907     JSFunction::SetFunctionPrototypeOrInstanceHClass(thread, cloneClass, cloneClassPrototype.GetTaggedValue());
908     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
909 
910     PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(cloneClass), true, false, true);
911     JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(cloneClassPrototype),
912                                          globalConst->GetHandledConstructorString(), ctorDesc);
913     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
914 
915     cloneClass->SetHomeObject(thread, cloneClassPrototype);
916 
917     if (!canShareHClass) {
918         RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(cloneClass), base);
919         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
920     }
921 
922     return cloneClass.GetTaggedValue();
923 }
924 
ShouldUseAOTHClass(const JSHandle<JSTaggedValue> & ihc,const JSHandle<JSTaggedValue> & chc,const JSHandle<ClassLiteral> & classLiteral)925 bool RuntimeStubs::ShouldUseAOTHClass(const JSHandle<JSTaggedValue> &ihc,
926                                       const JSHandle<JSTaggedValue> &chc,
927                                       const JSHandle<ClassLiteral> &classLiteral)
928 {
929     // In the case of incomplete data collection in PGO, AOT may not create ihc and chc at the same time.
930     // Therefore, there is no need to check for the existence of both at this point.
931     return (!ihc->IsUndefined() || !chc->IsUndefined()) && !classLiteral->GetIsAOTUsed();
932 }
933 
MaybeHasInterfacesType(JSThread * thread,const JSHandle<TaggedArray> & arrayHandle)934 bool RuntimeStubs::MaybeHasInterfacesType(JSThread *thread, const JSHandle<TaggedArray> &arrayHandle)
935 {
936     // this interface is one of the conditions for determining whether it is an interop scenario.
937     return arrayHandle->GetLength() != 0 && arrayHandle->Get(thread, arrayHandle->GetLength() - 1).IsString();
938 }
939 
DefineInterfaceTypeOwnProperty(JSThread * thread,JSHandle<JSFunction> & cls,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv,JSHandle<ClassInfoExtractor> & extractor,const JSHandle<JSTaggedValue> & ihc,const JSHandle<JSTaggedValue> & chc,const JSHandle<TaggedArray> & arrayHandle,const JSHandle<ClassLiteral> & classLiteral)940 void RuntimeStubs::DefineInterfaceTypeOwnProperty(JSThread *thread, JSHandle<JSFunction> &cls,
941                                                   const JSHandle<JSTaggedValue> &base,
942                                                   const JSHandle<JSTaggedValue> &lexenv,
943                                                   JSHandle<ClassInfoExtractor> &extractor,
944                                                   const JSHandle<JSTaggedValue> &ihc,
945                                                   const JSHandle<JSTaggedValue> &chc,
946                                                   const JSHandle<TaggedArray> &arrayHandle,
947                                                   const JSHandle<ClassLiteral> &classLiteral)
948 {
949     // set 1.2runtie interfaceType no property.
950     ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(
951         thread, extractor, arrayHandle, arrayHandle->GetLength(), ClassKind::NON_SENDABLE, 1);
952     cls = EntranceForDefineClass(thread, base, lexenv, extractor, ihc, chc, classLiteral);
953     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
954     JSHandle<JSTaggedValue> interfaceTypeSymbol = env->GetInterfaceTypeSymbol();
955     JSHandle<JSTaggedValue> interfaceTypeValue(thread, arrayHandle->Get(thread, arrayHandle->GetLength() - 1));
956     PropertyDescriptor desc(thread, interfaceTypeValue, false, false, false);
957     JSObject::DefineOwnProperty(
958         thread, JSHandle<JSObject>::Cast(cls), interfaceTypeSymbol, desc);
959 }
960 
EntranceForDefineClass(JSThread * thread,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv,JSHandle<ClassInfoExtractor> & extractor,const JSHandle<JSTaggedValue> & ihc,const JSHandle<JSTaggedValue> & chc,const JSHandle<ClassLiteral> & classLiteral)961 JSHandle<JSFunction> RuntimeStubs::EntranceForDefineClass(JSThread *thread,
962                                                           const JSHandle<JSTaggedValue> &base,
963                                                           const JSHandle<JSTaggedValue> &lexenv,
964                                                           JSHandle<ClassInfoExtractor> &extractor,
965                                                           const JSHandle<JSTaggedValue> &ihc,
966                                                           const JSHandle<JSTaggedValue> &chc,
967                                                           const JSHandle<ClassLiteral> &classLiteral)
968 {
969     if (ShouldUseAOTHClass(ihc, chc, classLiteral)) {
970         classLiteral->SetIsAOTUsed(true);
971         return ClassHelper::DefineClassWithIHClass(thread, base, extractor, lexenv, ihc, chc);
972     } else {
973         return ClassHelper::DefineClassFromExtractor(thread, base, extractor, lexenv);
974     }
975 }
976 // clone class may need re-set inheritance relationship due to extends may be a variable.
RuntimeCreateClassWithBuffer(JSThread * thread,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv,const JSHandle<JSTaggedValue> & constpool,uint16_t methodId,uint16_t literalId,const JSHandle<JSTaggedValue> & module,const JSHandle<JSTaggedValue> & length)977 JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
978                                                          const JSHandle<JSTaggedValue> &base,
979                                                          const JSHandle<JSTaggedValue> &lexenv,
980                                                          const JSHandle<JSTaggedValue> &constpool,
981                                                          uint16_t methodId, uint16_t literalId,
982                                                          const JSHandle<JSTaggedValue> &module,
983                                                          const JSHandle<JSTaggedValue> &length)
984 {
985     if (base->IsJSShared()) {
986         THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(NotSendableSubClass), JSTaggedValue::Exception());
987     }
988     [[maybe_unused]] EcmaHandleScope handleScope(thread);
989     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
990     CString entry = ModuleManager::GetRecordName(thread, module.GetTaggedValue());
991 
992     // For class constructor.
993     auto methodObj = ConstantPool::GetMethodFromCache(thread, constpool.GetTaggedValue(), methodId);
994     JSHandle<JSTaggedValue> method(thread, methodObj);
995     JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
996     JSHandle<JSFunction> cls;
997     JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
998     JSMutableHandle<JSTaggedValue> chc(thread, JSTaggedValue::Undefined());
999 
1000     JSHandle<ConstantPool> cp(thread,
1001         thread->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpoolHandle.GetTaggedValue()));
1002     JSTaggedValue val = cp->GetObjectFromCache(thread, literalId);
1003     if (val.IsAOTLiteralInfo()) {
1004         JSHandle<AOTLiteralInfo> aotLiteralInfo(thread, val);
1005         ihc.Update(aotLiteralInfo->GetIhc(thread));
1006         chc.Update(aotLiteralInfo->GetChc(thread));
1007     }
1008 
1009     JSTaggedValue literalObj = ConstantPool::GetClassLiteralFromCache(thread, cp, literalId, entry);
1010 
1011     JSHandle<ClassLiteral> classLiteral(thread, literalObj);
1012     JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray(thread));
1013     JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
1014     auto instance = ecmascript::Runtime::GetInstance();
1015     ASSERT(instance != nullptr);
1016     if (instance->IsHybridVm() && MaybeHasInterfacesType(thread, arrayHandle)) {
1017         DefineInterfaceTypeOwnProperty(thread, cls, base, lexenv, extractor, ihc, chc, arrayHandle, classLiteral);
1018     } else {
1019         auto literalLength = arrayHandle->GetLength();
1020         ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread, extractor, arrayHandle, literalLength);
1021 
1022         if (ShouldUseAOTHClass(ihc, chc, classLiteral)) {
1023             classLiteral->SetIsAOTUsed(true);
1024             cls = ClassHelper::DefineClassWithIHClass(thread, base, extractor, lexenv, ihc, chc);
1025         } else {
1026             cls = ClassHelper::DefineClassFromExtractor(thread, base, extractor, lexenv);
1027         }
1028     }
1029 
1030     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1031     RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(cls), base);
1032     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1033 
1034     cls->SetLexicalEnv(thread, lexenv.GetTaggedValue());
1035     cls->SetModule(thread, module.GetTaggedValue());
1036     RuntimeSetClassConstructorLength(thread, cls.GetTaggedValue(), length.GetTaggedValue());
1037     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1038 
1039     return cls.GetTaggedValue();
1040 }
1041 
SetProfileTypeInfoCellToFunction(JSThread * thread,const JSHandle<JSFunction> & jsFunc,const JSHandle<JSFunction> & definedFunc,uint16_t slotId)1042 void RuntimeStubs::SetProfileTypeInfoCellToFunction(JSThread *thread, const JSHandle<JSFunction> &jsFunc,
1043                                                     const JSHandle<JSFunction> &definedFunc, uint16_t slotId)
1044 {
1045     if (slotId == ProfileTypeInfo::INVALID_SLOT_INDEX) {  // do nothing for invalid slotId
1046         return;
1047     }
1048 
1049     ASSERT(definedFunc->IsJSFunction());
1050     ASSERT(!definedFunc->IsSharedFunction());
1051     ASSERT(jsFunc->IsJSFunction());
1052     ASSERT(!jsFunc->IsSharedFunction());
1053 
1054     auto profileTypeInfo = jsFunc->GetProfileTypeInfo(thread);
1055     if (profileTypeInfo.IsUndefined()) {
1056         JSHandle<Method> method(thread, jsFunc->GetMethod(thread));
1057         uint32_t slotSize = method->GetSlotSize();
1058         profileTypeInfo = RuntimeNotifyInlineCache(thread, jsFunc, slotSize);
1059     }
1060 
1061     ASSERT(!profileTypeInfo.IsUndefined());
1062 
1063     JSHandle<ProfileTypeInfo> profileTypeArray(thread, profileTypeInfo);
1064     JSTaggedValue slotValue = profileTypeArray->Get(thread, slotId);
1065     if (slotValue.IsUndefined()) {
1066         JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
1067         JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
1068             thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
1069         profileTypeArray->Set(thread, slotId, newProfileTypeInfoCell);
1070         definedFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
1071     } else {
1072         auto cellPtr = ProfileTypeInfoCell::Cast(slotValue.GetTaggedObject());
1073         cellPtr->UpdateProfileTypeInfoCellType(thread);
1074         definedFunc->SetRawProfileTypeInfo(thread, slotValue);
1075     }
1076 }
1077 
RuntimeCreateSharedClass(JSThread * thread,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & constpool,uint16_t methodId,uint16_t literalId,uint16_t length,const JSHandle<JSTaggedValue> & module)1078 JSTaggedValue RuntimeStubs::RuntimeCreateSharedClass(JSThread *thread,
1079                                                      const JSHandle<JSTaggedValue> &base,
1080                                                      const JSHandle<JSTaggedValue> &constpool,
1081                                                      uint16_t methodId, uint16_t literalId,
1082                                                      uint16_t length, const JSHandle<JSTaggedValue> &module)
1083 {
1084     if (!base->IsJSShared() && !base->IsHole()) {
1085         THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(ClassNotDerivedFromShared), JSTaggedValue::Exception());
1086     }
1087     [[maybe_unused]] EcmaHandleScope handleScope(thread);
1088     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1089     CString entry = ModuleManager::GetRecordName(thread, module.GetTaggedValue());
1090 
1091     auto methodObj = ConstantPool::GetMethodFromCache(thread, constpool.GetTaggedValue(), methodId);
1092     JSHandle<JSTaggedValue> method(thread, methodObj);
1093     JSHandle<Method>(method)->SetIsSendable(true);
1094     JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
1095 
1096     JSHandle<JSTaggedValue> sendableEnv(thread, JSTaggedValue::Undefined());
1097     if (module->IsSourceTextModule()) {
1098         JSHandle<SourceTextModule> moduleRecord = JSHandle<SourceTextModule>::Cast(module);
1099         sendableEnv = JSHandle<JSTaggedValue>(thread, moduleRecord->GetSendableEnv(thread));
1100     }
1101     auto literalObj = ConstantPool::GetClassLiteralFromCache(
1102         thread, constpoolHandle, literalId, entry, sendableEnv, ClassKind::SENDABLE);
1103     JSHandle<ClassLiteral> classLiteral(thread, literalObj);
1104     JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray(thread));
1105     auto literalLength = arrayHandle->GetLength();
1106     ASSERT(literalLength > 0);
1107     // fieldTypeId is the last element in literal buffer
1108     auto fieldTypeId = static_cast<uint32_t>(arrayHandle->Get(thread, literalLength - 1).GetInt());
1109     // Don't trim array, because define class maybe called on muilt-time in the same vm or diferrent vm
1110     JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
1111     ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread, extractor, arrayHandle,
1112                                                            literalLength - 1, ClassKind::SENDABLE);
1113 
1114     JSHandle<TaggedArray> fieldTypeArray = ConstantPool::GetFieldLiteral(thread, constpoolHandle, fieldTypeId, entry);
1115     JSHandle<TaggedArray> staticFieldArray = SendableClassDefiner::ExtractStaticFieldTypeArray(thread, fieldTypeArray);
1116     JSHandle<JSFunction> cls =
1117         SendableClassDefiner::DefineSendableClassFromExtractor(thread, extractor, staticFieldArray);
1118     ModuleManager *moduleManager = thread->GetModuleManager();
1119     JSHandle<JSTaggedValue> sendableClsModule = moduleManager->GenerateSendableFuncModule(module);
1120     if (sendableClsModule->IsSourceTextModule()) {
1121         JSHandle<SourceTextModule> sendableClsModuleRecord(sendableClsModule);
1122         sendableClsModuleRecord->SetSendableEnv(thread, sendableEnv);
1123     }
1124     cls->SetModule(thread, sendableClsModule.GetTaggedValue());
1125     RuntimeSetClassConstructorLength(thread, cls.GetTaggedValue(), JSTaggedValue(length));
1126     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1127     RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(cls), base, ClassKind::SENDABLE);
1128     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1129 
1130     uint32_t arrayLength = fieldTypeArray->GetLength();
1131     ASSERT(arrayLength > 0);
1132     auto instanceFieldNums = static_cast<uint32_t>(fieldTypeArray->Get(thread, arrayLength - 1).GetInt());
1133     // Don't trim array, because define class maybe called on muilt-time in the same vm or diferrent vm
1134     uint32_t instanceLength = instanceFieldNums * 2;  // 2: key and value
1135     ASSERT(instanceLength < arrayLength);
1136     SendableClassDefiner::DefineSendableInstanceHClass(thread, fieldTypeArray, instanceLength, cls, base);
1137     return cls.GetTaggedValue();
1138 }
1139 
RuntimeSetClassInheritanceRelationship(JSThread * thread,const JSHandle<JSTaggedValue> & ctor,const JSHandle<JSTaggedValue> & base,ClassKind kind)1140 JSTaggedValue RuntimeStubs::RuntimeSetClassInheritanceRelationship(JSThread *thread,
1141                                                                    const JSHandle<JSTaggedValue> &ctor,
1142                                                                    const JSHandle<JSTaggedValue> &base,
1143                                                                    ClassKind kind)
1144 {
1145     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1146     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1147 
1148     ASSERT(ctor->IsJSFunction());
1149     JSHandle<JSTaggedValue> parent = base;
1150 
1151     /*
1152      *         class A / class A extends null                             class A extends B
1153      *                                       a                                                 a
1154      *                                       |                                                 |
1155      *                                       |  __proto__                                      |  __proto__
1156      *                                       |                                                 |
1157      *       A            ---->         A.prototype                  A             ---->    A.prototype
1158      *       |                               |                       |                         |
1159      *       |  __proto__                    |  __proto__            |  __proto__              |  __proto__
1160      *       |                               |                       |                         |
1161      *   Function.prototype       Object.prototype / null            B             ---->    B.prototype
1162      */
1163 
1164     JSHandle<JSTaggedValue> parentPrototype;
1165     // hole means parent is not present
1166     Method *method = Method::Cast(JSHandle<JSFunction>::Cast(ctor)->GetMethod(thread).GetTaggedObject());
1167     if (parent->IsHole()) {
1168         method->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
1169         parentPrototype =
1170             (kind == ClassKind::SENDABLE) ? env->GetSObjectFunctionPrototype() : env->GetObjectFunctionPrototype();
1171         parent = (kind == ClassKind::SENDABLE) ? env->GetSFunctionPrototype() : env->GetFunctionPrototype();
1172     } else if (parent->IsNull()) {
1173         method->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
1174         parentPrototype = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Null());
1175         parent = (kind == ClassKind::SENDABLE) ? env->GetSFunctionPrototype() : env->GetFunctionPrototype();
1176     } else if (!parent->IsConstructor()) {
1177         return RuntimeThrowTypeError(thread, "parent class is not constructor");
1178     } else {
1179         method->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
1180         parentPrototype = JSTaggedValue::GetProperty(thread, parent,
1181             globalConst->GetHandledPrototypeString()).GetValue();
1182         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1183         if (!parentPrototype->IsECMAObject() && !parentPrototype->IsNull()) {
1184             return RuntimeThrowTypeError(thread, "parent class have no valid prototype");
1185         }
1186     }
1187 
1188     ctor->GetTaggedObject()->GetClass()->SetPrototype(thread, parent); // __proto__
1189 
1190     JSHandle<JSObject> clsPrototype(thread, JSHandle<JSFunction>(ctor)->GetFunctionPrototype(thread));
1191     clsPrototype->GetClass()->SetPrototype(thread, parentPrototype);
1192 
1193     // ctor -> hclass -> EnableProtoChangeMarker
1194     auto constructor = JSFunction::Cast(ctor.GetTaggedValue().GetTaggedObject());
1195     if (constructor->GetClass()->IsAOT()) {
1196         JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(thread, constructor->GetClass()));
1197         // prototype -> hclass -> EnableProtoChangeMarker
1198         JSHClass::EnableProtoChangeMarker(
1199             thread,
1200             JSHandle<JSHClass>(thread, constructor->GetFunctionPrototype(thread).GetTaggedObject()->GetClass()));
1201     }
1202 
1203     // by enableing the ProtoChangeMarker, the IHC generated in the Aot stage
1204     // is registered into the listener of its prototype. In this way, it is ensured
1205     // that when the prototype changes, the affected IHC can be notified.
1206     JSTaggedValue protoOrHClass = JSHandle<JSFunction>(ctor)->GetProtoOrHClass(thread);
1207     if (protoOrHClass.IsJSHClass()) {
1208         JSHClass *ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject());
1209         if (ihc->IsAOT()) {
1210             JSHandle<JSHClass> ihcHandle(thread, ihc);
1211             JSHClass::EnableProtoChangeMarker(thread, ihcHandle);
1212         }
1213     } else {
1214         JSHandle<JSObject> protoHandle(thread, protoOrHClass);
1215         if (protoHandle->GetJSHClass()->IsAOT()) {
1216             JSHClass::EnablePHCProtoChangeMarker(thread, JSHandle<JSHClass>(thread, protoHandle->GetJSHClass()));
1217         }
1218     }
1219 
1220     return JSTaggedValue::Undefined();
1221 }
1222 
RuntimeSetClassConstructorLength(JSThread * thread,JSTaggedValue ctor,JSTaggedValue length)1223 JSTaggedValue RuntimeStubs::RuntimeSetClassConstructorLength(JSThread *thread, JSTaggedValue ctor,
1224                                                              JSTaggedValue length)
1225 {
1226     ASSERT(ctor.IsClassConstructor());
1227 
1228     JSFunction* cls = JSFunction::Cast(ctor.GetTaggedObject());
1229     if (LIKELY(!cls->GetClass()->IsDictionaryMode())) {
1230         cls->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length);
1231     } else {
1232         const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1233         cls->UpdatePropertyInDictionary(thread, globalConst->GetLengthString(), length);
1234     }
1235     return JSTaggedValue::Undefined();
1236 }
1237 
RuntimeNotifyInlineCache(JSThread * thread,const JSHandle<JSFunction> & function,uint32_t icSlotSize)1238 JSTaggedValue RuntimeStubs::RuntimeNotifyInlineCache(JSThread *thread, const JSHandle<JSFunction> &function,
1239                                                      uint32_t icSlotSize)
1240 {
1241     // max ic slot index is 0xffff, the size of ic slot could extend more
1242     ASSERT(icSlotSize <= ProfileTypeInfo::MAX_SLOT_INDEX + MethodLiteral::EXTEND_SLOT_SIZE);
1243     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1244     JSHandle<ProfileTypeInfo> profileTypeInfo;
1245     if (function->IsSharedFunction()) {
1246         return JSTaggedValue::Undefined();
1247     } else {
1248         profileTypeInfo = factory->NewProfileTypeInfo(icSlotSize);
1249     }
1250     Method *method = Method::Cast(function->GetMethod(thread));
1251     auto codeSize = method->GetCodeSize(thread);
1252     if (pgo::PGOProfilerManager::GetInstance()->IsBigMethod(codeSize)) {
1253         LOG_ECMA(DEBUG) << "method size is too large, skip pgo. code size: " << codeSize
1254                         << ", max code size: " << pgo::PGOProfilerManager::GetInstance()->GetMaxAotMethodSize();
1255         profileTypeInfo->SetBigMethodPeriodIndex();
1256     }
1257     JSFunction::SetProfileTypeInfo(thread, function, JSHandle<JSTaggedValue>::Cast(profileTypeInfo));
1258     return profileTypeInfo.GetTaggedValue();
1259 }
1260 
RuntimeStOwnByValueWithNameSet(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)1261 JSTaggedValue RuntimeStubs::RuntimeStOwnByValueWithNameSet(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
1262                                                            const JSHandle<JSTaggedValue> &key,
1263                                                            const JSHandle<JSTaggedValue> &value)
1264 {
1265     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1266 
1267     if (obj->IsClassConstructor() && JSTaggedValue::SameValue(thread, key, globalConst->GetHandledPrototypeString())) {
1268         return RuntimeThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
1269     }
1270 
1271     // property in class is non-enumerable
1272     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
1273 
1274     PropertyDescriptor desc(thread, value, true, enumerable, true);
1275     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, key);
1276     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1277     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, propKey, desc);
1278     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1279     if (!ret) {
1280         return RuntimeThrowTypeError(thread, "StOwnByValueWithNameSet failed");
1281     }
1282     if (value->IsJSFunction()) {
1283         if (propKey->IsNumber()) {
1284             propKey = JSHandle<JSTaggedValue>(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
1285         }
1286         JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(value), propKey,
1287                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1288     }
1289     return JSTaggedValue::True();
1290 }
1291 
RuntimeStOwnByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)1292 JSTaggedValue RuntimeStubs::RuntimeStOwnByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
1293                                                const JSHandle<JSTaggedValue> &prop,
1294                                                const JSHandle<JSTaggedValue> &value)
1295 {
1296     ASSERT(prop->IsStringOrSymbol());
1297 
1298     // property in class is non-enumerable
1299     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
1300 
1301     PropertyDescriptor desc(thread, value, true, enumerable, true);
1302     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, prop, desc);
1303     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1304     if (!ret) {
1305         return RuntimeThrowTypeError(thread, "SetOwnByName failed");
1306     }
1307     return JSTaggedValue::True();
1308 }
1309 
RuntimeStOwnByNameWithNameSet(JSThread * thread,const JSHandle<JSTaggedValue> & objHandle,const JSHandle<JSTaggedValue> & propHandle,const JSHandle<JSTaggedValue> & valueHandle)1310 JSTaggedValue RuntimeStubs::RuntimeStOwnByNameWithNameSet(JSThread *thread,
1311                                                           const JSHandle<JSTaggedValue> &objHandle,
1312                                                           const JSHandle<JSTaggedValue> &propHandle,
1313                                                           const JSHandle<JSTaggedValue> &valueHandle)
1314 {
1315     ASSERT(propHandle->IsStringOrSymbol());
1316     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
1317     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1318     // property in class is non-enumerable
1319     bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1320 
1321     PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1322     bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propHandle, desc);
1323     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1324     if (!ret) {
1325         return RuntimeThrowTypeError(thread, "SetOwnByNameWithNameSet failed");
1326     }
1327     JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(valueHandle), propKey,
1328                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1329     return JSTaggedValue::True();
1330 }
1331 
RuntimeSuspendGenerator(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const JSHandle<JSTaggedValue> & value)1332 JSTaggedValue RuntimeStubs::RuntimeSuspendGenerator(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
1333                                                     const JSHandle<JSTaggedValue> &value)
1334 {
1335     if (genObj->IsAsyncGeneratorObject()) {
1336         JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
1337         JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext(thread));
1338         // save stack, should copy cur_frame, function execute over will free cur_frame
1339         SaveFrameToContext(thread, genContextHandle);
1340 
1341         // change state to SuspendedYield
1342         if (generatorObjectHandle->IsExecuting()) {
1343             return value.GetTaggedValue();
1344         }
1345         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1346         return generatorObjectHandle.GetTaggedValue();
1347     }
1348 
1349     if (genObj->IsGeneratorObject()) {
1350         JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
1351         JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext(thread));
1352         // set TaskInfo for TaskPool
1353         generatorObjectHandle->SetTaskInfo(thread->GetTaskInfo());
1354         // save stack, should copy cur_frame, function execute over will free cur_frame
1355         SaveFrameToContext(thread, genContextHandle);
1356 
1357         // change state to SuspendedYield
1358         if (generatorObjectHandle->IsExecuting()) {
1359             generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);
1360             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1361             return value.GetTaggedValue();
1362         }
1363         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1364         return generatorObjectHandle.GetTaggedValue();
1365     }
1366 
1367     return RuntimeThrowTypeError(thread, "RuntimeSuspendGenerator failed");
1368 }
1369 
RuntimeSetGeneratorState(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const int32_t index)1370 void RuntimeStubs::RuntimeSetGeneratorState(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
1371                                             const int32_t index)
1372 {
1373     JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
1374     JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext(thread));
1375 
1376     // change state
1377     switch (index) {
1378         case static_cast<int32_t>(JSAsyncGeneratorState::SUSPENDED_START):
1379             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_START);
1380             break;
1381         case static_cast<int32_t>(JSAsyncGeneratorState::SUSPENDED_YIELD):
1382             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_YIELD);
1383             break;
1384         case static_cast<int32_t>(JSAsyncGeneratorState::EXECUTING):
1385             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::EXECUTING);
1386             break;
1387         case static_cast<int32_t>(JSAsyncGeneratorState::COMPLETED):
1388             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::COMPLETED);
1389             break;
1390         case static_cast<int32_t>(JSAsyncGeneratorState::AWAITING_RETURN):
1391             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::AWAITING_RETURN);
1392             break;
1393         default:
1394             LOG_ECMA(FATAL) << "this branch is unreachable";
1395             UNREACHABLE();
1396     }
1397 }
1398 
RuntimeGetModuleNamespace(JSThread * thread,int32_t index)1399 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, int32_t index)
1400 {
1401     return ModuleValueAccessor::GetModuleNamespace(thread, index);
1402 }
1403 
RuntimeGetModuleNamespace(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1404 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, int32_t index,
1405                                                       JSTaggedValue jsFunc)
1406 {
1407     return ModuleValueAccessor::GetModuleNamespace(thread, index, jsFunc);
1408 }
1409 
RuntimeGetModuleNamespace(JSThread * thread,JSTaggedValue localName)1410 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, JSTaggedValue localName)
1411 {
1412     return DeprecatedModuleValueAccessor::GetModuleNamespace(thread, localName);
1413 }
1414 
RuntimeGetModuleNamespace(JSThread * thread,JSTaggedValue localName,JSTaggedValue jsFunc)1415 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, JSTaggedValue localName,
1416                                                       JSTaggedValue jsFunc)
1417 {
1418     return DeprecatedModuleValueAccessor::GetModuleNamespace(thread, localName, jsFunc);
1419 }
1420 
RuntimeStModuleVar(JSThread * thread,int32_t index,JSTaggedValue value)1421 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, int32_t index, JSTaggedValue value)
1422 {
1423     ModuleValueAccessor::StoreModuleValue(thread, index, value);
1424 }
1425 
RuntimeStModuleVar(JSThread * thread,int32_t index,JSTaggedValue value,JSTaggedValue jsFunc)1426 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, int32_t index, JSTaggedValue value,
1427                                       JSTaggedValue jsFunc)
1428 {
1429     ModuleValueAccessor::StoreModuleValue(thread, index, value, jsFunc);
1430 }
1431 
RuntimeStModuleVar(JSThread * thread,JSTaggedValue key,JSTaggedValue value)1432 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, JSTaggedValue key, JSTaggedValue value)
1433 {
1434     DeprecatedModuleValueAccessor::StoreModuleValue(thread, key, value);
1435 }
1436 
RuntimeStModuleVar(JSThread * thread,JSTaggedValue key,JSTaggedValue value,JSTaggedValue jsFunc)1437 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, JSTaggedValue key, JSTaggedValue value,
1438                                       JSTaggedValue jsFunc)
1439 {
1440     DeprecatedModuleValueAccessor::StoreModuleValue(thread, key, value, jsFunc);
1441 }
1442 
RuntimeLdLocalModuleVar(JSThread * thread,int32_t index)1443 JSTaggedValue RuntimeStubs::RuntimeLdLocalModuleVar(JSThread *thread, int32_t index)
1444 {
1445     return ModuleValueAccessor::GetModuleValueInner(thread, index);
1446 }
1447 
RuntimeLdLocalModuleVarWithModule(JSThread * thread,int32_t index,JSHandle<JSTaggedValue> moduleHdl)1448 inline JSTaggedValue RuntimeStubs::RuntimeLdLocalModuleVarWithModule(JSThread* thread, int32_t index,
1449     JSHandle<JSTaggedValue> moduleHdl)
1450 {
1451     JSTaggedValue module = moduleHdl.GetTaggedValue();
1452     ModuleManager* mmgr = thread->GetModuleManager();
1453     if (SourceTextModule::IsSendableFunctionModule(module)) {
1454         const CString recordNameStr = SourceTextModule::GetModuleName(module);
1455         module = mmgr->HostGetImportedModule(recordNameStr).GetTaggedValue();
1456     }
1457     return SourceTextModule::Cast(module)->GetModuleValue(thread, index, false);
1458 }
1459 
RuntimeLdLocalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1460 JSTaggedValue RuntimeStubs::RuntimeLdLocalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1461 {
1462     return ModuleValueAccessor::GetModuleValueInner(thread, index, jsFunc);
1463 }
1464 
RuntimeLdExternalModuleVar(JSThread * thread,int32_t index)1465 JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t index)
1466 {
1467     return ModuleValueAccessor::GetModuleValueOuter(thread, index);
1468 }
1469 
RuntimeLdExternalModuleVarWithModule(JSThread * thread,int32_t index,JSHandle<JSTaggedValue> moduleHdl)1470 inline JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVarWithModule(JSThread* thread, int32_t index,
1471     JSHandle<JSTaggedValue> moduleHdl)
1472 {
1473     JSTaggedValue module = moduleHdl.GetTaggedValue();
1474     ModuleManager* mmgr = thread->GetModuleManager();
1475     if (SourceTextModule::IsSendableFunctionModule(module)) {
1476         const CString recordNameStr = SourceTextModule::GetModuleName(module);
1477         module = mmgr->HostGetImportedModule(recordNameStr).GetTaggedValue();
1478         moduleHdl = JSHandle<JSTaggedValue>(thread, module);
1479     }
1480     return ModuleValueAccessor::GetModuleValueOuter(thread, index, moduleHdl);
1481 }
1482 
RuntimeLdSendableExternalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1483 JSTaggedValue RuntimeStubs::RuntimeLdSendableExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1484 {
1485     return ModuleValueAccessor::GetSendableModuleValueOuter(thread, index, jsFunc);
1486 }
1487 
RuntimeLdSendableLocalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1488 JSTaggedValue RuntimeStubs::RuntimeLdSendableLocalModuleVar(JSThread* thread, int32_t index, JSTaggedValue jsFunc)
1489 {
1490     return ModuleValueAccessor::GetSendableModuleValueInner(thread, index, jsFunc);
1491 }
1492 
RuntimeLdExternalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1493 JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1494 {
1495     return ModuleValueAccessor::GetModuleValueOuter(thread, index, jsFunc);
1496 }
1497 
RuntimeLdLazyExternalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1498 JSTaggedValue RuntimeStubs::RuntimeLdLazyExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1499 {
1500     return ModuleValueAccessor::GetLazyModuleValueOuter(thread, index, jsFunc);
1501 }
1502 
RuntimeLdLazySendableExternalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1503 JSTaggedValue RuntimeStubs::RuntimeLdLazySendableExternalModuleVar(
1504     JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1505 {
1506     return ModuleValueAccessor::GetLazySendableModuleValueOuter(thread, index, jsFunc);
1507 }
1508 
RuntimeLdModuleVar(JSThread * thread,JSTaggedValue key,bool inner)1509 JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner)
1510 {
1511     if (inner) {
1512         JSTaggedValue moduleValue = DeprecatedModuleValueAccessor::GetModuleValueInner(thread, key);
1513         return moduleValue;
1514     }
1515 
1516     return DeprecatedModuleValueAccessor::GetModuleValueOuter(thread, key);
1517 }
1518 
RuntimeLdModuleVar(JSThread * thread,JSTaggedValue key,bool inner,JSTaggedValue jsFunc)1519 JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner,
1520                                                JSTaggedValue jsFunc)
1521 {
1522     if (inner) {
1523         JSTaggedValue moduleValue = DeprecatedModuleValueAccessor::GetModuleValueInner(thread, key, jsFunc);
1524         return moduleValue;
1525     }
1526 
1527     return DeprecatedModuleValueAccessor::GetModuleValueOuter(thread, key, jsFunc);
1528 }
1529 
RuntimeGetPropIterator(JSThread * thread,const JSHandle<JSTaggedValue> & value)1530 JSTaggedValue RuntimeStubs::RuntimeGetPropIterator(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1531 {
1532     JSHandle<JSForInIterator> iteratorHandle = JSObject::EnumerateObjectProperties(thread, value);
1533     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1534     return iteratorHandle.GetTaggedValue();
1535 }
1536 
RuntimeAsyncFunctionEnter(JSThread * thread)1537 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionEnter(JSThread *thread)
1538 {
1539     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1540     // 1. create promise
1541     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
1542     JSHandle<JSFunction> promiseFunc(globalEnv->GetPromiseFunction());
1543 
1544     JSHandle<JSPromise> promiseObject(factory->NewJSObjectByConstructor(promiseFunc));
1545     if (thread->GetEcmaVM()->GetJSOptions().EnablePendingCheak()) {
1546         thread->GetEcmaVM()->InsertAsyncStackTrace(promiseObject);
1547     }
1548     promiseObject->SetPromiseState(PromiseState::PENDING);
1549     // 2. create asyncfuncobj
1550     JSHandle<JSAsyncFuncObject> asyncFuncObj = factory->NewJSAsyncFuncObject();
1551     asyncFuncObj->SetPromise(thread, promiseObject);
1552 
1553     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
1554     context->SetGeneratorObject(thread, asyncFuncObj);
1555 
1556     // change state to EXECUTING
1557     asyncFuncObj->SetGeneratorState(JSGeneratorState::EXECUTING);
1558     asyncFuncObj->SetGeneratorContext(thread, context);
1559 
1560     // 3. return asyncfuncobj
1561     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1562     return asyncFuncObj.GetTaggedValue();
1563 }
1564 
RuntimeGetIterator(JSThread * thread,const JSHandle<JSTaggedValue> & obj)1565 JSTaggedValue RuntimeStubs::RuntimeGetIterator(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
1566 {
1567     EcmaVM *vm = thread->GetEcmaVM();
1568     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1569     JSHandle<JSTaggedValue> valuesFunc =
1570         JSTaggedValue::GetProperty(thread, obj, env->GetIteratorSymbol()).GetValue();
1571     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1572     if (!valuesFunc->IsCallable()) {
1573         return valuesFunc.GetTaggedValue();
1574     }
1575 
1576     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1577     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, valuesFunc, obj, undefined, 0);
1578     return EcmaInterpreter::Execute(info);
1579 }
1580 
RuntimeGetAsyncIterator(JSThread * thread,const JSHandle<JSTaggedValue> & obj)1581 JSTaggedValue RuntimeStubs::RuntimeGetAsyncIterator(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
1582 {
1583     JSHandle<JSTaggedValue> asyncit = JSIterator::GetAsyncIterator(thread, obj);
1584     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1585     return asyncit.GetTaggedValue();
1586 }
1587 
RuntimeLdPrivateProperty(JSThread * thread,JSTaggedValue lexicalEnv,uint32_t levelIndex,uint32_t slotIndex,JSTaggedValue obj)1588 JSTaggedValue RuntimeStubs::RuntimeLdPrivateProperty(JSThread *thread, JSTaggedValue lexicalEnv,
1589     uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj)
1590 {
1591     JSTaggedValue currentLexicalEnv = lexicalEnv;
1592     for (uint32_t i = 0; i < levelIndex; i++) {
1593         currentLexicalEnv = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetParentEnv(thread);
1594         ASSERT(!currentLexicalEnv.IsUndefined());
1595     }
1596     JSTaggedValue key = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetProperties(thread, slotIndex);
1597     // private property is invisible for proxy
1598     JSHandle<JSTaggedValue> handleObj(thread, obj.IsJSProxy() ? JSProxy::Cast(obj)->GetPrivateField(thread) : obj);
1599     JSHandle<JSTaggedValue> handleKey(thread, key);
1600     if (handleKey->IsJSFunction()) {  // getter
1601         JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1602         // 0: getter has 0 arg
1603         EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, handleKey, handleObj, undefined, 0);
1604         JSTaggedValue resGetter = JSFunction::Call(info);
1605         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1606         return resGetter;
1607     }
1608     PropertyDescriptor desc(thread);
1609     if (!JSTaggedValue::IsPropertyKey(handleKey) ||
1610         !JSTaggedValue::GetOwnProperty(thread, handleObj, handleKey, desc)) {
1611         THROW_TYPE_ERROR_AND_RETURN(thread, "invalid or cannot find private key", JSTaggedValue::Exception());
1612     }
1613     JSTaggedValue res = desc.GetValue().GetTaggedValue();
1614     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1615     return res;
1616 }
1617 
RuntimeStPrivateProperty(JSThread * thread,JSTaggedValue lexicalEnv,uint32_t levelIndex,uint32_t slotIndex,JSTaggedValue obj,JSTaggedValue value)1618 JSTaggedValue RuntimeStubs::RuntimeStPrivateProperty(JSThread *thread, JSTaggedValue lexicalEnv,
1619     uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj, JSTaggedValue value)
1620 {
1621     JSTaggedValue currentLexicalEnv = lexicalEnv;
1622     for (uint32_t i = 0; i < levelIndex; i++) {
1623         currentLexicalEnv = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetParentEnv(thread);
1624         ASSERT(!currentLexicalEnv.IsUndefined());
1625     }
1626     JSTaggedValue key = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetProperties(thread, slotIndex);
1627     // private property is invisible for proxy
1628     JSHandle<JSTaggedValue> handleObj(thread, obj.IsJSProxy() ? JSProxy::Cast(obj)->GetPrivateField(thread) : obj);
1629     JSHandle<JSTaggedValue> handleKey(thread, key);
1630     JSHandle<JSTaggedValue> handleValue(thread, value);
1631     if (handleKey->IsJSFunction()) {  // setter
1632         JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1633         // 1: setter has 1 arg
1634         EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, handleKey, handleObj, undefined, 1);
1635         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1636         info->SetCallArg(handleValue.GetTaggedValue());
1637         JSTaggedValue resSetter = JSFunction::Call(info);
1638         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1639         return resSetter;
1640     }
1641     PropertyDescriptor desc(thread);
1642     if (!JSTaggedValue::IsPropertyKey(handleKey) ||
1643         !JSTaggedValue::GetOwnProperty(thread, handleObj, handleKey, desc)) {
1644         THROW_TYPE_ERROR_AND_RETURN(thread, "invalid or cannot find private key", JSTaggedValue::Exception());
1645     }
1646     desc.SetValue(handleValue);
1647     bool res = JSTaggedValue::DefineOwnProperty(thread, handleObj, handleKey, desc);
1648     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1649     return JSTaggedValue(res);
1650 }
1651 
RuntimeTestIn(JSThread * thread,JSTaggedValue lexicalEnv,uint32_t levelIndex,uint32_t slotIndex,JSTaggedValue obj)1652 JSTaggedValue RuntimeStubs::RuntimeTestIn(JSThread *thread, JSTaggedValue lexicalEnv,
1653     uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj)
1654 {
1655     if (!obj.IsECMAObject()) {
1656         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot use 'in' operator in Non-Object", JSTaggedValue::Exception());
1657     }
1658     JSTaggedValue currentLexicalEnv = lexicalEnv;
1659     for (uint32_t i = 0; i < levelIndex; i++) {
1660         currentLexicalEnv = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetParentEnv(thread);
1661         ASSERT(!currentLexicalEnv.IsUndefined());
1662     }
1663     JSTaggedValue key = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetProperties(thread, slotIndex);
1664     JSHandle<JSTaggedValue> handleObj(thread, obj.IsJSProxy() ? JSProxy::Cast(obj)->GetPrivateField(thread) : obj);
1665     JSHandle<JSTaggedValue> handleKey(thread, key);
1666     bool res = JSTaggedValue::IsPropertyKey(handleKey) && JSTaggedValue::HasProperty(thread, handleObj, handleKey);
1667     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1668     return JSTaggedValue(res);
1669 }
1670 
RuntimeThrow(JSThread * thread,JSTaggedValue value)1671 void RuntimeStubs::RuntimeThrow(JSThread *thread, JSTaggedValue value)
1672 {
1673     thread->SetException(value);
1674 }
1675 
RuntimeThrowThrowNotExists(JSThread * thread)1676 void RuntimeStubs::RuntimeThrowThrowNotExists(JSThread *thread)
1677 {
1678     THROW_TYPE_ERROR(thread, "Throw method is not defined");
1679 }
1680 
RuntimeThrowPatternNonCoercible(JSThread * thread)1681 void RuntimeStubs::RuntimeThrowPatternNonCoercible(JSThread *thread)
1682 {
1683     JSHandle<EcmaString> msg(thread->GlobalConstants()->GetHandledObjNotCoercibleString());
1684     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1685     THROW_NEW_ERROR_AND_RETURN(thread,
1686         factory->NewJSError(base::ErrorType::TYPE_ERROR, msg, StackCheck::NO).GetTaggedValue());
1687 }
1688 
RuntimeThrowDeleteSuperProperty(JSThread * thread)1689 void RuntimeStubs::RuntimeThrowDeleteSuperProperty(JSThread *thread)
1690 {
1691     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1692     JSHandle<EcmaString> info = factory->NewFromASCII("Can not delete super property");
1693     JSHandle<JSObject> errorObj = factory->NewJSError(base::ErrorType::REFERENCE_ERROR, info,  StackCheck::NO);
1694     THROW_NEW_ERROR_AND_RETURN(thread, errorObj.GetTaggedValue());
1695 }
1696 
RuntimeThrowUndefinedIfHole(JSThread * thread,const JSHandle<EcmaString> & obj)1697 void RuntimeStubs::RuntimeThrowUndefinedIfHole(JSThread *thread, const JSHandle<EcmaString> &obj)
1698 {
1699     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1700     JSHandle<EcmaString> info(thread->GlobalConstants()->GetHandledNotInitializedString());
1701 
1702     JSHandle<EcmaString> msg = factory->ConcatFromString(obj, info);
1703     THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::REFERENCE_ERROR,
1704         msg, StackCheck::NO).GetTaggedValue());
1705 }
1706 
RuntimeThrowIfNotObject(JSThread * thread)1707 void RuntimeStubs::RuntimeThrowIfNotObject(JSThread *thread)
1708 {
1709     THROW_TYPE_ERROR(thread, "Inner return result is not object");
1710 }
1711 
RuntimeThrowConstAssignment(JSThread * thread,const JSHandle<EcmaString> & value)1712 void RuntimeStubs::RuntimeThrowConstAssignment(JSThread *thread, const JSHandle<EcmaString> &value)
1713 {
1714     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1715 
1716     JSHandle<EcmaString> info = factory->NewFromASCII("Assignment to const variable ");
1717 
1718     JSHandle<EcmaString> msg = factory->ConcatFromString(info, value);
1719     THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::TYPE_ERROR,
1720                                                            msg, StackCheck::NO).GetTaggedValue());
1721 }
1722 
RuntimeLdGlobalRecord(JSThread * thread,JSTaggedValue key)1723 JSTaggedValue RuntimeStubs::RuntimeLdGlobalRecord(JSThread *thread, JSTaggedValue key)
1724 {
1725     EcmaVM *vm = thread->GetEcmaVM();
1726     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1727     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1728     int entry = dict->FindEntry(thread, key);
1729     if (entry != -1) {
1730         return JSTaggedValue(dict->GetBox(thread, entry));
1731     }
1732     return JSTaggedValue::Undefined();
1733 }
1734 
RuntimeTryLdGlobalByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop)1735 JSTaggedValue RuntimeStubs::RuntimeTryLdGlobalByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
1736                                                      const JSHandle<JSTaggedValue> &prop)
1737 {
1738     OperationResult res = JSTaggedValue::GetProperty(thread, obj, prop);
1739     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1740     if (!res.GetPropertyMetaData().IsFound()) {
1741         return RuntimeThrowReferenceError(thread, prop, " is not defined");
1742     }
1743     return res.GetValue().GetTaggedValue();
1744 }
1745 
RuntimeTryUpdateGlobalRecord(JSThread * thread,JSTaggedValue prop,JSTaggedValue value)1746 JSTaggedValue RuntimeStubs::RuntimeTryUpdateGlobalRecord(JSThread *thread, JSTaggedValue prop,
1747                                                          JSTaggedValue value)
1748 {
1749     EcmaVM *vm = thread->GetEcmaVM();
1750     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1751     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1752     int entry = dict->FindEntry(thread, prop);
1753     ASSERT(entry != -1);
1754 
1755     if (dict->GetAttributes(thread, entry).IsConstProps()) {
1756         return RuntimeThrowTypeError(thread, "const variable can not be modified");
1757     }
1758 
1759     PropertyBox *box = dict->GetBox(thread, entry);
1760     box->SetValue(thread, value);
1761     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1762     return JSTaggedValue::True();
1763 }
1764 
RuntimeThrowReferenceError(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const char * desc)1765 JSTaggedValue RuntimeStubs::RuntimeThrowReferenceError(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
1766                                                        const char *desc)
1767 {
1768     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1769     JSHandle<EcmaString> propName = JSTaggedValue::ToString(thread, prop);
1770     ASSERT_NO_ABRUPT_COMPLETION(thread);
1771     JSHandle<EcmaString> info = factory->NewFromUtf8(desc);
1772     JSHandle<EcmaString> msg = factory->ConcatFromString(propName, info);
1773     THROW_NEW_ERROR_AND_RETURN_VALUE(thread,
1774         factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg, StackCheck::NO).GetTaggedValue(),
1775         JSTaggedValue::Exception());
1776 }
1777 
RuntimeLdGlobalVarFromProto(JSThread * thread,const JSHandle<JSTaggedValue> & globalObj,const JSHandle<JSTaggedValue> & prop)1778 JSTaggedValue RuntimeStubs::RuntimeLdGlobalVarFromProto(JSThread *thread, const JSHandle<JSTaggedValue> &globalObj,
1779                                                         const JSHandle<JSTaggedValue> &prop)
1780 {
1781     ASSERT(globalObj->IsJSGlobalObject());
1782     JSHandle<JSObject> global(globalObj);
1783     JSHandle<JSTaggedValue> obj(thread, JSObject::GetPrototype(thread, global));
1784     OperationResult res = JSTaggedValue::GetProperty(thread, obj, prop);
1785     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1786     return res.GetValue().GetTaggedValue();
1787 }
1788 
RuntimeStGlobalVar(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)1789 JSTaggedValue RuntimeStubs::RuntimeStGlobalVar(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
1790                                                const JSHandle<JSTaggedValue> &value)
1791 {
1792     JSHandle<JSTaggedValue> global(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject());
1793 
1794     JSObject::GlobalSetProperty(thread, prop, value, true);
1795     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1796     return JSTaggedValue::True();
1797 }
1798 
RuntimeToNumber(JSThread * thread,const JSHandle<JSTaggedValue> & value)1799 JSTaggedValue RuntimeStubs::RuntimeToNumber(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1800 {
1801     return JSTaggedValue::ToNumber(thread, value);
1802 }
1803 
RuntimeToNumeric(JSThread * thread,const JSHandle<JSTaggedValue> & value)1804 JSTaggedValue RuntimeStubs::RuntimeToNumeric(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1805 {
1806     return JSTaggedValue::ToNumeric(thread, value).GetTaggedValue();
1807 }
1808 
RuntimeDynamicImport(JSThread * thread,const JSHandle<JSTaggedValue> & specifier,const JSHandle<JSTaggedValue> & func)1809 JSTaggedValue RuntimeStubs::RuntimeDynamicImport(JSThread *thread, const JSHandle<JSTaggedValue> &specifier,
1810     const JSHandle<JSTaggedValue> &func)
1811 {
1812     EcmaVM *ecmaVm = thread->GetEcmaVM();
1813     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
1814     ObjectFactory *factory = ecmaVm->GetFactory();
1815 
1816     // get current filename
1817     JSFunction *function = JSFunction::Cast(func->GetTaggedObject());
1818     const JSPandaFile *jsPandaFile = function->GetCallTarget(thread)->GetJSPandaFile(thread);
1819     ASSERT(jsPandaFile != nullptr);
1820     CString currentfilename = jsPandaFile->GetJSPandaFileDesc();
1821 
1822     JSMutableHandle<JSTaggedValue> dirPath(thread, thread->GlobalConstants()->GetUndefined());
1823     JSMutableHandle<JSTaggedValue> recordName(thread, thread->GlobalConstants()->GetUndefined());
1824     if (jsPandaFile->IsBundlePack()) {
1825         dirPath.Update(factory->NewFromUtf8(currentfilename).GetTaggedValue());
1826     } else {
1827         recordName.Update(factory->NewFromUtf8(function->GetRecordName(thread)));
1828         dirPath.Update(factory->NewFromUtf8(currentfilename).GetTaggedValue());
1829     }
1830 
1831     // 4. Let promiseCapability be !NewPromiseCapability(%Promise%).
1832     JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
1833     JSHandle<PromiseCapability> promiseCapability = JSPromise::NewPromiseCapability(thread, promiseFunc);
1834     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1835     JSHandle<job::MicroJobQueue> job = ecmaVm->GetMicroJobQueue();
1836 
1837     JSHandle<TaggedArray> argv = factory->NewTaggedArray(5); // 5: 5 means parameters stored in array
1838     argv->Set(thread, 0, promiseCapability->GetResolve(thread));
1839     argv->Set(thread, 1, promiseCapability->GetReject(thread));  // 1 : reject method
1840     argv->Set(thread, 2, dirPath);                           // 2 : current file path(containing file name)
1841     argv->Set(thread, 3, specifier);                         // 3 : request module's path
1842     argv->Set(thread, 4, recordName);                        // 4 : js recordName or undefined
1843 
1844     JSHandle<JSFunction> dynamicImportJob(env->GetDynamicImportJob());
1845     job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, dynamicImportJob, argv);
1846 
1847     return promiseCapability->GetPromise(thread);
1848 }
1849 
RuntimeEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1850 JSTaggedValue RuntimeStubs::RuntimeEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1851                                       const JSHandle<JSTaggedValue> &right)
1852 {
1853     bool ret = JSTaggedValue::Equal(thread, left, right);
1854     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1855     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1856 }
1857 
RuntimeNotEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1858 JSTaggedValue RuntimeStubs::RuntimeNotEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1859                                          const JSHandle<JSTaggedValue> &right)
1860 {
1861     bool ret = JSTaggedValue::Equal(thread, left, right);
1862     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1863     return (ret ? JSTaggedValue::False() : JSTaggedValue::True());
1864 }
1865 
RuntimeLess(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1866 JSTaggedValue RuntimeStubs::RuntimeLess(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1867                                         const JSHandle<JSTaggedValue> &right)
1868 {
1869     bool ret = JSTaggedValue::Compare(thread, left, right) == ComparisonResult::LESS;
1870     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1871     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1872 }
1873 
RuntimeLessEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1874 JSTaggedValue RuntimeStubs::RuntimeLessEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1875                                           const JSHandle<JSTaggedValue> &right)
1876 {
1877     bool ret = JSTaggedValue::Compare(thread, left, right) <= ComparisonResult::EQUAL;
1878     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1879     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1880 }
1881 
RuntimeGreater(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1882 JSTaggedValue RuntimeStubs::RuntimeGreater(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1883                                            const JSHandle<JSTaggedValue> &right)
1884 {
1885     bool ret = JSTaggedValue::Compare(thread, left, right) == ComparisonResult::GREAT;
1886     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1887     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1888 }
1889 
RuntimeGreaterEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1890 JSTaggedValue RuntimeStubs::RuntimeGreaterEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1891                                              const JSHandle<JSTaggedValue> &right)
1892 {
1893     ComparisonResult comparison = JSTaggedValue::Compare(thread, left, right);
1894     bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
1895     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1896     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1897 }
1898 
RuntimeAdd2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1899 JSTaggedValue RuntimeStubs::RuntimeAdd2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1900                                         const JSHandle<JSTaggedValue> &right)
1901 {
1902     if (left->IsString() && right->IsString()) {
1903         EcmaString *resultStr = EcmaStringAccessor::Concat(
1904             thread->GetEcmaVM(), JSHandle<EcmaString>(left), JSHandle<EcmaString>(right));
1905         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1906         return JSTaggedValue(resultStr);
1907     }
1908     JSHandle<JSTaggedValue> primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, left));
1909     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1910     JSHandle<JSTaggedValue> primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, right));
1911     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1912     // contain string
1913     if (primitiveA0->IsString() || primitiveA1->IsString()) {
1914         JSHandle<EcmaString> stringA0 = JSTaggedValue::ToString(thread, primitiveA0);
1915         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1916         JSHandle<EcmaString> stringA1 = JSTaggedValue::ToString(thread, primitiveA1);
1917         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1918         EcmaString *resultStr = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1);
1919         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1920         return JSTaggedValue(resultStr);
1921     }
1922     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, primitiveA0);
1923     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1924     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, primitiveA1);
1925     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1926     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1927         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1928             JSHandle<BigInt> bigLeft(valLeft);
1929             JSHandle<BigInt> bigRight(valRight);
1930             return BigInt::Add(thread, bigLeft, bigRight).GetTaggedValue();
1931         }
1932         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1933     }
1934     double doubleA0 = valLeft->GetNumber();
1935     double doubleA1 = valRight->GetNumber();
1936     return JSTaggedValue(doubleA0 + doubleA1);
1937 }
1938 
RuntimeShl2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1939 JSTaggedValue RuntimeStubs::RuntimeShl2(JSThread *thread,
1940                                         const JSHandle<JSTaggedValue> &left,
1941                                         const JSHandle<JSTaggedValue> &right)
1942 {
1943     JSHandle<JSTaggedValue> leftValue = JSTaggedValue::ToNumeric(thread, left);
1944     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1945     JSHandle<JSTaggedValue> rightValue = JSTaggedValue::ToNumeric(thread, right);
1946     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1947     if (leftValue->IsBigInt() || rightValue->IsBigInt()) {
1948         if (leftValue->IsBigInt() && rightValue->IsBigInt()) {
1949             JSHandle<BigInt> leftBigint(leftValue);
1950             JSHandle<BigInt> rightBigint(rightValue);
1951             return BigInt::LeftShift(thread, leftBigint, rightBigint).GetTaggedValue();
1952         }
1953         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1954     }
1955     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, leftValue);
1956     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1957     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, rightValue);
1958     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1959     int32_t opNumber0 = taggedNumber0.GetInt();
1960     int32_t opNumber1 = taggedNumber1.GetInt();
1961     uint32_t shift =
1962             static_cast<uint32_t>(opNumber1) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1963     using unsigned_type = std::make_unsigned_t<int32_t>;
1964     auto ret =
1965             static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift);  // NOLINT(hicpp-signed-bitwise)
1966     return JSTaggedValue(ret);
1967 }
1968 
RuntimeShr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1969 JSTaggedValue RuntimeStubs::RuntimeShr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1970                                         const JSHandle<JSTaggedValue> &right)
1971 {
1972     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1973     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1974     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1975     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1976     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1977         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1978             return BigInt::UnsignedRightShift(thread);
1979         }
1980         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1981     }
1982     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1983     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1984     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1985     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1986     int32_t opNumber0 = taggedNumber0.GetInt();
1987     int32_t opNumber1 = taggedNumber1.GetInt();
1988     uint32_t shift = static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1989     using unsigned_type = std::make_unsigned_t<uint32_t>;
1990     auto ret =
1991             static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise)
1992     return JSTaggedValue(ret);
1993 }
1994 
RuntimeSub2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1995 JSTaggedValue RuntimeStubs::RuntimeSub2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1996                                         const JSHandle<JSTaggedValue> &right)
1997 {
1998     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1999     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2000     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2001     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2002     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2003         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2004             JSHandle<BigInt> bigLeft(valLeft);
2005             JSHandle<BigInt> bigRight(valRight);
2006             return BigInt::Subtract(thread, bigLeft, bigRight).GetTaggedValue();
2007         }
2008         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2009     }
2010     JSTaggedNumber number0(valLeft.GetTaggedValue());
2011     JSTaggedNumber number1(valRight.GetTaggedValue());
2012     return number0 - number1;
2013 }
2014 
RuntimeMul2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2015 JSTaggedValue RuntimeStubs::RuntimeMul2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2016                                         const JSHandle<JSTaggedValue> &right)
2017 {
2018     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2019     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2020     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2021     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2022     // 9. ReturnIfAbrupt(rnum).
2023     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2024         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2025             JSHandle<BigInt> bigLeft(valLeft);
2026             JSHandle<BigInt> bigRight(valRight);
2027             return BigInt::Multiply(thread, bigLeft, bigRight).GetTaggedValue();
2028         }
2029         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2030     }
2031     // 12.6.3.1 Applying the * Operator
2032     JSTaggedNumber number0(valLeft.GetTaggedValue());
2033     JSTaggedNumber number1(valRight.GetTaggedValue());
2034     return number0 * number1;
2035 }
2036 
RuntimeDiv2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2037 JSTaggedValue RuntimeStubs::RuntimeDiv2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2038                                         const JSHandle<JSTaggedValue> &right)
2039 {
2040     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2041     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2042     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2043     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2044     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2045         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2046             JSHandle<BigInt> bigLeft(valLeft);
2047             JSHandle<BigInt> bigRight(valRight);
2048             return BigInt::Divide(thread, bigLeft, bigRight).GetTaggedValue();
2049         }
2050         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2051     }
2052     double dLeft = valLeft->GetNumber();
2053     double dRight = valRight->GetNumber();
2054     if (dRight == 0) {
2055         if (dLeft == 0 || std::isnan(dLeft)) {
2056             return JSTaggedValue(base::NAN_VALUE);
2057         }
2058         bool positive = (((base::bit_cast<uint64_t>(dRight)) & base::DOUBLE_SIGN_MASK) ==
2059                          ((base::bit_cast<uint64_t>(dLeft)) & base::DOUBLE_SIGN_MASK));
2060         return JSTaggedValue(positive ? base::POSITIVE_INFINITY : -base::POSITIVE_INFINITY);
2061     }
2062     return JSTaggedValue(dLeft / dRight);
2063 }
2064 
RuntimeMod2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2065 JSTaggedValue RuntimeStubs::RuntimeMod2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2066                                         const JSHandle<JSTaggedValue> &right)
2067 {
2068     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2069     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2070     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2071     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2072 
2073     // 12.6.3.3 Applying the % Operator
2074     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2075         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2076             JSHandle<BigInt> leftBigint(valLeft);
2077             JSHandle<BigInt> rightBigint(valRight);
2078             return BigInt::Remainder(thread, leftBigint, rightBigint).GetTaggedValue();
2079         }
2080         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2081     }
2082     double dLeft = valLeft->GetNumber();
2083     double dRight = valRight->GetNumber();
2084     // 12.6.3.3 Applying the % Operator
2085     if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
2086         return JSTaggedValue(base::NAN_VALUE);
2087     }
2088     if ((dLeft == 0.0) || std::isinf(dRight)) {
2089         return JSTaggedValue(dLeft);
2090     }
2091     return JSTaggedValue(std::fmod(dLeft, dRight));
2092 }
2093 
RuntimeAshr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2094 JSTaggedValue RuntimeStubs::RuntimeAshr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2095                                          const JSHandle<JSTaggedValue> &right)
2096 {
2097     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2098     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2099     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2100     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2101     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2102         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2103             JSHandle<BigInt> bigLeft(valLeft);
2104             JSHandle<BigInt> bigRight(valRight);
2105             return BigInt::SignedRightShift(thread, bigLeft, bigRight).GetTaggedValue();
2106         }
2107         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2108     }
2109     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
2110     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2111     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
2112     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2113     int32_t opNumber0 = taggedNumber0.GetInt();
2114     int32_t opNumber1 = taggedNumber1.GetInt();
2115     uint32_t shift = static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
2116     auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise)
2117     return JSTaggedValue(ret);
2118 }
2119 
RuntimeAnd2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2120 JSTaggedValue RuntimeStubs::RuntimeAnd2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2121                                         const JSHandle<JSTaggedValue> &right)
2122 {
2123     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2124     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2125     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2126     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2127     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2128         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2129             JSHandle<BigInt> leftBigint(valLeft);
2130             JSHandle<BigInt> rightBigint(valRight);
2131             return BigInt::BitwiseAND(thread, leftBigint, rightBigint).GetTaggedValue();
2132         }
2133         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2134     }
2135     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
2136     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2137     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
2138     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2139     int32_t opNumber0 = taggedNumber0.GetInt();
2140     int32_t opNumber1 = taggedNumber1.GetInt();
2141     // NOLINT(hicpp-signed-bitwise)
2142     auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
2143     return JSTaggedValue(static_cast<int32_t>(ret));
2144 }
2145 
RuntimeOr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2146 JSTaggedValue RuntimeStubs::RuntimeOr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2147                                        const JSHandle<JSTaggedValue> &right)
2148 {
2149     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2150     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2151     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2152     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2153     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2154         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2155             JSHandle<BigInt> leftBigint(valLeft);
2156             JSHandle<BigInt> rightBigint(valRight);
2157             return BigInt::BitwiseOR(thread, leftBigint, rightBigint).GetTaggedValue();
2158         }
2159         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2160     }
2161     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
2162     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2163     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
2164     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2165     int32_t opNumber0 = taggedNumber0.GetInt();
2166     int32_t opNumber1 = taggedNumber1.GetInt();
2167     // NOLINT(hicpp-signed-bitwise)
2168     auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
2169     return JSTaggedValue(static_cast<int32_t>(ret));
2170 }
2171 
RuntimeXor2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)2172 JSTaggedValue RuntimeStubs::RuntimeXor2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
2173                                         const JSHandle<JSTaggedValue> &right)
2174 {
2175     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
2176     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2177     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
2178     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2179     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
2180         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
2181             JSHandle<BigInt> leftBigint(valLeft);
2182             JSHandle<BigInt> rightBigint(valRight);
2183             return BigInt::BitwiseXOR(thread, leftBigint, rightBigint).GetTaggedValue();
2184         }
2185         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
2186     }
2187     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
2188     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2189     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
2190     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2191     int32_t opNumber0 = taggedNumber0.GetInt();
2192     int32_t opNumber1 = taggedNumber1.GetInt();
2193     // NOLINT(hicpp-signed-bitwise)
2194     auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
2195     return JSTaggedValue(static_cast<int32_t>(ret));
2196 }
2197 
RuntimeToJSTaggedValueWithInt32(JSThread * thread,const JSHandle<JSTaggedValue> & value)2198 JSTaggedValue RuntimeStubs::RuntimeToJSTaggedValueWithInt32(JSThread *thread,
2199                                                             const JSHandle<JSTaggedValue> &value)
2200 {
2201     int32_t res = JSTaggedValue::ToInt32(thread, value);
2202     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2203     return JSTaggedValue(res);
2204 }
2205 
RuntimeToJSTaggedValueWithUint32(JSThread * thread,const JSHandle<JSTaggedValue> & value)2206 JSTaggedValue RuntimeStubs::RuntimeToJSTaggedValueWithUint32(JSThread *thread, const JSHandle<JSTaggedValue> &value)
2207 {
2208     uint32_t res = JSTaggedValue::ToUint32(thread, value);
2209     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2210     return JSTaggedValue(res);
2211 }
2212 
RuntimeCreateEmptyObject(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)2213 JSTaggedValue RuntimeStubs::RuntimeCreateEmptyObject([[maybe_unused]] JSThread *thread, ObjectFactory *factory,
2214                                                      JSHandle<GlobalEnv> globalEnv)
2215 {
2216     JSHandle<JSFunction> builtinObj(globalEnv->GetObjectFunction());
2217     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(builtinObj);
2218     return obj.GetTaggedValue();
2219 }
2220 
RuntimeCreateEmptyArray(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)2221 JSTaggedValue RuntimeStubs::RuntimeCreateEmptyArray([[maybe_unused]] JSThread *thread, ObjectFactory *factory,
2222                                                     JSHandle<GlobalEnv> globalEnv)
2223 {
2224     JSHandle<JSFunction> builtinObj(globalEnv->GetArrayFunction());
2225     JSHandle<JSObject> arr = factory->NewJSObjectByConstructor(builtinObj);
2226     return arr.GetTaggedValue();
2227 }
2228 
RuntimeGetUnmapedArgs(JSThread * thread,JSTaggedType * sp,uint32_t actualNumArgs,uint32_t startIdx)2229 JSTaggedValue RuntimeStubs::RuntimeGetUnmapedArgs(JSThread *thread, JSTaggedType *sp, uint32_t actualNumArgs,
2230                                                   uint32_t startIdx)
2231 {
2232     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2233     JSHandle<TaggedArray> argumentsList = factory->NewTaggedArray(actualNumArgs);
2234     for (uint32_t i = 0; i < actualNumArgs; ++i) {
2235         argumentsList->Set(thread, i,
2236                            JSTaggedValue(sp[startIdx + i]));  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2237     }
2238     return RuntimeGetUnmapedJSArgumentObj(thread, argumentsList);
2239 }
2240 
RuntimeCopyRestArgs(JSThread * thread,JSTaggedType * sp,uint32_t restNumArgs,uint32_t startIdx)2241 JSTaggedValue RuntimeStubs::RuntimeCopyRestArgs(JSThread *thread, JSTaggedType *sp, uint32_t restNumArgs,
2242                                                 uint32_t startIdx)
2243 {
2244     return JSArray::ArrayCreateWithInit(
2245         thread, restNumArgs, [thread, sp, startIdx] (const JSHandle<TaggedArray> &newElements, uint32_t length) {
2246         for (uint32_t i = 0; i < length; ++i) {
2247             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2248             newElements->Set(thread, i, JSTaggedValue(sp[startIdx + i]));
2249         }
2250     });
2251 }
2252 
RuntimeCreateArrayWithBuffer(JSThread * thread,ObjectFactory * factory,const JSHandle<JSTaggedValue> & literal)2253 JSTaggedValue RuntimeStubs::RuntimeCreateArrayWithBuffer(JSThread *thread, ObjectFactory *factory,
2254                                                          const JSHandle<JSTaggedValue> &literal)
2255 {
2256     JSHandle<JSArray> array(literal);
2257     JSHandle<JSArray> arrLiteral = factory->CloneArrayLiteral(array);
2258     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2259 
2260     return arrLiteral.GetTaggedValue();
2261 }
2262 
RuntimeCreateObjectWithBuffer(JSThread * thread,ObjectFactory * factory,const JSHandle<JSObject> & literal)2263 JSTaggedValue RuntimeStubs::RuntimeCreateObjectWithBuffer(JSThread *thread, ObjectFactory *factory,
2264                                                           const JSHandle<JSObject> &literal)
2265 {
2266     JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(literal);
2267     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2268 
2269     return objLiteral.GetTaggedValue();
2270 }
2271 
RuntimeNewLexicalEnv(JSThread * thread,uint16_t numVars)2272 JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnv(JSThread *thread, uint16_t numVars)
2273 {
2274     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2275     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
2276     JSTaggedValue currentEnv = thread->GetCurrentLexenv();
2277     // currentEnv is LexicalEnv/GlobalEnv for normal function, and is SFunctionEnv for SharedFunction.
2278     JSTaggedValue globalEnv = BaseEnv::Cast(currentEnv.GetTaggedObject())->GetGlobalEnv(thread);
2279     if LIKELY(!globalEnv.IsHole()) {
2280         newEnv->SetGlobalEnv(thread, globalEnv);
2281     } else {
2282         newEnv->SetGlobalEnv(thread, thread->GetGlueGlobalEnv());
2283     }
2284     newEnv->SetParentEnv(thread, currentEnv);
2285     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2286     return newEnv.GetTaggedValue();
2287 }
2288 
RuntimeNewSendableEnv(JSThread * thread,uint16_t numVars)2289 JSTaggedValue RuntimeStubs::RuntimeNewSendableEnv(JSThread *thread, uint16_t numVars)
2290 {
2291     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2292     JSHandle<SendableEnv> newEnv = factory->NewSendableEnv(numVars);
2293 
2294     JSTaggedValue module = JSFunction::Cast(thread->GetCurrentFunction())->GetModule(thread);
2295     JSHandle<SourceTextModule> moduleHandle(thread, module);
2296     newEnv->SetParentEnv(thread, moduleHandle->GetSendableEnv(thread));
2297     newEnv->SetScopeInfo(thread, JSTaggedValue::Hole());
2298     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2299     return newEnv.GetTaggedValue();
2300 }
2301 
RuntimeNewObjRange(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,uint16_t firstArgIdx,uint16_t length)2302 JSTaggedValue RuntimeStubs::RuntimeNewObjRange(JSThread *thread, const JSHandle<JSTaggedValue> &func,
2303     const JSHandle<JSTaggedValue> &newTarget, uint16_t firstArgIdx, uint16_t length)
2304 {
2305     JSHandle<JSTaggedValue> preArgs(thread, JSTaggedValue::Undefined());
2306     JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
2307     FrameHandler frameHandler(thread);
2308     for (uint16_t i = 0; i < length; ++i) {
2309         JSTaggedValue value = frameHandler.GetVRegValue(firstArgIdx + i);
2310         args->Set(thread, i, value);
2311     }
2312     auto tagged = RuntimeOptConstruct(thread, func, newTarget, preArgs, args);
2313     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2314     return tagged;
2315 }
2316 
DumpInfoForMoreLdInfo(JSThread * thread,JSHandle<JSTaggedValue> & receiver,CString & msg)2317 void RuntimeStubs::DumpInfoForMoreLdInfo(JSThread *thread, JSHandle<JSTaggedValue> &receiver,
2318                                          CString &msg)
2319 {
2320     auto AddType = [&msg] (std::string_view s, JSHandle<JSTaggedValue> value) {
2321         msg += s;
2322         msg += " type: ";
2323         if (value->IsHeapObject()) {
2324             JSHandle<JSObject> obj(value);
2325             msg += JSHClass::DumpJSType(obj->GetClass()->GetObjectType());
2326         } else {
2327             if (value->IsNumber()) {
2328                 msg += "prim number";
2329             } else if (value->IsBoolean()) {
2330                 msg += "prim boolean";
2331             } else {
2332                 msg += "other prim";
2333             }
2334         }
2335         msg += ", ";
2336     };
2337     auto AddDepth = [&thread, &msg] (JSHandle<JSTaggedValue> value) {
2338         int depth = 0;
2339         while (value->IsECMAObject()) {
2340             depth++;
2341             auto currHC = value->GetTaggedObject()->GetClass();
2342             auto proto = currHC->GetProto(thread);
2343             value = JSHandle<JSTaggedValue>(thread, proto);
2344         }
2345         msg += "Depth: " + std::to_string(depth);
2346         msg += ", ";
2347     };
2348     bool isNeedDepth = true;
2349     bool isNeedTypeInformation = true;
2350     if (isNeedTypeInformation) {
2351         AddType("Receiver", receiver);
2352     }
2353     if (isNeedDepth) {
2354         AddDepth(receiver);
2355     }
2356 }
2357 
DumpInfoForLdObjByValue(JSThread * thread,JSHandle<JSTaggedValue> & profile,JSTaggedValue slotId,JSTaggedValue key,CString & msg)2358 void RuntimeStubs::DumpInfoForLdObjByValue(JSThread *thread, JSHandle<JSTaggedValue> &profile, JSTaggedValue slotId,
2359                                            JSTaggedValue key, CString &msg)
2360 {
2361     msg += "[DFX]Trace Load Value Detail: ";
2362     const int MONO_NUM = 2;
2363     if (profile->IsUndefined()) {
2364         msg += "ProfileTypeInfo Undefine";
2365     } else {
2366         auto prof = JSHandle<ProfileTypeInfo>::Cast(profile);
2367         auto slot = slotId.GetInt();
2368         auto first = prof->GetIcSlot(thread, slot);
2369         if (first.IsHole()) {
2370             msg += "state: mega";
2371         } else if (first.IsUndefined()) {
2372             msg += "state: not known";
2373         } else if (first.IsWeak()) {
2374             msg += "state: mono";
2375         } else {
2376             auto second = prof->GetIcSlot(thread, slot + 1);
2377             if (second.IsTaggedArray()) {
2378                 TaggedArray *elements = TaggedArray::Cast(second.GetTaggedObject());
2379                 if (elements->GetLength() == MONO_NUM) {
2380                     msg += "state: mono";
2381                 } else {
2382                     msg += "state: non-index poly";
2383                 }
2384             } else if (second.IsHole()) {
2385                 msg += "state: index poly";
2386             } else {
2387                 msg += "state: not known";
2388             }
2389         }
2390     }
2391     msg += " | ";
2392     if (key.IsString()) {
2393         msg += "key: string";
2394     } else if (key.IsNumber()) {
2395         msg += "key: number";
2396     } else if (key.IsSymbol()) {
2397         msg += "key: symbol";
2398     } else {
2399         msg += "key: other type";
2400     }
2401 }
DefineFuncTryUseAOTHClass(JSThread * thread,const JSHandle<JSFunction> & func,const JSHandle<JSTaggedValue> & ihc,const JSHandle<AOTLiteralInfo> & aotLiteralInfo)2402 void RuntimeStubs::DefineFuncTryUseAOTHClass(JSThread* thread,
2403                                              const JSHandle<JSFunction>& func,
2404                                              const JSHandle<JSTaggedValue>& ihc,
2405                                              const JSHandle<AOTLiteralInfo>& aotLiteralInfo)
2406 {
2407     FunctionKind kind = Method::Cast(func->GetMethod(thread))->GetFunctionKind();
2408     // The HClass of AOT comes from .ai deserialization
2409     if (!ihc->IsUndefined() && kind == FunctionKind::BASE_CONSTRUCTOR) {
2410         ASSERT(!aotLiteralInfo.GetTaggedValue().IsHole());
2411         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2412         const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2413         func->SetProtoOrHClass(thread, ihc);
2414 
2415         // build inheritance
2416         JSHandle<JSTaggedValue> parentPrototype = env->GetObjectFunctionPrototype();
2417         JSHandle<JSObject> clsPrototype(thread, func->GetFunctionPrototype(thread));
2418         clsPrototype->GetClass()->SetPrototype(thread, parentPrototype);
2419 
2420         // set "constructor" in prototype
2421         JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
2422         PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(func), true, false, true);
2423         JSObject::DefineOwnProperty(thread, clsPrototype, constructorKey, descriptor);
2424 
2425         // enable prototype change marker
2426         JSHClass::EnablePHCProtoChangeMarker(thread,
2427             JSHandle<JSHClass>(thread, parentPrototype->GetTaggedObject()->GetClass()));
2428         if (ihc->IsJSHClass()) {
2429             JSHClass::EnableProtoChangeMarker(thread, JSHandle<JSHClass>(ihc));
2430         } else {
2431             JSHClass::EnablePHCProtoChangeMarker(thread, JSHandle<JSHClass>(thread, clsPrototype->GetClass()));
2432         }
2433         //avoid one thread uses ihc twice or more times
2434         aotLiteralInfo->SetIhcPrimitive(JSTaggedValue::Undefined());
2435     }
2436 }
2437 
RuntimeDefinefunc(JSThread * thread,const JSHandle<JSTaggedValue> & constpool,uint16_t methodId,const JSHandle<JSTaggedValue> & module,uint16_t length,const JSHandle<JSTaggedValue> & envHandle,const JSHandle<JSTaggedValue> & homeObject)2438 JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<JSTaggedValue> &constpool,
2439                                               uint16_t methodId, const JSHandle<JSTaggedValue> &module,
2440                                               uint16_t length, const JSHandle<JSTaggedValue> &envHandle,
2441                                               const JSHandle<JSTaggedValue> &homeObject)
2442 {
2443     JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
2444     JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
2445     JSMutableHandle<AOTLiteralInfo> aotLiteralInfo(thread, JSTaggedValue::Hole());
2446     //AOT ihc infos always in unshareConstpool
2447     //If is runing on AOT,unshareConstpool is definitely not a hole
2448     //So wo can skip if unshareConstpool is hole
2449     JSTaggedValue unsharedCp = thread->GetEcmaVM()->FindUnsharedConstpool(constpoolHandle.GetTaggedValue());
2450     if (!unsharedCp.IsHole()) {
2451         JSHandle<ConstantPool> unsharedCpHandle(thread, unsharedCp);
2452         JSTaggedValue val = unsharedCpHandle->GetObjectFromCache(thread, methodId);
2453         if (val.IsAOTLiteralInfo()) {
2454             aotLiteralInfo.Update(val);
2455             ihc.Update(aotLiteralInfo->GetIhc(thread));
2456         }
2457     }
2458     JSTaggedValue method = ConstantPool::GetMethodFromCache(thread, constpoolHandle.GetTaggedValue(), methodId);
2459     const JSHandle<Method> methodHandle(thread, method);
2460     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2461     JSHandle<JSFunction> result;
2462     if (methodHandle->IsSendableMethod()) {
2463         result = factory->NewJSSendableFunction(methodHandle);
2464         ModuleManager *moduleManager = thread->GetModuleManager();
2465         JSHandle<JSTaggedValue> sendableFuncModule = moduleManager->GenerateSendableFuncModule(module);
2466         if (module->IsSourceTextModule()) {
2467             JSHandle<SourceTextModule> sendableFuncModuleRecord(sendableFuncModule);
2468             sendableFuncModuleRecord->SetSendableEnv(thread,
2469                                                      JSHandle<SourceTextModule>::Cast(module)->GetSendableEnv(thread));
2470         }
2471         result->SetModule(thread, sendableFuncModule.GetTaggedValue());
2472         auto globalConst = thread->GlobalConstants();
2473         JSHandle<JSTaggedValue> emptySFunctionEnvHandle = globalConst->GetHandledEmptySFunctionEnv();
2474         result->SetLexicalEnv<SKIP_BARRIER>(thread, emptySFunctionEnvHandle.GetTaggedValue());
2475     } else {
2476         result = factory->NewJSFunction(methodHandle);
2477         result->SetModule(thread, module.GetTaggedValue());
2478         result->SetLexicalEnv(thread, envHandle.GetTaggedValue());
2479         result->SetHomeObject(thread, homeObject.GetTaggedValue());
2480     }
2481     DefineFuncTryUseAOTHClass(thread, result, ihc, aotLiteralInfo);
2482 
2483     result->SetLength(length);
2484     return result.GetTaggedValue();
2485 }
2486 
RuntimeCreateRegExpWithLiteral(JSThread * thread,const JSHandle<JSTaggedValue> & pattern,uint8_t flags)2487 JSTaggedValue RuntimeStubs::RuntimeCreateRegExpWithLiteral(JSThread *thread,
2488                                                            const JSHandle<JSTaggedValue> &pattern, uint8_t flags)
2489 {
2490     JSHandle<JSTaggedValue> flagsHandle(thread, JSTaggedValue(flags));
2491     return builtins::BuiltinsRegExp::RegExpCreate(thread, pattern, flagsHandle);
2492 }
2493 
RuntimeThrowIfSuperNotCorrectCall(JSThread * thread,uint16_t index,JSTaggedValue thisValue)2494 JSTaggedValue RuntimeStubs::RuntimeThrowIfSuperNotCorrectCall(JSThread *thread, uint16_t index,
2495                                                               JSTaggedValue thisValue)
2496 {
2497     if (index == 0 && (thisValue.IsUndefined() || thisValue.IsHole())) {
2498         return RuntimeThrowReferenceError(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
2499                                        "sub-class must call super before use 'this'");
2500     }
2501     if (index == 1 && !thisValue.IsUndefined() && !thisValue.IsHole()) {
2502         return RuntimeThrowReferenceError(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
2503                                        "super() forbidden re-bind 'this'");
2504     }
2505     return JSTaggedValue::True();
2506 }
2507 
RuntimeCreateObjectHavingMethod(JSThread * thread,ObjectFactory * factory,const JSHandle<JSObject> & literal,const JSHandle<JSTaggedValue> & env)2508 JSTaggedValue RuntimeStubs::RuntimeCreateObjectHavingMethod(JSThread *thread, ObjectFactory *factory,
2509                                                             const JSHandle<JSObject> &literal,
2510                                                             const JSHandle<JSTaggedValue> &env)
2511 {
2512     JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(literal, env);
2513     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2514 
2515     return objLiteral.GetTaggedValue();
2516 }
2517 
CommonCreateObjectWithExcludedKeys(JSThread * thread,const JSHandle<JSTaggedValue> & objVal,uint32_t numExcludedKeys,JSHandle<TaggedArray> excludedKeys)2518 JSTaggedValue RuntimeStubs::CommonCreateObjectWithExcludedKeys(JSThread *thread,
2519                                                                const JSHandle<JSTaggedValue> &objVal,
2520                                                                uint32_t numExcludedKeys,
2521                                                                JSHandle<TaggedArray> excludedKeys)
2522 {
2523     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2524     JSHandle<JSObject> restObj = factory->NewEmptyJSObject();
2525     if (objVal->IsNull() || objVal->IsUndefined()) {
2526         return restObj.GetTaggedValue();
2527     }
2528     JSHandle<JSObject> obj(JSTaggedValue::ToObject(thread, objVal));
2529     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2530     JSHandle<TaggedArray> allKeys = JSObject::GetOwnPropertyKeys(thread, obj);
2531     uint32_t numAllKeys = allKeys->GetLength();
2532     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
2533     for (uint32_t i = 0; i < numAllKeys; i++) {
2534         key.Update(allKeys->Get(thread, i));
2535         bool isExcludedKey = false;
2536         for (uint32_t j = 0; j < numExcludedKeys; j++) {
2537             if (JSTaggedValue::Equal(thread, key, JSHandle<JSTaggedValue>(thread, excludedKeys->Get(thread, j)))) {
2538                 isExcludedKey = true;
2539                 break;
2540             }
2541         }
2542         if (!isExcludedKey) {
2543             PropertyDescriptor desc(thread);
2544             bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
2545             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2546             if (success && desc.IsEnumerable()) {
2547                 JSHandle<JSTaggedValue> value = JSObject::GetProperty(thread, obj, key).GetValue();
2548                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2549                 JSObject::SetProperty(thread, restObj, key, value, true);
2550                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2551             }
2552         }
2553     }
2554     return restObj.GetTaggedValue();
2555 }
2556 
RuntimeOptCreateObjectWithExcludedKeys(JSThread * thread,uintptr_t argv,uint32_t argc)2557 JSTaggedValue RuntimeStubs::RuntimeOptCreateObjectWithExcludedKeys(JSThread *thread, uintptr_t argv, uint32_t argc)
2558 {
2559     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2560     const JSHandle<JSTaggedValue> &objVal = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the objVal
2561     uint32_t firstArgRegIdx = 1; // 1: means the firstArgRegIdx
2562     uint32_t numExcludedKeys = 0;
2563     uint32_t numKeys = argc - 1;
2564     JSHandle<TaggedArray> excludedKeys = factory->NewTaggedArray(numKeys);
2565     JSTaggedValue excludedKey = GetArg(argv, argc, firstArgRegIdx);
2566     if (!excludedKey.IsUndefined()) {
2567         numExcludedKeys = numKeys;
2568         excludedKeys->Set(thread, 0, excludedKey);
2569         for (uint32_t i = 1; i < numExcludedKeys; i++) {
2570             excludedKey = GetArg(argv, argc, firstArgRegIdx + i);
2571             excludedKeys->Set(thread, i, excludedKey);
2572         }
2573     }
2574     return CommonCreateObjectWithExcludedKeys(thread, objVal, numExcludedKeys, excludedKeys);
2575 }
2576 
RuntimeCreateObjectWithExcludedKeys(JSThread * thread,uint16_t numKeys,const JSHandle<JSTaggedValue> & objVal,uint16_t firstArgRegIdx)2577 JSTaggedValue RuntimeStubs::RuntimeCreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys,
2578                                                                 const JSHandle<JSTaggedValue> &objVal,
2579                                                                 uint16_t firstArgRegIdx)
2580 {
2581     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2582     uint32_t numExcludedKeys = 0;
2583     JSHandle<TaggedArray> excludedKeys = factory->NewTaggedArray(numKeys + 1);
2584     FrameHandler frameHandler(thread);
2585     JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx);
2586     if (!excludedKey.IsUndefined()) {
2587         numExcludedKeys = numKeys + 1;
2588         excludedKeys->Set(thread, 0, excludedKey);
2589         for (uint32_t i = 1; i < numExcludedKeys; i++) {
2590             excludedKey = frameHandler.GetVRegValue(firstArgRegIdx + i);
2591             excludedKeys->Set(thread, i, excludedKey);
2592         }
2593     }
2594 
2595     JSHandle<JSTaggedValue> finalVal = objVal;
2596     if (finalVal->CheckIsJSProxy()) {
2597         JSHandle<JSProxy> proxyVal(thread, finalVal.GetTaggedValue());
2598         finalVal = proxyVal->GetSourceTarget(thread);
2599     }
2600 
2601     return CommonCreateObjectWithExcludedKeys(thread, finalVal, numExcludedKeys, excludedKeys);
2602 }
2603 
RuntimeDefineMethod(JSThread * thread,const JSHandle<Method> & methodHandle,const JSHandle<JSTaggedValue> & homeObject,uint16_t length,const JSHandle<JSTaggedValue> & env,const JSHandle<JSTaggedValue> & module)2604 JSTaggedValue RuntimeStubs::RuntimeDefineMethod(JSThread *thread, const JSHandle<Method> &methodHandle,
2605                                                 const JSHandle<JSTaggedValue> &homeObject, uint16_t length,
2606                                                 const JSHandle<JSTaggedValue> &env,
2607                                                 const JSHandle<JSTaggedValue> &module)
2608 {
2609     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2610     JSHandle<JSFunction> func = factory->NewJSFunction(methodHandle, homeObject);
2611     func->SetLength(length);
2612     func->SetLexicalEnv(thread, env);
2613     func->SetModule(thread, module);
2614     return func.GetTaggedValue();
2615 }
2616 
RuntimeLdSendableClass(JSThread * thread,const JSHandle<JSTaggedValue> & env,uint16_t level)2617 JSTaggedValue RuntimeStubs::RuntimeLdSendableClass(JSThread *thread, const JSHandle<JSTaggedValue> &env, uint16_t level)
2618 {
2619     JSTaggedValue currentEnv(env.GetTaggedValue());
2620     for (uint32_t i = 0; i < level; i++) {
2621         ASSERT(currentEnv.IsLexicalEnv());
2622         currentEnv = LexicalEnv::Cast(currentEnv.GetTaggedObject())->GetParentEnv(thread);
2623     }
2624     ASSERT(currentEnv.IsSFunctionEnv());
2625     return SFunctionEnv::Cast(currentEnv.GetTaggedObject())->GetConstructor(thread);
2626 }
2627 
RuntimeCallSpread(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & array)2628 JSTaggedValue RuntimeStubs::RuntimeCallSpread(JSThread *thread,
2629                                               const JSHandle<JSTaggedValue> &func,
2630                                               const JSHandle<JSTaggedValue> &obj,
2631                                               const JSHandle<JSTaggedValue> &array)
2632 {
2633     if ((!obj->IsUndefined() && !obj->IsECMAObject()) || !func->IsCallable() || !array->IsJSArray()) {
2634         THROW_TYPE_ERROR_AND_RETURN(thread, "cannot Callspread", JSTaggedValue::Exception());
2635     }
2636 
2637     JSHandle<TaggedArray> coretypesArray(thread, RuntimeGetCallSpreadArgs(thread, array));
2638     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2639     uint32_t length = coretypesArray->GetLength();
2640     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2641     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, obj, undefined, length);
2642     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2643     info->SetCallArg(length, coretypesArray);
2644     return EcmaInterpreter::Execute(info);
2645 }
2646 
RuntimeSetPatchModule(JSThread * thread,const JSHandle<JSFunction> & func)2647 void RuntimeStubs::RuntimeSetPatchModule(JSThread *thread, const JSHandle<JSFunction> &func)
2648 {
2649     JSHandle<Method> methodHandle(thread, Method::Cast(func->GetMethod(thread)));
2650     const JSHandle<JSTaggedValue> coldReloadRecordName = thread->GetEcmaVM()->FindPatchModule(
2651         MethodLiteral::GetRecordName(methodHandle->GetJSPandaFile(thread), methodHandle->GetMethodId()));
2652     if (!coldReloadRecordName->IsHole()) {
2653         func->SetModule(thread, coldReloadRecordName.GetTaggedValue());
2654     }
2655 }
2656 
RuntimeDefineGetterSetterByValue(JSThread * thread,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & getter,const JSHandle<JSTaggedValue> & setter,bool flag,const JSHandle<JSTaggedValue> & func,int32_t pcOffset)2657 JSTaggedValue RuntimeStubs::RuntimeDefineGetterSetterByValue(JSThread *thread, const JSHandle<JSObject> &obj,
2658                                                              const JSHandle<JSTaggedValue> &prop,
2659                                                              const JSHandle<JSTaggedValue> &getter,
2660                                                              const JSHandle<JSTaggedValue> &setter, bool flag,
2661                                                              const JSHandle<JSTaggedValue> &func,
2662                                                              int32_t pcOffset)
2663 {
2664     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
2665     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2666     auto globalConst = thread->GlobalConstants();
2667     if (obj.GetTaggedValue().IsClassConstructor() &&
2668         JSTaggedValue::SameValue(thread, propKey, globalConst->GetHandledPrototypeString())) {
2669         return RuntimeThrowTypeError(
2670             thread,
2671             "In a class, computed property names for static getter that are named 'prototype' throw a TypeError");
2672     }
2673 
2674     auto receiverHClass = obj->GetJSHClass();
2675 
2676     if (flag) {
2677         if (!getter->IsUndefined()) {
2678             if (propKey->IsNumber()) {
2679                 propKey =
2680                     JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
2681             }
2682             JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(getter), propKey,
2683                                             JSHandle<JSTaggedValue>(thread, globalConst->GetGetString()));
2684         }
2685 
2686         if (!setter->IsUndefined()) {
2687             if (propKey->IsNumber()) {
2688                 propKey =
2689                     JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
2690             }
2691             JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(setter), propKey,
2692                                             JSHandle<JSTaggedValue>(thread, globalConst->GetSetString()));
2693         }
2694     }
2695 
2696     // set accessor
2697     bool enumerable =
2698         !(obj.GetTaggedValue().IsClassPrototype() || obj.GetTaggedValue().IsClassConstructor());
2699     PropertyDescriptor desc(thread, true, enumerable, true);
2700     if (!getter->IsUndefined()) {
2701         Method *method = Method::Cast(JSHandle<JSFunction>::Cast(getter)->GetMethod(thread).GetTaggedObject());
2702         method->SetFunctionKind(FunctionKind::GETTER_FUNCTION);
2703         desc.SetGetter(getter);
2704     }
2705     if (!setter->IsUndefined()) {
2706         Method *method = Method::Cast(JSHandle<JSFunction>::Cast(setter)->GetMethod(thread).GetTaggedObject());
2707         method->SetFunctionKind(FunctionKind::SETTER_FUNCTION);
2708         desc.SetSetter(setter);
2709     }
2710 
2711     JSObject::DefineOwnProperty(thread, obj, propKey, desc);
2712     auto holderTraHClass = obj->GetJSHClass();
2713     if (receiverHClass != holderTraHClass) {
2714         if (holderTraHClass->IsAOT()) {
2715             JSHandle<JSHClass> phcHandle(thread, holderTraHClass);
2716             JSHClass::EnablePHCProtoChangeMarker(thread, phcHandle);
2717         }
2718         if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
2719             if (!func->IsUndefined()) {
2720                 thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineGetterSetter(
2721                     receiverHClass, holderTraHClass, func, pcOffset);
2722             }
2723         }
2724     }
2725     return obj.GetTaggedValue();
2726 }
2727 
RuntimeSuperCall(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,uint16_t firstVRegIdx,uint16_t length)2728 JSTaggedValue RuntimeStubs::RuntimeSuperCall(JSThread *thread, const JSHandle<JSTaggedValue> &func,
2729                                              const JSHandle<JSTaggedValue> &newTarget, uint16_t firstVRegIdx,
2730                                              uint16_t length)
2731 {
2732     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
2733     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2734 
2735     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2736     JSHandle<TaggedArray> argv = factory->NewTaggedArray(length);
2737     FrameHandler frameHandler(thread);
2738     for (size_t i = 0; i < length; ++i) {
2739         argv->Set(thread, i, frameHandler.GetVRegValue(firstVRegIdx + i));
2740     }
2741 
2742     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2743     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, length);
2744     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2745     info->SetCallArg(length, argv);
2746     JSTaggedValue result = JSFunction::Construct(info);
2747     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2748 
2749     return result;
2750 }
2751 
RuntimeOptSuperCall(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,const JSHandle<TaggedArray> & argv,uint16_t length)2752 JSTaggedValue RuntimeStubs::RuntimeOptSuperCall(JSThread *thread, const JSHandle<JSTaggedValue> &func,
2753                                                 const JSHandle<JSTaggedValue> &newTarget,
2754                                                 const JSHandle<TaggedArray> &argv,
2755                                                 uint16_t length)
2756 {
2757     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
2758     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2759     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2760     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, length);
2761     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2762     info->SetCallArg(length, argv);
2763     JSTaggedValue result = JSFunction::Construct(info);
2764     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2765     return result;
2766 }
2767 
RuntimeThrowTypeError(JSThread * thread,const char * message)2768 JSTaggedValue RuntimeStubs::RuntimeThrowTypeError(JSThread *thread, const char *message)
2769 {
2770     ASSERT_NO_ABRUPT_COMPLETION(thread);
2771     THROW_TYPE_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
2772 }
2773 
RuntimeGetCallSpreadArgs(JSThread * thread,const JSHandle<JSTaggedValue> & jsArray)2774 JSTaggedValue RuntimeStubs::RuntimeGetCallSpreadArgs(JSThread *thread, const JSHandle<JSTaggedValue> &jsArray)
2775 {
2776     uint32_t argvMayMaxLength = JSHandle<JSArray>::Cast(jsArray)->GetArrayLength();
2777 
2778     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2779     JSHandle<TaggedArray> argv = factory->NewTaggedArray(argvMayMaxLength);
2780     JSHandle<JSTaggedValue> itor = JSIterator::GetIterator(thread, jsArray);
2781     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2782 
2783     // Fast path when array is stablearray and Iterator not change.
2784     if (jsArray->IsStableJSArray(thread) && itor->IsJSArrayIterator()) {
2785         JSHandle<JSObject> jsArrayObj(jsArray);
2786         ElementAccessor::CopyJSArrayToTaggedArray(thread, jsArrayObj, argv, argvMayMaxLength);
2787         return argv.GetTaggedValue();
2788     }
2789 
2790     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2791     JSMutableHandle<JSTaggedValue> next(thread, JSTaggedValue::Undefined());
2792     JSMutableHandle<JSTaggedValue> nextArg(thread, JSTaggedValue::Undefined());
2793     size_t argvIndex = 0;
2794     while (true) {
2795         next.Update(JSIterator::IteratorStep(thread, itor).GetTaggedValue());
2796         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2797         if (JSTaggedValue::SameValue(thread, next.GetTaggedValue(), JSTaggedValue::False())) {
2798             break;
2799         }
2800         nextArg.Update(JSIterator::IteratorValue(thread, next).GetTaggedValue());
2801         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2802         if (UNLIKELY(argvIndex + 1 >= argvMayMaxLength)) {
2803             argvMayMaxLength = argvMayMaxLength + (argvMayMaxLength >> 1U) + 1U;
2804             argv = argv->SetCapacity(thread, argv, argvMayMaxLength);
2805         }
2806         argv->Set(thread, argvIndex++, nextArg);
2807     }
2808     argv = factory->CopyArray(argv, argvMayMaxLength, argvIndex);
2809     return argv.GetTaggedValue();
2810 }
2811 
RuntimeThrowSyntaxError(JSThread * thread,const char * message)2812 JSTaggedValue RuntimeStubs::RuntimeThrowSyntaxError(JSThread *thread, const char *message)
2813 {
2814     ASSERT_NO_ABRUPT_COMPLETION(thread);
2815     THROW_SYNTAX_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
2816 }
2817 
RuntimeLdBigInt(JSThread * thread,const JSHandle<JSTaggedValue> & numberBigInt)2818 JSTaggedValue RuntimeStubs::RuntimeLdBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &numberBigInt)
2819 {
2820     return JSTaggedValue::ToBigInt(thread, numberBigInt);
2821 }
2822 
RuntimeCallBigIntAsIntN(JSThread * thread,JSTaggedValue bits,JSTaggedValue bigint)2823 JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsIntN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint)
2824 {
2825     auto biginteger = JSHandle<BigInt>(thread, bigint);
2826     JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits);
2827     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2828     return BigInt::AsintN(thread, bitness, biginteger);
2829 }
2830 
RuntimeCallBigIntAsUintN(JSThread * thread,JSTaggedValue bits,JSTaggedValue bigint)2831 JSTaggedValue RuntimeStubs::RuntimeCallBigIntAsUintN(JSThread *thread, JSTaggedValue bits, JSTaggedValue bigint)
2832 {
2833     auto biginteger = JSHandle<BigInt>(thread, bigint);
2834     JSTaggedNumber bitness = JSTaggedValue::ToNumber(thread, bits);
2835     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2836     return BigInt::AsUintN(thread, bitness, biginteger);
2837 }
2838 
RuntimeNewLexicalEnvWithName(JSThread * thread,uint16_t numVars,uint16_t scopeId)2839 JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId)
2840 {
2841     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2842     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
2843     JSTaggedValue currentEnv = thread->GetCurrentLexenv();
2844     // currentEnv is LexicalEnv/GlobalEnv for normal function, and is SFunctionEnv for SharedFunction.
2845     JSTaggedValue globalEnv = BaseEnv::Cast(currentEnv.GetTaggedObject())->GetGlobalEnv(thread);
2846     if LIKELY(!globalEnv.IsHole()) {
2847         newEnv->SetGlobalEnv(thread, globalEnv);
2848     } else {
2849         newEnv->SetGlobalEnv(thread, thread->GetGlueGlobalEnv());
2850     }
2851     newEnv->SetParentEnv(thread, currentEnv);
2852     JSTaggedValue scopeInfo = ScopeInfoExtractor::GenerateScopeInfo(thread, scopeId);
2853     newEnv->SetScopeInfo(thread, scopeInfo);
2854     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2855     return newEnv.GetTaggedValue();
2856 }
2857 
RuntimeOptGetUnmapedArgs(JSThread * thread,uint32_t actualNumArgs)2858 JSTaggedValue RuntimeStubs::RuntimeOptGetUnmapedArgs(JSThread *thread, uint32_t actualNumArgs)
2859 {
2860     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2861     JSHandle<TaggedArray> argumentsList = factory->NewTaggedArray(actualNumArgs - NUM_MANDATORY_JSFUNC_ARGS);
2862 
2863     auto argv = GetActualArgvFromStub(thread);
2864     int idx = 0;
2865     for (uint32_t i = NUM_MANDATORY_JSFUNC_ARGS; i < actualNumArgs; ++i) {
2866         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2867         JSTaggedType arg = reinterpret_cast<JSTaggedType *>(argv)[i];
2868         JSTaggedValue args = JSTaggedValue(arg);
2869         argumentsList->Set(thread, idx++, args);
2870     }
2871     return RuntimeGetUnmapedJSArgumentObj(thread, argumentsList);
2872 }
2873 
RuntimeGetUnmapedJSArgumentObj(JSThread * thread,const JSHandle<TaggedArray> & argumentsList)2874 JSTaggedValue RuntimeStubs::RuntimeGetUnmapedJSArgumentObj(JSThread *thread, const JSHandle<TaggedArray> &argumentsList)
2875 {
2876     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2877     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
2878     // 1. Let len be the number of elements in argumentsList
2879     uint32_t len = argumentsList->GetLength();
2880     // 2. Let obj be ObjectCreate(%ObjectPrototype%, «[[ParameterMap]]»).
2881     // 3. Set obj’s [[ParameterMap]] internal slot to undefined.
2882     // [[ParameterMap]] setted as undifined.
2883     JSHandle<JSArguments> obj = factory->NewJSArguments();
2884     // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: true,
2885     // [[Enumerable]]: false, [[Configurable]]: true}).
2886     obj->SetPropertyInlinedPropsWithSize<JSArguments::SIZE, JSArguments::LENGTH_INLINE_PROPERTY_INDEX>(
2887         thread, JSTaggedValue(len));
2888     // 5. Let index be 0.
2889     // 6. Repeat while index < len,
2890     //    a. Let val be argumentsList[index].
2891     //    b. Perform CreateDataProperty(obj, ToString(index), val).
2892     //    c. Let index be index + 1
2893     obj->SetElements(thread, argumentsList.GetTaggedValue());
2894     // 7. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor
2895     // {[[Value]]:%ArrayProto_values%,
2896     // [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
2897     obj->SetPropertyInlinedPropsWithSize<JSArguments::SIZE, JSArguments::ITERATOR_INLINE_PROPERTY_INDEX>(
2898         thread, globalEnv->GetArrayProtoValuesFunction().GetTaggedValue());
2899     // 8. Perform DefinePropertyOrThrow(obj, "caller", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
2900     // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
2901     JSHandle<JSTaggedValue> accessorCaller = globalEnv->GetArgumentsCallerAccessor();
2902     obj->SetPropertyInlinedPropsWithSize<JSArguments::SIZE, JSArguments::CALLER_INLINE_PROPERTY_INDEX>(
2903         thread, accessorCaller.GetTaggedValue());
2904     // 9. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
2905     // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
2906     JSHandle<JSTaggedValue> accessorCallee = globalEnv->GetArgumentsCalleeAccessor();
2907     obj->SetPropertyInlinedPropsWithSize<JSArguments::SIZE, JSArguments::CALLEE_INLINE_PROPERTY_INDEX>(
2908         thread, accessorCallee.GetTaggedValue());
2909     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2910     // 11. Return obj
2911     return obj.GetTaggedValue();
2912 }
2913 
RuntimeOptNewLexicalEnvWithName(JSThread * thread,uint16_t numVars,uint16_t scopeId,JSHandle<JSTaggedValue> & currentEnv,JSHandle<JSTaggedValue> & func)2914 JSTaggedValue RuntimeStubs::RuntimeOptNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId,
2915                                                             JSHandle<JSTaggedValue> &currentEnv,
2916                                                             JSHandle<JSTaggedValue> &func)
2917 {
2918     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2919     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
2920     // currentEnv is LexicalEnv/GlobalEnv for normal function, and is SFunctionEnv for SharedFunction.
2921     TaggedObject* obj = currentEnv.GetTaggedValue().GetTaggedObject();
2922     JSTaggedValue globalEnv = BaseEnv::Cast(obj)->GetGlobalEnv(thread);
2923     if LIKELY(!globalEnv.IsHole()) {
2924         newEnv->SetGlobalEnv(thread, globalEnv);
2925     } else {
2926         newEnv->SetGlobalEnv(thread, thread->GetGlueGlobalEnv());
2927     }
2928     newEnv->SetParentEnv(thread, currentEnv.GetTaggedValue());
2929     JSTaggedValue scopeInfo = RuntimeOptGenerateScopeInfo(thread, scopeId, func.GetTaggedValue());
2930     newEnv->SetScopeInfo(thread, scopeInfo);
2931     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2932     JSTaggedValue taggedEnv = newEnv.GetTaggedValue();
2933     return taggedEnv;
2934 }
2935 
RuntimeOptCopyRestArgs(JSThread * thread,uint32_t actualArgc,uint32_t restIndex)2936 JSTaggedValue RuntimeStubs::RuntimeOptCopyRestArgs(JSThread *thread, uint32_t actualArgc, uint32_t restIndex)
2937 {
2938     // when only have three fixed args, restIndex in bytecode maybe not zero, but it actually should be zero.
2939     uint32_t actualRestNum = 0;
2940     if (actualArgc > NUM_MANDATORY_JSFUNC_ARGS + restIndex) {
2941         actualRestNum = actualArgc - NUM_MANDATORY_JSFUNC_ARGS - restIndex;
2942     }
2943     JSHandle<JSTaggedValue> restArray = JSArray::ArrayCreate(thread, JSTaggedNumber(actualRestNum));
2944 
2945     auto argv = GetActualArgv(thread);
2946     int idx = 0;
2947     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
2948 
2949     for (uint32_t i = NUM_MANDATORY_JSFUNC_ARGS + restIndex; i < actualArgc; ++i) {
2950         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2951         JSTaggedType arg = reinterpret_cast<JSTaggedType *>(argv)[i];
2952         element.Update(JSTaggedValue(arg));
2953         JSObject::SetProperty(thread, restArray, idx++, element, true);
2954     }
2955     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2956     return restArray.GetTaggedValue();
2957 }
2958 
RuntimeOptSuspendGenerator(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const JSHandle<JSTaggedValue> & value)2959 JSTaggedValue RuntimeStubs::RuntimeOptSuspendGenerator(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
2960                                                        const JSHandle<JSTaggedValue> &value)
2961 {
2962     if (genObj->IsAsyncGeneratorObject()) {
2963         JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
2964         // change state to SuspendedYield
2965         if (generatorObjectHandle->IsExecuting()) {
2966             return value.GetTaggedValue();
2967         }
2968         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2969         return generatorObjectHandle.GetTaggedValue();
2970     }
2971 
2972     if (genObj->IsGeneratorObject()) {
2973         JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
2974         // set TaskInfo for TaskPool
2975         generatorObjectHandle->SetTaskInfo(thread->GetTaskInfo());
2976         // change state to SuspendedYield
2977         if (generatorObjectHandle->IsExecuting()) {
2978             generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);
2979             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2980             return value.GetTaggedValue();
2981         }
2982         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2983         return generatorObjectHandle.GetTaggedValue();
2984     }
2985 
2986     return RuntimeThrowTypeError(thread, "RuntimeSuspendGenerator failed");
2987 }
2988 
RuntimeOptAsyncGeneratorResolve(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value,JSTaggedValue flag)2989 JSTaggedValue RuntimeStubs::RuntimeOptAsyncGeneratorResolve(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
2990                                                             JSHandle<JSTaggedValue> value, JSTaggedValue flag)
2991 {
2992     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2993 
2994     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
2995     JSHandle<JSTaggedValue> valueHandle(value);
2996     JSHandle<GeneratorContext> genContextHandle(thread, asyncGeneratorObjHandle->GetGeneratorContext(thread));
2997     ASSERT(flag.IsBoolean());
2998     bool done = flag.IsTrue();
2999     return JSAsyncGeneratorObject::AsyncGeneratorResolve(thread, asyncGeneratorObjHandle, valueHandle, done);
3000 }
3001 
RuntimeOptConstruct(JSThread * thread,JSHandle<JSTaggedValue> ctor,JSHandle<JSTaggedValue> newTarget,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)3002 JSTaggedValue RuntimeStubs::RuntimeOptConstruct(JSThread *thread, JSHandle<JSTaggedValue> ctor,
3003                                                 JSHandle<JSTaggedValue> newTarget, JSHandle<JSTaggedValue> preArgs,
3004                                                 JSHandle<TaggedArray> args)
3005 {
3006     if (newTarget->IsUndefined()) {
3007         newTarget = ctor;
3008     }
3009 
3010     if (!(newTarget->IsConstructor() && ctor->IsConstructor())) {
3011         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
3012     }
3013 
3014     if (ctor->IsJSFunction()) {
3015         return RuntimeOptConstructGeneric(thread, JSHandle<JSFunction>::Cast(ctor), newTarget, preArgs, args);
3016     }
3017     if (ctor->IsBoundFunction()) {
3018         return RuntimeOptConstructBoundFunction(
3019             thread, JSHandle<JSBoundFunction>::Cast(ctor), newTarget, preArgs, args);
3020     }
3021     if (ctor->IsJSProxy()) {
3022         return RuntimeOptConstructProxy(thread, JSHandle<JSProxy>::Cast(ctor), newTarget, preArgs, args);
3023     }
3024     THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor NonConstructor", JSTaggedValue::Exception());
3025 }
3026 
RuntimeOptConstructProxy(JSThread * thread,JSHandle<JSProxy> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)3027 JSTaggedValue RuntimeStubs::RuntimeOptConstructProxy(JSThread *thread, JSHandle<JSProxy> ctor,
3028                                                      JSHandle<JSTaggedValue> newTgt, JSHandle<JSTaggedValue> preArgs,
3029                                                      JSHandle<TaggedArray> args)
3030 {
3031     STACK_LIMIT_CHECK(thread, JSTaggedValue::Exception());
3032     // step 1 ~ 4 get ProxyHandler and ProxyTarget
3033     JSHandle<JSTaggedValue> handler(thread, ctor->GetHandler(thread));
3034     if (handler->IsNull()) {
3035         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor: handler is null", JSTaggedValue::Exception());
3036     }
3037     ASSERT(handler->IsECMAObject());
3038     JSHandle<JSTaggedValue> target(thread, ctor->GetTarget(thread));
3039 
3040     // 5.Let trap be GetMethod(handler, "construct").
3041     JSHandle<JSTaggedValue> key(thread->GlobalConstants()->GetHandledProxyConstructString());
3042     JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
3043 
3044     // 6.ReturnIfAbrupt(trap).
3045     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3046     // 7.If trap is undefined, then
3047     //   a.Assert: target has a [[Construct]] internal method.
3048     //   b.Return Construct(target, argumentsList, newTarget).
3049     if (method->IsUndefined()) {
3050         ASSERT(target->IsConstructor());
3051         return RuntimeOptConstruct(thread, target, newTgt, preArgs, args);
3052     }
3053 
3054     // 8.Let argArray be CreateArrayFromList(argumentsList).
3055     uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
3056     const uint32_t argsCount = args->GetLength();
3057     const uint32_t size = preArgsSize + argsCount;
3058     JSHandle<TaggedArray> arr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(size);
3059     if (preArgsSize > 0) {
3060         JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
3061         for (uint32_t i = 0; i < preArgsSize; ++i) {
3062             JSTaggedValue value = tgaPreArgs->Get(thread, i);
3063             arr->Set(thread, i, value);
3064         }
3065     }
3066 
3067     for (uint32_t i = 0; i < argsCount; ++i) {
3068         JSTaggedValue value = args->Get(thread, i);
3069         arr->Set(thread, i + preArgsSize, value);
3070     }
3071     JSHandle<JSArray> newArr = JSArray::CreateArrayFromList(thread, arr);
3072 
3073     // step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »).
3074     const uint32_t argsLength = 3;  // 3: «target, argArray, newTarget »
3075     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
3076     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
3077     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3078     info->SetCallArg(target.GetTaggedValue(), newArr.GetTaggedValue(), newTgt.GetTaggedValue());
3079     JSTaggedValue newObjValue = JSFunction::Call(info);
3080     // 10.ReturnIfAbrupt(newObj).
3081     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3082     // 11.If Type(newObj) is not Object, throw a TypeError exception.
3083     if (!newObjValue.IsECMAObject()) {
3084         THROW_TYPE_ERROR_AND_RETURN(thread, "new object is not object", JSTaggedValue::Exception());
3085     }
3086     // 12.Return newObj.
3087     return newObjValue;
3088 }
3089 
RuntimeOptConstructBoundFunction(JSThread * thread,JSHandle<JSBoundFunction> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)3090 JSTaggedValue RuntimeStubs::RuntimeOptConstructBoundFunction(JSThread *thread, JSHandle<JSBoundFunction> ctor,
3091                                                              JSHandle<JSTaggedValue> newTgt,
3092                                                              JSHandle<JSTaggedValue> preArgs,
3093                                                              JSHandle<TaggedArray> args)
3094 {
3095     JSHandle<JSTaggedValue> target(thread, ctor->GetBoundTarget(thread));
3096     if (!target->IsConstructor()) {
3097         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
3098     }
3099 
3100     JSHandle<TaggedArray> boundArgs(thread, ctor->GetBoundArguments(thread));
3101     JSMutableHandle<JSTaggedValue> newPreArgs(thread, preArgs.GetTaggedValue());
3102     if (newPreArgs->IsUndefined()) {
3103         newPreArgs.Update(boundArgs.GetTaggedValue());
3104     } else {
3105         newPreArgs.Update(
3106             TaggedArray::Append(thread, boundArgs, JSHandle<TaggedArray>::Cast(preArgs)).GetTaggedValue());
3107     }
3108     JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTgt.GetTaggedValue());
3109     if (JSTaggedValue::SameValue(thread, ctor.GetTaggedValue(), newTgt.GetTaggedValue())) {
3110         newTargetMutable.Update(target.GetTaggedValue());
3111     }
3112     return RuntimeOptConstruct(thread, target, newTargetMutable, newPreArgs, args);
3113 }
3114 
GetResultValue(JSThread * thread,bool isAotMethod,JSHandle<JSFunction> ctor,CVector<JSTaggedType> & values,JSHandle<JSTaggedValue> newTgt,uint32_t & size,JSHandle<JSTaggedValue> obj)3115 JSTaggedValue RuntimeStubs::GetResultValue(JSThread *thread, bool isAotMethod, JSHandle<JSFunction> ctor,
3116     CVector<JSTaggedType> &values, JSHandle<JSTaggedValue> newTgt, uint32_t &size, JSHandle<JSTaggedValue> obj)
3117 {
3118     JSTaggedValue resultValue;
3119     if (isAotMethod) {
3120         uint32_t numArgs = ctor->GetCallTarget(thread)->GetNumArgsWithCallField();
3121         bool needPushArgv = numArgs != size;
3122         const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
3123         if (ctor->IsCompiledFastCall()) {
3124             if (needPushArgv) {
3125                 values.reserve(numArgs + NUM_MANDATORY_JSFUNC_ARGS - 1);
3126                 for (uint32_t i = size; i < numArgs; i++) {
3127                     values.emplace_back(JSTaggedValue::VALUE_UNDEFINED);
3128                 }
3129                 size = numArgs;
3130             }
3131             resultValue = thread->GetEcmaVM()->FastCallAot(size, values.data(), prevFp);
3132         } else {
3133             resultValue = thread->GetEcmaVM()->ExecuteAot(size, values.data(), prevFp, needPushArgv);
3134         }
3135     } else {
3136         EcmaRuntimeCallInfo *info =
3137             EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(ctor), obj, newTgt, size);
3138         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3139         info->SetCallArg(size, values.data());
3140         resultValue = EcmaInterpreter::Execute(info);
3141     }
3142     return resultValue;
3143 }
3144 
RuntimeOptConstructGeneric(JSThread * thread,JSHandle<JSFunction> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)3145 JSTaggedValue RuntimeStubs::RuntimeOptConstructGeneric(JSThread *thread, JSHandle<JSFunction> ctor,
3146                                                        JSHandle<JSTaggedValue> newTgt,
3147                                                        JSHandle<JSTaggedValue> preArgs, JSHandle<TaggedArray> args)
3148 {
3149     if (!ctor->IsConstructor()) {
3150         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
3151     }
3152 
3153     JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
3154     if (ctor->IsBase(thread)) {
3155         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
3156         obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(ctor, newTgt));
3157         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3158     }
3159 
3160     uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
3161     const uint32_t argsCount = args->GetLength();
3162     uint32_t size = preArgsSize + argsCount;
3163     CVector<JSTaggedType> values;
3164     bool isCompiledCode = ctor->IsCompiledCode();
3165     if (isCompiledCode) {
3166         if (ctor->IsCompiledFastCall()) {
3167             values.reserve(size + NUM_MANDATORY_JSFUNC_ARGS - 1);
3168             values.emplace_back(ctor.GetTaggedValue().GetRawData());
3169             values.emplace_back(obj.GetTaggedValue().GetRawData());
3170         } else {
3171             values.reserve(size + NUM_MANDATORY_JSFUNC_ARGS);
3172             values.emplace_back(ctor.GetTaggedValue().GetRawData());
3173             values.emplace_back(newTgt.GetTaggedValue().GetRawData());
3174             values.emplace_back(obj.GetTaggedValue().GetRawData());
3175         }
3176     } else {
3177         values.reserve(size);
3178     }
3179 
3180     if (preArgsSize > 0) {
3181         JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
3182         for (uint32_t i = 0; i < preArgsSize; ++i) {
3183             JSTaggedValue value = tgaPreArgs->Get(thread, i);
3184             values.emplace_back(value.GetRawData());
3185         }
3186         for (uint32_t i = 0; i < argsCount; ++i) {
3187             values.emplace_back(args->Get(thread, i).GetRawData());
3188         }
3189     } else {
3190         for (uint32_t i = 0; i < argsCount; ++i) {
3191             values.emplace_back(args->Get(thread, i).GetRawData());
3192         }
3193     }
3194     JSTaggedValue resultValue = RuntimeStubs::GetResultValue(thread, isCompiledCode, ctor, values, newTgt, size, obj);
3195     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3196     // 9.3.2 [[Construct]] (argumentsList, newTarget)
3197     if (resultValue.IsECMAObject()) {
3198         if (resultValue.IsJSShared()) {
3199             JSObject::Cast(resultValue.GetTaggedObject())->GetJSHClass()->SetExtensible(false);
3200         }
3201         return resultValue;
3202     }
3203 
3204     if (ctor->IsBase(thread)) {
3205         return obj.GetTaggedValue();
3206     }
3207     if (!resultValue.IsUndefined()) {
3208         THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
3209     }
3210     return obj.GetTaggedValue();
3211 }
3212 
RuntimeOptNewObjRange(JSThread * thread,uintptr_t argv,uint32_t argc)3213 JSTaggedValue RuntimeStubs::RuntimeOptNewObjRange(JSThread *thread, uintptr_t argv, uint32_t argc)
3214 {
3215     JSHandle<JSTaggedValue> ctor = GetHArg<JSTaggedValue>(argv, argc, 0);
3216     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
3217     const size_t firstArgOffset = 1;
3218     ASSERT(argc > 0);
3219     size_t arrLength = argc - firstArgOffset;
3220     JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(arrLength);
3221     for (size_t i = 0; i < arrLength; ++i) {
3222         args->Set(thread, i, GetArg(argv, argc, i + firstArgOffset));
3223     }
3224     JSTaggedValue object = RuntimeOptConstruct(thread, ctor, ctor, undefined, args);
3225     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3226     if (!object.IsUndefined() && !object.IsECMAObject() && !JSHandle<JSFunction>(ctor)->IsBase(thread)) {
3227         THROW_TYPE_ERROR_AND_RETURN(thread, "Derived constructor must return object or undefined",
3228                                     JSTaggedValue::Exception());
3229     }
3230     return object;
3231 }
3232 
RuntimeOptGenerateScopeInfo(JSThread * thread,uint16_t scopeId,JSTaggedValue func)3233 JSTaggedValue RuntimeStubs::RuntimeOptGenerateScopeInfo(JSThread *thread, uint16_t scopeId, JSTaggedValue func)
3234 {
3235     EcmaVM *ecmaVm = thread->GetEcmaVM();
3236     ObjectFactory *factory = ecmaVm->GetFactory();
3237     Method *method = ECMAObject::Cast(func.GetTaggedObject())->GetCallTarget(thread);
3238     const JSPandaFile *jsPandaFile = method->GetJSPandaFile(thread);
3239     JSHandle<ConstantPool> constpool(thread, method->GetConstantPool(thread));
3240     panda_file::File::EntityId id = constpool->GetEntityId(scopeId);
3241     JSHandle<TaggedArray> elementsLiteral =
3242         LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id, constpool);
3243 
3244     ASSERT(elementsLiteral->GetLength() > 0);
3245 
3246     auto *scopeDebugInfo = ecmaVm->GetNativeAreaAllocator()->New<ScopeDebugInfo>();
3247     if (scopeDebugInfo == nullptr) {
3248         return JSTaggedValue::Hole();
3249     }
3250 
3251     size_t length = elementsLiteral->GetLength();
3252     for (size_t i = 1; i < length; i += 2) {  // 2: Each literal buffer contains a pair of key-value.
3253         JSTaggedValue val = elementsLiteral->Get(thread, i);
3254         ASSERT(val.IsString());
3255         CString name = ConvertToString(thread, EcmaString::Cast(val.GetTaggedObject()));
3256         int32_t slot = elementsLiteral->Get(thread, i + 1).GetInt();
3257         scopeDebugInfo->scopeInfo.emplace(name, slot);
3258     }
3259 
3260     JSHandle<JSNativePointer> pointer = factory->NewJSNativePointer(
3261         scopeDebugInfo, NativeAreaAllocator::FreeObjectFunc<ScopeDebugInfo>, ecmaVm->GetNativeAreaAllocator());
3262     return pointer.GetTaggedValue();
3263 }
3264 
GetActualArgv(JSThread * thread)3265 JSTaggedType *RuntimeStubs::GetActualArgv(JSThread *thread)
3266 {
3267     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
3268     FrameIterator it(current, thread);
3269     ASSERT(it.IsLeaveFrame());
3270     it.Advance<GCVisitedFlag::VISITED>();
3271     ASSERT(it.IsAotOrJitFunctionFrame());
3272     if (it.IsFastJitFunctionFrame()) {
3273         auto optimizedJSJITFunctionFrame = it.GetFrame<FASTJITFunctionFrame>();
3274         return optimizedJSJITFunctionFrame->GetArgv(it);
3275     } else {
3276         auto optimizedJSFunctionFrame = it.GetFrame<OptimizedJSFunctionFrame>();
3277         return optimizedJSFunctionFrame->GetArgv(it);
3278     }
3279 }
3280 
GetActualArgvFromStub(JSThread * thread)3281 JSTaggedType *RuntimeStubs::GetActualArgvFromStub(JSThread *thread)
3282 {
3283     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
3284     FrameIterator it(current, thread);
3285     ASSERT(it.IsLeaveFrame());
3286     it.Advance<GCVisitedFlag::VISITED>();
3287     ASSERT(it.IsOptimizedFrame());
3288     it.Advance<GCVisitedFlag::VISITED>();
3289     ASSERT(it.IsAotOrJitFunctionFrame());
3290     if (it.IsFastJitFunctionFrame()) {
3291         auto optimizedJSJITFunctionFrame = it.GetFrame<FASTJITFunctionFrame>();
3292         return optimizedJSJITFunctionFrame->GetArgv(it);
3293     }
3294     auto optimizedJSFunctionFrame = it.GetFrame<OptimizedJSFunctionFrame>();
3295     return optimizedJSFunctionFrame->GetArgv(it);
3296 }
3297 
GetOptimizedJSFunctionFrame(JSThread * thread)3298 OptimizedJSFunctionFrame *RuntimeStubs::GetOptimizedJSFunctionFrame(JSThread *thread)
3299 {
3300     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
3301     FrameIterator it(current, thread);
3302     ASSERT(it.IsLeaveFrame());
3303     it.Advance();
3304     ASSERT(it.IsOptimizedJSFunctionFrame());
3305     return it.GetFrame<OptimizedJSFunctionFrame>();
3306 }
3307 
GetOptimizedJSFunctionFrameNoGC(JSThread * thread)3308 OptimizedJSFunctionFrame *RuntimeStubs::GetOptimizedJSFunctionFrameNoGC(JSThread *thread)
3309 {
3310     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
3311     FrameIterator it(current, thread);
3312     ASSERT(it.IsOptimizedFrame());
3313     it.Advance();
3314     ASSERT(it.IsOptimizedJSFunctionFrame());
3315     return it.GetFrame<OptimizedJSFunctionFrame>();
3316 }
3317 
RuntimeLdPatchVar(JSThread * thread,uint32_t index)3318 JSTaggedValue RuntimeStubs::RuntimeLdPatchVar(JSThread *thread, uint32_t index)
3319 {
3320     JSHandle<TaggedArray> globalPatch =
3321         JSHandle<TaggedArray>::Cast(thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalPatch());
3322 
3323     return globalPatch->Get(thread, index);
3324 }
3325 
RuntimeStPatchVar(JSThread * thread,uint32_t index,const JSHandle<JSTaggedValue> & value)3326 JSTaggedValue RuntimeStubs::RuntimeStPatchVar(JSThread *thread, uint32_t index, const JSHandle<JSTaggedValue> &value)
3327 {
3328     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
3329 
3330     JSHandle<TaggedArray> globalPatch = JSHandle<TaggedArray>::Cast(env->GetGlobalPatch());
3331     if (index >= globalPatch->GetLength()) {
3332         globalPatch = TaggedArray::SetCapacity(thread, globalPatch, index + 1);
3333     }
3334     globalPatch->Set(thread, index, value);
3335     env->SetGlobalPatch(thread, globalPatch.GetTaggedValue());
3336     return JSTaggedValue::True();
3337 }
3338 
RuntimeNotifyConcurrentResult(JSThread * thread,JSTaggedValue result,JSTaggedValue hint)3339 JSTaggedValue RuntimeStubs::RuntimeNotifyConcurrentResult(JSThread *thread, JSTaggedValue result, JSTaggedValue hint)
3340 {
3341     thread->GetEcmaVM()->TriggerConcurrentCallback(result, hint);
3342     return JSTaggedValue::Undefined();
3343 }
3344 
RuntimeUpdateAOTHClass(JSThread * thread,const JSHandle<JSHClass> & oldhclass,const JSHandle<JSHClass> & newhclass,JSTaggedValue key)3345 JSTaggedValue RuntimeStubs::RuntimeUpdateAOTHClass(JSThread *thread,
3346     const JSHandle<JSHClass> &oldhclass, const JSHandle<JSHClass> &newhclass, JSTaggedValue key)
3347 {
3348 #if ECMASCRIPT_ENABLE_IC
3349     JSHClass::ProcessAotHClassTransition(thread, oldhclass, newhclass, key);
3350 #endif
3351     return JSTaggedValue::Undefined();
3352 }
3353 
RuntimeDefineField(JSThread * thread,JSTaggedValue obj,JSTaggedValue propKey,JSTaggedValue value)3354 JSTaggedValue RuntimeStubs::RuntimeDefineField(JSThread *thread, JSTaggedValue obj,
3355                                                JSTaggedValue propKey, JSTaggedValue value)
3356 {
3357     // Do the same thing as Object.defineProperty(obj, propKey, {value: value,
3358     //                                                           writable:true, enumerable: true, configurable: true})
3359     if (!obj.IsECMAObject()) {
3360         THROW_TYPE_ERROR_AND_RETURN(thread, "DefineField: obj is not Object", JSTaggedValue::Exception());
3361     }
3362     JSHandle<JSObject> handleObj(thread, obj);
3363     JSHandle<JSTaggedValue> handleValue(thread, value);
3364     JSHandle<JSTaggedValue> handleKey = JSTaggedValue::ToPropertyKey(thread, JSHandle<JSTaggedValue>(thread, propKey));
3365     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3366 
3367     JSObject::CreateDataPropertyOrThrow(thread, handleObj, handleKey, handleValue, SCheckMode::CHECK);
3368     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3369 
3370     return JSTaggedValue::Undefined();
3371 }
3372 
RuntimeCreatePrivateProperty(JSThread * thread,JSTaggedValue lexicalEnv,uint32_t count,JSTaggedValue constpool,uint32_t literalId,JSTaggedValue module)3373 JSTaggedValue RuntimeStubs::RuntimeCreatePrivateProperty(JSThread *thread, JSTaggedValue lexicalEnv,
3374     uint32_t count, JSTaggedValue constpool, uint32_t literalId, JSTaggedValue module)
3375 {
3376     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
3377     JSHandle<LexicalEnv> handleLexicalEnv(thread, lexicalEnv);
3378     JSHandle<ConstantPool> handleConstpool(thread, constpool);
3379     JSHandle<JSTaggedValue> handleModule(thread, module);
3380     JSHandle<ConstantPool> unsharedConstpoolHandle(
3381         thread, thread->GetEcmaVM()->FindOrCreateUnsharedConstpool(constpool));
3382     CString entry = ModuleManager::GetRecordName(thread, handleModule.GetTaggedValue());
3383     uint32_t length = handleLexicalEnv->GetLength() - LexicalEnv::RESERVED_ENV_LENGTH;
3384     uint32_t startIndex = 0;
3385     while (startIndex < length && !handleLexicalEnv->GetProperties(thread, startIndex).IsHole()) {
3386         startIndex++;
3387     }
3388 
3389     JSTaggedValue aotSymbolInfo = unsharedConstpoolHandle->GetAotSymbolInfo(thread);
3390     JSHandle<TaggedArray> aotSymbolInfoHandle(thread, aotSymbolInfo);
3391     FrameHandler frameHandler(thread);
3392     uint32_t abcId = frameHandler.GetAbcId();
3393     ASSERT(startIndex + count <= length);
3394     for (uint32_t i = 0; i < count; i++) {
3395         auto index = startIndex + i;
3396         uint64_t id = JSSymbol::GeneratePrivateId(abcId, literalId, index);
3397         JSHandle<JSSymbol> symbolHandle;
3398         JSTaggedValue symbol = ConstantPool::GetSymbolFromSymbolInfo(thread, aotSymbolInfoHandle, id);
3399         if (ConstantPool::IsAotSymbolInfoExist(aotSymbolInfoHandle, symbol)) {
3400             symbolHandle = JSHandle<JSSymbol>(thread, symbol);
3401         } else {
3402             symbolHandle = factory->NewJSSymbol();
3403             symbolHandle->SetPrivateId(id);
3404             symbolHandle->SetPrivate();
3405         }
3406         handleLexicalEnv->SetProperties(thread, index, symbolHandle.GetTaggedValue());
3407     }
3408 
3409     JSTaggedValue literalObj =
3410         ConstantPool::GetClassLiteralFromCache(thread, unsharedConstpoolHandle, literalId, entry);
3411     JSHandle<ClassLiteral> classLiteral(thread, literalObj);
3412     JSHandle<TaggedArray> literalBuffer(thread, classLiteral->GetArray(thread));
3413     uint32_t literalBufferLength = literalBuffer->GetLength();
3414     if (literalBufferLength == 0) {
3415         return JSTaggedValue::Undefined();
3416     }
3417     // instace property number is hidden in the last index of literal buffer
3418     uint32_t instacePropertyCount = static_cast<uint32_t>(literalBuffer->Get(thread, literalBufferLength - 1).GetInt());
3419     ASSERT(startIndex + count + literalBufferLength - (instacePropertyCount == 0) <= length);
3420 
3421     JSMutableHandle<JSTaggedValue> literalValue(thread, JSTaggedValue::Undefined());
3422     for (uint32_t i = 0; i < literalBufferLength - 1; i++) {
3423         literalValue.Update(literalBuffer->Get(thread, i));
3424         if (LIKELY(literalValue->IsFunctionTemplate())) {
3425             auto literalFunc = JSHandle<FunctionTemplate>::Cast(literalValue);
3426             JSHandle<JSFunction> func = factory->CreateJSFunctionFromTemplate(literalFunc);
3427             func->SetLexicalEnv(thread, handleLexicalEnv.GetTaggedValue());
3428             func->SetModule(thread, handleModule.GetTaggedValue());
3429             literalValue.Update(func);
3430         }
3431         handleLexicalEnv->SetProperties(thread, startIndex + count + i, literalValue.GetTaggedValue());
3432     }
3433     if (instacePropertyCount > 0) {
3434         auto index = startIndex + count + literalBufferLength - 1;
3435         uint64_t id = JSSymbol::GeneratePrivateId(abcId, literalId, index);
3436         JSHandle<JSSymbol> symbolHandle;
3437         JSTaggedValue symbol = ConstantPool::GetSymbolFromSymbolInfo(thread, aotSymbolInfoHandle, id);
3438         if (ConstantPool::IsAotSymbolInfoExist(aotSymbolInfoHandle, symbol)) {
3439             symbolHandle = JSHandle<JSSymbol>(thread, symbol);
3440         } else {
3441             symbolHandle = factory->NewPublicSymbolWithChar("method");
3442             symbolHandle->SetPrivateId(id);
3443             symbolHandle->SetPrivate();
3444         }
3445         handleLexicalEnv->SetProperties(thread, index, symbolHandle.GetTaggedValue());
3446     }
3447     return JSTaggedValue::Undefined();
3448 }
3449 
RuntimeDefinePrivateProperty(JSThread * thread,JSTaggedValue lexicalEnv,uint32_t levelIndex,uint32_t slotIndex,JSTaggedValue obj,JSTaggedValue value)3450 JSTaggedValue RuntimeStubs::RuntimeDefinePrivateProperty(JSThread *thread, JSTaggedValue lexicalEnv,
3451     uint32_t levelIndex, uint32_t slotIndex, JSTaggedValue obj, JSTaggedValue value)
3452 {
3453     JSTaggedValue currentLexicalEnv = lexicalEnv;
3454     for (uint32_t i = 0; i < levelIndex; i++) {
3455         currentLexicalEnv = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetParentEnv(thread);
3456         ASSERT(!currentLexicalEnv.IsUndefined());
3457     }
3458     JSTaggedValue key = LexicalEnv::Cast(currentLexicalEnv.GetTaggedObject())->GetProperties(thread, slotIndex);
3459     // private property is invisible for proxy
3460     JSHandle<JSTaggedValue> handleObj(thread, obj.IsJSProxy() ? JSProxy::Cast(obj)->GetPrivateField(thread) : obj);
3461     JSHandle<JSTaggedValue> handleKey(thread, key);
3462     JSHandle<JSTaggedValue> handleValue(thread, value);
3463     PropertyDescriptor desc(thread);
3464     if (!JSTaggedValue::IsPropertyKey(handleKey) &&
3465         JSTaggedValue::GetOwnProperty(thread, handleObj, handleKey, desc)) {
3466         THROW_TYPE_ERROR_AND_RETURN(thread, "invalid private key or already exists", JSTaggedValue::Exception());
3467     }
3468     bool extensible = handleObj->IsExtensible(thread);
3469     if (handleObj->IsUndefined()) {
3470         THROW_TYPE_ERROR_AND_RETURN(thread, "DefinePrivateProperty obj is undefined", JSTaggedValue::Exception());
3471     }
3472     if (handleObj->IsJSShared()) {
3473         THROW_TYPE_ERROR_AND_RETURN(thread, "shared obj cannot use # to define private property",
3474                                     JSTaggedValue::Exception());
3475     }
3476     if (!extensible) {
3477         // private key should be always extensible
3478         handleObj->GetTaggedObject()->GetClass()->SetExtensible(true);
3479     }
3480     bool result = JSObject::CreateDataPropertyOrThrow(thread, JSHandle<JSObject>::Cast(handleObj),
3481                                                       handleKey, handleValue);
3482     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3483     if (!extensible) {
3484         handleObj->GetTaggedObject()->GetClass()->SetExtensible(false);
3485     }
3486     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
3487     return JSTaggedValue(result);
3488 }
3489 
RuntimeNotifyDebuggerStatement(JSThread * thread)3490 JSTaggedValue RuntimeStubs::RuntimeNotifyDebuggerStatement(JSThread *thread)
3491 {
3492     FrameHandler frameHandler(thread);
3493     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
3494         if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) {
3495             continue;
3496         }
3497         Method *method = frameHandler.GetMethod();
3498         if (method->IsNativeWithCallField()) {
3499             continue;
3500         }
3501         auto bcOffset = frameHandler.GetBytecodeOffset();
3502         auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager();
3503         debuggerMgr->GetNotificationManager()->DebuggerStmtEvent(thread, method, bcOffset);
3504         return JSTaggedValue::Hole();
3505     }
3506     return JSTaggedValue::Hole();
3507 }
3508 
CheckElementsNumber(const JSThread * thread,JSHandle<TaggedArray> elements,uint32_t len)3509 bool RuntimeStubs::CheckElementsNumber(const JSThread *thread, JSHandle<TaggedArray> elements, uint32_t len)
3510 {
3511     ASSERT(len <= elements->GetLength());
3512     for (uint32_t i = 0; i < len; i++) {
3513         if (!elements->Get(thread, i).IsNumber()) {
3514             return false;
3515         }
3516     }
3517     return true;
3518 }
3519 
GetOrCreateNumberString(JSThread * thread,JSHandle<JSTaggedValue> presentValue,std::map<uint64_t,JSHandle<JSTaggedValue>> & cachedString)3520 JSHandle<JSTaggedValue> RuntimeStubs::GetOrCreateNumberString(JSThread *thread, JSHandle<JSTaggedValue> presentValue,
3521                                                               std::map<uint64_t, JSHandle<JSTaggedValue>> &cachedString)
3522 {
3523     JSMutableHandle<JSTaggedValue> presentString(thread, JSTaggedValue::Undefined());
3524     auto iter = cachedString.find(presentValue->GetRawData());
3525     if (iter != cachedString.end()) {
3526         presentString.Update(iter->second);
3527     } else {
3528         presentString.Update(JSTaggedValue::ToString(thread, presentValue).GetTaggedValue());
3529         cachedString[presentValue->GetRawData()] = presentString;
3530     }
3531     return presentString;
3532 }
3533 
TryCopyCOWArray(JSThread * thread,JSHandle<JSArray> holderHandler,bool & isCOWArray)3534 JSTaggedValue RuntimeStubs::TryCopyCOWArray(JSThread *thread, JSHandle<JSArray> holderHandler, bool &isCOWArray)
3535 {
3536     if (isCOWArray) {
3537         JSArray::CheckAndCopyArray(thread, holderHandler);
3538         isCOWArray = false;
3539     }
3540     return holderHandler->GetElements(thread);
3541 }
3542 
ArrayNumberSort(JSThread * thread,JSHandle<JSObject> thisObj,uint32_t len)3543 JSTaggedValue RuntimeStubs::ArrayNumberSort(JSThread *thread, JSHandle<JSObject> thisObj, uint32_t len)
3544 {
3545     JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
3546     JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
3547     JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
3548     bool isCOWArray = JSHandle<JSTaggedValue>(thisObj)->IsJSCOWArray(thread);
3549     JSMutableHandle<TaggedArray> elements(thread, thisObj->GetElements(thread));
3550     std::map<uint64_t, JSHandle<JSTaggedValue>> cachedString;
3551     for (uint32_t i = 1; i < len; i++) {
3552         uint32_t beginIndex = 0;
3553         uint32_t endIndex = i;
3554         presentValue.Update(elements->Get(thread, i));
3555         JSHandle<JSTaggedValue> presentString = GetOrCreateNumberString(thread, presentValue, cachedString);
3556         while (beginIndex < endIndex) {
3557             uint32_t middleIndex = beginIndex + (endIndex - beginIndex) / 2; // 2 : half
3558             middleValue.Update(elements->Get(thread, middleIndex));
3559             JSHandle<JSTaggedValue> middleString = GetOrCreateNumberString(thread, middleValue, cachedString);
3560             double compareResult = ArrayHelper::StringSortCompare(thread, middleString, presentString);
3561             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
3562             if (compareResult > 0) {
3563                 endIndex = middleIndex;
3564             } else {
3565                 beginIndex = middleIndex + 1;
3566             }
3567         }
3568         if (endIndex >= 0 && endIndex < i) {
3569             for (uint32_t j = i; j > endIndex; j--) {
3570                 previousValue.Update(elements->Get(thread, j - 1));
3571                 elements.Update(TryCopyCOWArray(thread, JSHandle<JSArray>(thisObj), isCOWArray));
3572                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
3573                 elements->Set(thread, j, previousValue);
3574             }
3575             elements.Update(TryCopyCOWArray(thread, JSHandle<JSArray>(thisObj), isCOWArray));
3576             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
3577             elements->Set(thread, endIndex, presentValue);
3578         }
3579     }
3580     return thisObj.GetTaggedValue();
3581 }
3582 
RuntimeTryGetInternString(uintptr_t argGlue,const JSHandle<EcmaString> & string)3583 JSTaggedType RuntimeStubs::RuntimeTryGetInternString(uintptr_t argGlue, const JSHandle<EcmaString> &string)
3584 {
3585     auto thread = JSThread::GlueToJSThread(argGlue);
3586 #if ENABLE_NEXT_OPTIMIZATION
3587     EcmaString *str = thread->GetEcmaVM()->GetEcmaStringTable()->TryGetInternString(thread, string);
3588 #else
3589     EcmaString *str =
3590         thread->GetEcmaVM()->GetEcmaStringTable()->TryGetInternString(thread, string);
3591 #endif
3592     if (str == nullptr) {
3593         return JSTaggedValue::Hole().GetRawData();
3594     }
3595     return JSTaggedValue::Cast(static_cast<void *>(str));
3596 }
3597 
RuntimeGetBytecodePcOfstForBaseline(JSThread * thread,const JSHandle<JSFunction> & func,uintptr_t nativePc)3598 uint32_t RuntimeStubs::RuntimeGetBytecodePcOfstForBaseline(JSThread *thread, const JSHandle<JSFunction> &func,
3599                                                            uintptr_t nativePc)
3600 {
3601     // Compute current bytecodePc according to nativePc of returnAddress
3602     LOG_BASELINEJIT(DEBUG) << "nativePc address: " << std::hex << nativePc;
3603     const MachineCode *machineCode = MachineCode::Cast(func->GetBaselineCode(thread).GetTaggedObject());
3604     const uintptr_t nativePcStart = machineCode->GetFuncAddr();
3605     LOG_BASELINEJIT(DEBUG) << "baselineCode nativeStart address: " << std::hex << nativePcStart;
3606     const Method *thisMethod = Method::Cast(func->GetMethod(thread).GetTaggedObject());
3607     const uint8_t *bytecodeStart = thisMethod->GetBytecodeArray();
3608     const uint8_t *bytecodeEnd = bytecodeStart + thisMethod->GetCodeSize(thread);
3609     LOG_BASELINEJIT(DEBUG) << "bytecodePc start: " << reinterpret_cast<uintptr_t>(bytecodeStart);
3610     LOG_BASELINEJIT(DEBUG) << "bytecodePc end: " << reinterpret_cast<uintptr_t>(bytecodeEnd);
3611     const uint8_t *offsetTableAddr = machineCode->GetStackMapOrOffsetTableAddress();
3612     const uint32_t offsetTableSize = machineCode->GetStackMapOrOffsetTableSize();
3613     uintptr_t nativePcEnd = nativePcStart;
3614     uint32_t pcOffsetIndex = 0;
3615     auto opcode = kungfu::Bytecodes::GetOpcode(bytecodeStart);
3616     while (nativePcEnd < nativePc && pcOffsetIndex < offsetTableSize) {
3617         nativePcEnd += static_cast<uintptr_t>(offsetTableAddr[pcOffsetIndex++]);
3618         opcode = kungfu::Bytecodes::GetOpcode(bytecodeStart);
3619         bytecodeStart += BytecodeInstruction::Size(opcode);
3620     }
3621     // Since the nativePc is returnAddress, we need to take the previous bytecode
3622     bytecodeStart -= BytecodeInstruction::Size(opcode);
3623     if (nativePcEnd < nativePc) {
3624         LOG_ECMA(FATAL) <<
3625             "invalid nativePc or pcOffsetTable for getting bytecode pc in baseline code, the nativePcEnd is " <<
3626             std::hex << nativePcEnd;
3627     }
3628     if (bytecodeStart > bytecodeEnd) {
3629         LOG_ECMA(FATAL) <<
3630             "out of bytecodeArray range for getting bytecode pc in baseline code, the bytecodePc is " <<
3631             reinterpret_cast<uintptr_t>(bytecodeStart);
3632     }
3633     auto bytecodePcOffset = static_cast<uint32_t>(bytecodeStart - thisMethod->GetBytecodeArray());
3634     LOG_BASELINEJIT(DEBUG) << "current bytecodePc offset: " << bytecodePcOffset;
3635     return bytecodePcOffset;
3636 }
3637 
RuntimeGetNativePcOfstForBaseline(JSThread * thread,const JSHandle<JSFunction> & func,uint64_t bytecodePos)3638 uintptr_t RuntimeStubs::RuntimeGetNativePcOfstForBaseline(JSThread *thread, const JSHandle<JSFunction> &func,
3639                                                           uint64_t bytecodePos)
3640 {
3641     const uint8_t *bytecodePc = reinterpret_cast<uint8_t*>(bytecodePos);
3642     // Compute current nativePc according to bytecodePc
3643     LOG_BASELINEJIT(DEBUG) << "bytecodePc address: " << std::hex << reinterpret_cast<uintptr_t>(bytecodePc);
3644     auto opcode = kungfu::Bytecodes::GetOpcode(bytecodePc);
3645     LOG_BASELINEJIT(DEBUG) << "bytecode: " << kungfu::GetEcmaOpcodeStr(opcode);
3646     const Method *thisMethod = Method::Cast(func->GetMethod(thread).GetTaggedObject());
3647     LOG_TRACE(INFO) << "deopt to baseline method name: " << thisMethod->GetMethodName(thread);
3648     const uint8_t *bytecodeStart = thisMethod->GetBytecodeArray();
3649     const uint8_t *bytecodeEnd = bytecodeStart + thisMethod->GetCodeSize(thread);
3650     ASSERT(bytecodeStart < bytecodeEnd);
3651     LOG_BASELINEJIT(DEBUG) << "bytecodePc start: " << std::hex << reinterpret_cast<uintptr_t>(bytecodeStart);
3652     LOG_BASELINEJIT(DEBUG) << "bytecodePc end: " << std::hex << reinterpret_cast<uintptr_t>(bytecodeEnd);
3653     ASSERT(bytecodeEnd >= bytecodeStart && bytecodePc <= bytecodeEnd);
3654 
3655     const MachineCode *machineCode = MachineCode::Cast(func->GetBaselineCode(thread).GetTaggedObject());
3656     const uintptr_t nativePcStart = machineCode->GetFuncAddr();
3657     LOG_BASELINEJIT(DEBUG) << "baselineCode nativeStart address: " << std::hex << nativePcStart;
3658     const uint8_t *offsetTableAddr = machineCode->GetStackMapOrOffsetTableAddress();
3659     const uint32_t offsetTableSize = machineCode->GetStackMapOrOffsetTableSize();
3660     uintptr_t nativePc = nativePcStart;
3661     uint32_t pcOffsetIndex = 0;
3662     uint8_t *bytecodetmp = const_cast<uint8_t*>(bytecodeStart);
3663     while (bytecodetmp < bytecodePc && pcOffsetIndex < offsetTableSize) {
3664         nativePc += static_cast<uintptr_t>(offsetTableAddr[pcOffsetIndex++]);
3665         opcode = kungfu::Bytecodes::GetOpcode(bytecodetmp);
3666         bytecodetmp += BytecodeInstruction::Size(opcode);
3667     }
3668     LOG_BASELINEJIT(DEBUG) << "baselineCode nativePc address: " << std::hex << nativePc;
3669     return nativePc;
3670 }
3671 }  // namespace panda::ecmascript
3672 #endif  // ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
3673