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