• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
17 #define ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
18 
19 #include "ecmascript/stubs/runtime_stubs.h"
20 
21 #include "ecmascript/builtins/builtins_regexp.h"
22 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
23 #include "ecmascript/ecma_string_table.h"
24 #include "ecmascript/global_dictionary-inl.h"
25 #include "ecmascript/global_env.h"
26 #include "ecmascript/ic/profile_type_info.h"
27 #include "ecmascript/interpreter/frame_handler.h"
28 #include "ecmascript/jobs/micro_job_queue.h"
29 #include "ecmascript/js_arguments.h"
30 #include "ecmascript/js_async_function.h"
31 #include "ecmascript/js_async_generator_object.h"
32 #include "ecmascript/js_for_in_iterator.h"
33 #include "ecmascript/js_generator_object.h"
34 #include "ecmascript/js_iterator.h"
35 #include "ecmascript/js_promise.h"
36 #include "ecmascript/jspandafile/class_info_extractor.h"
37 #include "ecmascript/jspandafile/literal_data_extractor.h"
38 #include "ecmascript/jspandafile/scope_info_extractor.h"
39 #include "ecmascript/module/js_module_manager.h"
40 #include "ecmascript/module/js_module_source_text.h"
41 #include "ecmascript/platform/file.h"
42 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
43 #include "ecmascript/template_string.h"
44 #include "ecmascript/ts_types/ts_manager.h"
45 
46 namespace panda::ecmascript {
RuntimeInc(JSThread * thread,const JSHandle<JSTaggedValue> & value)47 JSTaggedValue RuntimeStubs::RuntimeInc(JSThread *thread, const JSHandle<JSTaggedValue> &value)
48 {
49     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
50     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
51     if (inputVal->IsBigInt()) {
52         JSHandle<BigInt> bigValue(inputVal);
53         return BigInt::BigintAddOne(thread, bigValue).GetTaggedValue();
54     }
55     JSTaggedNumber number(inputVal.GetTaggedValue());
56     return JSTaggedValue(++number);
57 }
58 
RuntimeDec(JSThread * thread,const JSHandle<JSTaggedValue> & value)59 JSTaggedValue RuntimeStubs::RuntimeDec(JSThread *thread, const JSHandle<JSTaggedValue> &value)
60 {
61     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
62     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
63     if (inputVal->IsBigInt()) {
64         JSHandle<BigInt> bigValue(inputVal);
65         return BigInt::BigintSubOne(thread, bigValue).GetTaggedValue();
66     }
67     JSTaggedNumber number(inputVal.GetTaggedValue());
68     return JSTaggedValue(--number);
69 }
70 
RuntimeExp(JSThread * thread,JSTaggedValue base,JSTaggedValue exponent)71 JSTaggedValue RuntimeStubs::RuntimeExp(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent)
72 {
73     JSHandle<JSTaggedValue> baseTag(thread, base);
74     JSHandle<JSTaggedValue> exponentTag(thread, exponent);
75     JSHandle<JSTaggedValue> valBase = JSTaggedValue::ToNumeric(thread, baseTag);
76     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
77     JSHandle<JSTaggedValue> valExponent = JSTaggedValue::ToNumeric(thread, exponentTag);
78     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
79     if (valBase->IsBigInt() || valExponent->IsBigInt()) {
80         if (valBase->IsBigInt() && valExponent->IsBigInt()) {
81             JSHandle<BigInt> bigBaseVale(valBase);
82             JSHandle<BigInt> bigExponentValue(valExponent);
83             return BigInt::Exponentiate(thread, bigBaseVale, bigExponentValue).GetTaggedValue();
84         }
85         THROW_TYPE_ERROR_AND_RETURN(thread, "Cannot mix BigInt and other types, use explicit conversions",
86                                     JSTaggedValue::Exception());
87     }
88     double doubleBase = valBase->GetNumber();
89     double doubleExponent = valExponent->GetNumber();
90     if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) {
91         return JSTaggedValue(base::NAN_VALUE);
92     }
93     if (((doubleBase == 0) &&
94         ((base::bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
95         std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
96         base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == (doubleExponent / 2)) {  // 2: half
97         if (doubleExponent > 0) {
98             return JSTaggedValue(-0.0);
99         }
100         if (doubleExponent < 0) {
101             return JSTaggedValue(-base::POSITIVE_INFINITY);
102         }
103     }
104     return JSTaggedValue(std::pow(doubleBase, doubleExponent));
105 }
106 
RuntimeIsIn(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & obj)107 JSTaggedValue RuntimeStubs::RuntimeIsIn(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
108                                         const JSHandle<JSTaggedValue> &obj)
109 {
110     if (!obj->IsECMAObject()) {
111         return RuntimeThrowTypeError(thread, "Cannot use 'in' operator in Non-Object");
112     }
113     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
114     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
115     bool ret = JSTaggedValue::HasProperty(thread, obj, propKey);
116     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
117     return JSTaggedValue(ret);
118 }
119 
RuntimeInstanceof(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & target)120 JSTaggedValue RuntimeStubs::RuntimeInstanceof(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
121                                               const JSHandle<JSTaggedValue> &target)
122 {
123     bool ret = JSObject::InstanceOf(thread, obj, target);
124     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
125     return JSTaggedValue(ret);
126 }
127 
RuntimeInstanceofByHandler(JSThread * thread,JSHandle<JSTaggedValue> target,JSHandle<JSTaggedValue> object,JSHandle<JSTaggedValue> instOfHandler)128 JSTaggedValue RuntimeStubs::RuntimeInstanceofByHandler(JSThread *thread, JSHandle<JSTaggedValue> target,
129                                                        JSHandle<JSTaggedValue> object,
130                                                        JSHandle<JSTaggedValue> instOfHandler)
131 {
132     // 3. ReturnIfAbrupt(instOfHandler).
133     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
134     // 4. If instOfHandler is not undefined, then
135     if (!instOfHandler->IsUndefined()) {
136         // a. Return ! ToBoolean(? Call(instOfHandler, target, «object»)).
137         JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
138         JSTaggedValue function = env->GetTaggedHasInstanceFunction();
139         JSTaggedValue instOf = instOfHandler.GetTaggedValue();
140         // slowpath
141         if (function != instOf) {
142             JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
143             EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, instOfHandler, target,
144                                                                             undefined, 1);
145             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
146             info->SetCallArg(object.GetTaggedValue());
147             JSTaggedValue tagged = JSFunction::Call(info);
148 
149             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
150             return tagged;
151         }
152     }
153     // 5. If IsCallable(target) is false, throw a TypeError exception.
154     if (!target->IsCallable()) {
155         THROW_TYPE_ERROR_AND_RETURN(thread, "InstanceOf error when target is not Callable", JSTaggedValue::Exception());
156     }
157     // fastpath
158     // 6. Return ? OrdinaryHasInstance(target, object).
159     bool res = JSFunction::OrdinaryHasInstance(thread, target, object);
160     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
161     return JSTaggedValue(res);
162 }
163 
RuntimeCreateGeneratorObj(JSThread * thread,const JSHandle<JSTaggedValue> & genFunc)164 JSTaggedValue RuntimeStubs::RuntimeCreateGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc)
165 {
166     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
167     JSHandle<JSGeneratorObject> obj = factory->NewJSGeneratorObject(genFunc);
168     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
169     context->SetGeneratorObject(thread, obj.GetTaggedValue());
170 
171     // change state to SUSPENDED_START
172     obj->SetGeneratorState(JSGeneratorState::SUSPENDED_START);
173     obj->SetGeneratorContext(thread, context);
174 
175     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
176     return obj.GetTaggedValue();
177 }
178 
RuntimeCreateAsyncGeneratorObj(JSThread * thread,const JSHandle<JSTaggedValue> & genFunc)179 JSTaggedValue RuntimeStubs::RuntimeCreateAsyncGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc)
180 {
181     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
182     JSHandle<JSAsyncGeneratorObject> obj = factory->NewJSAsyncGeneratorObject(genFunc);
183     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
184     context->SetGeneratorObject(thread, obj.GetTaggedValue());
185 
186     // change state to SUSPENDED_START
187     obj->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_START);
188     obj->SetGeneratorContext(thread, context);
189 
190     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
191     return obj.GetTaggedValue();
192 }
193 
RuntimeGetTemplateObject(JSThread * thread,const JSHandle<JSTaggedValue> & literal)194 JSTaggedValue RuntimeStubs::RuntimeGetTemplateObject(JSThread *thread, const JSHandle<JSTaggedValue> &literal)
195 {
196     JSHandle<JSTaggedValue> templateObj = TemplateString::GetTemplateObject(thread, literal);
197     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
198     return templateObj.GetTaggedValue();
199 }
200 
RuntimeGetNextPropName(JSThread * thread,const JSHandle<JSTaggedValue> & iter)201 JSTaggedValue RuntimeStubs::RuntimeGetNextPropName(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
202 {
203     ASSERT(iter->IsForinIterator());
204     std::pair<JSTaggedValue, bool> res =
205         JSForInIterator::NextInternal(thread, JSHandle<JSForInIterator>::Cast(iter));
206     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
207     return res.first;
208 }
209 
RuntimeIterNext(JSThread * thread,const JSHandle<JSTaggedValue> & iter)210 JSTaggedValue RuntimeStubs::RuntimeIterNext(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
211 {
212     JSHandle<JSTaggedValue> resultObj = JSIterator::IteratorNext(thread, iter);
213     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
214     return resultObj.GetTaggedValue();
215 }
216 
RuntimeCloseIterator(JSThread * thread,const JSHandle<JSTaggedValue> & iter)217 JSTaggedValue RuntimeStubs::RuntimeCloseIterator(JSThread *thread, const JSHandle<JSTaggedValue> &iter)
218 {
219     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
220     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
221 
222     JSHandle<JSTaggedValue> record;
223     if (thread->HasPendingException()) {
224         record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(
225             CompletionRecordType::THROW, JSHandle<JSTaggedValue>(thread, thread->GetException())));
226     } else {
227         JSHandle<JSTaggedValue> undefinedVal = globalConst->GetHandledUndefined();
228         record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(CompletionRecordType::NORMAL, undefinedVal));
229     }
230     JSHandle<JSTaggedValue> result = JSIterator::IteratorClose(thread, iter, record);
231     if (result->IsCompletionRecord()) {
232         return CompletionRecord::Cast(result->GetTaggedObject())->GetValue();
233     }
234     return result.GetTaggedValue();
235 }
236 
RuntimeSuperCallSpread(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,const JSHandle<JSTaggedValue> & array)237 JSTaggedValue RuntimeStubs::RuntimeSuperCallSpread(JSThread *thread, const JSHandle<JSTaggedValue> &func,
238                                                    const JSHandle<JSTaggedValue> &newTarget,
239                                                    const JSHandle<JSTaggedValue> &array)
240 {
241     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
242     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
243     if (!superFunc->IsJSFunction()) {
244         THROW_TYPE_ERROR_AND_RETURN(thread, "Super constructor is not JSFunction", JSTaggedValue::Exception());
245     }
246 
247     JSHandle<TaggedArray> argv(thread, RuntimeGetCallSpreadArgs(thread, array));
248     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
249     const uint32_t argsLength = argv->GetLength();
250     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
251     EcmaRuntimeCallInfo *info =
252         EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, argsLength);
253     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
254     info->SetCallArg(argsLength, argv);
255     JSTaggedValue result = JSFunction::Construct(info);
256     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
257 
258     return result;
259 }
260 
RuntimeDelObjProp(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop)261 JSTaggedValue RuntimeStubs::RuntimeDelObjProp(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
262                                               const JSHandle<JSTaggedValue> &prop)
263 {
264     JSHandle<JSTaggedValue> jsObj(JSTaggedValue::ToObject(thread, obj));
265     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
266     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
267     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
268     bool ret = JSTaggedValue::DeletePropertyOrThrow(thread, jsObj, propKey);
269     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
270     return JSTaggedValue(ret);
271 }
272 
RuntimeNewObjApply(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & array)273 JSTaggedValue RuntimeStubs::RuntimeNewObjApply(JSThread *thread, const JSHandle<JSTaggedValue> &func,
274                                                const JSHandle<JSTaggedValue> &array)
275 {
276     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
277     if (!array->IsJSArray()) {
278         return RuntimeThrowTypeError(thread, "Cannot Newobjspread");
279     }
280 
281     uint32_t length = JSHandle<JSArray>::Cast(array)->GetArrayLength();
282     JSHandle<TaggedArray> argsArray = factory->NewTaggedArray(length);
283     for (uint32_t i = 0; i < length; ++i) {
284         auto prop = JSTaggedValue::GetProperty(thread, array, i).GetValue();
285         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
286         argsArray->Set(thread, i, prop);
287         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
288     }
289     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
290     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, undefined, func, length);
291     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
292     info->SetCallArg(length, argsArray);
293     return NewObject(info);
294 }
295 
RuntimeCreateIterResultObj(JSThread * thread,const JSHandle<JSTaggedValue> & value,JSTaggedValue flag)296 JSTaggedValue RuntimeStubs::RuntimeCreateIterResultObj(JSThread *thread, const JSHandle<JSTaggedValue> &value,
297                                                        JSTaggedValue flag)
298 {
299     ASSERT(flag.IsBoolean());
300     bool done = flag.IsTrue();
301     JSHandle<JSObject> iter = JSIterator::CreateIterResultObject(thread, value, done);
302     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
303     return iter.GetTaggedValue();
304 }
305 
RuntimeAsyncFunctionAwaitUncaught(JSThread * thread,const JSHandle<JSTaggedValue> & asyncFuncObj,const JSHandle<JSTaggedValue> & value)306 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionAwaitUncaught(JSThread *thread,
307                                                               const JSHandle<JSTaggedValue> &asyncFuncObj,
308                                                               const JSHandle<JSTaggedValue> &value)
309 {
310     JSAsyncFunction::AsyncFunctionAwait(thread, asyncFuncObj, value);
311     if (asyncFuncObj->IsAsyncGeneratorObject()) {
312         JSHandle<JSObject> obj = JSTaggedValue::ToObject(thread, asyncFuncObj);
313         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
314         JSHandle<JSAsyncGeneratorObject> generator = JSHandle<JSAsyncGeneratorObject>::Cast(obj);
315         JSHandle<TaggedQueue> queue(thread, generator->GetAsyncGeneratorQueue());
316         if (queue->Empty()) {
317             return JSTaggedValue::Undefined();
318         }
319         JSHandle<AsyncGeneratorRequest> next(thread, queue->Front());
320         JSHandle<PromiseCapability> completion(thread, next->GetCapability());
321         JSHandle<JSPromise> promise(thread, completion->GetPromise());
322         return promise.GetTaggedValue();
323     }
324     JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(asyncFuncObj);
325     JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise());
326 
327     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
328     return promise.GetTaggedValue();
329 }
330 
RuntimeAsyncFunctionResolveOrReject(JSThread * thread,const JSHandle<JSTaggedValue> & asyncFuncObj,const JSHandle<JSTaggedValue> & value,bool is_resolve)331 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionResolveOrReject(JSThread *thread,
332     const JSHandle<JSTaggedValue> &asyncFuncObj, const JSHandle<JSTaggedValue> &value, bool is_resolve)
333 {
334     JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(asyncFuncObj);
335     JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise());
336 
337     // ActivePromise
338     JSHandle<ResolvingFunctionsRecord> reactions = JSPromise::CreateResolvingFunctions(thread, promise);
339     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
340     JSHandle<JSTaggedValue> thisArg = globalConst->GetHandledUndefined();
341     JSHandle<JSTaggedValue> activeFunc;
342     if (is_resolve) {
343         activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetResolveFunction());
344     } else {
345         activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetRejectFunction());
346     }
347     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
348     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, activeFunc, thisArg, undefined, 1);
349     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
350     info->SetCallArg(value.GetTaggedValue());
351     [[maybe_unused]] JSTaggedValue res = JSFunction::Call(info);
352 
353     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
354     return promise.GetTaggedValue();
355 }
356 
RuntimeAsyncGeneratorResolve(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value,JSTaggedValue flag)357 JSTaggedValue RuntimeStubs::RuntimeAsyncGeneratorResolve(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
358                                                          JSHandle<JSTaggedValue> value, JSTaggedValue flag)
359 {
360     [[maybe_unused]] EcmaHandleScope handleScope(thread);
361 
362     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
363     JSHandle<JSTaggedValue> valueHandle(value);
364     JSHandle<GeneratorContext> genContextHandle(thread, asyncGeneratorObjHandle->GetGeneratorContext());
365     // save stack, should copy cur_frame, function execute over will free cur_frame
366     SaveFrameToContext(thread, genContextHandle);
367 
368     ASSERT(flag.IsBoolean());
369     bool done = flag.IsTrue();
370 
371     return JSAsyncGeneratorObject::AsyncGeneratorResolve(thread, asyncGeneratorObjHandle, valueHandle, done);
372 }
373 
RuntimeAsyncGeneratorReject(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value)374 JSTaggedValue RuntimeStubs::RuntimeAsyncGeneratorReject(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
375                                                         JSHandle<JSTaggedValue> value)
376 {
377     [[maybe_unused]] EcmaHandleScope handleScope(thread);
378 
379     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
380     JSHandle<JSTaggedValue> valueHandle(value);
381 
382     return JSAsyncGeneratorObject::AsyncGeneratorReject(thread, asyncGeneratorObjHandle, valueHandle);
383 }
384 
RuntimeCopyDataProperties(JSThread * thread,const JSHandle<JSTaggedValue> & dst,const JSHandle<JSTaggedValue> & src)385 JSTaggedValue RuntimeStubs::RuntimeCopyDataProperties(JSThread *thread, const JSHandle<JSTaggedValue> &dst,
386                                                       const JSHandle<JSTaggedValue> &src)
387 {
388     if (!src->IsNull() && !src->IsUndefined()) {
389         // 2. Let from be ! ToObject(source).
390         JSHandle<JSTaggedValue> from(JSTaggedValue::ToObject(thread, src));
391         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
392         JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, from);
393         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
394 
395         JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
396         uint32_t keysLen = keys->GetLength();
397         for (uint32_t i = 0; i < keysLen; i++) {
398             PropertyDescriptor desc(thread);
399             key.Update(keys->Get(i));
400             bool success = JSTaggedValue::GetOwnProperty(thread, from, key, desc);
401             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
402 
403             if (success && desc.IsEnumerable()) {
404                 JSTaggedValue::DefineOwnProperty(thread, dst, key, desc);
405                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
406             }
407         }
408     }
409     return dst.GetTaggedValue();
410 }
411 
RuntimeStArraySpread(JSThread * thread,const JSHandle<JSTaggedValue> & dst,JSTaggedValue index,const JSHandle<JSTaggedValue> & src)412 JSTaggedValue RuntimeStubs::RuntimeStArraySpread(JSThread *thread, const JSHandle<JSTaggedValue> &dst,
413                                                  JSTaggedValue index, const JSHandle<JSTaggedValue> &src)
414 {
415     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
416     ASSERT(dst->IsJSArray());
417     if (dst->IsJSArray()) {
418         if (src->IsNull() || src->IsUndefined()) {
419             THROW_TYPE_ERROR_AND_RETURN(thread, "src is not iterable", JSTaggedValue::Exception());
420         }
421     } else {
422         THROW_TYPE_ERROR_AND_RETURN(thread, "dst is not iterable", JSTaggedValue::Exception());
423     }
424     if (src->IsString()) {
425         JSHandle<EcmaString> srcString = JSTaggedValue::ToString(thread, src);
426         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
427         JSHandle<EcmaString> srcFlat = JSHandle<EcmaString>(thread,
428             EcmaStringAccessor::Flatten(thread->GetEcmaVM(), srcString));
429         uint32_t dstLen = static_cast<uint32_t>(index.GetInt());
430         uint32_t strLen = EcmaStringAccessor(srcFlat).GetLength();
431         for (uint32_t i = 0; i < strLen; i++) {
432             uint16_t res = EcmaStringAccessor(srcFlat).Get<false>(i);
433             JSHandle<JSTaggedValue> strValue(factory->NewFromUtf16Literal(&res, 1));
434             JSTaggedValue::SetProperty(thread, dst, dstLen + i, strValue, true);
435             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
436         }
437         JSHandle<JSTaggedValue> length(thread, JSTaggedValue(dstLen + strLen));
438         if (strLen == 0U) {
439             JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
440             JSTaggedValue::SetProperty(thread, dst, lengthKey, length);
441         }
442         return length.GetTaggedValue();
443     }
444 
445     if (index.GetInt() == 0 && src->IsStableJSArray(thread)) {
446         JSHandle<TaggedArray> srcElements(thread, JSHandle<JSObject>::Cast(src)->GetElements());
447         uint32_t length = JSHandle<JSArray>::Cast(src)->GetArrayLength();
448         JSHandle<TaggedArray> dstElements = factory->NewTaggedArray(length);
449         JSHandle<JSArray> dstArray = JSHandle<JSArray>::Cast(dst);
450         dstArray->SetElements(thread, dstElements);
451         dstArray->SetArrayLength(thread, length);
452         TaggedArray::CopyTaggedArrayElement(thread, srcElements, dstElements, length);
453         return JSTaggedValue(length);
454     }
455 
456     JSHandle<JSTaggedValue> iter;
457     auto globalConst = thread->GlobalConstants();
458     if (src->IsJSArrayIterator() || src->IsJSMapIterator() || src->IsJSSetIterator() ||
459         src->IsIterator()) {
460         iter = src;
461     } else if (src->IsJSArray()) {
462         JSHandle<JSTaggedValue> valuesStr = globalConst->GetHandledValuesString();
463         JSHandle<JSTaggedValue> valuesMethod = JSObject::GetMethod(thread, src, valuesStr);
464         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
465         iter = JSIterator::GetIterator(thread, src, valuesMethod);
466         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
467     } else {
468         iter = JSIterator::GetIterator(thread, src);
469         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
470     }
471 
472     JSMutableHandle<JSTaggedValue> indexHandle(thread, index);
473     JSHandle<JSTaggedValue> valueStr = globalConst->GetHandledValueString();
474     PropertyDescriptor desc(thread);
475     JSHandle<JSTaggedValue> iterResult;
476     uint32_t srcLen = 0U;
477     do {
478         iterResult = JSIterator::IteratorStep(thread, iter);
479         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
480         if (iterResult->IsFalse()) {
481             break;
482         }
483         bool success = JSTaggedValue::GetOwnProperty(thread, iterResult, valueStr, desc);
484         if (success && desc.IsEnumerable()) {
485             JSTaggedValue::DefineOwnProperty(thread, dst, indexHandle, desc);
486             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
487             int tmp = indexHandle->GetInt();
488             indexHandle.Update(JSTaggedValue(tmp + 1));
489             ++srcLen;
490         }
491     } while (true);
492     if (srcLen == 0U) {
493         JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
494         JSTaggedValue::SetProperty(thread, dst, lengthKey, indexHandle);
495     }
496     return indexHandle.GetTaggedValue();
497 }
498 
RuntimeGetIteratorNext(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & method)499 JSTaggedValue RuntimeStubs::RuntimeGetIteratorNext(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
500                                                    const JSHandle<JSTaggedValue> &method)
501 {
502     ASSERT(method->IsCallable());
503     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
504     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, obj, undefined, 0);
505     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
506     JSTaggedValue ret = JSFunction::Call(info);
507     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
508     if (!ret.IsECMAObject()) {
509         return RuntimeThrowTypeError(thread, "the Iterator is not an ecmaobject.");
510     }
511     return ret;
512 }
513 
RuntimeSetObjectWithProto(JSThread * thread,const JSHandle<JSTaggedValue> & proto,const JSHandle<JSObject> & obj)514 JSTaggedValue RuntimeStubs::RuntimeSetObjectWithProto(JSThread *thread, const JSHandle<JSTaggedValue> &proto,
515                                                       const JSHandle<JSObject> &obj)
516 {
517     if (!proto->IsECMAObject() && !proto->IsNull()) {
518         return JSTaggedValue::False();
519     }
520     JSObject::SetPrototype(thread, obj, proto);
521     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
522     return JSTaggedValue::True();
523 }
524 
RuntimeLdObjByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,bool callGetter,JSTaggedValue receiver)525 JSTaggedValue RuntimeStubs::RuntimeLdObjByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
526                                                 const JSHandle<JSTaggedValue> &prop, bool callGetter,
527                                                 JSTaggedValue receiver)
528 {
529     // Ecma Spec 2015 12.3.2.1
530     // 7. Let bv be RequireObjectCoercible(baseValue).
531     // 8. ReturnIfAbrupt(bv).
532     JSHandle<JSTaggedValue> object =
533         JSTaggedValue::RequireObjectCoercible(thread, obj, "Cannot load property of null or undefined");
534     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
535 
536     JSTaggedValue res;
537     if (callGetter) {
538         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), object);
539     } else {
540         JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
541         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
542         res = JSTaggedValue::GetProperty(thread, object, propKey).GetValue().GetTaggedValue();
543     }
544     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
545     return res;
546 }
547 
RuntimeStObjByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)548 JSTaggedValue RuntimeStubs::RuntimeStObjByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
549                                                 const JSHandle<JSTaggedValue> &prop,
550                                                 const JSHandle<JSTaggedValue> &value)
551 {
552     // Ecma Spec 2015 12.3.2.1
553     // 7. Let bv be RequireObjectCoercible(baseValue).
554     // 8. ReturnIfAbrupt(bv).
555     JSHandle<JSTaggedValue> object =
556         JSTaggedValue::RequireObjectCoercible(thread, obj, "Cannot store property of null or undefined");
557     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
558 
559     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, prop));
560     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
561     // strict mode is true
562     JSTaggedValue::SetProperty(thread, object, propKey, value, true);
563     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
564     return JSTaggedValue::True();
565 }
566 
RuntimeStOwnByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)567 JSTaggedValue RuntimeStubs::RuntimeStOwnByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
568                                                 const JSHandle<JSTaggedValue> &key,
569                                                 const JSHandle<JSTaggedValue> &value)
570 {
571     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
572 
573     if (obj->IsClassConstructor() &&
574         JSTaggedValue::SameValue(key, globalConst->GetHandledPrototypeString())) {
575         return RuntimeThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
576     }
577 
578     // property in class is non-enumerable
579     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
580 
581     PropertyDescriptor desc(thread, value, true, enumerable, true);
582     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, key);
583     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
584     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, propKey, desc);
585     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
586     if (!ret) {
587         return RuntimeThrowTypeError(thread, "StOwnByValue failed");
588     }
589     return JSTaggedValue::True();
590 }
591 
RuntimeLdSuperByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,JSTaggedValue thisFunc)592 JSTaggedValue RuntimeStubs::RuntimeLdSuperByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
593                                                   const JSHandle<JSTaggedValue> &key, JSTaggedValue thisFunc)
594 {
595     ASSERT(thisFunc.IsJSFunction());
596     // get Homeobject form function
597     JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject());
598 
599     if (obj->IsUndefined()) {
600         return RuntimeThrowReferenceError(thread, obj, "this is uninitialized.");
601     }
602 
603     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, key));
604     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
605     JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
606     JSTaggedValue::RequireObjectCoercible(thread, superBase);
607     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
608 
609     JSTaggedValue res = JSTaggedValue::GetProperty(thread, superBase, propKey, obj).GetValue().GetTaggedValue();
610     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
611     return res;
612 }
613 
RuntimeStSuperByValue(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value,JSTaggedValue thisFunc)614 JSTaggedValue RuntimeStubs::RuntimeStSuperByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
615                                                   const JSHandle<JSTaggedValue> &key,
616                                                   const JSHandle<JSTaggedValue> &value, JSTaggedValue thisFunc)
617 {
618     ASSERT(thisFunc.IsJSFunction());
619     // get Homeobject form function
620     JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject());
621 
622     if (obj->IsUndefined()) {
623         return RuntimeThrowReferenceError(thread, obj, "this is uninitialized.");
624     }
625 
626     JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, key));
627     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
628     JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
629     JSTaggedValue::RequireObjectCoercible(thread, superBase);
630     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
631 
632     // check may_throw is false?
633     JSTaggedValue::SetProperty(thread, superBase, propKey, value, obj, true);
634     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
635     return JSTaggedValue::True();
636 }
637 
RuntimeLdObjByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,uint32_t idx,bool callGetter,JSTaggedValue receiver)638 JSTaggedValue RuntimeStubs::RuntimeLdObjByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
639                                                 uint32_t idx, bool callGetter, JSTaggedValue receiver)
640 {
641     JSTaggedValue res;
642     if (callGetter) {
643         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), obj);
644     } else {
645         res = JSTaggedValue::GetProperty(thread, obj, idx).GetValue().GetTaggedValue();
646     }
647     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
648     return res;
649 }
650 
RuntimeLdObjByName(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,bool callGetter,JSTaggedValue receiver)651 JSTaggedValue RuntimeStubs::RuntimeLdObjByName(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop,
652                                                bool callGetter, JSTaggedValue receiver)
653 {
654     JSHandle<JSTaggedValue> objHandle(thread, obj);
655     JSTaggedValue res;
656     if (callGetter) {
657         res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), objHandle);
658     } else {
659         JSHandle<JSTaggedValue> propHandle(thread, prop);
660         res = JSTaggedValue::GetProperty(thread, objHandle, propHandle).GetValue().GetTaggedValue();
661     }
662     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
663     return res;
664 }
665 
RuntimeStObjByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)666 JSTaggedValue RuntimeStubs::RuntimeStObjByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
667                                                const JSHandle<JSTaggedValue> &prop,
668                                                const JSHandle<JSTaggedValue> &value)
669 {
670     JSTaggedValue::SetProperty(thread, obj, prop, value, true);
671     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
672     return JSTaggedValue::True();
673 }
674 
RuntimeStObjByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,uint32_t idx,const JSHandle<JSTaggedValue> & value)675 JSTaggedValue RuntimeStubs::RuntimeStObjByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
676                                                 uint32_t idx, const JSHandle<JSTaggedValue> &value)
677 {
678     JSTaggedValue::SetProperty(thread, obj, idx, value, true);
679     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
680     return JSTaggedValue::True();
681 }
682 
RuntimeStOwnByIndex(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & idx,const JSHandle<JSTaggedValue> & value)683 JSTaggedValue RuntimeStubs::RuntimeStOwnByIndex(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
684                                                 const JSHandle<JSTaggedValue> &idx,
685                                                 const JSHandle<JSTaggedValue> &value)
686 {
687     // property in class is non-enumerable
688     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
689 
690     PropertyDescriptor desc(thread, value, true, enumerable, true);
691     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, idx, desc);
692     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
693     if (!ret) {
694         return RuntimeThrowTypeError(thread, "SetOwnByIndex failed");
695     }
696     return JSTaggedValue::True();
697 }
698 
RuntimeStGlobalRecord(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value,bool isConst)699 JSTaggedValue RuntimeStubs::RuntimeStGlobalRecord(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
700                                                   const JSHandle<JSTaggedValue> &value, bool isConst)
701 {
702     EcmaVM *vm = thread->GetEcmaVM();
703     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
704     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
705 
706     // cross files global record name binding judgment
707     int entry = dict->FindEntry(prop.GetTaggedValue());
708     if (entry != -1) {
709         return RuntimeThrowSyntaxError(thread, "Duplicate identifier");
710     }
711 
712     PropertyAttributes attributes;
713     if (isConst) {
714         attributes.SetIsConstProps(true);
715     }
716     JSHandle<GlobalDictionary> dictHandle(thread, dict);
717 
718     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
719     JSHandle<PropertyBox> box = factory->NewPropertyBox(value);
720     PropertyBoxType boxType = value->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT;
721     attributes.SetBoxType(boxType);
722 
723     dict = *GlobalDictionary::PutIfAbsent(thread, dictHandle, prop, JSHandle<JSTaggedValue>(box), attributes);
724     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
725     env->SetGlobalRecord(thread, JSTaggedValue(dict));
726     return JSTaggedValue::True();
727 }
728 
RuntimeNeg(JSThread * thread,const JSHandle<JSTaggedValue> & value)729 JSTaggedValue RuntimeStubs::RuntimeNeg(JSThread *thread, const JSHandle<JSTaggedValue> &value)
730 {
731     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
732     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
733     if (inputVal->IsBigInt()) {
734         JSHandle<BigInt> bigValue(inputVal);
735         return BigInt::UnaryMinus(thread, bigValue).GetTaggedValue();
736     }
737     JSTaggedNumber number(inputVal.GetTaggedValue());
738     if (number.IsInt()) {
739         int32_t intValue = number.GetInt();
740         if (intValue == 0) {
741             return JSTaggedValue(-0.0);
742         }
743         if (intValue == INT32_MIN) {
744             return JSTaggedValue(-static_cast<double>(INT32_MIN));
745         }
746         return JSTaggedValue(-intValue);
747     }
748     if (number.IsDouble()) {
749         return JSTaggedValue(-number.GetDouble());
750     }
751     LOG_ECMA(FATAL) << "this branch is unreachable";
752     UNREACHABLE();
753 }
754 
RuntimeNot(JSThread * thread,const JSHandle<JSTaggedValue> & value)755 JSTaggedValue RuntimeStubs::RuntimeNot(JSThread *thread, const JSHandle<JSTaggedValue> &value)
756 {
757     JSHandle<JSTaggedValue> inputVal = JSTaggedValue::ToNumeric(thread, value);
758     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
759     if (inputVal->IsBigInt()) {
760         JSHandle<BigInt> bigValue(inputVal);
761         return BigInt::BitwiseNOT(thread, bigValue).GetTaggedValue();
762     }
763     int32_t number = JSTaggedValue::ToInt32(thread, inputVal);
764     return JSTaggedValue(~number); // NOLINT(hicpp-signed-bitwise)
765 }
766 
RuntimeResolveClass(JSThread * thread,const JSHandle<JSFunction> & ctor,const JSHandle<TaggedArray> & literal,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv)767 JSTaggedValue RuntimeStubs::RuntimeResolveClass(JSThread *thread, const JSHandle<JSFunction> &ctor,
768                                                 const JSHandle<TaggedArray> &literal,
769                                                 const JSHandle<JSTaggedValue> &base,
770                                                 const JSHandle<JSTaggedValue> &lexenv)
771 {
772     ASSERT(ctor.GetTaggedValue().IsClassConstructor());
773 
774     FrameHandler frameHandler(thread);
775     JSTaggedValue currentFunc = frameHandler.GetFunction();
776     JSHandle<JSTaggedValue> ecmaModule(thread, JSFunction::Cast(currentFunc.GetTaggedObject())->GetModule());
777 
778     RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(ctor), base);
779     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
780 
781     uint32_t literalBufferLength = literal->GetLength();
782 
783     // only traverse the value of key-value pair
784     for (uint32_t index = 1; index < literalBufferLength - 1; index += 2) {  // 2: key-value pair
785         JSTaggedValue value = literal->Get(index);
786         if (LIKELY(value.IsJSFunction())) {
787             JSFunction *func = JSFunction::Cast(value.GetTaggedObject());
788             func->SetLexicalEnv(thread, lexenv.GetTaggedValue());
789             func->SetModule(thread, ecmaModule);
790         }
791     }
792 
793     return ctor.GetTaggedValue();
794 }
795 
RuntimeCloneClassFromTemplate(JSThread * thread,const JSHandle<JSFunction> & ctor,const JSHandle<JSTaggedValue> & base,const JSHandle<JSTaggedValue> & lexenv)796 JSTaggedValue RuntimeStubs::RuntimeCloneClassFromTemplate(JSThread *thread, const JSHandle<JSFunction> &ctor,
797                                                           const JSHandle<JSTaggedValue> &base,
798                                                           const JSHandle<JSTaggedValue> &lexenv)
799 {
800     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
801     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
802 
803     ASSERT(ctor.GetTaggedValue().IsClassConstructor());
804     JSHandle<JSObject> clsPrototype(thread, ctor->GetFunctionPrototype());
805 
806     bool canShareHClass = false;
807     JSHandle<JSFunction> cloneClass = factory->CloneClassCtor(ctor, lexenv, canShareHClass);
808     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
809     JSHandle<JSObject> cloneClassPrototype = factory->CloneObjectLiteral(JSHandle<JSObject>(clsPrototype), lexenv,
810                                                                          canShareHClass);
811     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
812 
813     // After clone both, reset "constructor" and "prototype" properties.
814     cloneClass->SetFunctionPrototype(thread, cloneClassPrototype.GetTaggedValue());
815     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
816 
817     PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(cloneClass), true, false, true);
818     JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(cloneClassPrototype),
819                                          globalConst->GetHandledConstructorString(), ctorDesc);
820     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
821 
822     cloneClass->SetHomeObject(thread, cloneClassPrototype);
823 
824     if (!canShareHClass) {
825         RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(cloneClass), base);
826         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
827     }
828 
829     return cloneClass.GetTaggedValue();
830 }
831 
832 // 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)833 JSTaggedValue RuntimeStubs::RuntimeCreateClassWithBuffer(JSThread *thread,
834                                                          const JSHandle<JSTaggedValue> &base,
835                                                          const JSHandle<JSTaggedValue> &lexenv,
836                                                          const JSHandle<JSTaggedValue> &constpool,
837                                                          uint16_t methodId, uint16_t literalId,
838                                                          const JSHandle<JSTaggedValue> &module)
839 {
840     [[maybe_unused]] EcmaHandleScope handleScope(thread);
841     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
842     CString entry = ModuleManager::GetRecordName(module.GetTaggedValue());
843 
844     // For class constructor.
845     auto methodObj = ConstantPool::GetMethodFromCache(thread, constpool.GetTaggedValue(), methodId);
846     JSHandle<JSTaggedValue> method(thread, methodObj);
847     JSHandle<ConstantPool> constpoolHandle = JSHandle<ConstantPool>::Cast(constpool);
848     JSHandle<JSFunction> cls;
849     JSMutableHandle<JSTaggedValue> ihc(thread, JSTaggedValue::Undefined());
850     JSMutableHandle<JSTaggedValue> chc(thread, JSTaggedValue::Undefined());
851 
852     JSTaggedValue val = constpoolHandle->GetObjectFromCache(literalId);
853     if (val.IsAOTLiteralInfo()) {
854         JSHandle<AOTLiteralInfo> aotLiteralInfo(thread, val);
855         ihc.Update(aotLiteralInfo->GetIhc());
856         chc.Update(aotLiteralInfo->GetChc());
857     }
858     auto literalObj = ConstantPool::GetClassLiteralFromCache(thread, constpoolHandle, literalId, entry);
859     JSHandle<ClassLiteral> classLiteral(thread, literalObj);
860     JSHandle<TaggedArray> arrayHandle(thread, classLiteral->GetArray());
861     JSHandle<ClassInfoExtractor> extractor = factory->NewClassInfoExtractor(method);
862     ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(thread, extractor, arrayHandle);
863 
864     if ((ihc->IsUndefined() && chc->IsUndefined()) ||
865         (classLiteral->GetIsAOTUsed())) {
866         cls = ClassHelper::DefineClassFromExtractor(thread, base, extractor, lexenv);
867     } else {
868         classLiteral->SetIsAOTUsed(true);
869         JSHandle<JSHClass> ihclass(ihc);
870         JSHandle<JSHClass> chclass(chc);
871         cls = ClassHelper::DefineClassWithIHClass(thread, extractor,
872                                                   lexenv, ihclass, chclass);
873     }
874 
875     RuntimeSetClassInheritanceRelationship(thread, JSHandle<JSTaggedValue>(cls), base);
876     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
877     return cls.GetTaggedValue();
878 }
879 
RuntimeSetClassInheritanceRelationship(JSThread * thread,const JSHandle<JSTaggedValue> & ctor,const JSHandle<JSTaggedValue> & base)880 JSTaggedValue RuntimeStubs::RuntimeSetClassInheritanceRelationship(JSThread *thread,
881                                                                    const JSHandle<JSTaggedValue> &ctor,
882                                                                    const JSHandle<JSTaggedValue> &base)
883 {
884     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
885     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
886 
887     ASSERT(ctor->IsJSFunction());
888     JSHandle<JSTaggedValue> parent = base;
889 
890     /*
891      *         class A / class A extends null                             class A extends B
892      *                                       a                                                 a
893      *                                       |                                                 |
894      *                                       |  __proto__                                      |  __proto__
895      *                                       |                                                 |
896      *       A            ---->         A.prototype                  A             ---->    A.prototype
897      *       |                               |                       |                         |
898      *       |  __proto__                    |  __proto__            |  __proto__              |  __proto__
899      *       |                               |                       |                         |
900      *   Function.prototype       Object.prototype / null            B             ---->    B.prototype
901      */
902 
903     JSHandle<JSTaggedValue> parentPrototype;
904     // hole means parent is not present
905     Method *method = Method::Cast(JSHandle<JSFunction>::Cast(ctor)->GetMethod().GetTaggedObject());
906     if (parent->IsHole()) {
907         method->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
908         parentPrototype = env->GetObjectFunctionPrototype();
909         parent = env->GetFunctionPrototype();
910     } else if (parent->IsNull()) {
911         method->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
912         parentPrototype = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Null());
913         parent = env->GetFunctionPrototype();
914     } else if (!parent->IsConstructor()) {
915         return RuntimeThrowTypeError(thread, "parent class is not constructor");
916     } else {
917         method->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
918         parentPrototype = JSTaggedValue::GetProperty(thread, parent,
919             globalConst->GetHandledPrototypeString()).GetValue();
920         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
921         if (!parentPrototype->IsECMAObject() && !parentPrototype->IsNull()) {
922             return RuntimeThrowTypeError(thread, "parent class have no valid prototype");
923         }
924     }
925 
926     ctor->GetTaggedObject()->GetClass()->SetPrototype(thread, parent);
927 
928     JSHandle<JSObject> clsPrototype(thread, JSHandle<JSFunction>(ctor)->GetFunctionPrototype());
929     clsPrototype->GetClass()->SetPrototype(thread, parentPrototype);
930 
931     // by enableing the ProtoChangeMarker, the IHC generated in the Aot stage
932     // is registered into the listener of its prototype. In this way, it is ensured
933     // that when the prototype changes, the affected IHC can be notified.
934     JSTaggedValue protoOrHClass = JSHandle<JSFunction>(ctor)->GetProtoOrHClass();
935     if (protoOrHClass.IsJSHClass()) {
936         JSHClass *ihc = JSHClass::Cast(protoOrHClass.GetTaggedObject());
937         if (ihc->IsTS()) {
938             JSHandle<JSHClass> ihcHandle(thread, ihc);
939             JSHClass::EnableProtoChangeMarker(thread, ihcHandle);
940         }
941     }
942 
943     return JSTaggedValue::Undefined();
944 }
945 
RuntimeSetClassConstructorLength(JSThread * thread,JSTaggedValue ctor,JSTaggedValue length)946 JSTaggedValue RuntimeStubs::RuntimeSetClassConstructorLength(JSThread *thread, JSTaggedValue ctor,
947                                                              JSTaggedValue length)
948 {
949     ASSERT(ctor.IsClassConstructor());
950 
951     JSFunction* cls = JSFunction::Cast(ctor.GetTaggedObject());
952     if (LIKELY(!cls->GetClass()->IsDictionaryMode())) {
953         cls->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length);
954     } else {
955         const GlobalEnvConstants *globalConst = thread->GlobalConstants();
956         cls->UpdatePropertyInDictionary(thread, globalConst->GetLengthString(), length);
957     }
958     return JSTaggedValue::Undefined();
959 }
960 
RuntimeNotifyInlineCache(JSThread * thread,const JSHandle<Method> & method,uint32_t icSlotSize)961 JSTaggedValue RuntimeStubs::RuntimeNotifyInlineCache(JSThread *thread, const JSHandle<Method> &method,
962                                                      uint32_t icSlotSize)
963 {
964     if (icSlotSize == 0) {
965         return JSTaggedValue::Undefined();
966     }
967     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
968     JSHandle<ProfileTypeInfo> profileTypeInfo = factory->NewProfileTypeInfo(icSlotSize);
969     // overflow 8bit
970     if (icSlotSize > ProfileTypeInfo::INVALID_SLOT_INDEX) {
971         // set as mega
972         profileTypeInfo->Set(thread, ProfileTypeInfo::INVALID_SLOT_INDEX, JSTaggedValue::Hole());
973         ASSERT(icSlotSize <= ProfileTypeInfo::MAX_SLOT_INDEX + 1);
974     }
975     method->SetProfileTypeInfo(thread, profileTypeInfo.GetTaggedValue());
976     return profileTypeInfo.GetTaggedValue();
977 }
978 
RuntimeStOwnByValueWithNameSet(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)979 JSTaggedValue RuntimeStubs::RuntimeStOwnByValueWithNameSet(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
980                                                            const JSHandle<JSTaggedValue> &key,
981                                                            const JSHandle<JSTaggedValue> &value)
982 {
983     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
984 
985     if (obj->IsClassConstructor() &&
986         JSTaggedValue::SameValue(key, globalConst->GetHandledPrototypeString())) {
987         return RuntimeThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
988     }
989 
990     // property in class is non-enumerable
991     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
992 
993     PropertyDescriptor desc(thread, value, true, enumerable, true);
994     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, key);
995     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
996     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, propKey, desc);
997     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
998     if (!ret) {
999         return RuntimeThrowTypeError(thread, "StOwnByValueWithNameSet failed");
1000     }
1001     if (value->IsJSFunction()) {
1002         if (propKey->IsNumber()) {
1003             propKey = JSHandle<JSTaggedValue>(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
1004         }
1005         JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(value), propKey,
1006                                         JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1007     }
1008     return JSTaggedValue::True();
1009 }
1010 
RuntimeStOwnByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)1011 JSTaggedValue RuntimeStubs::RuntimeStOwnByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
1012                                                const JSHandle<JSTaggedValue> &prop,
1013                                                const JSHandle<JSTaggedValue> &value)
1014 {
1015     ASSERT(prop->IsStringOrSymbol());
1016 
1017     // property in class is non-enumerable
1018     bool enumerable = !(obj->IsClassPrototype() || obj->IsClassConstructor());
1019 
1020     PropertyDescriptor desc(thread, value, true, enumerable, true);
1021     bool ret = JSTaggedValue::DefineOwnProperty(thread, obj, prop, desc);
1022     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1023     if (!ret) {
1024         return RuntimeThrowTypeError(thread, "SetOwnByName failed");
1025     }
1026     return JSTaggedValue::True();
1027 }
1028 
RuntimeStOwnByNameWithNameSet(JSThread * thread,const JSHandle<JSTaggedValue> & objHandle,const JSHandle<JSTaggedValue> & propHandle,const JSHandle<JSTaggedValue> & valueHandle)1029 JSTaggedValue RuntimeStubs::RuntimeStOwnByNameWithNameSet(JSThread *thread,
1030                                                           const JSHandle<JSTaggedValue> &objHandle,
1031                                                           const JSHandle<JSTaggedValue> &propHandle,
1032                                                           const JSHandle<JSTaggedValue> &valueHandle)
1033 {
1034     ASSERT(propHandle->IsStringOrSymbol());
1035     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
1036     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1037     // property in class is non-enumerable
1038     bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1039 
1040     PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1041     bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propHandle, desc);
1042     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1043     if (!ret) {
1044         return RuntimeThrowTypeError(thread, "SetOwnByNameWithNameSet failed");
1045     }
1046     JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(valueHandle), propKey,
1047                                     JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1048     return JSTaggedValue::True();
1049 }
1050 
RuntimeSuspendGenerator(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const JSHandle<JSTaggedValue> & value)1051 JSTaggedValue RuntimeStubs::RuntimeSuspendGenerator(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
1052                                                     const JSHandle<JSTaggedValue> &value)
1053 {
1054     if (genObj->IsAsyncGeneratorObject()) {
1055         JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
1056         JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext());
1057         // save stack, should copy cur_frame, function execute over will free cur_frame
1058         SaveFrameToContext(thread, genContextHandle);
1059 
1060         // change state to SuspendedYield
1061         if (generatorObjectHandle->IsExecuting()) {
1062             return value.GetTaggedValue();
1063         }
1064         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1065         return generatorObjectHandle.GetTaggedValue();
1066     }
1067 
1068     if (genObj->IsGeneratorObject()) {
1069         JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
1070         JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext());
1071         // save stack, should copy cur_frame, function execute over will free cur_frame
1072         SaveFrameToContext(thread, genContextHandle);
1073 
1074         // change state to SuspendedYield
1075         if (generatorObjectHandle->IsExecuting()) {
1076             generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);
1077             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1078             return value.GetTaggedValue();
1079         }
1080         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1081         return generatorObjectHandle.GetTaggedValue();
1082     }
1083 
1084     return RuntimeThrowTypeError(thread, "RuntimeSuspendGenerator failed");
1085 }
1086 
RuntimeSetGeneratorState(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const int32_t index)1087 void RuntimeStubs::RuntimeSetGeneratorState(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
1088                                             const int32_t index)
1089 {
1090     JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
1091     JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext());
1092 
1093     // change state
1094     switch (index) {
1095         case static_cast<int32_t>(JSAsyncGeneratorState::SUSPENDED_START):
1096             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_START);
1097             break;
1098         case static_cast<int32_t>(JSAsyncGeneratorState::SUSPENDED_YIELD):
1099             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::SUSPENDED_YIELD);
1100             break;
1101         case static_cast<int32_t>(JSAsyncGeneratorState::EXECUTING):
1102             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::EXECUTING);
1103             break;
1104         case static_cast<int32_t>(JSAsyncGeneratorState::COMPLETED):
1105             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::COMPLETED);
1106             break;
1107         case static_cast<int32_t>(JSAsyncGeneratorState::AWAITING_RETURN):
1108             generatorObjectHandle->SetAsyncGeneratorState(JSAsyncGeneratorState::AWAITING_RETURN);
1109             break;
1110         default:
1111             LOG_ECMA(FATAL) << "this branch is unreachable";
1112             UNREACHABLE();
1113     }
1114 }
1115 
RuntimeGetModuleNamespace(JSThread * thread,int32_t index)1116 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, int32_t index)
1117 {
1118     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleNamespace(index);
1119 }
1120 
RuntimeGetModuleNamespace(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1121 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, int32_t index,
1122                                                       JSTaggedValue jsFunc)
1123 {
1124     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleNamespace(index, jsFunc);
1125 }
1126 
RuntimeGetModuleNamespace(JSThread * thread,JSTaggedValue localName)1127 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, JSTaggedValue localName)
1128 {
1129     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleNamespace(localName);
1130 }
1131 
RuntimeGetModuleNamespace(JSThread * thread,JSTaggedValue localName,JSTaggedValue jsFunc)1132 JSTaggedValue RuntimeStubs::RuntimeGetModuleNamespace(JSThread *thread, JSTaggedValue localName,
1133                                                       JSTaggedValue jsFunc)
1134 {
1135     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleNamespace(localName, jsFunc);
1136 }
1137 
RuntimeStModuleVar(JSThread * thread,int32_t index,JSTaggedValue value)1138 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, int32_t index, JSTaggedValue value)
1139 {
1140     thread->GetCurrentEcmaContext()->GetModuleManager()->StoreModuleValue(index, value);
1141 }
1142 
RuntimeStModuleVar(JSThread * thread,int32_t index,JSTaggedValue value,JSTaggedValue jsFunc)1143 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, int32_t index, JSTaggedValue value,
1144                                       JSTaggedValue jsFunc)
1145 {
1146     thread->GetCurrentEcmaContext()->GetModuleManager()->StoreModuleValue(index, value, jsFunc);
1147 }
1148 
RuntimeStModuleVar(JSThread * thread,JSTaggedValue key,JSTaggedValue value)1149 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, JSTaggedValue key, JSTaggedValue value)
1150 {
1151     thread->GetCurrentEcmaContext()->GetModuleManager()->StoreModuleValue(key, value);
1152 }
1153 
RuntimeStModuleVar(JSThread * thread,JSTaggedValue key,JSTaggedValue value,JSTaggedValue jsFunc)1154 void RuntimeStubs::RuntimeStModuleVar(JSThread *thread, JSTaggedValue key, JSTaggedValue value,
1155                                       JSTaggedValue jsFunc)
1156 {
1157     thread->GetCurrentEcmaContext()->GetModuleManager()->StoreModuleValue(key, value, jsFunc);
1158 }
1159 
RuntimeLdLocalModuleVar(JSThread * thread,int32_t index)1160 JSTaggedValue RuntimeStubs::RuntimeLdLocalModuleVar(JSThread *thread, int32_t index)
1161 {
1162     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueInner(index);
1163 }
1164 
RuntimeLdLocalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1165 JSTaggedValue RuntimeStubs::RuntimeLdLocalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1166 {
1167     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueInner(index, jsFunc);
1168 }
1169 
RuntimeLdExternalModuleVar(JSThread * thread,int32_t index)1170 JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t index)
1171 {
1172     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(index);
1173 }
1174 
RuntimeLdExternalModuleVar(JSThread * thread,int32_t index,JSTaggedValue jsFunc)1175 JSTaggedValue RuntimeStubs::RuntimeLdExternalModuleVar(JSThread *thread, int32_t index, JSTaggedValue jsFunc)
1176 {
1177     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(index, jsFunc);
1178 }
1179 
RuntimeLdModuleVar(JSThread * thread,JSTaggedValue key,bool inner)1180 JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner)
1181 {
1182     if (inner) {
1183         JSTaggedValue moduleValue = thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueInner(key);
1184         return moduleValue;
1185     }
1186 
1187     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(key);
1188 }
1189 
RuntimeLdModuleVar(JSThread * thread,JSTaggedValue key,bool inner,JSTaggedValue jsFunc)1190 JSTaggedValue RuntimeStubs::RuntimeLdModuleVar(JSThread *thread, JSTaggedValue key, bool inner,
1191                                                JSTaggedValue jsFunc)
1192 {
1193     if (inner) {
1194         JSTaggedValue moduleValue =
1195             thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueInner(key, jsFunc);
1196         return moduleValue;
1197     }
1198 
1199     return thread->GetCurrentEcmaContext()->GetModuleManager()->GetModuleValueOutter(key, jsFunc);
1200 }
1201 
RuntimeGetPropIterator(JSThread * thread,const JSHandle<JSTaggedValue> & value)1202 JSTaggedValue RuntimeStubs::RuntimeGetPropIterator(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1203 {
1204     JSHandle<JSForInIterator> iteratorHandle = JSObject::EnumerateObjectProperties(thread, value);
1205     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1206     return iteratorHandle.GetTaggedValue();
1207 }
1208 
RuntimeAsyncFunctionEnter(JSThread * thread)1209 JSTaggedValue RuntimeStubs::RuntimeAsyncFunctionEnter(JSThread *thread)
1210 {
1211     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1212     // 1. create promise
1213     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
1214     JSHandle<JSFunction> promiseFunc(globalEnv->GetPromiseFunction());
1215 
1216     JSHandle<JSPromise> promiseObject(factory->NewJSObjectByConstructor(promiseFunc));
1217     promiseObject->SetPromiseState(PromiseState::PENDING);
1218     // 2. create asyncfuncobj
1219     JSHandle<JSAsyncFuncObject> asyncFuncObj = factory->NewJSAsyncFuncObject();
1220     asyncFuncObj->SetPromise(thread, promiseObject);
1221 
1222     JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
1223     context->SetGeneratorObject(thread, asyncFuncObj);
1224 
1225     // change state to EXECUTING
1226     asyncFuncObj->SetGeneratorState(JSGeneratorState::EXECUTING);
1227     asyncFuncObj->SetGeneratorContext(thread, context);
1228 
1229     // 3. return asyncfuncobj
1230     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1231     return asyncFuncObj.GetTaggedValue();
1232 }
1233 
RuntimeGetIterator(JSThread * thread,const JSHandle<JSTaggedValue> & obj)1234 JSTaggedValue RuntimeStubs::RuntimeGetIterator(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
1235 {
1236     EcmaVM *vm = thread->GetEcmaVM();
1237     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1238     JSHandle<JSTaggedValue> valuesFunc =
1239         JSTaggedValue::GetProperty(thread, obj, env->GetIteratorSymbol()).GetValue();
1240     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1241     if (!valuesFunc->IsCallable()) {
1242         return valuesFunc.GetTaggedValue();
1243     }
1244 
1245     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
1246     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, valuesFunc, obj, undefined, 0);
1247     return EcmaInterpreter::Execute(info);
1248 }
1249 
RuntimeGetAsyncIterator(JSThread * thread,const JSHandle<JSTaggedValue> & obj)1250 JSTaggedValue RuntimeStubs::RuntimeGetAsyncIterator(JSThread *thread, const JSHandle<JSTaggedValue> &obj)
1251 {
1252     JSHandle<JSTaggedValue> asyncit = JSIterator::GetAsyncIterator(thread, obj);
1253     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1254     return asyncit.GetTaggedValue();
1255 }
1256 
RuntimeThrow(JSThread * thread,JSTaggedValue value)1257 void RuntimeStubs::RuntimeThrow(JSThread *thread, JSTaggedValue value)
1258 {
1259     thread->SetException(value);
1260 }
1261 
RuntimeThrowThrowNotExists(JSThread * thread)1262 void RuntimeStubs::RuntimeThrowThrowNotExists(JSThread *thread)
1263 {
1264     THROW_TYPE_ERROR(thread, "Throw method is not defined");
1265 }
1266 
RuntimeThrowPatternNonCoercible(JSThread * thread)1267 void RuntimeStubs::RuntimeThrowPatternNonCoercible(JSThread *thread)
1268 {
1269     JSHandle<EcmaString> msg(thread->GlobalConstants()->GetHandledObjNotCoercibleString());
1270     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1271     THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::TYPE_ERROR, msg).GetTaggedValue());
1272 }
1273 
RuntimeThrowDeleteSuperProperty(JSThread * thread)1274 void RuntimeStubs::RuntimeThrowDeleteSuperProperty(JSThread *thread)
1275 {
1276     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1277     JSHandle<EcmaString> info = factory->NewFromASCII("Can not delete super property");
1278     JSHandle<JSObject> errorObj = factory->NewJSError(base::ErrorType::REFERENCE_ERROR, info);
1279     THROW_NEW_ERROR_AND_RETURN(thread, errorObj.GetTaggedValue());
1280 }
1281 
RuntimeThrowUndefinedIfHole(JSThread * thread,const JSHandle<EcmaString> & obj)1282 void RuntimeStubs::RuntimeThrowUndefinedIfHole(JSThread *thread, const JSHandle<EcmaString> &obj)
1283 {
1284     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1285     JSHandle<EcmaString> info = factory->NewFromASCII(" is not initialized");
1286 
1287     JSHandle<EcmaString> msg = factory->ConcatFromString(obj, info);
1288     THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg).GetTaggedValue());
1289 }
1290 
RuntimeThrowIfNotObject(JSThread * thread)1291 void RuntimeStubs::RuntimeThrowIfNotObject(JSThread *thread)
1292 {
1293     THROW_TYPE_ERROR(thread, "Inner return result is not object");
1294 }
1295 
RuntimeThrowConstAssignment(JSThread * thread,const JSHandle<EcmaString> & value)1296 void RuntimeStubs::RuntimeThrowConstAssignment(JSThread *thread, const JSHandle<EcmaString> &value)
1297 {
1298     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1299 
1300     JSHandle<EcmaString> info = factory->NewFromASCII("Assignment to const variable ");
1301 
1302     JSHandle<EcmaString> msg = factory->ConcatFromString(info, value);
1303     THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::TYPE_ERROR, msg).GetTaggedValue());
1304 }
1305 
RuntimeLdGlobalRecord(JSThread * thread,JSTaggedValue key)1306 JSTaggedValue RuntimeStubs::RuntimeLdGlobalRecord(JSThread *thread, JSTaggedValue key)
1307 {
1308     EcmaVM *vm = thread->GetEcmaVM();
1309     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1310     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1311     int entry = dict->FindEntry(key);
1312     if (entry != -1) {
1313         return JSTaggedValue(dict->GetBox(entry));
1314     }
1315     return JSTaggedValue::Undefined();
1316 }
1317 
RuntimeTryLdGlobalByName(JSThread * thread,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & prop)1318 JSTaggedValue RuntimeStubs::RuntimeTryLdGlobalByName(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
1319                                                      const JSHandle<JSTaggedValue> &prop)
1320 {
1321     OperationResult res = JSTaggedValue::GetProperty(thread, obj, prop);
1322     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1323     if (!res.GetPropertyMetaData().IsFound()) {
1324         return RuntimeThrowReferenceError(thread, prop, " is not defined");
1325     }
1326     return res.GetValue().GetTaggedValue();
1327 }
1328 
RuntimeTryUpdateGlobalRecord(JSThread * thread,JSTaggedValue prop,JSTaggedValue value)1329 JSTaggedValue RuntimeStubs::RuntimeTryUpdateGlobalRecord(JSThread *thread, JSTaggedValue prop,
1330                                                          JSTaggedValue value)
1331 {
1332     EcmaVM *vm = thread->GetEcmaVM();
1333     JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1334     GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1335     int entry = dict->FindEntry(prop);
1336     ASSERT(entry != -1);
1337 
1338     if (dict->GetAttributes(entry).IsConstProps()) {
1339         return RuntimeThrowTypeError(thread, "const variable can not be modified");
1340     }
1341 
1342     PropertyBox *box = dict->GetBox(entry);
1343     box->SetValue(thread, value);
1344     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1345     return JSTaggedValue::True();
1346 }
1347 
RuntimeThrowReferenceError(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const char * desc)1348 JSTaggedValue RuntimeStubs::RuntimeThrowReferenceError(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
1349                                                        const char *desc)
1350 {
1351     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1352     JSHandle<EcmaString> propName = JSTaggedValue::ToString(thread, prop);
1353     ASSERT_NO_ABRUPT_COMPLETION(thread);
1354     JSHandle<EcmaString> info = factory->NewFromUtf8(desc);
1355     JSHandle<EcmaString> msg = factory->ConcatFromString(propName, info);
1356     THROW_NEW_ERROR_AND_RETURN_VALUE(thread,
1357                                      factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg).GetTaggedValue(),
1358                                      JSTaggedValue::Exception());
1359 }
1360 
RuntimeLdGlobalVarFromProto(JSThread * thread,const JSHandle<JSTaggedValue> & globalObj,const JSHandle<JSTaggedValue> & prop)1361 JSTaggedValue RuntimeStubs::RuntimeLdGlobalVarFromProto(JSThread *thread, const JSHandle<JSTaggedValue> &globalObj,
1362                                                         const JSHandle<JSTaggedValue> &prop)
1363 {
1364     ASSERT(globalObj->IsJSGlobalObject());
1365     JSHandle<JSObject> global(globalObj);
1366     JSHandle<JSTaggedValue> obj(thread, JSObject::GetPrototype(global));
1367     OperationResult res = JSTaggedValue::GetProperty(thread, obj, prop);
1368     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1369     return res.GetValue().GetTaggedValue();
1370 }
1371 
RuntimeStGlobalVar(JSThread * thread,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & value)1372 JSTaggedValue RuntimeStubs::RuntimeStGlobalVar(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
1373                                                const JSHandle<JSTaggedValue> &value)
1374 {
1375     JSHandle<JSTaggedValue> global(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject());
1376 
1377     JSObject::GlobalSetProperty(thread, prop, value, true);
1378     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1379     return JSTaggedValue::True();
1380 }
1381 
RuntimeToNumber(JSThread * thread,const JSHandle<JSTaggedValue> & value)1382 JSTaggedValue RuntimeStubs::RuntimeToNumber(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1383 {
1384     return JSTaggedValue::ToNumber(thread, value);
1385 }
1386 
RuntimeToNumeric(JSThread * thread,const JSHandle<JSTaggedValue> & value)1387 JSTaggedValue RuntimeStubs::RuntimeToNumeric(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1388 {
1389     return JSTaggedValue::ToNumeric(thread, value).GetTaggedValue();
1390 }
1391 
RuntimeDynamicImport(JSThread * thread,const JSHandle<JSTaggedValue> & specifier,const JSHandle<JSTaggedValue> & func)1392 JSTaggedValue RuntimeStubs::RuntimeDynamicImport(JSThread *thread, const JSHandle<JSTaggedValue> &specifier,
1393     const JSHandle<JSTaggedValue> &func)
1394 {
1395     EcmaVM *ecmaVm = thread->GetEcmaVM();
1396     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
1397     ObjectFactory *factory = ecmaVm->GetFactory();
1398 
1399     // get current filename
1400     Method *method = JSFunction::Cast(func->GetTaggedObject())->GetCallTarget();
1401     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
1402     CString currentfilename = jsPandaFile->GetJSPandaFileDesc();
1403 
1404     JSMutableHandle<JSTaggedValue> dirPath(thread, thread->GlobalConstants()->GetUndefined());
1405     JSMutableHandle<JSTaggedValue> recordName(thread, thread->GlobalConstants()->GetUndefined());
1406     if (jsPandaFile->IsBundlePack()) {
1407         dirPath.Update(factory->NewFromUtf8(currentfilename).GetTaggedValue());
1408     } else {
1409         JSFunction *function = JSFunction::Cast(func.GetTaggedValue().GetTaggedObject());
1410         recordName.Update(function->GetRecordName());
1411         dirPath.Update(factory->NewFromUtf8(currentfilename).GetTaggedValue());
1412     }
1413 
1414     // 4. Let promiseCapability be !NewPromiseCapability(%Promise%).
1415     JSHandle<JSTaggedValue> promiseFunc = env->GetPromiseFunction();
1416     JSHandle<PromiseCapability> promiseCapability = JSPromise::NewPromiseCapability(thread, promiseFunc);
1417     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1418     JSHandle<job::MicroJobQueue> job = thread->GetCurrentEcmaContext()->GetMicroJobQueue();
1419 
1420     JSHandle<TaggedArray> argv = factory->NewTaggedArray(5); // 5: 5 means parameters stored in array
1421     argv->Set(thread, 0, promiseCapability->GetResolve());
1422     argv->Set(thread, 1, promiseCapability->GetReject());    // 1 : reject method
1423     argv->Set(thread, 2, dirPath);                           // 2 : current file path(containing file name)
1424     argv->Set(thread, 3, specifier);                         // 3 : request module's path
1425     argv->Set(thread, 4, recordName);                        // 4 : js recordName or undefined
1426 
1427     JSHandle<JSFunction> dynamicImportJob(env->GetDynamicImportJob());
1428     job::MicroJobQueue::EnqueueJob(thread, job, job::QueueType::QUEUE_PROMISE, dynamicImportJob, argv);
1429 
1430     return promiseCapability->GetPromise();
1431 }
1432 
RuntimeEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1433 JSTaggedValue RuntimeStubs::RuntimeEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1434                                       const JSHandle<JSTaggedValue> &right)
1435 {
1436     bool ret = JSTaggedValue::Equal(thread, left, right);
1437     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1438     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1439 }
1440 
RuntimeNotEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1441 JSTaggedValue RuntimeStubs::RuntimeNotEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1442                                          const JSHandle<JSTaggedValue> &right)
1443 {
1444     bool ret = JSTaggedValue::Equal(thread, left, right);
1445     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1446     return (ret ? JSTaggedValue::False() : JSTaggedValue::True());
1447 }
1448 
RuntimeLess(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1449 JSTaggedValue RuntimeStubs::RuntimeLess(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1450                                         const JSHandle<JSTaggedValue> &right)
1451 {
1452     bool ret = JSTaggedValue::Compare(thread, left, right) == ComparisonResult::LESS;
1453     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1454     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1455 }
1456 
RuntimeLessEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1457 JSTaggedValue RuntimeStubs::RuntimeLessEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1458                                           const JSHandle<JSTaggedValue> &right)
1459 {
1460     bool ret = JSTaggedValue::Compare(thread, left, right) <= ComparisonResult::EQUAL;
1461     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1462     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1463 }
1464 
RuntimeGreater(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1465 JSTaggedValue RuntimeStubs::RuntimeGreater(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1466                                            const JSHandle<JSTaggedValue> &right)
1467 {
1468     bool ret = JSTaggedValue::Compare(thread, left, right) == ComparisonResult::GREAT;
1469     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1470     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1471 }
1472 
RuntimeGreaterEq(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1473 JSTaggedValue RuntimeStubs::RuntimeGreaterEq(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1474                                              const JSHandle<JSTaggedValue> &right)
1475 {
1476     ComparisonResult comparison = JSTaggedValue::Compare(thread, left, right);
1477     bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
1478     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1479     return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
1480 }
1481 
RuntimeAdd2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1482 JSTaggedValue RuntimeStubs::RuntimeAdd2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1483                                         const JSHandle<JSTaggedValue> &right)
1484 {
1485     if (left->IsString() && right->IsString()) {
1486         EcmaString *resultStr = EcmaStringAccessor::Concat(
1487             thread->GetEcmaVM(), JSHandle<EcmaString>(left), JSHandle<EcmaString>(right));
1488         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1489         return JSTaggedValue(resultStr);
1490     }
1491     JSHandle<JSTaggedValue> primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, left));
1492     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1493     JSHandle<JSTaggedValue> primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, right));
1494     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1495     // contain string
1496     if (primitiveA0->IsString() || primitiveA1->IsString()) {
1497         JSHandle<EcmaString> stringA0 = JSTaggedValue::ToString(thread, primitiveA0);
1498         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1499         JSHandle<EcmaString> stringA1 = JSTaggedValue::ToString(thread, primitiveA1);
1500         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1501         EcmaString *resultStr = EcmaStringAccessor::Concat(thread->GetEcmaVM(), stringA0, stringA1);
1502         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1503         return JSTaggedValue(resultStr);
1504     }
1505     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, primitiveA0);
1506     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1507     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, primitiveA1);
1508     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1509     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1510         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1511             JSHandle<BigInt> bigLeft(valLeft);
1512             JSHandle<BigInt> bigRight(valRight);
1513             return BigInt::Add(thread, bigLeft, bigRight).GetTaggedValue();
1514         }
1515         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1516     }
1517     double doubleA0 = valLeft->GetNumber();
1518     double doubleA1 = valRight->GetNumber();
1519     return JSTaggedValue(doubleA0 + doubleA1);
1520 }
1521 
RuntimeShl2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1522 JSTaggedValue RuntimeStubs::RuntimeShl2(JSThread *thread,
1523                                         const JSHandle<JSTaggedValue> &left,
1524                                         const JSHandle<JSTaggedValue> &right)
1525 {
1526     JSHandle<JSTaggedValue> leftValue = JSTaggedValue::ToNumeric(thread, left);
1527     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1528     JSHandle<JSTaggedValue> rightValue = JSTaggedValue::ToNumeric(thread, right);
1529     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1530     if (leftValue->IsBigInt() || rightValue->IsBigInt()) {
1531         if (leftValue->IsBigInt() && rightValue->IsBigInt()) {
1532             JSHandle<BigInt> leftBigint(leftValue);
1533             JSHandle<BigInt> rightBigint(rightValue);
1534             return BigInt::LeftShift(thread, leftBigint, rightBigint).GetTaggedValue();
1535         }
1536         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1537     }
1538     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, leftValue);
1539     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1540     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, rightValue);
1541     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1542     int32_t opNumber0 = taggedNumber0.GetInt();
1543     int32_t opNumber1 = taggedNumber1.GetInt();
1544     uint32_t shift =
1545             static_cast<uint32_t>(opNumber1) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1546     using unsigned_type = std::make_unsigned_t<int32_t>;
1547     auto ret =
1548             static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift);  // NOLINT(hicpp-signed-bitwise)
1549     return JSTaggedValue(ret);
1550 }
1551 
RuntimeShr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1552 JSTaggedValue RuntimeStubs::RuntimeShr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1553                                         const JSHandle<JSTaggedValue> &right)
1554 {
1555     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1556     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1557     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1558     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1559     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1560         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1561             return BigInt::UnsignedRightShift(thread);
1562         }
1563         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1564     }
1565     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1566     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1567     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1568     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1569     int32_t opNumber0 = taggedNumber0.GetInt();
1570     int32_t opNumber1 = taggedNumber1.GetInt();
1571     uint32_t shift = static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1572     using unsigned_type = std::make_unsigned_t<uint32_t>;
1573     auto ret =
1574             static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise)
1575     return JSTaggedValue(ret);
1576 }
1577 
RuntimeSub2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1578 JSTaggedValue RuntimeStubs::RuntimeSub2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1579                                         const JSHandle<JSTaggedValue> &right)
1580 {
1581     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1582     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1583     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1584     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1585     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1586         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1587             JSHandle<BigInt> bigLeft(valLeft);
1588             JSHandle<BigInt> bigRight(valRight);
1589             return BigInt::Subtract(thread, bigLeft, bigRight).GetTaggedValue();
1590         }
1591         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1592     }
1593     JSTaggedNumber number0(valLeft.GetTaggedValue());
1594     JSTaggedNumber number1(valRight.GetTaggedValue());
1595     return number0 - number1;
1596 }
1597 
RuntimeMul2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1598 JSTaggedValue RuntimeStubs::RuntimeMul2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1599                                         const JSHandle<JSTaggedValue> &right)
1600 {
1601     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1602     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1603     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1604     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1605     // 9. ReturnIfAbrupt(rnum).
1606     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1607         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1608             JSHandle<BigInt> bigLeft(valLeft);
1609             JSHandle<BigInt> bigRight(valRight);
1610             return BigInt::Multiply(thread, bigLeft, bigRight).GetTaggedValue();
1611         }
1612         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1613     }
1614     // 12.6.3.1 Applying the * Operator
1615     JSTaggedNumber number0(valLeft.GetTaggedValue());
1616     JSTaggedNumber number1(valRight.GetTaggedValue());
1617     return number0 * number1;
1618 }
1619 
RuntimeDiv2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1620 JSTaggedValue RuntimeStubs::RuntimeDiv2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1621                                         const JSHandle<JSTaggedValue> &right)
1622 {
1623     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1624     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1625     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1626     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1627     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1628         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1629             JSHandle<BigInt> bigLeft(valLeft);
1630             JSHandle<BigInt> bigRight(valRight);
1631             return BigInt::Divide(thread, bigLeft, bigRight).GetTaggedValue();
1632         }
1633         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1634     }
1635     double dLeft = valLeft->GetNumber();
1636     double dRight = valRight->GetNumber();
1637     if (dRight == 0) {
1638         if (dLeft == 0 || std::isnan(dLeft)) {
1639             return JSTaggedValue(base::NAN_VALUE);
1640         }
1641         bool positive = (((base::bit_cast<uint64_t>(dRight)) & base::DOUBLE_SIGN_MASK) ==
1642                          ((base::bit_cast<uint64_t>(dLeft)) & base::DOUBLE_SIGN_MASK));
1643         return JSTaggedValue(positive ? base::POSITIVE_INFINITY : -base::POSITIVE_INFINITY);
1644     }
1645     return JSTaggedValue(dLeft / dRight);
1646 }
1647 
RuntimeMod2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1648 JSTaggedValue RuntimeStubs::RuntimeMod2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1649                                         const JSHandle<JSTaggedValue> &right)
1650 {
1651     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1652     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1653     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1654     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1655 
1656     // 12.6.3.3 Applying the % Operator
1657     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1658         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1659             JSHandle<BigInt> leftBigint(valLeft);
1660             JSHandle<BigInt> rightBigint(valRight);
1661             return BigInt::Remainder(thread, leftBigint, rightBigint).GetTaggedValue();
1662         }
1663         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1664     }
1665     double dLeft = valLeft->GetNumber();
1666     double dRight = valRight->GetNumber();
1667     // 12.6.3.3 Applying the % Operator
1668     if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
1669         return JSTaggedValue(base::NAN_VALUE);
1670     }
1671     if ((dLeft == 0.0) || std::isinf(dRight)) {
1672         return JSTaggedValue(dLeft);
1673     }
1674     return JSTaggedValue(std::fmod(dLeft, dRight));
1675 }
1676 
RuntimeAshr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1677 JSTaggedValue RuntimeStubs::RuntimeAshr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1678                                          const JSHandle<JSTaggedValue> &right)
1679 {
1680     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1681     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1682     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1683     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1684     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1685         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1686             JSHandle<BigInt> bigLeft(valLeft);
1687             JSHandle<BigInt> bigRight(valRight);
1688             return BigInt::SignedRightShift(thread, bigLeft, bigRight).GetTaggedValue();
1689         }
1690         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1691     }
1692     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1693     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1694     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1695     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1696     int32_t opNumber0 = taggedNumber0.GetInt();
1697     int32_t opNumber1 = taggedNumber1.GetInt();
1698     uint32_t shift = static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
1699     auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise)
1700     return JSTaggedValue(ret);
1701 }
1702 
RuntimeAnd2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1703 JSTaggedValue RuntimeStubs::RuntimeAnd2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1704                                         const JSHandle<JSTaggedValue> &right)
1705 {
1706     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1707     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1708     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1709     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1710     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1711         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1712             JSHandle<BigInt> leftBigint(valLeft);
1713             JSHandle<BigInt> rightBigint(valRight);
1714             return BigInt::BitwiseAND(thread, leftBigint, rightBigint).GetTaggedValue();
1715         }
1716         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1717     }
1718     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1719     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1720     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1721     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1722     int32_t opNumber0 = taggedNumber0.GetInt();
1723     int32_t opNumber1 = taggedNumber1.GetInt();
1724     // NOLINT(hicpp-signed-bitwise)
1725     auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
1726     return JSTaggedValue(static_cast<int32_t>(ret));
1727 }
1728 
RuntimeOr2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1729 JSTaggedValue RuntimeStubs::RuntimeOr2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1730                                        const JSHandle<JSTaggedValue> &right)
1731 {
1732     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1733     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1734     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1735     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1736     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1737         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1738             JSHandle<BigInt> leftBigint(valLeft);
1739             JSHandle<BigInt> rightBigint(valRight);
1740             return BigInt::BitwiseOR(thread, leftBigint, rightBigint).GetTaggedValue();
1741         }
1742         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1743     }
1744     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1745     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1746     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1747     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1748     int32_t opNumber0 = taggedNumber0.GetInt();
1749     int32_t opNumber1 = taggedNumber1.GetInt();
1750     // NOLINT(hicpp-signed-bitwise)
1751     auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
1752     return JSTaggedValue(static_cast<int32_t>(ret));
1753 }
1754 
RuntimeXor2(JSThread * thread,const JSHandle<JSTaggedValue> & left,const JSHandle<JSTaggedValue> & right)1755 JSTaggedValue RuntimeStubs::RuntimeXor2(JSThread *thread, const JSHandle<JSTaggedValue> &left,
1756                                         const JSHandle<JSTaggedValue> &right)
1757 {
1758     JSHandle<JSTaggedValue> valLeft = JSTaggedValue::ToNumeric(thread, left);
1759     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1760     JSHandle<JSTaggedValue> valRight = JSTaggedValue::ToNumeric(thread, right);
1761     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1762     if (valLeft->IsBigInt() || valRight->IsBigInt()) {
1763         if (valLeft->IsBigInt() && valRight->IsBigInt()) {
1764             JSHandle<BigInt> leftBigint(valLeft);
1765             JSHandle<BigInt> rightBigint(valRight);
1766             return BigInt::BitwiseXOR(thread, leftBigint, rightBigint).GetTaggedValue();
1767         }
1768         return RuntimeThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
1769     }
1770     JSTaggedValue taggedNumber0 = RuntimeToJSTaggedValueWithInt32(thread, valLeft);
1771     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1772     JSTaggedValue taggedNumber1 = RuntimeToJSTaggedValueWithInt32(thread, valRight);
1773     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1774     int32_t opNumber0 = taggedNumber0.GetInt();
1775     int32_t opNumber1 = taggedNumber1.GetInt();
1776     // NOLINT(hicpp-signed-bitwise)
1777     auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
1778     return JSTaggedValue(static_cast<int32_t>(ret));
1779 }
1780 
RuntimeToJSTaggedValueWithInt32(JSThread * thread,const JSHandle<JSTaggedValue> & value)1781 JSTaggedValue RuntimeStubs::RuntimeToJSTaggedValueWithInt32(JSThread *thread,
1782                                                             const JSHandle<JSTaggedValue> &value)
1783 {
1784     int32_t res = JSTaggedValue::ToInt32(thread, value);
1785     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1786     return JSTaggedValue(res);
1787 }
1788 
RuntimeToJSTaggedValueWithUint32(JSThread * thread,const JSHandle<JSTaggedValue> & value)1789 JSTaggedValue RuntimeStubs::RuntimeToJSTaggedValueWithUint32(JSThread *thread, const JSHandle<JSTaggedValue> &value)
1790 {
1791     uint32_t res = JSTaggedValue::ToUint32(thread, value);
1792     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1793     return JSTaggedValue(res);
1794 }
1795 
RuntimeCreateEmptyObject(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)1796 JSTaggedValue RuntimeStubs::RuntimeCreateEmptyObject([[maybe_unused]] JSThread *thread, ObjectFactory *factory,
1797                                                      JSHandle<GlobalEnv> globalEnv)
1798 {
1799     JSHandle<JSFunction> builtinObj(globalEnv->GetObjectFunction());
1800     JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(builtinObj);
1801     return obj.GetTaggedValue();
1802 }
1803 
RuntimeCreateEmptyArray(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)1804 JSTaggedValue RuntimeStubs::RuntimeCreateEmptyArray([[maybe_unused]] JSThread *thread, ObjectFactory *factory,
1805                                                     JSHandle<GlobalEnv> globalEnv)
1806 {
1807     JSHandle<JSFunction> builtinObj(globalEnv->GetArrayFunction());
1808     JSHandle<JSObject> arr = factory->NewJSObjectByConstructor(builtinObj);
1809     return arr.GetTaggedValue();
1810 }
1811 
RuntimeGetUnmapedArgs(JSThread * thread,JSTaggedType * sp,uint32_t actualNumArgs,uint32_t startIdx)1812 JSTaggedValue RuntimeStubs::RuntimeGetUnmapedArgs(JSThread *thread, JSTaggedType *sp, uint32_t actualNumArgs,
1813                                                   uint32_t startIdx)
1814 {
1815     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1816     JSHandle<TaggedArray> argumentsList = factory->NewTaggedArray(actualNumArgs);
1817     for (uint32_t i = 0; i < actualNumArgs; ++i) {
1818         argumentsList->Set(thread, i,
1819                            JSTaggedValue(sp[startIdx + i]));  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1820     }
1821     return RuntimeGetUnmapedJSArgumentObj(thread, argumentsList);
1822 }
1823 
RuntimeCopyRestArgs(JSThread * thread,JSTaggedType * sp,uint32_t restNumArgs,uint32_t startIdx)1824 JSTaggedValue RuntimeStubs::RuntimeCopyRestArgs(JSThread *thread, JSTaggedType *sp, uint32_t restNumArgs,
1825                                                 uint32_t startIdx)
1826 {
1827     JSHandle<JSTaggedValue> restArray = JSArray::ArrayCreate(thread, JSTaggedNumber(restNumArgs));
1828 
1829     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1830     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
1831     for (uint32_t i = 0; i < restNumArgs; ++i) {
1832         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1833         element.Update(JSTaggedValue(sp[startIdx + i]));
1834         JSObject::SetProperty(thread, restArray, i, element, true);
1835     }
1836     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1837     return restArray.GetTaggedValue();
1838 }
1839 
RuntimeCreateArrayWithBuffer(JSThread * thread,ObjectFactory * factory,const JSHandle<JSTaggedValue> & literal)1840 JSTaggedValue RuntimeStubs::RuntimeCreateArrayWithBuffer(JSThread *thread, ObjectFactory *factory,
1841                                                          const JSHandle<JSTaggedValue> &literal)
1842 {
1843     JSHandle<JSArray> array(literal);
1844     JSHandle<JSArray> arrLiteral = factory->CloneArrayLiteral(array);
1845     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1846 
1847     return arrLiteral.GetTaggedValue();
1848 }
1849 
RuntimeCreateObjectWithBuffer(JSThread * thread,ObjectFactory * factory,const JSHandle<JSObject> & literal)1850 JSTaggedValue RuntimeStubs::RuntimeCreateObjectWithBuffer(JSThread *thread, ObjectFactory *factory,
1851                                                           const JSHandle<JSObject> &literal)
1852 {
1853     JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(literal);
1854     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1855 
1856     return objLiteral.GetTaggedValue();
1857 }
1858 
RuntimeNewLexicalEnv(JSThread * thread,uint16_t numVars)1859 JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnv(JSThread *thread, uint16_t numVars)
1860 {
1861     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1862     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
1863 
1864     JSTaggedValue currentLexenv = thread->GetCurrentLexenv();
1865     newEnv->SetParentEnv(thread, currentLexenv);
1866     newEnv->SetScopeInfo(thread, JSTaggedValue::Hole());
1867     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1868     return newEnv.GetTaggedValue();
1869 }
1870 
RuntimeNewObjRange(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,uint16_t firstArgIdx,uint16_t length)1871 JSTaggedValue RuntimeStubs::RuntimeNewObjRange(JSThread *thread, const JSHandle<JSTaggedValue> &func,
1872     const JSHandle<JSTaggedValue> &newTarget, uint16_t firstArgIdx, uint16_t length)
1873 {
1874     JSHandle<JSTaggedValue> preArgs(thread, JSTaggedValue::Undefined());
1875     JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
1876     FrameHandler frameHandler(thread);
1877     for (uint16_t i = 0; i < length; ++i) {
1878         JSTaggedValue value = frameHandler.GetVRegValue(firstArgIdx + i);
1879         args->Set(thread, i, value);
1880     }
1881     auto tagged = RuntimeOptConstruct(thread, func, newTarget, preArgs, args);
1882     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1883     return tagged;
1884 }
1885 
RuntimeDefinefunc(JSThread * thread,const JSHandle<Method> & methodHandle)1886 JSTaggedValue RuntimeStubs::RuntimeDefinefunc(JSThread *thread, const JSHandle<Method> &methodHandle)
1887 {
1888     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1889     return factory->NewJSFunction(methodHandle).GetTaggedValue();
1890 }
1891 
RuntimeCreateRegExpWithLiteral(JSThread * thread,const JSHandle<JSTaggedValue> & pattern,uint8_t flags)1892 JSTaggedValue RuntimeStubs::RuntimeCreateRegExpWithLiteral(JSThread *thread,
1893                                                            const JSHandle<JSTaggedValue> &pattern, uint8_t flags)
1894 {
1895     JSHandle<JSTaggedValue> flagsHandle(thread, JSTaggedValue(flags));
1896     return builtins::BuiltinsRegExp::RegExpCreate(thread, pattern, flagsHandle);
1897 }
1898 
RuntimeThrowIfSuperNotCorrectCall(JSThread * thread,uint16_t index,JSTaggedValue thisValue)1899 JSTaggedValue RuntimeStubs::RuntimeThrowIfSuperNotCorrectCall(JSThread *thread, uint16_t index,
1900                                                               JSTaggedValue thisValue)
1901 {
1902     if (index == 0 && (thisValue.IsUndefined() || thisValue.IsHole())) {
1903         return RuntimeThrowReferenceError(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
1904                                        "sub-class must call super before use 'this'");
1905     }
1906     if (index == 1 && !thisValue.IsUndefined() && !thisValue.IsHole()) {
1907         return RuntimeThrowReferenceError(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()),
1908                                        "super() forbidden re-bind 'this'");
1909     }
1910     return JSTaggedValue::True();
1911 }
1912 
RuntimeCreateObjectHavingMethod(JSThread * thread,ObjectFactory * factory,const JSHandle<JSObject> & literal,const JSHandle<JSTaggedValue> & env)1913 JSTaggedValue RuntimeStubs::RuntimeCreateObjectHavingMethod(JSThread *thread, ObjectFactory *factory,
1914                                                             const JSHandle<JSObject> &literal,
1915                                                             const JSHandle<JSTaggedValue> &env)
1916 {
1917     JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(literal, env);
1918     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1919 
1920     return objLiteral.GetTaggedValue();
1921 }
1922 
CommonCreateObjectWithExcludedKeys(JSThread * thread,const JSHandle<JSTaggedValue> & objVal,uint32_t numExcludedKeys,JSHandle<TaggedArray> excludedKeys)1923 JSTaggedValue RuntimeStubs::CommonCreateObjectWithExcludedKeys(JSThread *thread,
1924                                                                const JSHandle<JSTaggedValue> &objVal,
1925                                                                uint32_t numExcludedKeys,
1926                                                                JSHandle<TaggedArray> excludedKeys)
1927 {
1928     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1929     JSHandle<JSObject> restObj = factory->NewEmptyJSObject();
1930     if (objVal->IsNull() || objVal->IsUndefined()) {
1931         return restObj.GetTaggedValue();
1932     }
1933     JSHandle<JSObject> obj(JSTaggedValue::ToObject(thread, objVal));
1934     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1935     JSHandle<TaggedArray> allKeys = JSObject::GetOwnPropertyKeys(thread, obj);
1936     uint32_t numAllKeys = allKeys->GetLength();
1937     JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1938     for (uint32_t i = 0; i < numAllKeys; i++) {
1939         key.Update(allKeys->Get(i));
1940         bool isExcludedKey = false;
1941         for (uint32_t j = 0; j < numExcludedKeys; j++) {
1942             if (JSTaggedValue::Equal(thread, key, JSHandle<JSTaggedValue>(thread, excludedKeys->Get(j)))) {
1943                 isExcludedKey = true;
1944                 break;
1945             }
1946         }
1947         if (!isExcludedKey) {
1948             PropertyDescriptor desc(thread);
1949             bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
1950             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1951             if (success && desc.IsEnumerable()) {
1952                 JSHandle<JSTaggedValue> value = JSObject::GetProperty(thread, obj, key).GetValue();
1953                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1954                 JSObject::SetProperty(thread, restObj, key, value, true);
1955                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1956             }
1957         }
1958     }
1959     return restObj.GetTaggedValue();
1960 }
1961 
RuntimeOptCreateObjectWithExcludedKeys(JSThread * thread,uint16_t numKeys,const JSHandle<JSTaggedValue> & objVal,uint16_t firstArgRegIdx,uintptr_t argv,uint32_t argc)1962 JSTaggedValue RuntimeStubs::RuntimeOptCreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys,
1963                                                                    const JSHandle<JSTaggedValue> &objVal,
1964                                                                    uint16_t firstArgRegIdx,
1965                                                                    uintptr_t argv, uint32_t argc)
1966 {
1967     firstArgRegIdx += 4; // firstArgRegIdx + 4: means the remain parameter
1968     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1969     uint32_t numExcludedKeys = 0;
1970     JSHandle<TaggedArray> excludedKeys = factory->NewTaggedArray(numKeys + 1);
1971     JSTaggedValue excludedKey = GetArg(argv, argc, firstArgRegIdx);
1972     if (!excludedKey.IsUndefined()) {
1973         numExcludedKeys = numKeys + 1;
1974         excludedKeys->Set(thread, 0, excludedKey);
1975         for (uint32_t i = 1; i < numExcludedKeys; i++) {
1976             excludedKey = GetArg(argv, argc, firstArgRegIdx + i);
1977             excludedKeys->Set(thread, i, excludedKey);
1978         }
1979     }
1980     return CommonCreateObjectWithExcludedKeys(thread, objVal, numExcludedKeys, excludedKeys);
1981 }
1982 
RuntimeCreateObjectWithExcludedKeys(JSThread * thread,uint16_t numKeys,const JSHandle<JSTaggedValue> & objVal,uint16_t firstArgRegIdx)1983 JSTaggedValue RuntimeStubs::RuntimeCreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys,
1984                                                                 const JSHandle<JSTaggedValue> &objVal,
1985                                                                 uint16_t firstArgRegIdx)
1986 {
1987     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1988     uint32_t numExcludedKeys = 0;
1989     JSHandle<TaggedArray> excludedKeys = factory->NewTaggedArray(numKeys + 1);
1990     FrameHandler frameHandler(thread);
1991     JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx);
1992     if (!excludedKey.IsUndefined()) {
1993         numExcludedKeys = numKeys + 1;
1994         excludedKeys->Set(thread, 0, excludedKey);
1995         for (uint32_t i = 1; i < numExcludedKeys; i++) {
1996             excludedKey = frameHandler.GetVRegValue(firstArgRegIdx + i);
1997             excludedKeys->Set(thread, i, excludedKey);
1998         }
1999     }
2000 
2001     JSHandle<JSTaggedValue> finalVal = objVal;
2002     if (finalVal->CheckIsJSProxy()) {
2003         JSHandle<JSProxy> proxyVal(thread, finalVal.GetTaggedValue());
2004 
2005         finalVal = proxyVal->GetSourceTarget(thread);
2006     }
2007 
2008     return CommonCreateObjectWithExcludedKeys(thread, finalVal, numExcludedKeys, excludedKeys);
2009 }
2010 
RuntimeDefineMethod(JSThread * thread,const JSHandle<Method> & methodHandle,const JSHandle<JSTaggedValue> & homeObject)2011 JSTaggedValue RuntimeStubs::RuntimeDefineMethod(JSThread *thread, const JSHandle<Method> &methodHandle,
2012                                                 const JSHandle<JSTaggedValue> &homeObject)
2013 {
2014     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2015     return factory->NewJSFunction(methodHandle, homeObject).GetTaggedValue();
2016 }
2017 
RuntimeCallSpread(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & obj,const JSHandle<JSTaggedValue> & array)2018 JSTaggedValue RuntimeStubs::RuntimeCallSpread(JSThread *thread,
2019                                               const JSHandle<JSTaggedValue> &func,
2020                                               const JSHandle<JSTaggedValue> &obj,
2021                                               const JSHandle<JSTaggedValue> &array)
2022 {
2023     if ((!obj->IsUndefined() && !obj->IsECMAObject()) || !func->IsCallable() || !array->IsJSArray()) {
2024         THROW_TYPE_ERROR_AND_RETURN(thread, "cannot Callspread", JSTaggedValue::Exception());
2025     }
2026 
2027     JSHandle<TaggedArray> coretypesArray(thread, RuntimeGetCallSpreadArgs(thread, array));
2028     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2029     uint32_t length = coretypesArray->GetLength();
2030     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2031     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, func, obj, undefined, length);
2032     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2033     info->SetCallArg(length, coretypesArray);
2034     return EcmaInterpreter::Execute(info);
2035 }
2036 
RuntimeDefineGetterSetterByValue(JSThread * thread,const JSHandle<JSObject> & obj,const JSHandle<JSTaggedValue> & prop,const JSHandle<JSTaggedValue> & getter,const JSHandle<JSTaggedValue> & setter,bool flag)2037 JSTaggedValue RuntimeStubs::RuntimeDefineGetterSetterByValue(JSThread *thread, const JSHandle<JSObject> &obj,
2038                                                              const JSHandle<JSTaggedValue> &prop,
2039                                                              const JSHandle<JSTaggedValue> &getter,
2040                                                              const JSHandle<JSTaggedValue> &setter, bool flag)
2041 {
2042     JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, prop);
2043     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2044     auto globalConst = thread->GlobalConstants();
2045     if (obj.GetTaggedValue().IsClassConstructor() &&
2046         JSTaggedValue::SameValue(propKey, globalConst->GetHandledPrototypeString())) {
2047         return RuntimeThrowTypeError(
2048             thread,
2049             "In a class, computed property names for static getter that are named 'prototype' throw a TypeError");
2050     }
2051 
2052     if (flag) {
2053         if (!getter->IsUndefined()) {
2054             if (propKey->IsNumber()) {
2055                 propKey =
2056                     JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
2057             }
2058             JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(getter), propKey,
2059                                             JSHandle<JSTaggedValue>(thread, globalConst->GetGetString()));
2060         }
2061 
2062         if (!setter->IsUndefined()) {
2063             if (propKey->IsNumber()) {
2064                 propKey =
2065                     JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
2066             }
2067             JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(setter), propKey,
2068                                             JSHandle<JSTaggedValue>(thread, globalConst->GetSetString()));
2069         }
2070     }
2071 
2072     // set accessor
2073     bool enumerable =
2074         !(obj.GetTaggedValue().IsClassPrototype() || obj.GetTaggedValue().IsClassConstructor());
2075     PropertyDescriptor desc(thread, true, enumerable, true);
2076     if (!getter->IsUndefined()) {
2077         Method *method = Method::Cast(JSHandle<JSFunction>::Cast(getter)->GetMethod().GetTaggedObject());
2078         method->SetFunctionKind(FunctionKind::GETTER_FUNCTION);
2079         desc.SetGetter(getter);
2080     }
2081     if (!setter->IsUndefined()) {
2082         Method *method = Method::Cast(JSHandle<JSFunction>::Cast(setter)->GetMethod().GetTaggedObject());
2083         method->SetFunctionKind(FunctionKind::SETTER_FUNCTION);
2084         desc.SetSetter(setter);
2085     }
2086     JSObject::DefineOwnProperty(thread, obj, propKey, desc);
2087 
2088     return obj.GetTaggedValue();
2089 }
2090 
RuntimeSuperCall(JSThread * thread,const JSHandle<JSTaggedValue> & func,const JSHandle<JSTaggedValue> & newTarget,uint16_t firstVRegIdx,uint16_t length)2091 JSTaggedValue RuntimeStubs::RuntimeSuperCall(JSThread *thread, const JSHandle<JSTaggedValue> &func,
2092                                              const JSHandle<JSTaggedValue> &newTarget, uint16_t firstVRegIdx,
2093                                              uint16_t length)
2094 {
2095     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
2096     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2097 
2098     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2099     JSHandle<TaggedArray> argv = factory->NewTaggedArray(length);
2100     FrameHandler frameHandler(thread);
2101     for (size_t i = 0; i < length; ++i) {
2102         argv->Set(thread, i, frameHandler.GetVRegValue(firstVRegIdx + i));
2103     }
2104 
2105     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2106     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, length);
2107     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2108     info->SetCallArg(length, argv);
2109     JSTaggedValue result = JSFunction::Construct(info);
2110     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2111 
2112     return result;
2113 }
2114 
RuntimeOptSuperCall(JSThread * thread,uintptr_t argv,uint32_t argc)2115 JSTaggedValue RuntimeStubs::RuntimeOptSuperCall(JSThread *thread, uintptr_t argv, uint32_t argc)
2116 {
2117     constexpr size_t fixNums = 2;
2118     JSHandle<JSTaggedValue> func = GetHArg<JSTaggedValue>(argv, argc, 0);
2119     JSHandle<JSTaggedValue> newTarget = GetHArg<JSTaggedValue>(argv, argc, 1);
2120     JSHandle<JSTaggedValue> superFunc(thread, JSTaggedValue::GetPrototype(thread, func));
2121     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2122     uint16_t length = argc - fixNums;
2123     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2124     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, superFunc, undefined, newTarget, length);
2125     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2126     for (size_t i = 0; i < length; ++i) {
2127         JSTaggedType arg = reinterpret_cast<JSTaggedType *>(argv)[i + fixNums];
2128         info->SetCallArg(i, JSTaggedValue(arg));
2129     }
2130     JSTaggedValue result = JSFunction::Construct(info);
2131     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2132 
2133     return result;
2134 }
2135 
RuntimeThrowTypeError(JSThread * thread,const char * message)2136 JSTaggedValue RuntimeStubs::RuntimeThrowTypeError(JSThread *thread, const char *message)
2137 {
2138     ASSERT_NO_ABRUPT_COMPLETION(thread);
2139     THROW_TYPE_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
2140 }
2141 
RuntimeGetCallSpreadArgs(JSThread * thread,const JSHandle<JSTaggedValue> & jsArray)2142 JSTaggedValue RuntimeStubs::RuntimeGetCallSpreadArgs(JSThread *thread, const JSHandle<JSTaggedValue> &jsArray)
2143 {
2144     uint32_t argvMayMaxLength = JSHandle<JSArray>::Cast(jsArray)->GetArrayLength();
2145 
2146     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2147     JSHandle<TaggedArray> argv = factory->NewTaggedArray(argvMayMaxLength);
2148     JSHandle<JSTaggedValue> itor = JSIterator::GetIterator(thread, jsArray);
2149     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2150     JSMutableHandle<JSTaggedValue> next(thread, JSTaggedValue::Undefined());
2151     JSMutableHandle<JSTaggedValue> nextArg(thread, JSTaggedValue::Undefined());
2152     size_t argvIndex = 0;
2153     while (true) {
2154         next.Update(JSIterator::IteratorStep(thread, itor).GetTaggedValue());
2155         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2156         if (JSTaggedValue::SameValue(next.GetTaggedValue(), JSTaggedValue::False())) {
2157             break;
2158         }
2159         nextArg.Update(JSIterator::IteratorValue(thread, next).GetTaggedValue());
2160         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2161         if (UNLIKELY(argvIndex + 1 >= argvMayMaxLength)) {
2162             argvMayMaxLength = argvMayMaxLength + (argvMayMaxLength >> 1U) + 1U;
2163             argv = argv->SetCapacity(thread, argv, argvMayMaxLength);
2164         }
2165         argv->Set(thread, argvIndex++, nextArg);
2166     }
2167     argv = factory->CopyArray(argv, argvMayMaxLength, argvIndex);
2168     return argv.GetTaggedValue();
2169 }
2170 
RuntimeThrowSyntaxError(JSThread * thread,const char * message)2171 JSTaggedValue RuntimeStubs::RuntimeThrowSyntaxError(JSThread *thread, const char *message)
2172 {
2173     ASSERT_NO_ABRUPT_COMPLETION(thread);
2174     THROW_SYNTAX_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
2175 }
2176 
RuntimeLdBigInt(JSThread * thread,const JSHandle<JSTaggedValue> & numberBigInt)2177 JSTaggedValue RuntimeStubs::RuntimeLdBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &numberBigInt)
2178 {
2179     return JSTaggedValue::ToBigInt(thread, numberBigInt);
2180 }
2181 
RuntimeNewLexicalEnvWithName(JSThread * thread,uint16_t numVars,uint16_t scopeId)2182 JSTaggedValue RuntimeStubs::RuntimeNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId)
2183 {
2184     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2185     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
2186 
2187     JSTaggedValue currentLexenv = thread->GetCurrentLexenv();
2188     newEnv->SetParentEnv(thread, currentLexenv);
2189     JSTaggedValue scopeInfo = ScopeInfoExtractor::GenerateScopeInfo(thread, scopeId);
2190     newEnv->SetScopeInfo(thread, scopeInfo);
2191     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2192     return newEnv.GetTaggedValue();
2193 }
2194 
RuntimeOptGetUnmapedArgs(JSThread * thread,uint32_t actualNumArgs)2195 JSTaggedValue RuntimeStubs::RuntimeOptGetUnmapedArgs(JSThread *thread, uint32_t actualNumArgs)
2196 {
2197     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2198     JSHandle<TaggedArray> argumentsList = factory->NewTaggedArray(actualNumArgs - NUM_MANDATORY_JSFUNC_ARGS);
2199 
2200     auto argv = GetActualArgvFromStub(thread);
2201     int idx = 0;
2202     for (uint32_t i = NUM_MANDATORY_JSFUNC_ARGS; i < actualNumArgs; ++i) {
2203         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2204         JSTaggedType arg = reinterpret_cast<JSTaggedType *>(argv)[i];
2205         JSTaggedValue args = JSTaggedValue(arg);
2206         argumentsList->Set(thread, idx++, args);
2207     }
2208     return RuntimeGetUnmapedJSArgumentObj(thread, argumentsList);
2209 }
2210 
RuntimeGetUnmapedJSArgumentObj(JSThread * thread,const JSHandle<TaggedArray> & argumentsList)2211 JSTaggedValue RuntimeStubs::RuntimeGetUnmapedJSArgumentObj(JSThread *thread, const JSHandle<TaggedArray> &argumentsList)
2212 {
2213     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2214     JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
2215     // 1. Let len be the number of elements in argumentsList
2216     uint32_t len = argumentsList->GetLength();
2217     // 2. Let obj be ObjectCreate(%ObjectPrototype%, «[[ParameterMap]]»).
2218     // 3. Set obj’s [[ParameterMap]] internal slot to undefined.
2219     // [[ParameterMap]] setted as undifined.
2220     JSHandle<JSArguments> obj = factory->NewJSArguments();
2221     // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: true,
2222     // [[Enumerable]]: false, [[Configurable]]: true}).
2223     obj->SetPropertyInlinedProps(thread, JSArguments::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(len));
2224     // 5. Let index be 0.
2225     // 6. Repeat while index < len,
2226     //    a. Let val be argumentsList[index].
2227     //    b. Perform CreateDataProperty(obj, ToString(index), val).
2228     //    c. Let index be index + 1
2229     obj->SetElements(thread, argumentsList.GetTaggedValue());
2230     // 7. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor
2231     // {[[Value]]:%ArrayProto_values%,
2232     // [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
2233     obj->SetPropertyInlinedProps(thread, JSArguments::ITERATOR_INLINE_PROPERTY_INDEX,
2234                                  globalEnv->GetArrayProtoValuesFunction().GetTaggedValue());
2235     // 8. Perform DefinePropertyOrThrow(obj, "caller", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
2236     // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
2237     JSHandle<JSTaggedValue> accessorCaller = globalEnv->GetArgumentsCallerAccessor();
2238     obj->SetPropertyInlinedProps(thread, JSArguments::CALLER_INLINE_PROPERTY_INDEX, accessorCaller.GetTaggedValue());
2239     // 9. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
2240     // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
2241     JSHandle<JSTaggedValue> accessorCallee = globalEnv->GetArgumentsCalleeAccessor();
2242     obj->SetPropertyInlinedProps(thread, JSArguments::CALLEE_INLINE_PROPERTY_INDEX, accessorCallee.GetTaggedValue());
2243     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2244     // 11. Return obj
2245     return obj.GetTaggedValue();
2246 }
2247 
RuntimeOptNewLexicalEnvWithName(JSThread * thread,uint16_t numVars,uint16_t scopeId,JSHandle<JSTaggedValue> & currentLexEnv,JSHandle<JSTaggedValue> & func)2248 JSTaggedValue RuntimeStubs::RuntimeOptNewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId,
2249                                                             JSHandle<JSTaggedValue> &currentLexEnv,
2250                                                             JSHandle<JSTaggedValue> &func)
2251 {
2252     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2253     JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
2254 
2255     newEnv->SetParentEnv(thread, currentLexEnv.GetTaggedValue());
2256     JSTaggedValue scopeInfo = RuntimeOptGenerateScopeInfo(thread, scopeId, func.GetTaggedValue());
2257     newEnv->SetScopeInfo(thread, scopeInfo);
2258     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2259     JSTaggedValue taggedEnv = newEnv.GetTaggedValue();
2260     return taggedEnv;
2261 }
2262 
RuntimeOptCopyRestArgs(JSThread * thread,uint32_t actualArgc,uint32_t restIndex)2263 JSTaggedValue RuntimeStubs::RuntimeOptCopyRestArgs(JSThread *thread, uint32_t actualArgc, uint32_t restIndex)
2264 {
2265     // when only have three fixed args, restIndex in bytecode maybe not zero, but it actually should be zero.
2266     uint32_t actualRestNum = 0;
2267     if (actualArgc > NUM_MANDATORY_JSFUNC_ARGS + restIndex) {
2268         actualRestNum = actualArgc - NUM_MANDATORY_JSFUNC_ARGS - restIndex;
2269     }
2270     JSHandle<JSTaggedValue> restArray = JSArray::ArrayCreate(thread, JSTaggedNumber(actualRestNum));
2271 
2272     auto argv = GetActualArgv(thread);
2273     int idx = 0;
2274     JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
2275 
2276     for (uint32_t i = NUM_MANDATORY_JSFUNC_ARGS + restIndex; i < actualArgc; ++i) {
2277         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
2278         JSTaggedType arg = reinterpret_cast<JSTaggedType *>(argv)[i];
2279         element.Update(JSTaggedValue(arg));
2280         JSObject::SetProperty(thread, restArray, idx++, element, true);
2281     }
2282     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2283     return restArray.GetTaggedValue();
2284 }
2285 
RuntimeOptSuspendGenerator(JSThread * thread,const JSHandle<JSTaggedValue> & genObj,const JSHandle<JSTaggedValue> & value)2286 JSTaggedValue RuntimeStubs::RuntimeOptSuspendGenerator(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
2287                                                        const JSHandle<JSTaggedValue> &value)
2288 {
2289     if (genObj->IsAsyncGeneratorObject()) {
2290         JSHandle<JSAsyncGeneratorObject> generatorObjectHandle(genObj);
2291         // change state to SuspendedYield
2292         if (generatorObjectHandle->IsExecuting()) {
2293             return value.GetTaggedValue();
2294         }
2295         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2296         return generatorObjectHandle.GetTaggedValue();
2297     }
2298 
2299     if (genObj->IsGeneratorObject()) {
2300         JSHandle<JSGeneratorObject> generatorObjectHandle(genObj);
2301         // change state to SuspendedYield
2302         if (generatorObjectHandle->IsExecuting()) {
2303             generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);
2304             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2305             return value.GetTaggedValue();
2306         }
2307         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2308         return generatorObjectHandle.GetTaggedValue();
2309     }
2310 
2311     return RuntimeThrowTypeError(thread, "RuntimeSuspendGenerator failed");
2312 }
2313 
RuntimeOptAsyncGeneratorResolve(JSThread * thread,JSHandle<JSTaggedValue> asyncFuncObj,JSHandle<JSTaggedValue> value,JSTaggedValue flag)2314 JSTaggedValue RuntimeStubs::RuntimeOptAsyncGeneratorResolve(JSThread *thread, JSHandle<JSTaggedValue> asyncFuncObj,
2315                                                             JSHandle<JSTaggedValue> value, JSTaggedValue flag)
2316 {
2317     [[maybe_unused]] EcmaHandleScope handleScope(thread);
2318 
2319     JSHandle<JSAsyncGeneratorObject> asyncGeneratorObjHandle(asyncFuncObj);
2320     JSHandle<JSTaggedValue> valueHandle(value);
2321     JSHandle<GeneratorContext> genContextHandle(thread, asyncGeneratorObjHandle->GetGeneratorContext());
2322     ASSERT(flag.IsBoolean());
2323     bool done = flag.IsTrue();
2324     return JSAsyncGeneratorObject::AsyncGeneratorResolve(thread, asyncGeneratorObjHandle, valueHandle, done);
2325 }
2326 
RuntimeOptConstruct(JSThread * thread,JSHandle<JSTaggedValue> ctor,JSHandle<JSTaggedValue> newTarget,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)2327 JSTaggedValue RuntimeStubs::RuntimeOptConstruct(JSThread *thread, JSHandle<JSTaggedValue> ctor,
2328                                                 JSHandle<JSTaggedValue> newTarget, JSHandle<JSTaggedValue> preArgs,
2329                                                 JSHandle<TaggedArray> args)
2330 {
2331     if (newTarget->IsUndefined()) {
2332         newTarget = ctor;
2333     }
2334 
2335     if (!(newTarget->IsConstructor() && ctor->IsConstructor())) {
2336         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
2337     }
2338 
2339     if (ctor->IsJSFunction()) {
2340         return RuntimeOptConstructGeneric(thread, JSHandle<JSFunction>::Cast(ctor), newTarget, preArgs, args);
2341     }
2342     if (ctor->IsBoundFunction()) {
2343         return RuntimeOptConstructBoundFunction(
2344             thread, JSHandle<JSBoundFunction>::Cast(ctor), newTarget, preArgs, args);
2345     }
2346     if (ctor->IsJSProxy()) {
2347         return RuntimeOptConstructProxy(thread, JSHandle<JSProxy>::Cast(ctor), newTarget, preArgs, args);
2348     }
2349     THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor NonConstructor", JSTaggedValue::Exception());
2350 }
2351 
RuntimeOptConstructProxy(JSThread * thread,JSHandle<JSProxy> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)2352 JSTaggedValue RuntimeStubs::RuntimeOptConstructProxy(JSThread *thread, JSHandle<JSProxy> ctor,
2353                                                      JSHandle<JSTaggedValue> newTgt, JSHandle<JSTaggedValue> preArgs,
2354                                                      JSHandle<TaggedArray> args)
2355 {
2356     // step 1 ~ 4 get ProxyHandler and ProxyTarget
2357     JSHandle<JSTaggedValue> handler(thread, ctor->GetHandler());
2358     if (handler->IsNull()) {
2359         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor: handler is null", JSTaggedValue::Exception());
2360     }
2361     ASSERT(handler->IsJSObject());
2362     JSHandle<JSTaggedValue> target(thread, ctor->GetTarget());
2363 
2364     // 5.Let trap be GetMethod(handler, "construct").
2365     JSHandle<JSTaggedValue> key(thread->GlobalConstants()->GetHandledProxyConstructString());
2366     JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
2367 
2368     // 6.ReturnIfAbrupt(trap).
2369     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2370     // 7.If trap is undefined, then
2371     //   a.Assert: target has a [[Construct]] internal method.
2372     //   b.Return Construct(target, argumentsList, newTarget).
2373     if (method->IsUndefined()) {
2374         ASSERT(target->IsConstructor());
2375         return RuntimeOptConstruct(thread, target, newTgt, preArgs, args);
2376     }
2377 
2378     // 8.Let argArray be CreateArrayFromList(argumentsList).
2379     uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
2380     const uint32_t argsCount = args->GetLength();
2381     const uint32_t size = preArgsSize + argsCount;
2382     JSHandle<TaggedArray> arr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(size);
2383     if (preArgsSize > 0) {
2384         JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
2385         for (uint32_t i = 0; i < preArgsSize; ++i) {
2386             JSTaggedValue value = tgaPreArgs->Get(i);
2387             arr->Set(thread, i, value);
2388         }
2389     }
2390 
2391     for (uint32_t i = 0; i < argsCount; ++i) {
2392         JSTaggedValue value = args->Get(i);
2393         arr->Set(thread, i + preArgsSize, value);
2394     }
2395     JSHandle<JSArray> newArr = JSArray::CreateArrayFromList(thread, arr);
2396 
2397     // step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »).
2398     const uint32_t argsLength = 3;  // 3: «target, argArray, newTarget »
2399     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2400     EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
2401     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2402     info->SetCallArg(target.GetTaggedValue(), newArr.GetTaggedValue(), newTgt.GetTaggedValue());
2403     JSTaggedValue newObjValue = JSFunction::Call(info);
2404     // 10.ReturnIfAbrupt(newObj).
2405     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2406     // 11.If Type(newObj) is not Object, throw a TypeError exception.
2407     if (!newObjValue.IsECMAObject()) {
2408         THROW_TYPE_ERROR_AND_RETURN(thread, "new object is not object", JSTaggedValue::Exception());
2409     }
2410     // 12.Return newObj.
2411     return newObjValue;
2412 }
2413 
RuntimeOptConstructBoundFunction(JSThread * thread,JSHandle<JSBoundFunction> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)2414 JSTaggedValue RuntimeStubs::RuntimeOptConstructBoundFunction(JSThread *thread, JSHandle<JSBoundFunction> ctor,
2415                                                              JSHandle<JSTaggedValue> newTgt,
2416                                                              JSHandle<JSTaggedValue> preArgs,
2417                                                              JSHandle<TaggedArray> args)
2418 {
2419     JSHandle<JSTaggedValue> target(thread, ctor->GetBoundTarget());
2420     ASSERT(target->IsConstructor());
2421 
2422     JSHandle<TaggedArray> boundArgs(thread, ctor->GetBoundArguments());
2423     JSMutableHandle<JSTaggedValue> newPreArgs(thread, preArgs.GetTaggedValue());
2424     if (newPreArgs->IsUndefined()) {
2425         newPreArgs.Update(boundArgs.GetTaggedValue());
2426     } else {
2427         newPreArgs.Update(
2428             TaggedArray::Append(thread, boundArgs, JSHandle<TaggedArray>::Cast(preArgs)).GetTaggedValue());
2429     }
2430     JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTgt.GetTaggedValue());
2431     if (JSTaggedValue::SameValue(ctor.GetTaggedValue(), newTgt.GetTaggedValue())) {
2432         newTargetMutable.Update(target.GetTaggedValue());
2433     }
2434     return RuntimeOptConstruct(thread, target, newTargetMutable, newPreArgs, args);
2435 }
2436 
RuntimeOptConstructGeneric(JSThread * thread,JSHandle<JSFunction> ctor,JSHandle<JSTaggedValue> newTgt,JSHandle<JSTaggedValue> preArgs,JSHandle<TaggedArray> args)2437 JSTaggedValue RuntimeStubs::RuntimeOptConstructGeneric(JSThread *thread, JSHandle<JSFunction> ctor,
2438                                                        JSHandle<JSTaggedValue> newTgt,
2439                                                        JSHandle<JSTaggedValue> preArgs, JSHandle<TaggedArray> args)
2440 {
2441     if (!ctor->IsConstructor()) {
2442         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
2443     }
2444 
2445     JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
2446     if (ctor->IsBase()) {
2447         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2448         obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(ctor, newTgt));
2449         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2450     }
2451 
2452     uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
2453     const uint32_t argsCount = args->GetLength();
2454     uint32_t size = preArgsSize + argsCount;
2455     CVector<JSTaggedType> values;
2456     Method *method = ctor->GetCallTarget();
2457     bool isAotMethod = method->IsAotWithCallField();
2458     if (isAotMethod && ctor->IsClassConstructor()) {
2459         if (method->IsFastCall()) {
2460             values.reserve(size + NUM_MANDATORY_JSFUNC_ARGS - 1);
2461             values.emplace_back(ctor.GetTaggedValue().GetRawData());
2462             values.emplace_back(obj.GetTaggedValue().GetRawData());
2463         } else {
2464             values.reserve(size + NUM_MANDATORY_JSFUNC_ARGS);
2465             values.emplace_back(ctor.GetTaggedValue().GetRawData());
2466             values.emplace_back(newTgt.GetTaggedValue().GetRawData());
2467             values.emplace_back(obj.GetTaggedValue().GetRawData());
2468         }
2469     } else {
2470         values.reserve(size);
2471     }
2472 
2473     if (preArgsSize > 0) {
2474         JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
2475         for (uint32_t i = 0; i < preArgsSize; ++i) {
2476             JSTaggedValue value = tgaPreArgs->Get(i);
2477             values.emplace_back(value.GetRawData());
2478         }
2479         for (uint32_t i = 0; i < argsCount; ++i) {
2480             values.emplace_back(args->Get(i).GetRawData());
2481         }
2482     } else {
2483         for (uint32_t i = 0; i < argsCount; ++i) {
2484             values.emplace_back(args->Get(i).GetRawData());
2485         }
2486     }
2487     JSTaggedValue resultValue;
2488     if (isAotMethod && ctor->IsClassConstructor()) {
2489         uint32_t numArgs = ctor->GetCallTarget()->GetNumArgsWithCallField();
2490         bool needPushUndefined = numArgs > size;
2491         const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
2492         if (ctor->GetCallTarget()->IsFastCall()) {
2493             if (needPushUndefined) {
2494                 values.reserve(numArgs + NUM_MANDATORY_JSFUNC_ARGS - 1);
2495                 for (uint32_t i = size; i < numArgs; i++) {
2496                     values.emplace_back(JSTaggedValue::VALUE_UNDEFINED);
2497                 }
2498                 size = numArgs;
2499             }
2500             resultValue = thread->GetEcmaVM()->FastCallAot(size, values.data(), prevFp);
2501         } else {
2502             resultValue = thread->GetCurrentEcmaContext()->ExecuteAot(size, values.data(), prevFp, needPushUndefined);
2503         }
2504     } else {
2505         ctor->GetCallTarget()->SetAotCodeBit(false); // if Construct is not ClassConstructor, don't run aot
2506         EcmaRuntimeCallInfo *info =
2507             EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(ctor), obj, newTgt, size);
2508         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2509         info->SetCallArg(size, values.data());
2510         resultValue = EcmaInterpreter::Execute(info);
2511     }
2512     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2513     // 9.3.2 [[Construct]] (argumentsList, newTarget)
2514     if (resultValue.IsECMAObject()) {
2515         return resultValue;
2516     }
2517 
2518     if (ctor->IsBase()) {
2519         return obj.GetTaggedValue();
2520     }
2521     if (!resultValue.IsUndefined()) {
2522         THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
2523     }
2524     return obj.GetTaggedValue();
2525 }
2526 
RuntimeOptNewObjRange(JSThread * thread,uintptr_t argv,uint32_t argc)2527 JSTaggedValue RuntimeStubs::RuntimeOptNewObjRange(JSThread *thread, uintptr_t argv, uint32_t argc)
2528 {
2529     JSHandle<JSTaggedValue> ctor = GetHArg<JSTaggedValue>(argv, argc, 0);
2530     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
2531     const size_t firstArgOffset = 1;
2532     size_t arrLength = argc - firstArgOffset;
2533     JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(arrLength);
2534     for (size_t i = 0; i < arrLength; ++i) {
2535         args->Set(thread, i, GetArg(argv, argc, i + firstArgOffset));
2536     }
2537     JSTaggedValue object = RuntimeOptConstruct(thread, ctor, ctor, undefined, args);
2538     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2539     if (!object.IsUndefined() && !object.IsECMAObject() && !JSHandle<JSFunction>(ctor)->IsBase()) {
2540         THROW_TYPE_ERROR_AND_RETURN(thread, "Derived constructor must return object or undefined",
2541                                     JSTaggedValue::Exception());
2542     }
2543     return object;
2544 }
2545 
RuntimeOptGenerateScopeInfo(JSThread * thread,uint16_t scopeId,JSTaggedValue func)2546 JSTaggedValue RuntimeStubs::RuntimeOptGenerateScopeInfo(JSThread *thread, uint16_t scopeId, JSTaggedValue func)
2547 {
2548     EcmaVM *ecmaVm = thread->GetEcmaVM();
2549     ObjectFactory *factory = ecmaVm->GetFactory();
2550     Method *method = ECMAObject::Cast(func.GetTaggedObject())->GetCallTarget();
2551     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
2552     JSHandle<ConstantPool> constpool(thread, method->GetConstantPool());
2553     panda_file::File::EntityId id = constpool->GetEntityId(scopeId);
2554     JSHandle<TaggedArray> elementsLiteral =
2555         LiteralDataExtractor::GetDatasIgnoreType(thread, jsPandaFile, id, constpool);
2556 
2557     ASSERT(elementsLiteral->GetLength() > 0);
2558 
2559     auto *scopeDebugInfo = ecmaVm->GetNativeAreaAllocator()->New<ScopeDebugInfo>();
2560     if (scopeDebugInfo == nullptr) {
2561         return JSTaggedValue::Hole();
2562     }
2563 
2564     size_t length = elementsLiteral->GetLength();
2565     for (size_t i = 1; i < length; i += 2) {  // 2: Each literal buffer contains a pair of key-value.
2566         JSTaggedValue val = elementsLiteral->Get(i);
2567         ASSERT(val.IsString());
2568         CString name = ConvertToString(EcmaString::Cast(val.GetTaggedObject()));
2569         int32_t slot = elementsLiteral->Get(i + 1).GetInt();
2570         scopeDebugInfo->scopeInfo.emplace(name, slot);
2571     }
2572 
2573     JSHandle<JSNativePointer> pointer = factory->NewJSNativePointer(
2574         scopeDebugInfo, NativeAreaAllocator::FreeObjectFunc<ScopeDebugInfo>, ecmaVm->GetNativeAreaAllocator());
2575     return pointer.GetTaggedValue();
2576 }
2577 
GetActualArgv(JSThread * thread)2578 JSTaggedType *RuntimeStubs::GetActualArgv(JSThread *thread)
2579 {
2580     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
2581     FrameIterator it(current, thread);
2582     ASSERT(it.IsLeaveFrame());
2583     it.Advance<GCVisitedFlag::VISITED>();
2584     ASSERT(it.IsOptimizedJSFunctionFrame());
2585     auto optimizedJSFunctionFrame = it.GetFrame<OptimizedJSFunctionFrame>();
2586     return optimizedJSFunctionFrame->GetArgv(it);
2587 }
2588 
GetActualArgvFromStub(JSThread * thread)2589 JSTaggedType *RuntimeStubs::GetActualArgvFromStub(JSThread *thread)
2590 {
2591     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
2592     FrameIterator it(current, thread);
2593     ASSERT(it.IsLeaveFrame());
2594     it.Advance<GCVisitedFlag::VISITED>();
2595     ASSERT(it.IsOptimizedFrame());
2596     it.Advance<GCVisitedFlag::VISITED>();
2597     ASSERT(it.IsOptimizedJSFunctionFrame());
2598     auto optimizedJSFunctionFrame = it.GetFrame<OptimizedJSFunctionFrame>();
2599     return optimizedJSFunctionFrame->GetArgv(it);
2600 }
2601 
GetOptimizedJSFunctionFrame(JSThread * thread)2602 OptimizedJSFunctionFrame *RuntimeStubs::GetOptimizedJSFunctionFrame(JSThread *thread)
2603 {
2604     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
2605     FrameIterator it(current, thread);
2606     ASSERT(it.IsLeaveFrame());
2607     it.Advance();
2608     ASSERT(it.IsOptimizedJSFunctionFrame());
2609     return it.GetFrame<OptimizedJSFunctionFrame>();
2610 }
2611 
GetOptimizedJSFunctionFrameNoGC(JSThread * thread)2612 OptimizedJSFunctionFrame *RuntimeStubs::GetOptimizedJSFunctionFrameNoGC(JSThread *thread)
2613 {
2614     JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetLastLeaveFrame());
2615     FrameIterator it(current, thread);
2616     ASSERT(it.IsOptimizedFrame());
2617     it.Advance();
2618     ASSERT(it.IsOptimizedJSFunctionFrame());
2619     return it.GetFrame<OptimizedJSFunctionFrame>();
2620 }
2621 
RuntimeLdPatchVar(JSThread * thread,uint32_t index)2622 JSTaggedValue RuntimeStubs::RuntimeLdPatchVar(JSThread *thread, uint32_t index)
2623 {
2624     JSHandle<TaggedArray> globalPatch =
2625         JSHandle<TaggedArray>::Cast(thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalPatch());
2626 
2627     return globalPatch->Get(thread, index);
2628 }
2629 
RuntimeStPatchVar(JSThread * thread,uint32_t index,const JSHandle<JSTaggedValue> & value)2630 JSTaggedValue RuntimeStubs::RuntimeStPatchVar(JSThread *thread, uint32_t index, const JSHandle<JSTaggedValue> &value)
2631 {
2632     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2633 
2634     JSHandle<TaggedArray> globalPatch = JSHandle<TaggedArray>::Cast(env->GetGlobalPatch());
2635     if (index >= globalPatch->GetLength()) {
2636         globalPatch = TaggedArray::SetCapacity(thread, globalPatch, index + 1);
2637     }
2638     globalPatch->Set(thread, index, value);
2639     env->SetGlobalPatch(thread, globalPatch.GetTaggedValue());
2640     return JSTaggedValue::True();
2641 }
2642 
RuntimeNotifyConcurrentResult(JSThread * thread,JSTaggedValue result,JSTaggedValue hint)2643 JSTaggedValue RuntimeStubs::RuntimeNotifyConcurrentResult(JSThread *thread, JSTaggedValue result, JSTaggedValue hint)
2644 {
2645     thread->GetEcmaVM()->TriggerConcurrentCallback(result, hint);
2646     return JSTaggedValue::Undefined();
2647 }
2648 
RuntimeNotifyDebuggerStatement(JSThread * thread)2649 JSTaggedValue RuntimeStubs::RuntimeNotifyDebuggerStatement(JSThread *thread)
2650 {
2651     FrameHandler frameHandler(thread);
2652     for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
2653         if (frameHandler.IsEntryFrame() || frameHandler.IsBuiltinFrame()) {
2654             continue;
2655         }
2656         Method *method = frameHandler.GetMethod();
2657         if (method->IsNativeWithCallField()) {
2658             continue;
2659         }
2660         auto bcOffset = frameHandler.GetBytecodeOffset();
2661         auto *debuggerMgr = thread->GetEcmaVM()->GetJsDebuggerManager();
2662         debuggerMgr->GetNotificationManager()->DebuggerStmtEvent(thread, method, bcOffset);
2663         return JSTaggedValue::Hole();
2664     }
2665     return JSTaggedValue::Hole();
2666 }
2667 }  // namespace panda::ecmascript
2668 #endif  // ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
2669