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