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