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