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