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