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