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