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