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