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