1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/interpreter/slow_runtime_stub.h"
17
18 #include "ecmascript/base/number_helper.h"
19 #include "ecmascript/builtins/builtins_regexp.h"
20 #include "ecmascript/jspandafile/program_object-inl.h"
21 #include "ecmascript/ecma_module.h"
22 #include "ecmascript/global_dictionary-inl.h"
23 #include "ecmascript/ic/profile_type_info.h"
24 #include "ecmascript/internal_call_params.h"
25 #include "ecmascript/interpreter/fast_runtime_stub-inl.h"
26 #include "ecmascript/interpreter/frame_handler.h"
27 #include "ecmascript/interpreter/slow_runtime_helper.h"
28 #include "ecmascript/js_arguments.h"
29 #include "ecmascript/js_array.h"
30 #include "ecmascript/js_array_iterator.h"
31 #include "ecmascript/js_async_function.h"
32 #include "ecmascript/js_for_in_iterator.h"
33 #include "ecmascript/js_function.h"
34 #include "ecmascript/js_generator_object.h"
35 #include "ecmascript/js_hclass-inl.h"
36 #include "ecmascript/js_invoker.h"
37 #include "ecmascript/js_iterator.h"
38 #include "ecmascript/js_promise.h"
39 #include "ecmascript/js_proxy.h"
40 #include "ecmascript/js_tagged_value-inl.h"
41 #include "ecmascript/js_thread.h"
42 #include "ecmascript/jspandafile/scope_info_extractor.h"
43 #include "ecmascript/tagged_dictionary.h"
44 #include "ecmascript/runtime_call_id.h"
45 #include "ecmascript/template_string.h"
46
47 namespace panda::ecmascript {
CallSpreadDyn(JSThread * thread,JSTaggedValue func,JSTaggedValue obj,JSTaggedValue array)48 JSTaggedValue SlowRuntimeStub::CallSpreadDyn(JSThread *thread, JSTaggedValue func, JSTaggedValue obj,
49 JSTaggedValue array)
50 {
51 INTERPRETER_TRACE(thread, CallSpreadDyn);
52 if ((!obj.IsUndefined() && !obj.IsECMAObject()) || !func.IsJSFunction() || !array.IsJSArray()) {
53 THROW_TYPE_ERROR_AND_RETURN(thread, "cannot Callspread", JSTaggedValue::Exception());
54 }
55 [[maybe_unused]] EcmaHandleScope handleScope(thread);
56
57 JSHandle<JSFunction> jsFunc(thread, func);
58 JSHandle<JSTaggedValue> jsArray(thread, array);
59 JSHandle<JSTaggedValue> taggedObj(thread, obj);
60
61 JSHandle<TaggedArray> coretypesArray(thread, GetCallSpreadArgs(thread, jsArray.GetTaggedValue()));
62 InternalCallParams *params = thread->GetInternalCallParams();
63 params->MakeArgList(*coretypesArray);
64 JSHandle<JSTaggedValue> newTarget(thread, JSTaggedValue::Undefined());
65 JSTaggedValue res = InvokeJsFunction(thread, jsFunc, taggedObj, newTarget, params);
66
67 return res;
68 }
69
NegDyn(JSThread * thread,JSTaggedValue value)70 JSTaggedValue SlowRuntimeStub::NegDyn(JSThread *thread, JSTaggedValue value)
71 {
72 INTERPRETER_TRACE(thread, NegDyn);
73 [[maybe_unused]] EcmaHandleScope handleScope(thread);
74
75 JSHandle<JSTaggedValue> input(thread, value);
76 JSHandle<JSTaggedValue> inputVal(thread, JSTaggedValue::ToNumeric(thread, input));
77 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
78 if (inputVal->IsBigInt()) {
79 JSHandle<BigInt> bigValue(inputVal);
80 return BigInt::UnaryMinus(thread, bigValue).GetTaggedValue();
81 }
82 JSTaggedNumber number(inputVal.GetTaggedValue());
83 if (number.IsInt()) {
84 int32_t intValue = number.GetInt();
85 if (intValue == 0) {
86 return JSTaggedValue(-0.0);
87 }
88 return JSTaggedValue(-intValue);
89 }
90 if (number.IsDouble()) {
91 return JSTaggedValue(-number.GetDouble());
92 }
93 UNREACHABLE();
94 }
95
AsyncFunctionEnter(JSThread * thread)96 JSTaggedValue SlowRuntimeStub::AsyncFunctionEnter(JSThread *thread)
97 {
98 INTERPRETER_TRACE(thread, AsyncFunctionEnter);
99 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
100 [[maybe_unused]] EcmaHandleScope handleScope(thread);
101 // 1. create promise
102 JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
103 JSHandle<JSTaggedValue> promiseFunc = globalEnv->GetPromiseFunction();
104
105 JSHandle<JSPromise> promiseObject =
106 JSHandle<JSPromise>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(promiseFunc), promiseFunc));
107 promiseObject->SetPromiseState(PromiseState::PENDING);
108 // 2. create asyncfuncobj
109 JSHandle<JSAsyncFuncObject> asyncFuncObj = factory->NewJSAsyncFuncObject();
110 asyncFuncObj->SetPromise(thread, promiseObject);
111
112 JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
113 context->SetGeneratorObject(thread, asyncFuncObj);
114
115 // change state to EXECUTING
116 asyncFuncObj->SetGeneratorState(JSGeneratorState::EXECUTING);
117 asyncFuncObj->SetGeneratorContext(thread, context);
118
119 // 3. return asyncfuncobj
120 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
121 return asyncFuncObj.GetTaggedValue();
122 }
123
ToNumber(JSThread * thread,JSTaggedValue value)124 JSTaggedValue SlowRuntimeStub::ToNumber(JSThread *thread, JSTaggedValue value)
125 {
126 INTERPRETER_TRACE(thread, Tonumber);
127 [[maybe_unused]] EcmaHandleScope handleScope(thread);
128
129 JSHandle<JSTaggedValue> number(thread, value);
130 // may return exception
131 return JSTaggedValue::ToNumeric(thread, number);
132 }
133
NotDyn(JSThread * thread,JSTaggedValue value)134 JSTaggedValue SlowRuntimeStub::NotDyn(JSThread *thread, JSTaggedValue value)
135 {
136 INTERPRETER_TRACE(thread, NotDyn);
137 [[maybe_unused]] EcmaHandleScope handleScope(thread);
138 JSHandle<JSTaggedValue> input(thread, value);
139 JSHandle<JSTaggedValue> inputVal(thread, JSTaggedValue::ToNumeric(thread, input));
140 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
141 if (inputVal->IsBigInt()) {
142 JSHandle<BigInt> bigValue(inputVal);
143 return BigInt::BitwiseNOT(thread, bigValue).GetTaggedValue();
144 }
145 int32_t number = JSTaggedValue::ToInt32(thread, inputVal);
146 return JSTaggedValue(~number); // NOLINT(hicpp-signed-bitwise)
147 }
148
IncDyn(JSThread * thread,JSTaggedValue value)149 JSTaggedValue SlowRuntimeStub::IncDyn(JSThread *thread, JSTaggedValue value)
150 {
151 INTERPRETER_TRACE(thread, IncDyn);
152 [[maybe_unused]] EcmaHandleScope handleScope(thread);
153
154 JSHandle<JSTaggedValue> input(thread, value);
155 JSHandle<JSTaggedValue> inputVal(thread, JSTaggedValue::ToNumeric(thread, input));
156 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
157 if (inputVal->IsBigInt()) {
158 JSHandle<BigInt> bigValue(inputVal);
159 return BigInt::BigintAddOne(thread, bigValue).GetTaggedValue();
160 }
161 JSTaggedNumber number(inputVal.GetTaggedValue());
162 return JSTaggedValue(++number);
163 }
164
DecDyn(JSThread * thread,JSTaggedValue value)165 JSTaggedValue SlowRuntimeStub::DecDyn(JSThread *thread, JSTaggedValue value)
166 {
167 INTERPRETER_TRACE(thread, DecDyn);
168 [[maybe_unused]] EcmaHandleScope handleScope(thread);
169
170 JSHandle<JSTaggedValue> input(thread, value);
171 JSHandle<JSTaggedValue> inputVal(thread, JSTaggedValue::ToNumeric(thread, input));
172 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
173 if (inputVal->IsBigInt()) {
174 JSHandle<BigInt> bigValue(inputVal);
175 return BigInt::BigintSubOne(thread, bigValue).GetTaggedValue();
176 }
177 JSTaggedNumber number(inputVal.GetTaggedValue());
178 return JSTaggedValue(--number);
179 }
180
ThrowDyn(JSThread * thread,JSTaggedValue value)181 void SlowRuntimeStub::ThrowDyn(JSThread *thread, JSTaggedValue value)
182 {
183 INTERPRETER_TRACE(thread, ThrowDyn);
184 thread->SetException(value);
185 }
186
GetPropIterator(JSThread * thread,JSTaggedValue value)187 JSTaggedValue SlowRuntimeStub::GetPropIterator(JSThread *thread, JSTaggedValue value)
188 {
189 INTERPRETER_TRACE(thread, GetPropIterator);
190 [[maybe_unused]] EcmaHandleScope handleScope(thread);
191
192 JSHandle<JSTaggedValue> objHandle(thread, value);
193 JSHandle<JSForInIterator> iteratorHandle = JSObject::EnumerateObjectProperties(thread, objHandle);
194 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
195 return iteratorHandle.GetTaggedValue();
196 }
197
ThrowConstAssignment(JSThread * thread,JSTaggedValue value)198 void SlowRuntimeStub::ThrowConstAssignment(JSThread *thread, JSTaggedValue value)
199 {
200 INTERPRETER_TRACE(thread, ThrowConstAssignment);
201 [[maybe_unused]] EcmaHandleScope handleScope(thread);
202
203 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
204
205 JSHandle<EcmaString> name(thread, value.GetTaggedObject());
206 JSHandle<EcmaString> info = factory->NewFromCanBeCompressString("Assignment to const variable ");
207
208 JSHandle<EcmaString> msg = factory->ConcatFromString(info, name);
209 THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::TYPE_ERROR, msg).GetTaggedValue());
210 }
211
Add2Dyn(JSThread * thread,EcmaVM * ecma_vm,JSTaggedValue left,JSTaggedValue right)212 JSTaggedValue SlowRuntimeStub::Add2Dyn(JSThread *thread, EcmaVM *ecma_vm, JSTaggedValue left, JSTaggedValue right)
213 {
214 INTERPRETER_TRACE(thread, Add2Dyn);
215 [[maybe_unused]] EcmaHandleScope handleScope(thread);
216
217 JSHandle<JSTaggedValue> leftValue(thread, left);
218 JSHandle<JSTaggedValue> rightValue(thread, right);
219 if (leftValue->IsString() && rightValue->IsString()) {
220 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
221 JSHandle<EcmaString> newString =
222 factory->ConcatFromString(JSHandle<EcmaString>(leftValue), JSHandle<EcmaString>(rightValue));
223 return newString.GetTaggedValue();
224 }
225 JSHandle<JSTaggedValue> primitiveA0(thread, JSTaggedValue::ToPrimitive(thread, leftValue));
226 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
227 JSHandle<JSTaggedValue> primitiveA1(thread, JSTaggedValue::ToPrimitive(thread, rightValue));
228 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
229 // contain string
230 if (primitiveA0->IsString() || primitiveA1->IsString()) {
231 JSHandle<EcmaString> stringA0 = JSTaggedValue::ToString(thread, primitiveA0);
232 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
233 JSHandle<EcmaString> stringA1 = JSTaggedValue::ToString(thread, primitiveA1);
234 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
235 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
236 JSHandle<EcmaString> newString = factory->ConcatFromString(stringA0, stringA1);
237 return newString.GetTaggedValue();
238 }
239 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, primitiveA0));
240 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
241 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, primitiveA1));
242 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
243 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
244 JSHandle<BigInt> bigLeft(valLeft);
245 JSHandle<BigInt> bigRight(valRight);
246 return BigInt::Add(thread, bigLeft, bigRight).GetTaggedValue();
247 }
248 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
249 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
250 }
251 double a0Double = valLeft->GetNumber();
252 double a1Double = valRight->GetNumber();
253 return JSTaggedValue(a0Double + a1Double);
254 }
255
Sub2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)256 JSTaggedValue SlowRuntimeStub::Sub2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
257 {
258 INTERPRETER_TRACE(thread, Sub2Dyn);
259 [[maybe_unused]] EcmaHandleScope handleScope(thread);
260
261 JSHandle<JSTaggedValue> leftHandle(thread, left);
262 JSHandle<JSTaggedValue> rightHandle(thread, right);
263 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
264 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
265 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
266 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
267 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
268 JSHandle<BigInt> bigLeft(valLeft);
269 JSHandle<BigInt> bigRight(valRight);
270 return BigInt::Subtract(thread, bigLeft, bigRight).GetTaggedValue();
271 }
272 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
273 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
274 }
275 JSTaggedNumber number0(valLeft.GetTaggedValue());
276 JSTaggedNumber number1(valRight.GetTaggedValue());
277 return number0 - number1;
278 }
279
Mul2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)280 JSTaggedValue SlowRuntimeStub::Mul2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
281 {
282 INTERPRETER_TRACE(thread, Mul2Dyn);
283 [[maybe_unused]] EcmaHandleScope handleScope(thread);
284
285 JSHandle<JSTaggedValue> leftHandle(thread, left);
286 JSHandle<JSTaggedValue> rightHandle(thread, right);
287 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
288 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
289 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
290 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
291 // 9. ReturnIfAbrupt(rnum).
292 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
293 JSHandle<BigInt> bigLeft(valLeft);
294 JSHandle<BigInt> bigRight(valRight);
295 return BigInt::Multiply(thread, bigLeft, bigRight).GetTaggedValue();
296 }
297 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
298 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
299 }
300 // 12.6.3.1 Applying the * Operator
301 JSTaggedNumber number0(valLeft.GetTaggedValue());
302 JSTaggedNumber number1(valRight.GetTaggedValue());
303 return number0 * number1;
304 }
305
Div2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)306 JSTaggedValue SlowRuntimeStub::Div2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
307 {
308 INTERPRETER_TRACE(thread, Div2Dyn);
309 [[maybe_unused]] EcmaHandleScope handleScope(thread);
310
311 JSHandle<JSTaggedValue> leftHandle(thread, left);
312 JSHandle<JSTaggedValue> rightHandle(thread, right);
313 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
314 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
315 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
316 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
317 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
318 JSHandle<BigInt> bigLeft(valLeft);
319 JSHandle<BigInt> bigRight(valRight);
320 return BigInt::Divide(thread, bigLeft, bigRight).GetTaggedValue();
321 }
322 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
323 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
324 }
325 double dLeft = valLeft->GetNumber();
326 double dRight = valRight->GetNumber();
327 if (dRight == 0) {
328 if (dLeft == 0 || std::isnan(dLeft)) {
329 return JSTaggedValue(base::NAN_VALUE);
330 }
331 bool positive = (((bit_cast<uint64_t>(dRight)) & base::DOUBLE_SIGN_MASK) ==
332 ((bit_cast<uint64_t>(dLeft)) & base::DOUBLE_SIGN_MASK));
333 return JSTaggedValue(positive ? base::POSITIVE_INFINITY : -base::POSITIVE_INFINITY);
334 }
335 return JSTaggedValue(dLeft / dRight);
336 }
337
Mod2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)338 JSTaggedValue SlowRuntimeStub::Mod2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
339 {
340 INTERPRETER_TRACE(thread, Mod2Dyn);
341 [[maybe_unused]] EcmaHandleScope handleScope(thread);
342
343 JSHandle<JSTaggedValue> leftHandle(thread, left);
344 JSHandle<JSTaggedValue> rightHandle(thread, right);
345 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
346 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
347 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
348 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
349
350 // 12.6.3.3 Applying the % Operator
351 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
352 JSHandle<BigInt> leftBigint(valLeft);
353 JSHandle<BigInt> rightBigint(valRight);
354 return BigInt::Remainder(thread, leftBigint, rightBigint).GetTaggedValue();
355 }
356 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
357 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
358 }
359 double dLeft = valLeft->GetNumber();
360 double dRight = valRight->GetNumber();
361 // 12.6.3.3 Applying the % Operator
362 if ((dRight == 0.0) || std::isnan(dRight) || std::isnan(dLeft) || std::isinf(dLeft)) {
363 return JSTaggedValue(base::NAN_VALUE);
364 }
365 if ((dLeft == 0.0) || std::isinf(dRight)) {
366 return JSTaggedValue(dLeft);
367 }
368 return JSTaggedValue(std::fmod(dLeft, dRight));
369 }
370
EqDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)371 JSTaggedValue SlowRuntimeStub::EqDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
372 {
373 INTERPRETER_TRACE(thread, EqDyn);
374 [[maybe_unused]] EcmaHandleScope handleScope(thread);
375
376 JSHandle<JSTaggedValue> leftValue(thread, left);
377 JSHandle<JSTaggedValue> rightValue(thread, right);
378 bool ret = JSTaggedValue::Equal(thread, leftValue, rightValue);
379 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
380 return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
381 }
382
NotEqDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)383 JSTaggedValue SlowRuntimeStub::NotEqDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
384 {
385 INTERPRETER_TRACE(thread, NotEqDyn);
386 [[maybe_unused]] EcmaHandleScope handleScope(thread);
387
388 JSHandle<JSTaggedValue> leftValue(thread, left);
389 JSHandle<JSTaggedValue> rightValue(thread, right);
390 bool ret = JSTaggedValue::Equal(thread, leftValue, rightValue);
391 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
392 return (ret ? JSTaggedValue::False() : JSTaggedValue::True());
393 }
394
LessDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)395 JSTaggedValue SlowRuntimeStub::LessDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
396 {
397 INTERPRETER_TRACE(thread, LessDyn);
398 [[maybe_unused]] EcmaHandleScope handleScope(thread);
399
400 JSHandle<JSTaggedValue> leftValue(thread, left);
401 JSHandle<JSTaggedValue> rightValue(thread, right);
402 bool ret = JSTaggedValue::Compare(thread, leftValue, rightValue) == ComparisonResult::LESS;
403 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
404 return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
405 }
406
LessEqDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)407 JSTaggedValue SlowRuntimeStub::LessEqDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
408 {
409 INTERPRETER_TRACE(thread, LessEqDyn);
410 [[maybe_unused]] EcmaHandleScope handleScope(thread);
411
412 JSHandle<JSTaggedValue> leftValue(thread, left);
413 JSHandle<JSTaggedValue> rightValue(thread, right);
414 bool ret = JSTaggedValue::Compare(thread, leftValue, rightValue) <= ComparisonResult::EQUAL;
415 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
416 return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
417 }
418
GreaterDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)419 JSTaggedValue SlowRuntimeStub::GreaterDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
420 {
421 INTERPRETER_TRACE(thread, GreaterDyn);
422 [[maybe_unused]] EcmaHandleScope handleScope(thread);
423
424 JSHandle<JSTaggedValue> leftValue(thread, left);
425 JSHandle<JSTaggedValue> rightValue(thread, right);
426 bool ret = JSTaggedValue::Compare(thread, leftValue, rightValue) == ComparisonResult::GREAT;
427 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
428 return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
429 }
430
GreaterEqDyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)431 JSTaggedValue SlowRuntimeStub::GreaterEqDyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
432 {
433 INTERPRETER_TRACE(thread, GreaterEqDyn);
434 [[maybe_unused]] EcmaHandleScope handleScope(thread);
435
436 JSHandle<JSTaggedValue> leftValue(thread, left);
437 JSHandle<JSTaggedValue> rightValue(thread, right);
438 ComparisonResult comparison = JSTaggedValue::Compare(thread, leftValue, rightValue);
439 bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
440 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
441 return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
442 }
443
Shl2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)444 JSTaggedValue SlowRuntimeStub::Shl2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
445 {
446 INTERPRETER_TRACE(thread, Shl2Dyn);
447 [[maybe_unused]] EcmaHandleScope handleScope(thread);
448 JSHandle<JSTaggedValue> leftHandle(thread, left);
449 JSHandle<JSTaggedValue> rightHandle(thread, right);
450 JSHandle<JSTaggedValue> leftValue(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
451 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
452 JSHandle<JSTaggedValue> rightValue(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
453 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
454 if (leftValue->IsBigInt() && rightValue->IsBigInt()) {
455 JSHandle<BigInt> leftBigint(leftValue);
456 JSHandle<BigInt> rightBigint(rightValue);
457 return BigInt::LeftShift(thread, leftBigint, rightBigint).GetTaggedValue();
458 }
459 if (leftValue->IsBigInt() || rightValue->IsBigInt()) {
460 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
461 }
462 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, leftValue.GetTaggedValue());
463 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
464 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, rightValue.GetTaggedValue());
465 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
466 int32_t opNumber0 = taggedNumber0.GetInt();
467 int32_t opNumber1 = taggedNumber1.GetInt();
468 uint32_t shift =
469 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
470 using unsigned_type = std::make_unsigned_t<int32_t>;
471 auto ret =
472 static_cast<int32_t>(static_cast<unsigned_type>(opNumber0) << shift); // NOLINT(hicpp-signed-bitwise)
473 return JSTaggedValue(ret);
474 }
475
Shr2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)476 JSTaggedValue SlowRuntimeStub::Shr2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
477 {
478 INTERPRETER_TRACE(thread, Shr2Dyn);
479 [[maybe_unused]] EcmaHandleScope handleScope(thread);
480
481 JSHandle<JSTaggedValue> leftHandle(thread, left);
482 JSHandle<JSTaggedValue> rightHandle(thread, right);
483 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
484 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
485 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
486 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
487 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
488 JSHandle<BigInt> bigLeft(valLeft);
489 JSHandle<BigInt> bigRight(valRight);
490 return BigInt::SignedRightShift(thread, bigLeft, bigRight).GetTaggedValue();
491 }
492 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
493 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
494 }
495 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valLeft.GetTaggedValue());
496 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
497 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, valRight.GetTaggedValue());
498 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
499 int32_t opNumber0 = taggedNumber0.GetInt();
500 int32_t opNumber1 = taggedNumber1.GetInt();
501 uint32_t shift =
502 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
503 auto ret = static_cast<int32_t>(opNumber0 >> shift); // NOLINT(hicpp-signed-bitwise)
504 return JSTaggedValue(ret);
505 }
506
Ashr2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)507 JSTaggedValue SlowRuntimeStub::Ashr2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
508 {
509 INTERPRETER_TRACE(thread, Ashr2Dyn);
510 [[maybe_unused]] EcmaHandleScope handleScope(thread);
511
512 JSHandle<JSTaggedValue> leftHandle(thread, left);
513 JSHandle<JSTaggedValue> rightHandle(thread, right);
514 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
515 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
516 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
517 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
518 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
519 return BigInt::UnsignedRightShift(thread);
520 }
521 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
522 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
523 }
524 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, valLeft.GetTaggedValue());
525 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
526 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, valRight.GetTaggedValue());
527 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
528 int32_t opNumber0 = taggedNumber0.GetInt();
529 int32_t opNumber1 = taggedNumber1.GetInt();
530 uint32_t shift =
531 static_cast<uint32_t>(opNumber1) & 0x1f; // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
532 using unsigned_type = std::make_unsigned_t<uint32_t>;
533 auto ret =
534 static_cast<uint32_t>(static_cast<unsigned_type>(opNumber0) >> shift); // NOLINT(hicpp-signed-bitwise)
535 return JSTaggedValue(ret);
536 }
537
And2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)538 JSTaggedValue SlowRuntimeStub::And2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
539 {
540 INTERPRETER_TRACE(thread, And2Dyn);
541 [[maybe_unused]] EcmaHandleScope handleScope(thread);
542
543 JSHandle<JSTaggedValue> leftHandle(thread, left);
544 JSHandle<JSTaggedValue> rightHandle(thread, right);
545 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
546 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
547 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
548 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
549 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
550 JSHandle<BigInt> leftBigint(valLeft);
551 JSHandle<BigInt> rightBigint(valRight);
552 return BigInt::BitwiseAND(thread, leftBigint, rightBigint).GetTaggedValue();
553 }
554 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
555 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
556 }
557 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valLeft.GetTaggedValue());
558 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
559 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valRight.GetTaggedValue());
560 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
561 int32_t opNumber0 = taggedNumber0.GetInt();
562 int32_t opNumber1 = taggedNumber1.GetInt();
563 // NOLINT(hicpp-signed-bitwise)
564 auto ret = static_cast<uint32_t>(opNumber0) & static_cast<uint32_t>(opNumber1);
565 return JSTaggedValue(static_cast<int32_t>(ret));
566 }
567
Or2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)568 JSTaggedValue SlowRuntimeStub::Or2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
569 {
570 INTERPRETER_TRACE(thread, Or2Dyn);
571 [[maybe_unused]] EcmaHandleScope handleScope(thread);
572
573 JSHandle<JSTaggedValue> leftHandle(thread, left);
574 JSHandle<JSTaggedValue> rightHandle(thread, right);
575 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
576 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
577 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
578 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
579 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
580 JSHandle<BigInt> leftBigint(valLeft);
581 JSHandle<BigInt> rightBigint(valRight);
582 return BigInt::BitwiseOR(thread, leftBigint, rightBigint).GetTaggedValue();
583 }
584 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
585 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
586 }
587 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valLeft.GetTaggedValue());
588 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
589 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valRight.GetTaggedValue());
590 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
591 int32_t opNumber0 = taggedNumber0.GetInt();
592 int32_t opNumber1 = taggedNumber1.GetInt();
593 // NOLINT(hicpp-signed-bitwise)
594 auto ret = static_cast<uint32_t>(opNumber0) | static_cast<uint32_t>(opNumber1);
595 return JSTaggedValue(static_cast<int32_t>(ret));
596 }
597
Xor2Dyn(JSThread * thread,JSTaggedValue left,JSTaggedValue right)598 JSTaggedValue SlowRuntimeStub::Xor2Dyn(JSThread *thread, JSTaggedValue left, JSTaggedValue right)
599 {
600 INTERPRETER_TRACE(thread, Xor2Dyn);
601 [[maybe_unused]] EcmaHandleScope handleScope(thread);
602
603 JSHandle<JSTaggedValue> leftHandle(thread, left);
604 JSHandle<JSTaggedValue> rightHandle(thread, right);
605 JSHandle<JSTaggedValue> valLeft(thread, JSTaggedValue::ToNumeric(thread, leftHandle));
606 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
607 JSHandle<JSTaggedValue> valRight(thread, JSTaggedValue::ToNumeric(thread, rightHandle));
608 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
609 if (valLeft->IsBigInt() && valRight->IsBigInt()) {
610 JSHandle<BigInt> leftBigint(valLeft);
611 JSHandle<BigInt> rightBigint(valRight);
612 return BigInt::BitwiseXOR(thread, leftBigint, rightBigint).GetTaggedValue();
613 }
614 if (valLeft->IsBigInt() || valRight->IsBigInt()) {
615 return ThrowTypeError(thread, "Cannot mix BigInt and other types, use explicit conversions");
616 }
617 JSTaggedValue taggedNumber0 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valLeft.GetTaggedValue());
618 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
619 JSTaggedValue taggedNumber1 = SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, valRight.GetTaggedValue());
620 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
621 int32_t opNumber0 = taggedNumber0.GetInt();
622 int32_t opNumber1 = taggedNumber1.GetInt();
623 // NOLINT(hicpp-signed-bitwise)
624 auto ret = static_cast<uint32_t>(opNumber0) ^ static_cast<uint32_t>(opNumber1);
625 return JSTaggedValue(static_cast<int32_t>(ret));
626 }
627
ToJSTaggedValueWithInt32(JSThread * thread,JSTaggedValue value)628 JSTaggedValue SlowRuntimeStub::ToJSTaggedValueWithInt32(JSThread *thread, JSTaggedValue value)
629 {
630 INTERPRETER_TRACE(thread, ToJSTaggedValueWithInt32);
631 [[maybe_unused]] EcmaHandleScope handleScope(thread);
632 JSHandle<JSTaggedValue> valueHandle(thread, value);
633 int32_t res = JSTaggedValue::ToInt32(thread, valueHandle);
634 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
635 return JSTaggedValue(res);
636 }
637
ToJSTaggedValueWithUint32(JSThread * thread,JSTaggedValue value)638 JSTaggedValue SlowRuntimeStub::ToJSTaggedValueWithUint32(JSThread *thread, JSTaggedValue value)
639 {
640 INTERPRETER_TRACE(thread, ToJSTaggedValueWithUint32);
641 [[maybe_unused]] EcmaHandleScope handleScope(thread);
642 JSHandle<JSTaggedValue> valueHandle(thread, value);
643 int32_t res = JSTaggedValue::ToUint32(thread, valueHandle);
644 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
645 return JSTaggedValue(res);
646 }
647
DelObjProp(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop)648 JSTaggedValue SlowRuntimeStub::DelObjProp(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop)
649 {
650 INTERPRETER_TRACE(thread, Delobjprop);
651 [[maybe_unused]] EcmaHandleScope handleScope(thread);
652
653 JSHandle<JSTaggedValue> objHandle(thread, obj);
654 JSHandle<JSTaggedValue> propHandle(thread, prop);
655 JSHandle<JSTaggedValue> jsObj(JSTaggedValue::ToObject(thread, objHandle));
656 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
657 JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
658 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
659 bool ret = JSTaggedValue::DeletePropertyOrThrow(thread, jsObj, propKey);
660 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
661 return JSTaggedValue(ret);
662 }
663
NewObjDynRange(JSThread * thread,JSTaggedValue func,JSTaggedValue newTarget,uint16_t firstArgIdx,uint16_t length)664 JSTaggedValue SlowRuntimeStub::NewObjDynRange(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
665 uint16_t firstArgIdx, uint16_t length)
666 {
667 INTERPRETER_TRACE(thread, NewobjDynrange);
668 [[maybe_unused]] EcmaHandleScope handleScope(thread);
669
670 JSHandle<JSTaggedValue> funcHandle(thread, func);
671 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
672
673 JSHandle<JSTaggedValue> preArgs(thread, JSTaggedValue::Undefined());
674 auto tagged = SlowRuntimeHelper::Construct(thread, funcHandle, newTargetHandle, preArgs, length, firstArgIdx);
675 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
676 return tagged;
677 }
678
CreateObjectWithExcludedKeys(JSThread * thread,uint16_t numKeys,JSTaggedValue objVal,uint16_t firstArgRegIdx)679 JSTaggedValue SlowRuntimeStub::CreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys, JSTaggedValue objVal,
680 uint16_t firstArgRegIdx)
681 {
682 INTERPRETER_TRACE(thread, CreateObjectWithExcludedKeys);
683 [[maybe_unused]] EcmaHandleScope handleScope(thread);
684
685 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
686
687 ASSERT(objVal.IsJSObject());
688 JSHandle<JSObject> obj(thread, objVal);
689 uint32_t numExcludedKeys = 0;
690 JSHandle<TaggedArray> excludedKeys = factory->NewTaggedArray(numKeys + 1);
691 InterpretedFrameHandler frameHandler(thread);
692 JSTaggedValue excludedKey = frameHandler.GetVRegValue(firstArgRegIdx);
693 if (!excludedKey.IsUndefined()) {
694 numExcludedKeys = numKeys + 1;
695 excludedKeys->Set(thread, 0, excludedKey);
696 for (uint32_t i = 1; i < numExcludedKeys; i++) {
697 excludedKey = frameHandler.GetVRegValue(firstArgRegIdx + i);
698 excludedKeys->Set(thread, i, excludedKey);
699 }
700 }
701
702 uint32_t numAllKeys = obj->GetNumberOfKeys();
703 JSHandle<TaggedArray> allKeys = factory->NewTaggedArray(numAllKeys);
704 JSObject::GetAllKeys(thread, obj, 0, allKeys);
705
706 JSHandle<JSObject> restObj = factory->NewEmptyJSObject();
707 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
708 for (uint32_t i = 0; i < numAllKeys; i++) {
709 key.Update(allKeys->Get(i));
710 bool isExcludedKey = false;
711 for (uint32_t j = 0; j < numExcludedKeys; j++) {
712 if (JSTaggedValue::Equal(thread, key, JSHandle<JSTaggedValue>(thread, excludedKeys->Get(j)))) {
713 isExcludedKey = true;
714 break;
715 }
716 }
717 if (!isExcludedKey) {
718 PropertyDescriptor desc(thread);
719 bool success = JSObject::GetOwnProperty(thread, obj, key, desc);
720 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
721 if (success && desc.IsEnumerable()) {
722 JSHandle<JSTaggedValue> value = JSObject::GetProperty(thread, obj, key).GetValue();
723 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
724 JSObject::SetProperty(thread, restObj, key, value, true);
725 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
726 }
727 }
728 }
729 return restObj.GetTaggedValue();
730 }
731
ExpDyn(JSThread * thread,JSTaggedValue base,JSTaggedValue exponent)732 JSTaggedValue SlowRuntimeStub::ExpDyn(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent)
733 {
734 INTERPRETER_TRACE(thread, ExpDyn);
735 [[maybe_unused]] EcmaHandleScope handleScope(thread);
736
737 JSTaggedNumber baseNumber = JSTaggedValue::ToNumber(thread, JSHandle<JSTaggedValue>(thread, base));
738 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
739 double doubleBase = baseNumber.GetNumber();
740 JSTaggedNumber exponentNumber = JSTaggedValue::ToNumber(thread, JSHandle<JSTaggedValue>(thread, exponent));
741 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
742 double doubleExponent = exponentNumber.GetNumber();
743 if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) {
744 return JSTaggedValue(base::NAN_VALUE);
745 }
746
747 if (((doubleBase == 0) && ((bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
748 std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
749 base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == (doubleExponent / 2)) { // 2: half
750 if (doubleExponent > 0) {
751 return JSTaggedValue(-0.0);
752 }
753 if (doubleExponent < 0) {
754 return JSTaggedValue(-base::POSITIVE_INFINITY);
755 }
756 }
757 return JSTaggedValue(std::pow(doubleBase, doubleExponent));
758 }
759
IsInDyn(JSThread * thread,JSTaggedValue prop,JSTaggedValue obj)760 JSTaggedValue SlowRuntimeStub::IsInDyn(JSThread *thread, JSTaggedValue prop, JSTaggedValue obj)
761 {
762 INTERPRETER_TRACE(thread, IsInDyn);
763 [[maybe_unused]] EcmaHandleScope handleScope(thread);
764
765 JSHandle<JSTaggedValue> propHandle(thread, prop);
766 JSHandle<JSTaggedValue> objHandle(thread, obj);
767 if (!objHandle->IsECMAObject()) {
768 return ThrowTypeError(thread, "Cannot use 'in' operator in Non-Object");
769 }
770 JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
771 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
772 bool ret = JSTaggedValue::HasProperty(thread, objHandle, propKey);
773 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
774 return JSTaggedValue(ret);
775 }
776
InstanceofDyn(JSThread * thread,JSTaggedValue obj,JSTaggedValue target)777 JSTaggedValue SlowRuntimeStub::InstanceofDyn(JSThread *thread, JSTaggedValue obj, JSTaggedValue target)
778 {
779 INTERPRETER_TRACE(thread, InstanceofDyn);
780 [[maybe_unused]] EcmaHandleScope handleScope(thread);
781
782 JSHandle<JSTaggedValue> objHandle(thread, obj);
783 JSHandle<JSTaggedValue> targetHandle(thread, target);
784 bool ret = JSObject::InstanceOf(thread, objHandle, targetHandle);
785 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
786 return JSTaggedValue(ret);
787 }
788
NewLexicalEnvDyn(JSThread * thread,uint16_t numVars)789 JSTaggedValue SlowRuntimeStub::NewLexicalEnvDyn(JSThread *thread, uint16_t numVars)
790 {
791 INTERPRETER_TRACE(thread, NewlexenvDyn);
792 [[maybe_unused]] EcmaHandleScope handleScope(thread);
793
794 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
795 JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
796
797 JSTaggedValue currentLexenv = thread->GetCurrentLexenv();
798 newEnv->SetParentEnv(thread, currentLexenv);
799 newEnv->SetScopeInfo(thread, JSTaggedValue::Hole());
800 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
801 return newEnv.GetTaggedValue();
802 }
803
NewLexicalEnvWithNameDyn(JSThread * thread,uint16_t numVars,uint16_t scopeId)804 JSTaggedValue SlowRuntimeStub::NewLexicalEnvWithNameDyn(JSThread *thread, uint16_t numVars, uint16_t scopeId)
805 {
806 INTERPRETER_TRACE(thread, NewlexenvwithNameDyn);
807 [[maybe_unused]] EcmaHandleScope handleScope(thread);
808
809 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
810 JSHandle<LexicalEnv> newEnv = factory->NewLexicalEnv(numVars);
811
812 JSTaggedValue currentLexenv = thread->GetCurrentLexenv();
813 newEnv->SetParentEnv(thread, currentLexenv);
814 JSTaggedValue scopeInfo = ScopeInfoExtractor::GenerateScopeInfo(thread, scopeId);
815 newEnv->SetScopeInfo(thread, scopeInfo);
816 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
817 return newEnv.GetTaggedValue();
818 }
819
CreateIterResultObj(JSThread * thread,JSTaggedValue value,JSTaggedValue flag)820 JSTaggedValue SlowRuntimeStub::CreateIterResultObj(JSThread *thread, JSTaggedValue value, JSTaggedValue flag)
821 {
822 INTERPRETER_TRACE(thread, CreateIterResultObj);
823 [[maybe_unused]] EcmaHandleScope handleScope(thread);
824
825 JSHandle<JSTaggedValue> valueHandle(thread, value);
826 ASSERT(flag.IsBoolean());
827 bool done = flag.IsTrue();
828 JSHandle<JSObject> iter = JSIterator::CreateIterResultObject(thread, valueHandle, done);
829 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
830 return iter.GetTaggedValue();
831 }
832
CreateGeneratorObj(JSThread * thread,JSTaggedValue genFunc)833 JSTaggedValue SlowRuntimeStub::CreateGeneratorObj(JSThread *thread, JSTaggedValue genFunc)
834 {
835 INTERPRETER_TRACE(thread, CreateGeneratorObj);
836 [[maybe_unused]] EcmaHandleScope handleScope(thread);
837
838 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
839 JSHandle<JSTaggedValue> generatorFunction(thread, genFunc);
840 JSHandle<JSGeneratorObject> obj = factory->NewJSGeneratorObject(generatorFunction);
841 JSHandle<GeneratorContext> context = factory->NewGeneratorContext();
842 context->SetGeneratorObject(thread, obj.GetTaggedValue());
843
844 // change state to SUSPENDED_START
845 obj->SetGeneratorState(JSGeneratorState::SUSPENDED_START);
846 obj->SetGeneratorContext(thread, context);
847
848 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
849 return obj.GetTaggedValue();
850 }
851
SuspendGenerator(JSThread * thread,JSTaggedValue genObj,JSTaggedValue value)852 JSTaggedValue SlowRuntimeStub::SuspendGenerator(JSThread *thread, JSTaggedValue genObj, JSTaggedValue value)
853 {
854 INTERPRETER_TRACE(thread, SuspendGenerator);
855 [[maybe_unused]] EcmaHandleScope handleScope(thread);
856
857 JSHandle<JSGeneratorObject> generatorObjectHandle(thread, genObj);
858 JSHandle<GeneratorContext> genContextHandle(thread, generatorObjectHandle->GetGeneratorContext());
859 JSHandle<JSTaggedValue> valueHandle(thread, value);
860 // save stack, should copy cur_frame, function execute over will free cur_frame
861 SlowRuntimeHelper::SaveFrameToContext(thread, genContextHandle);
862
863 // change state to SuspendedYield
864 if (generatorObjectHandle->IsExecuting()) {
865 generatorObjectHandle->SetGeneratorState(JSGeneratorState::SUSPENDED_YIELD);
866 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
867 return valueHandle.GetTaggedValue();
868 }
869 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
870 return generatorObjectHandle.GetTaggedValue();
871 }
872
AsyncFunctionAwaitUncaught(JSThread * thread,JSTaggedValue asyncFuncObj,JSTaggedValue value)873 JSTaggedValue SlowRuntimeStub::AsyncFunctionAwaitUncaught(JSThread *thread, JSTaggedValue asyncFuncObj,
874 JSTaggedValue value)
875 {
876 INTERPRETER_TRACE(thread, AsyncFunctionAwaitUncaught);
877 [[maybe_unused]] EcmaHandleScope handleScope(thread);
878
879 JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(thread, asyncFuncObj);
880 JSHandle<JSTaggedValue> valueHandle(thread, value);
881 JSAsyncFunction::AsyncFunctionAwait(thread, asyncFuncObjHandle, valueHandle);
882 JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise());
883
884 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
885 return promise.GetTaggedValue();
886 }
887
AsyncFunctionResolveOrReject(JSThread * thread,JSTaggedValue asyncFuncObj,JSTaggedValue value,bool is_resolve)888 JSTaggedValue SlowRuntimeStub::AsyncFunctionResolveOrReject(JSThread *thread, JSTaggedValue asyncFuncObj,
889 JSTaggedValue value, bool is_resolve)
890 {
891 INTERPRETER_TRACE(thread, AsyncFunctionResolveOrReject);
892 [[maybe_unused]] EcmaHandleScope handleScope(thread);
893
894 JSHandle<JSAsyncFuncObject> asyncFuncObjHandle(thread, asyncFuncObj);
895 JSHandle<JSPromise> promise(thread, asyncFuncObjHandle->GetPromise());
896 JSHandle<JSTaggedValue> valueHandle(thread, value);
897
898 // ActivePromise
899 JSHandle<ResolvingFunctionsRecord> reactions = JSPromise::CreateResolvingFunctions(thread, promise);
900 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
901 JSHandle<JSTaggedValue> thisArg = globalConst->GetHandledUndefined();
902 JSHandle<JSTaggedValue> activeFunc;
903 if (is_resolve) {
904 activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetResolveFunction());
905 } else {
906 activeFunc = JSHandle<JSTaggedValue>(thread, reactions->GetRejectFunction());
907 }
908 InternalCallParams *arguments = thread->GetInternalCallParams();
909 arguments->MakeArgv(valueHandle);
910 [[maybe_unused]] JSTaggedValue res = JSFunction::Call(thread, activeFunc, thisArg, 1, arguments->GetArgv());
911
912 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
913 return promise.GetTaggedValue();
914 }
915
NewObjSpreadDyn(JSThread * thread,JSTaggedValue func,JSTaggedValue newTarget,JSTaggedValue array)916 JSTaggedValue SlowRuntimeStub::NewObjSpreadDyn(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
917 JSTaggedValue array)
918 {
919 INTERPRETER_TRACE(thread, NewobjspreadDyn);
920 [[maybe_unused]] EcmaHandleScope handleScope(thread);
921
922 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
923 JSHandle<JSTaggedValue> funcHandle(thread, func);
924 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
925 JSHandle<JSTaggedValue> jsArray(thread, array);
926 if (!jsArray->IsJSArray()) {
927 return ThrowTypeError(thread, "Cannot Newobjspread");
928 }
929
930 uint32_t length = JSHandle<JSArray>::Cast(jsArray)->GetArrayLength();
931 JSHandle<TaggedArray> argsArray = factory->NewTaggedArray(length);
932 for (uint32_t i = 0; i < length; ++i) {
933 auto prop = JSTaggedValue::GetProperty(thread, jsArray, i).GetValue();
934 argsArray->Set(thread, i, prop);
935 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
936 }
937 InternalCallParams *arguments = thread->GetInternalCallParams();
938 arguments->MakeArgList(*argsArray);
939 auto tagged = SlowRuntimeHelper::NewObject(thread, funcHandle, newTargetHandle, length, arguments->GetArgv());
940 return tagged;
941 }
942
ThrowUndefinedIfHole(JSThread * thread,JSTaggedValue obj)943 void SlowRuntimeStub::ThrowUndefinedIfHole(JSThread *thread, JSTaggedValue obj)
944 {
945 INTERPRETER_TRACE(thread, ThrowUndefinedIfHole);
946 [[maybe_unused]] EcmaHandleScope handleScope(thread);
947
948 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
949 JSHandle<EcmaString> name(thread, obj);
950 JSHandle<EcmaString> info = factory->NewFromCanBeCompressString(" is not initialized");
951
952 JSHandle<EcmaString> msg = factory->ConcatFromString(info, name);
953 THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg).GetTaggedValue());
954 }
955
ThrowIfSuperNotCorrectCall(JSThread * thread,uint16_t index,JSTaggedValue thisValue)956 JSTaggedValue SlowRuntimeStub::ThrowIfSuperNotCorrectCall(JSThread *thread, uint16_t index, JSTaggedValue thisValue)
957 {
958 INTERPRETER_TRACE(thread, ThrowIfSuperNotCorrectCall);
959 [[maybe_unused]] EcmaHandleScope handleScope(thread);
960
961 if (index == 0 && (thisValue.IsUndefined() || thisValue.IsHole())) {
962 return ThrowReferenceError(thread, JSTaggedValue::Undefined(), "sub-class must call super before use 'this'");
963 }
964 if (index == 1 && !thisValue.IsUndefined() && !thisValue.IsHole()) {
965 return ThrowReferenceError(thread, JSTaggedValue::Undefined(), "super() forbidden re-bind 'this'");
966 }
967 return JSTaggedValue::True();
968 }
969
ThrowIfNotObject(JSThread * thread)970 void SlowRuntimeStub::ThrowIfNotObject(JSThread *thread)
971 {
972 INTERPRETER_TRACE(thread, ThrowIfNotObject);
973 [[maybe_unused]] EcmaHandleScope handleScope(thread);
974
975 THROW_TYPE_ERROR(thread, "Inner return result is not object");
976 }
977
ThrowThrowNotExists(JSThread * thread)978 void SlowRuntimeStub::ThrowThrowNotExists(JSThread *thread)
979 {
980 INTERPRETER_TRACE(thread, ThrowThrowNotExists);
981 [[maybe_unused]] EcmaHandleScope handleScope(thread);
982
983 THROW_TYPE_ERROR(thread, "Throw method is not defined");
984 }
985
ThrowPatternNonCoercible(JSThread * thread)986 void SlowRuntimeStub::ThrowPatternNonCoercible(JSThread *thread)
987 {
988 INTERPRETER_TRACE(thread, ThrowPatternNonCoercible);
989 [[maybe_unused]] EcmaHandleScope handleScope(thread);
990
991 JSHandle<EcmaString> msg(thread->GlobalConstants()->GetHandledObjNotCoercibleString());
992 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
993 THROW_NEW_ERROR_AND_RETURN(thread, factory->NewJSError(base::ErrorType::TYPE_ERROR, msg).GetTaggedValue());
994 }
995
StOwnByName(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,JSTaggedValue value)996 JSTaggedValue SlowRuntimeStub::StOwnByName(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop, JSTaggedValue value)
997 {
998 INTERPRETER_TRACE(thread, StOwnByNameDyn);
999 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1000
1001 JSHandle<JSTaggedValue> objHandle(thread, obj);
1002 JSHandle<JSTaggedValue> propHandle(thread, prop);
1003 JSHandle<JSTaggedValue> valueHandle(thread, value);
1004 ASSERT(propHandle->IsStringOrSymbol());
1005
1006 // property in class is non-enumerable
1007 bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1008
1009 PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1010 bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propHandle, desc);
1011 if (!ret) {
1012 return ThrowTypeError(thread, "SetOwnByName failed");
1013 }
1014 return JSTaggedValue::True();
1015 }
1016
StOwnByNameWithNameSet(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,JSTaggedValue value)1017 JSTaggedValue SlowRuntimeStub::StOwnByNameWithNameSet(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop,
1018 JSTaggedValue value)
1019 {
1020 INTERPRETER_TRACE(thread, StOwnByNameDyn);
1021 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1022
1023 JSHandle<JSTaggedValue> objHandle(thread, obj);
1024 JSHandle<JSTaggedValue> propHandle(thread, prop);
1025 JSHandle<JSTaggedValue> valueHandle(thread, value);
1026 ASSERT(propHandle->IsStringOrSymbol());
1027
1028 JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
1029
1030 // property in class is non-enumerable
1031 bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1032
1033 PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1034 bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propHandle, desc);
1035 if (!ret) {
1036 return ThrowTypeError(thread, "SetOwnByNameWithNameSet failed");
1037 }
1038 JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(valueHandle), propKey,
1039 JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1040 return JSTaggedValue::True();
1041 }
1042
StOwnByIndex(JSThread * thread,JSTaggedValue obj,uint32_t idx,JSTaggedValue value)1043 JSTaggedValue SlowRuntimeStub::StOwnByIndex(JSThread *thread, JSTaggedValue obj, uint32_t idx, JSTaggedValue value)
1044 {
1045 INTERPRETER_TRACE(thread, StOwnByIdDyn);
1046 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1047
1048 JSHandle<JSTaggedValue> objHandle(thread, obj);
1049 JSHandle<JSTaggedValue> idxHandle(thread, JSTaggedValue(idx));
1050 JSHandle<JSTaggedValue> valueHandle(thread, value);
1051
1052 // property in class is non-enumerable
1053 bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1054
1055 PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1056 bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, idxHandle, desc);
1057 if (!ret) {
1058 return ThrowTypeError(thread, "SetOwnByIndex failed");
1059 }
1060 return JSTaggedValue::True();
1061 }
1062
StOwnByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue key,JSTaggedValue value)1063 JSTaggedValue SlowRuntimeStub::StOwnByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key, JSTaggedValue value)
1064 {
1065 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1066
1067 INTERPRETER_TRACE(thread, StOwnByValueDyn);
1068 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1069 JSHandle<JSTaggedValue> objHandle(thread, obj);
1070 JSHandle<JSTaggedValue> keyHandle(thread, key);
1071 JSHandle<JSTaggedValue> valueHandle(thread, value);
1072
1073 if (objHandle->IsClassConstructor() &&
1074 JSTaggedValue::SameValue(keyHandle, globalConst->GetHandledPrototypeString())) {
1075 return ThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
1076 }
1077
1078 // property in class is non-enumerable
1079 bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1080
1081 PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1082 JSMutableHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, keyHandle));
1083 bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propKey, desc);
1084 if (!ret) {
1085 return ThrowTypeError(thread, "StOwnByValue failed");
1086 }
1087 return JSTaggedValue::True();
1088 }
1089
StOwnByValueWithNameSet(JSThread * thread,JSTaggedValue obj,JSTaggedValue key,JSTaggedValue value)1090 JSTaggedValue SlowRuntimeStub::StOwnByValueWithNameSet(JSThread *thread, JSTaggedValue obj, JSTaggedValue key,
1091 JSTaggedValue value)
1092 {
1093 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1094 INTERPRETER_TRACE(thread, StOwnByValueDyn);
1095 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1096 JSHandle<JSTaggedValue> objHandle(thread, obj);
1097 JSHandle<JSTaggedValue> keyHandle(thread, key);
1098 JSHandle<JSTaggedValue> valueHandle(thread, value);
1099
1100 if (objHandle->IsClassConstructor() &&
1101 JSTaggedValue::SameValue(keyHandle, globalConst->GetHandledPrototypeString())) {
1102 return ThrowTypeError(thread, "In a class, static property named 'prototype' throw a TypeError");
1103 }
1104
1105 // property in class is non-enumerable
1106 bool enumerable = !(objHandle->IsClassPrototype() || objHandle->IsClassConstructor());
1107
1108 PropertyDescriptor desc(thread, valueHandle, true, enumerable, true);
1109 JSMutableHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, keyHandle));
1110 bool ret = JSTaggedValue::DefineOwnProperty(thread, objHandle, propKey, desc);
1111 if (!ret) {
1112 return ThrowTypeError(thread, "StOwnByValueWithNameSet failed");
1113 }
1114 if (valueHandle->IsJSFunction()) {
1115 if (propKey->IsNumber()) {
1116 propKey.Update(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()).GetTaggedValue());
1117 }
1118 JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(valueHandle), propKey,
1119 JSHandle<JSTaggedValue>(thread, JSTaggedValue::Undefined()));
1120 }
1121 return JSTaggedValue::True();
1122 }
1123
CreateEmptyArray(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)1124 JSTaggedValue SlowRuntimeStub::CreateEmptyArray(JSThread *thread, ObjectFactory *factory, JSHandle<GlobalEnv> globalEnv)
1125 {
1126 INTERPRETER_TRACE(thread, CreateEmptyArray);
1127 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1128
1129 JSHandle<JSFunction> builtinObj(globalEnv->GetArrayFunction());
1130 JSHandle<JSObject> arr = factory->NewJSObjectByConstructor(builtinObj, JSHandle<JSTaggedValue>(builtinObj));
1131 return arr.GetTaggedValue();
1132 }
1133
CreateEmptyObject(JSThread * thread,ObjectFactory * factory,JSHandle<GlobalEnv> globalEnv)1134 JSTaggedValue SlowRuntimeStub::CreateEmptyObject(JSThread *thread, ObjectFactory *factory,
1135 JSHandle<GlobalEnv> globalEnv)
1136 {
1137 INTERPRETER_TRACE(thread, CreateEmptyObject);
1138 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1139
1140 JSHandle<JSFunction> builtinObj(globalEnv->GetObjectFunction());
1141 JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(builtinObj, JSHandle<JSTaggedValue>(builtinObj));
1142 return obj.GetTaggedValue();
1143 }
1144
CreateObjectWithBuffer(JSThread * thread,ObjectFactory * factory,JSObject * literal)1145 JSTaggedValue SlowRuntimeStub::CreateObjectWithBuffer(JSThread *thread, ObjectFactory *factory, JSObject *literal)
1146 {
1147 INTERPRETER_TRACE(thread, CreateObjectWithBuffer);
1148 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1149
1150 JSHandle<JSObject> obj(thread, literal);
1151 JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(obj);
1152 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1153
1154 return objLiteral.GetTaggedValue();
1155 }
1156
CreateObjectHavingMethod(JSThread * thread,ObjectFactory * factory,JSObject * literal,JSTaggedValue env,ConstantPool * constpool)1157 JSTaggedValue SlowRuntimeStub::CreateObjectHavingMethod(JSThread *thread, ObjectFactory *factory, JSObject *literal,
1158 JSTaggedValue env, ConstantPool *constpool)
1159 {
1160 INTERPRETER_TRACE(thread, CreateObjectHavingMethod);
1161 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1162
1163 JSHandle<JSObject> obj(thread, literal);
1164 JSHandle<JSObject> objLiteral = factory->CloneObjectLiteral(
1165 obj, JSHandle<JSTaggedValue>(thread, env), JSHandle<JSTaggedValue>(thread, JSTaggedValue(constpool)));
1166 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1167
1168 return objLiteral.GetTaggedValue();
1169 }
1170
SetObjectWithProto(JSThread * thread,JSTaggedValue proto,JSTaggedValue obj)1171 JSTaggedValue SlowRuntimeStub::SetObjectWithProto(JSThread *thread, JSTaggedValue proto, JSTaggedValue obj)
1172 {
1173 INTERPRETER_TRACE(thread, SetObjectWithProto);
1174 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1175
1176 if (!proto.IsECMAObject() && !proto.IsNull()) {
1177 return JSTaggedValue::False();
1178 }
1179 JSHandle<JSTaggedValue> protoHandle(thread, proto);
1180 JSHandle<JSObject> objHandle(thread, obj);
1181 JSObject::SetPrototype(thread, objHandle, protoHandle);
1182 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1183 return JSTaggedValue::True();
1184 }
1185
IterNext(JSThread * thread,JSTaggedValue iter)1186 JSTaggedValue SlowRuntimeStub::IterNext(JSThread *thread, JSTaggedValue iter)
1187 {
1188 INTERPRETER_TRACE(thread, IterNext);
1189 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1190
1191 JSHandle<JSTaggedValue> iterHandle(thread, iter);
1192 JSHandle<JSObject> resultObj = JSIterator::IteratorNext(thread, iterHandle);
1193 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1194 return resultObj.GetTaggedValue();
1195 }
1196
CloseIterator(JSThread * thread,JSTaggedValue iter)1197 JSTaggedValue SlowRuntimeStub::CloseIterator(JSThread *thread, JSTaggedValue iter)
1198 {
1199 INTERPRETER_TRACE(thread, CloseIterator);
1200 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1201
1202 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1203 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
1204
1205 JSHandle<JSTaggedValue> iterHandle(thread, iter);
1206 JSHandle<JSTaggedValue> record;
1207 if (thread->HasPendingException()) {
1208 record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(
1209 CompletionRecordType::THROW, JSHandle<JSTaggedValue>(thread, thread->GetException())));
1210 } else {
1211 JSHandle<JSTaggedValue> undefinedVal = globalConst->GetHandledUndefined();
1212 record = JSHandle<JSTaggedValue>(factory->NewCompletionRecord(CompletionRecordType::NORMAL, undefinedVal));
1213 }
1214 JSHandle<JSTaggedValue> result = JSIterator::IteratorClose(thread, iterHandle, record);
1215 if (result->IsCompletionRecord()) {
1216 return CompletionRecord::Cast(result->GetTaggedObject())->GetValue();
1217 }
1218 return result.GetTaggedValue();
1219 }
1220
ImportModule(JSThread * thread,JSTaggedValue moduleName)1221 JSTaggedValue SlowRuntimeStub::ImportModule([[maybe_unused]] JSThread *thread,
1222 [[maybe_unused]] JSTaggedValue moduleName)
1223 {
1224 INTERPRETER_TRACE(thread, ImportModule);
1225 [[maybe_unused]] EcmaHandleScope scope(thread);
1226 JSHandle<JSTaggedValue> name(thread, moduleName);
1227 JSHandle<JSTaggedValue> module = thread->GetEcmaVM()->GetModuleByName(name);
1228 return module.GetTaggedValue(); // return moduleRef
1229 }
1230
StModuleVar(JSThread * thread,JSTaggedValue exportName,JSTaggedValue exportObj)1231 void SlowRuntimeStub::StModuleVar([[maybe_unused]] JSThread *thread, [[maybe_unused]] JSTaggedValue exportName,
1232 [[maybe_unused]] JSTaggedValue exportObj)
1233 {
1234 INTERPRETER_TRACE(thread, StModuleVar);
1235 [[maybe_unused]] EcmaHandleScope scope(thread);
1236 JSHandle<JSTaggedValue> name(thread, exportName);
1237 JSHandle<JSTaggedValue> value(thread, exportObj);
1238 thread->GetEcmaVM()->GetModuleManager()->AddModuleItem(thread, name, value);
1239 }
1240
CopyModule(JSThread * thread,JSTaggedValue srcModule)1241 void SlowRuntimeStub::CopyModule(JSThread *thread, JSTaggedValue srcModule)
1242 {
1243 INTERPRETER_TRACE(thread, CopyModule);
1244 [[maybe_unused]] EcmaHandleScope scope(thread);
1245 JSHandle<JSTaggedValue> srcModuleObj(thread, srcModule);
1246 thread->GetEcmaVM()->GetModuleManager()->CopyModule(thread, srcModuleObj);
1247 }
1248
LdModvarByName(JSThread * thread,JSTaggedValue moduleObj,JSTaggedValue itemName)1249 JSTaggedValue SlowRuntimeStub::LdModvarByName([[maybe_unused]] JSThread *thread,
1250 [[maybe_unused]] JSTaggedValue moduleObj,
1251 [[maybe_unused]] JSTaggedValue itemName)
1252 {
1253 INTERPRETER_TRACE(thread, LdModvarByName);
1254 [[maybe_unused]] EcmaHandleScope scope(thread);
1255 JSHandle<JSTaggedValue> module(thread, moduleObj);
1256 JSHandle<JSTaggedValue> item(thread, itemName);
1257 JSHandle<JSTaggedValue> moduleVar = thread->GetEcmaVM()->GetModuleManager()->GetModuleItem(thread, module, item);
1258 return moduleVar.GetTaggedValue();
1259 }
1260
CreateRegExpWithLiteral(JSThread * thread,JSTaggedValue pattern,uint8_t flags)1261 JSTaggedValue SlowRuntimeStub::CreateRegExpWithLiteral(JSThread *thread, JSTaggedValue pattern, uint8_t flags)
1262 {
1263 INTERPRETER_TRACE(thread, CreateRegExpWithLiteral);
1264 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1265
1266 JSHandle<JSTaggedValue> patternHandle(thread, pattern);
1267 JSHandle<JSTaggedValue> flagsHandle(thread, JSTaggedValue(flags));
1268
1269 return builtins::BuiltinsRegExp::RegExpCreate(thread, patternHandle, flagsHandle);
1270 }
1271
CreateArrayWithBuffer(JSThread * thread,ObjectFactory * factory,JSArray * literal)1272 JSTaggedValue SlowRuntimeStub::CreateArrayWithBuffer(JSThread *thread, ObjectFactory *factory, JSArray *literal)
1273 {
1274 INTERPRETER_TRACE(thread, CreateArrayWithBuffer);
1275 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1276
1277 JSHandle<JSArray> array(thread, literal);
1278 JSHandle<JSArray> arrLiteral = factory->CloneArrayLiteral(array);
1279 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1280
1281 return arrLiteral.GetTaggedValue();
1282 }
1283
GetTemplateObject(JSThread * thread,JSTaggedValue literal)1284 JSTaggedValue SlowRuntimeStub::GetTemplateObject(JSThread *thread, JSTaggedValue literal)
1285 {
1286 INTERPRETER_TRACE(thread, GetTemplateObject);
1287 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1288
1289 JSHandle<JSTaggedValue> templateLiteral(thread, literal);
1290 JSHandle<JSTaggedValue> templateObj = TemplateString::GetTemplateObject(thread, templateLiteral);
1291 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1292 return templateObj.GetTaggedValue();
1293 }
1294
GetNextPropName(JSThread * thread,JSTaggedValue iter)1295 JSTaggedValue SlowRuntimeStub::GetNextPropName(JSThread *thread, JSTaggedValue iter)
1296 {
1297 INTERPRETER_TRACE(thread, GetNextPropName);
1298 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1299
1300 JSHandle<JSTaggedValue> iterator(thread, iter);
1301 ASSERT(iterator->IsForinIterator());
1302 std::pair<JSTaggedValue, bool> res =
1303 JSForInIterator::NextInternal(thread, JSHandle<JSForInIterator>::Cast(iterator));
1304 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1305 return res.first;
1306 }
1307
CopyDataProperties(JSThread * thread,JSTaggedValue dst,JSTaggedValue src)1308 JSTaggedValue SlowRuntimeStub::CopyDataProperties(JSThread *thread, JSTaggedValue dst, JSTaggedValue src)
1309 {
1310 INTERPRETER_TRACE(thread, CopyDataProperties);
1311 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1312
1313 JSHandle<JSTaggedValue> dstHandle(thread, dst);
1314 JSHandle<JSTaggedValue> srcHandle(thread, src);
1315 if (!srcHandle->IsNull() && !srcHandle->IsUndefined()) {
1316 JSHandle<TaggedArray> keys = JSTaggedValue::GetOwnPropertyKeys(thread, srcHandle);
1317 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1318
1319 JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined());
1320 uint32_t keysLen = keys->GetLength();
1321 for (uint32_t i = 0; i < keysLen; i++) {
1322 PropertyDescriptor desc(thread);
1323 key.Update(keys->Get(i));
1324 bool success = JSTaggedValue::GetOwnProperty(thread, srcHandle, key, desc);
1325 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1326
1327 if (success && desc.IsEnumerable()) {
1328 JSTaggedValue::DefineOwnProperty(thread, dstHandle, key, desc);
1329 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1330 }
1331 }
1332 }
1333 return dstHandle.GetTaggedValue();
1334 }
1335
GetIteratorNext(JSThread * thread,JSTaggedValue obj,JSTaggedValue method)1336 JSTaggedValue SlowRuntimeStub::GetIteratorNext(JSThread *thread, JSTaggedValue obj, JSTaggedValue method)
1337 {
1338 INTERPRETER_TRACE(thread, GetIteratorNext);
1339 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1340
1341 JSHandle<JSTaggedValue> iter(thread, obj);
1342 JSHandle<JSTaggedValue> next(thread, method);
1343
1344 ASSERT(next->IsCallable());
1345 JSTaggedValue ret = JSFunction::Call(thread, next, iter, 0, nullptr);
1346 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1347 if (!ret.IsECMAObject()) {
1348 return ThrowTypeError(thread, "the Iterator is not an ecmaobject.");
1349 }
1350 return ret;
1351 }
1352
GetUnmapedArgs(JSThread * thread,JSTaggedType * sp,uint32_t actualNumArgs,uint32_t startIdx)1353 JSTaggedValue SlowRuntimeStub::GetUnmapedArgs(JSThread *thread, JSTaggedType *sp, uint32_t actualNumArgs,
1354 uint32_t startIdx)
1355 {
1356 INTERPRETER_TRACE(thread, GetUnmapedArgs);
1357 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1358
1359 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1360 JSHandle<GlobalEnv> globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
1361 JSHandle<TaggedArray> argumentsList = factory->NewTaggedArray(actualNumArgs);
1362 for (uint32_t i = 0; i < actualNumArgs; ++i) {
1363 argumentsList->Set(thread, i,
1364 JSTaggedValue(sp[startIdx + i])); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1365 }
1366 // 1. Let len be the number of elements in argumentsList
1367 int32_t len = argumentsList->GetLength();
1368 // 2. Let obj be ObjectCreate(%ObjectPrototype%, «[[ParameterMap]]»).
1369 // 3. Set obj’s [[ParameterMap]] internal slot to undefined.
1370 JSHandle<JSArguments> obj = factory->NewJSArguments();
1371 // 4. Perform DefinePropertyOrThrow(obj, "length", PropertyDescriptor{[[Value]]: len, [[Writable]]: true,
1372 // [[Enumerable]]: false, [[Configurable]]: true}).
1373 obj->SetPropertyInlinedProps(thread, JSArguments::LENGTH_INLINE_PROPERTY_INDEX, JSTaggedValue(len));
1374 // 5. Let index be 0.
1375 // 6. Repeat while index < len,
1376 // a. Let val be argumentsList[index].
1377 // b. Perform CreateDataProperty(obj, ToString(index), val).
1378 // c. Let index be index + 1
1379 obj->SetElements(thread, argumentsList.GetTaggedValue());
1380 // 7. Perform DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor
1381 // {[[Value]]:%ArrayProto_values%,
1382 // [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true}).
1383 obj->SetPropertyInlinedProps(thread, JSArguments::ITERATOR_INLINE_PROPERTY_INDEX,
1384 globalEnv->GetArrayProtoValuesFunction().GetTaggedValue());
1385 // 8. Perform DefinePropertyOrThrow(obj, "caller", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
1386 // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
1387 JSHandle<JSTaggedValue> throwFunction = globalEnv->GetThrowTypeError();
1388 JSHandle<AccessorData> accessor = factory->NewAccessorData();
1389 accessor->SetGetter(thread, throwFunction);
1390 accessor->SetSetter(thread, throwFunction);
1391 obj->SetPropertyInlinedProps(thread, JSArguments::CALLER_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
1392 // 9. Perform DefinePropertyOrThrow(obj, "callee", PropertyDescriptor {[[Get]]: %ThrowTypeError%,
1393 // [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false}).
1394 accessor = factory->NewAccessorData();
1395 accessor->SetGetter(thread, throwFunction);
1396 accessor->SetSetter(thread, throwFunction);
1397 obj->SetPropertyInlinedProps(thread, JSArguments::CALLEE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
1398 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1399 // 11. Return obj
1400 return obj.GetTaggedValue();
1401 }
1402
CopyRestArgs(JSThread * thread,JSTaggedType * sp,uint32_t restNumArgs,uint32_t startIdx)1403 JSTaggedValue SlowRuntimeStub::CopyRestArgs(JSThread *thread, JSTaggedType *sp, uint32_t restNumArgs, uint32_t startIdx)
1404 {
1405 INTERPRETER_TRACE(thread, Copyrestargs);
1406 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1407
1408 JSHandle<JSTaggedValue> restArray = JSArray::ArrayCreate(thread, JSTaggedNumber(restNumArgs));
1409
1410 JSMutableHandle<JSTaggedValue> element(thread, JSTaggedValue::Undefined());
1411 for (uint32_t i = 0; i < restNumArgs; ++i) {
1412 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1413 element.Update(JSTaggedValue(sp[startIdx + i]));
1414 JSObject::SetProperty(thread, restArray, i, element, true);
1415 }
1416 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1417 return restArray.GetTaggedValue();
1418 }
1419
GetIterator(JSThread * thread,JSTaggedValue obj)1420 JSTaggedValue SlowRuntimeStub::GetIterator(JSThread *thread, JSTaggedValue obj)
1421 {
1422 INTERPRETER_TRACE(thread, GetIterator);
1423 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1424 EcmaVM *vm = thread->GetEcmaVM();
1425 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1426 JSHandle<JSTaggedValue> objHandle(thread, obj);
1427 JSHandle<JSTaggedValue> valuesFunc =
1428 JSTaggedValue::GetProperty(thread, objHandle, env->GetIteratorSymbol()).GetValue();
1429 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1430 if (!valuesFunc->IsCallable()) {
1431 return valuesFunc.GetTaggedValue();
1432 }
1433 JSHandle<JSTaggedValue> newTarget(thread, JSTaggedValue::Undefined());
1434 InternalCallParams *params = thread->GetInternalCallParams();
1435 params->MakeEmptyArgv();
1436 JSTaggedValue res = InvokeJsFunction(thread, JSHandle<JSFunction>(valuesFunc), objHandle, newTarget, params);
1437
1438 return res;
1439 }
1440
DefineGetterSetterByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,JSTaggedValue getter,JSTaggedValue setter,bool flag)1441 JSTaggedValue SlowRuntimeStub::DefineGetterSetterByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop,
1442 JSTaggedValue getter, JSTaggedValue setter, bool flag)
1443 {
1444 INTERPRETER_TRACE(thread, DefineGetterSetterByValue);
1445 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1446 JSHandle<JSObject> objHandle(thread, obj);
1447 JSHandle<JSTaggedValue> propHandle(thread, prop);
1448
1449 JSHandle<JSTaggedValue> getterHandle(thread, getter);
1450 JSHandle<JSTaggedValue> setterHandle(thread, setter);
1451 JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, propHandle);
1452
1453 auto globalConst = thread->GlobalConstants();
1454 if (objHandle.GetTaggedValue().IsClassConstructor() &&
1455 JSTaggedValue::SameValue(propKey, globalConst->GetHandledPrototypeString())) {
1456 return ThrowTypeError(
1457 thread,
1458 "In a class, computed property names for static getter that are named 'prototype' throw a TypeError");
1459 }
1460
1461 if (flag) {
1462 if (!getterHandle->IsUndefined()) {
1463 if (propKey->IsNumber()) {
1464 propKey =
1465 JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
1466 }
1467 JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(getterHandle), propKey,
1468 JSHandle<JSTaggedValue>(thread, globalConst->GetGetString()));
1469 }
1470
1471 if (!setterHandle->IsUndefined()) {
1472 if (propKey->IsNumber()) {
1473 propKey =
1474 JSHandle<JSTaggedValue>::Cast(base::NumberHelper::NumberToString(thread, propKey.GetTaggedValue()));
1475 }
1476 JSFunctionBase::SetFunctionName(thread, JSHandle<JSFunctionBase>::Cast(setterHandle), propKey,
1477 JSHandle<JSTaggedValue>(thread, globalConst->GetSetString()));
1478 }
1479 }
1480
1481 // set accessor
1482 bool enumerable =
1483 !(objHandle.GetTaggedValue().IsClassPrototype() || objHandle.GetTaggedValue().IsClassConstructor());
1484 PropertyDescriptor desc(thread, true, enumerable, true);
1485 if (!getterHandle->IsUndefined()) {
1486 JSHandle<JSFunction>::Cast(getterHandle)->SetFunctionKind(FunctionKind::GETTER_FUNCTION);
1487 desc.SetGetter(getterHandle);
1488 }
1489 if (!setterHandle->IsUndefined()) {
1490 JSHandle<JSFunction>::Cast(setterHandle)->SetFunctionKind(FunctionKind::SETTER_FUNCTION);
1491 desc.SetSetter(setterHandle);
1492 }
1493 JSObject::DefineOwnProperty(thread, objHandle, propKey, desc);
1494
1495 return objHandle.GetTaggedValue();
1496 }
1497
LdObjByIndex(JSThread * thread,JSTaggedValue obj,uint32_t idx,bool callGetter,JSTaggedValue receiver)1498 JSTaggedValue SlowRuntimeStub::LdObjByIndex(JSThread *thread, JSTaggedValue obj, uint32_t idx, bool callGetter,
1499 JSTaggedValue receiver)
1500 {
1501 INTERPRETER_TRACE(thread, LdObjByIndexDyn);
1502 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1503
1504 JSTaggedValue res;
1505 JSHandle<JSTaggedValue> objHandle(thread, obj);
1506 if (callGetter) {
1507 res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), objHandle);
1508 } else {
1509 res = JSTaggedValue::GetProperty(thread, objHandle, idx).GetValue().GetTaggedValue();
1510 }
1511 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1512 return res;
1513 }
1514
StObjByIndex(JSThread * thread,JSTaggedValue obj,uint32_t idx,JSTaggedValue value)1515 JSTaggedValue SlowRuntimeStub::StObjByIndex(JSThread *thread, JSTaggedValue obj, uint32_t idx, JSTaggedValue value)
1516 {
1517 INTERPRETER_TRACE(thread, StObjByIndexDyn);
1518 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1519
1520 JSTaggedValue::SetProperty(thread, JSHandle<JSTaggedValue>(thread, obj), idx,
1521 JSHandle<JSTaggedValue>(thread, value), true);
1522 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1523 return JSTaggedValue::True();
1524 }
1525
LdObjByName(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,bool callGetter,JSTaggedValue receiver)1526 JSTaggedValue SlowRuntimeStub::LdObjByName(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop, bool callGetter,
1527 JSTaggedValue receiver)
1528 {
1529 INTERPRETER_TRACE(thread, LdObjByNameDyn);
1530 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1531
1532 JSHandle<JSTaggedValue> objHandle(thread, obj);
1533 JSTaggedValue res;
1534 if (callGetter) {
1535 res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), objHandle);
1536 } else {
1537 JSHandle<JSTaggedValue> propHandle(thread, prop);
1538 res = JSTaggedValue::GetProperty(thread, objHandle, propHandle).GetValue().GetTaggedValue();
1539 }
1540 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1541 return res;
1542 }
1543
StObjByName(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,JSTaggedValue value)1544 JSTaggedValue SlowRuntimeStub::StObjByName(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop, JSTaggedValue value)
1545 {
1546 INTERPRETER_TRACE(thread, StObjByNameDyn);
1547 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1548
1549 JSHandle<JSTaggedValue> objHandle(thread, obj);
1550 JSHandle<JSTaggedValue> propHandle(thread, prop);
1551 JSHandle<JSTaggedValue> valueHandle(thread, value);
1552 JSTaggedValue::SetProperty(thread, objHandle, propHandle, valueHandle, true);
1553 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1554 return JSTaggedValue::True();
1555 }
1556
LdObjByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,bool callGetter,JSTaggedValue receiver)1557 JSTaggedValue SlowRuntimeStub::LdObjByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop, bool callGetter,
1558 JSTaggedValue receiver)
1559 {
1560 INTERPRETER_TRACE(thread, LdObjByValueDyn);
1561 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1562
1563 JSHandle<JSTaggedValue> objHandle(thread, obj);
1564 JSTaggedValue res;
1565 if (callGetter) {
1566 res = JSObject::CallGetter(thread, AccessorData::Cast(receiver.GetTaggedObject()), objHandle);
1567 } else {
1568 JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, JSHandle<JSTaggedValue>(thread, prop));
1569 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1570 res = JSTaggedValue::GetProperty(thread, objHandle, propKey).GetValue().GetTaggedValue();
1571 }
1572 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1573 return res;
1574 }
1575
StObjByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue prop,JSTaggedValue value)1576 JSTaggedValue SlowRuntimeStub::StObjByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue prop,
1577 JSTaggedValue value)
1578 {
1579 INTERPRETER_TRACE(thread, StObjByValueDyn);
1580 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1581
1582 JSHandle<JSTaggedValue> objHandle(thread, obj);
1583 JSHandle<JSTaggedValue> propHandle(thread, prop);
1584 JSHandle<JSTaggedValue> valueHandle(thread, value);
1585 JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, propHandle));
1586
1587 // strict mode is true
1588 JSTaggedValue::SetProperty(thread, objHandle, propKey, valueHandle, true);
1589 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1590 return JSTaggedValue::True();
1591 }
1592
TryLdGlobalByName(JSThread * thread,JSTaggedValue global,JSTaggedValue prop)1593 JSTaggedValue SlowRuntimeStub::TryLdGlobalByName(JSThread *thread, JSTaggedValue global, JSTaggedValue prop)
1594 {
1595 INTERPRETER_TRACE(thread, Trygetobjprop);
1596 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1597
1598 JSHandle<JSTaggedValue> obj(thread, global.GetTaggedObject()->GetClass()->GetPrototype());
1599 JSHandle<JSTaggedValue> propHandle(thread, prop);
1600 OperationResult res = JSTaggedValue::GetProperty(thread, obj, propHandle);
1601 if (!res.GetPropertyMetaData().IsFound()) {
1602 return ThrowReferenceError(thread, prop, " is not defined");
1603 }
1604 return res.GetValue().GetTaggedValue();
1605 }
1606
TryStGlobalByName(JSThread * thread,JSTaggedValue prop)1607 JSTaggedValue SlowRuntimeStub::TryStGlobalByName(JSThread *thread, JSTaggedValue prop)
1608 {
1609 INTERPRETER_TRACE(thread, TryStGlobalByName);
1610 // If fast path is fail, not need slow path, just throw error.
1611 return ThrowReferenceError(thread, prop, " is not defined");
1612 }
1613
LdGlobalVar(JSThread * thread,JSTaggedValue global,JSTaggedValue prop)1614 JSTaggedValue SlowRuntimeStub::LdGlobalVar(JSThread *thread, JSTaggedValue global, JSTaggedValue prop)
1615 {
1616 INTERPRETER_TRACE(thread, LdGlobalVar);
1617 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1618
1619 JSHandle<JSTaggedValue> objHandle(thread, global.GetTaggedObject()->GetClass()->GetPrototype());
1620 JSHandle<JSTaggedValue> propHandle(thread, prop);
1621 OperationResult res = JSTaggedValue::GetProperty(thread, objHandle, propHandle);
1622 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1623 return res.GetValue().GetTaggedValue();
1624 }
1625
StGlobalVar(JSThread * thread,JSTaggedValue prop,JSTaggedValue value)1626 JSTaggedValue SlowRuntimeStub::StGlobalVar(JSThread *thread, JSTaggedValue prop, JSTaggedValue value)
1627 {
1628 INTERPRETER_TRACE(thread, StGlobalVar);
1629 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1630
1631 JSHandle<JSTaggedValue> global(thread, thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject());
1632 JSHandle<JSTaggedValue> propHandle(thread, prop);
1633 JSHandle<JSTaggedValue> valueHandle(thread, value);
1634
1635 JSObject::GlobalSetProperty(thread, propHandle, valueHandle, true);
1636 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1637 return JSTaggedValue::True();
1638 }
1639
TryUpdateGlobalRecord(JSThread * thread,JSTaggedValue prop,JSTaggedValue value)1640 JSTaggedValue SlowRuntimeStub::TryUpdateGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value)
1641 {
1642 INTERPRETER_TRACE(thread, TryUpdateGlobalRecord);
1643 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1644
1645 EcmaVM *vm = thread->GetEcmaVM();
1646 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1647 GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1648 int entry = dict->FindEntry(prop);
1649 ASSERT(entry != -1);
1650
1651 if (dict->GetAttributes(entry).IsConstProps()) {
1652 return ThrowSyntaxError(thread, "const variable can not be modified");
1653 }
1654
1655 PropertyBox *box = dict->GetBox(entry);
1656 box->SetValue(thread, value);
1657 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1658 return JSTaggedValue::True();
1659 }
1660
1661 // return box
LdGlobalRecord(JSThread * thread,JSTaggedValue key)1662 JSTaggedValue SlowRuntimeStub::LdGlobalRecord(JSThread *thread, JSTaggedValue key)
1663 {
1664 INTERPRETER_TRACE(thread, LdGlobalRecord);
1665 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1666
1667 EcmaVM *vm = thread->GetEcmaVM();
1668 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1669 GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1670 int entry = dict->FindEntry(key);
1671 if (entry != -1) {
1672 return JSTaggedValue(dict->GetBox(entry));
1673 }
1674 return JSTaggedValue::Undefined();
1675 }
1676
StGlobalRecord(JSThread * thread,JSTaggedValue prop,JSTaggedValue value,bool isConst)1677 JSTaggedValue SlowRuntimeStub::StGlobalRecord(JSThread *thread, JSTaggedValue prop, JSTaggedValue value, bool isConst)
1678 {
1679 INTERPRETER_TRACE(thread, StGlobalRecord);
1680 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1681
1682 EcmaVM *vm = thread->GetEcmaVM();
1683 JSHandle<GlobalEnv> env = vm->GetGlobalEnv();
1684 GlobalDictionary *dict = GlobalDictionary::Cast(env->GetGlobalRecord()->GetTaggedObject());
1685
1686 // cross files global record name binding judgment
1687 int entry = dict->FindEntry(prop);
1688 if (entry != -1) {
1689 return ThrowSyntaxError(thread, "Duplicate identifier");
1690 }
1691
1692 PropertyAttributes attributes;
1693 if (isConst) {
1694 attributes.SetIsConstProps(true);
1695 }
1696 JSHandle<JSTaggedValue> propHandle(thread, prop);
1697 JSHandle<JSTaggedValue> valueHandle(thread, value);
1698 JSHandle<GlobalDictionary> dictHandle(thread, dict);
1699
1700 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1701 JSHandle<PropertyBox> box = factory->NewPropertyBox(valueHandle);
1702 PropertyBoxType boxType = valueHandle->IsUndefined() ? PropertyBoxType::UNDEFINED : PropertyBoxType::CONSTANT;
1703 attributes.SetBoxType(boxType);
1704
1705 dict = *GlobalDictionary::PutIfAbsent(thread, dictHandle, propHandle, JSHandle<JSTaggedValue>(box), attributes);
1706 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1707 env->SetGlobalRecord(thread, JSTaggedValue(dict));
1708 return JSTaggedValue::True();
1709 }
1710
ThrowReferenceError(JSThread * thread,JSTaggedValue prop,const char * desc)1711 JSTaggedValue SlowRuntimeStub::ThrowReferenceError(JSThread *thread, JSTaggedValue prop, const char *desc)
1712 {
1713 INTERPRETER_TRACE(thread, ThrowReferenceError);
1714 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1715 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1716 JSHandle<EcmaString> propName = JSTaggedValue::ToString(thread, JSHandle<JSTaggedValue>(thread, prop));
1717 ASSERT_NO_ABRUPT_COMPLETION(thread);
1718 JSHandle<EcmaString> info = factory->NewFromString(desc);
1719 JSHandle<EcmaString> msg = factory->ConcatFromString(propName, info);
1720 THROW_NEW_ERROR_AND_RETURN_VALUE(thread,
1721 factory->NewJSError(base::ErrorType::REFERENCE_ERROR, msg).GetTaggedValue(),
1722 JSTaggedValue::Exception());
1723 }
1724
ThrowTypeError(JSThread * thread,const char * message)1725 JSTaggedValue SlowRuntimeStub::ThrowTypeError(JSThread *thread, const char *message)
1726 {
1727 INTERPRETER_TRACE(thread, ThrowTypeError);
1728 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1729 ASSERT_NO_ABRUPT_COMPLETION(thread);
1730 THROW_TYPE_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
1731 }
1732
ThrowSyntaxError(JSThread * thread,const char * message)1733 JSTaggedValue SlowRuntimeStub::ThrowSyntaxError(JSThread *thread, const char *message)
1734 {
1735 INTERPRETER_TRACE(thread, ThrowSyntaxError);
1736 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1737 ASSERT_NO_ABRUPT_COMPLETION(thread);
1738 THROW_SYNTAX_ERROR_AND_RETURN(thread, message, JSTaggedValue::Exception());
1739 }
1740
StArraySpread(JSThread * thread,JSTaggedValue dst,JSTaggedValue index,JSTaggedValue src)1741 JSTaggedValue SlowRuntimeStub::StArraySpread(JSThread *thread, JSTaggedValue dst, JSTaggedValue index,
1742 JSTaggedValue src)
1743 {
1744 INTERPRETER_TRACE(thread, StArraySpread);
1745 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1746
1747 JSHandle<JSTaggedValue> dstHandle(thread, dst);
1748 JSHandle<JSTaggedValue> srcHandle(thread, src);
1749 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1750 ASSERT(dstHandle->IsJSArray() && !srcHandle->IsNull() && !srcHandle->IsUndefined());
1751 if (srcHandle->IsString()) {
1752 JSHandle<EcmaString> srcString = JSTaggedValue::ToString(thread, srcHandle);
1753 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1754 uint32_t dstLen = index.GetInt();
1755 uint32_t strLen = srcString->GetLength();
1756 for (uint32_t i = 0; i < strLen; i++) {
1757 uint16_t res = srcString->At<false>(i);
1758 JSHandle<JSTaggedValue> strValue(factory->NewFromUtf16Literal(&res, 1));
1759 JSTaggedValue::SetProperty(thread, dstHandle, dstLen + i, strValue, true);
1760 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1761 }
1762 return JSTaggedValue(dstLen + strLen);
1763 }
1764
1765 JSHandle<JSTaggedValue> iter;
1766 auto globalConst = thread->GlobalConstants();
1767 if (srcHandle->IsJSArrayIterator() || srcHandle->IsJSMapIterator() || srcHandle->IsJSSetIterator() ||
1768 srcHandle->IsIterator()) {
1769 iter = srcHandle;
1770 } else if (srcHandle->IsJSArray() || srcHandle->IsJSMap() || srcHandle->IsTypedArray() || srcHandle->IsJSSet()) {
1771 JSHandle<JSTaggedValue> valuesStr = globalConst->GetHandledValuesString();
1772 JSHandle<JSTaggedValue> valuesMethod = JSObject::GetMethod(thread, srcHandle, valuesStr);
1773 iter = JSIterator::GetIterator(thread, srcHandle, valuesMethod);
1774 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1775 } else {
1776 iter = JSIterator::GetIterator(thread, srcHandle);
1777 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1778 }
1779
1780 JSMutableHandle<JSTaggedValue> indexHandle(thread, index);
1781 JSHandle<JSTaggedValue> valueStr = globalConst->GetHandledValueString();
1782 PropertyDescriptor desc(thread);
1783 JSHandle<JSTaggedValue> iterResult;
1784 do {
1785 iterResult = JSIterator::IteratorStep(thread, iter);
1786 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1787 if (iterResult->IsFalse()) {
1788 break;
1789 }
1790 bool success = JSTaggedValue::GetOwnProperty(thread, iterResult, valueStr, desc);
1791 if (success && desc.IsEnumerable()) {
1792 JSTaggedValue::DefineOwnProperty(thread, dstHandle, indexHandle, desc);
1793 int tmp = indexHandle->GetInt();
1794 indexHandle.Update(JSTaggedValue(tmp + 1));
1795 }
1796 } while (true);
1797
1798 return indexHandle.GetTaggedValue();
1799 }
1800
DefineGeneratorFunc(JSThread * thread,JSFunction * func)1801 JSTaggedValue SlowRuntimeStub::DefineGeneratorFunc(JSThread *thread, JSFunction *func)
1802 {
1803 INTERPRETER_TRACE(thread, DefineGeneratorFunc);
1804 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1805 auto method = func->GetCallTarget();
1806
1807 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1808 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1809 JSHandle<JSFunction> jsFunc = factory->NewJSGeneratorFunction(method);
1810 ASSERT_NO_ABRUPT_COMPLETION(thread);
1811
1812 // 26.3.4.3 prototype
1813 // Whenever a GeneratorFunction instance is created another ordinary object is also created and
1814 // is the initial value of the generator function's "prototype" property.
1815 JSHandle<JSTaggedValue> objFun = env->GetObjectFunction();
1816 JSHandle<JSObject> initialGeneratorFuncPrototype =
1817 factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun);
1818 JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetGeneratorPrototype());
1819 ASSERT_NO_ABRUPT_COMPLETION(thread);
1820 jsFunc->SetProtoOrDynClass(thread, initialGeneratorFuncPrototype);
1821
1822 return jsFunc.GetTaggedValue();
1823 }
1824
DefineAsyncFunc(JSThread * thread,JSFunction * func)1825 JSTaggedValue SlowRuntimeStub::DefineAsyncFunc(JSThread *thread, JSFunction *func)
1826 {
1827 INTERPRETER_TRACE(thread, DefineAsyncFunc);
1828 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1829 auto method = func->GetCallTarget();
1830
1831 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1832 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1833 JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
1834 JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::ASYNC_FUNCTION);
1835 ASSERT_NO_ABRUPT_COMPLETION(thread);
1836 return jsFunc.GetTaggedValue();
1837 }
1838
DefineNCFuncDyn(JSThread * thread,JSFunction * func)1839 JSTaggedValue SlowRuntimeStub::DefineNCFuncDyn(JSThread *thread, JSFunction *func)
1840 {
1841 INTERPRETER_TRACE(thread, DefineNCFuncDyn);
1842 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1843 auto method = func->GetCallTarget();
1844
1845 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1846 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1847 JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
1848 JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::ARROW_FUNCTION);
1849 ASSERT_NO_ABRUPT_COMPLETION(thread);
1850 return jsFunc.GetTaggedValue();
1851 }
1852
DefinefuncDyn(JSThread * thread,JSFunction * func)1853 JSTaggedValue SlowRuntimeStub::DefinefuncDyn(JSThread *thread, JSFunction *func)
1854 {
1855 INTERPRETER_TRACE(thread, DefinefuncDyn);
1856 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1857 auto method = func->GetCallTarget();
1858
1859 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1860 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1861 JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithProto());
1862 JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::BASE_CONSTRUCTOR);
1863 ASSERT_NO_ABRUPT_COMPLETION(thread);
1864 return jsFunc.GetTaggedValue();
1865 }
1866
SuperCall(JSThread * thread,JSTaggedValue func,JSTaggedValue newTarget,uint16_t firstVRegIdx,uint16_t length)1867 JSTaggedValue SlowRuntimeStub::SuperCall(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
1868 uint16_t firstVRegIdx, uint16_t length)
1869 {
1870 INTERPRETER_TRACE(thread, SuperCall);
1871 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1872 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1873 InterpretedFrameHandler frameHandler(thread);
1874
1875 JSHandle<JSTaggedValue> funcHandle(thread, func);
1876 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
1877
1878 JSHandle<JSTaggedValue> superFunc(thread, JSHandle<JSObject>::Cast(funcHandle)->GetPrototype(thread));
1879 ASSERT(superFunc->IsJSFunction());
1880
1881 JSHandle<TaggedArray> argv = factory->NewTaggedArray(length);
1882 for (size_t i = 0; i < length; ++i) {
1883 argv->Set(thread, i, frameHandler.GetVRegValue(firstVRegIdx + i));
1884 }
1885 InternalCallParams *arguments = thread->GetInternalCallParams();
1886 arguments->MakeArgList(*argv);
1887 JSTaggedValue result = JSFunction::Construct(thread, superFunc, length, arguments->GetArgv(), newTargetHandle);
1888 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1889
1890 return result;
1891 }
1892
SuperCallSpread(JSThread * thread,JSTaggedValue func,JSTaggedValue newTarget,JSTaggedValue array)1893 JSTaggedValue SlowRuntimeStub::SuperCallSpread(JSThread *thread, JSTaggedValue func, JSTaggedValue newTarget,
1894 JSTaggedValue array)
1895 {
1896 INTERPRETER_TRACE(thread, SuperCallSpread);
1897 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1898 InterpretedFrameHandler frameHandler(thread);
1899
1900 JSHandle<JSTaggedValue> funcHandle(thread, func);
1901 JSHandle<JSTaggedValue> newTargetHandle(thread, newTarget);
1902 JSHandle<JSTaggedValue> jsArray(thread, array);
1903
1904 JSHandle<JSTaggedValue> superFunc(thread, JSHandle<JSObject>::Cast(funcHandle)->GetPrototype(thread));
1905 ASSERT(superFunc->IsJSFunction());
1906
1907 JSHandle<TaggedArray> argv(thread, GetCallSpreadArgs(thread, jsArray.GetTaggedValue()));
1908 InternalCallParams *arguments = thread->GetInternalCallParams();
1909 arguments->MakeArgList(*argv);
1910 JSTaggedValue result =
1911 JSFunction::Construct(thread, superFunc, argv->GetLength(), arguments->GetArgv(), newTargetHandle);
1912 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1913
1914 return result;
1915 }
1916
DefineMethod(JSThread * thread,JSFunction * func,JSTaggedValue homeObject)1917 JSTaggedValue SlowRuntimeStub::DefineMethod(JSThread *thread, JSFunction *func, JSTaggedValue homeObject)
1918 {
1919 INTERPRETER_TRACE(thread, DefineMethod);
1920 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1921 ASSERT(homeObject.IsECMAObject());
1922 JSHandle<JSTaggedValue> homeObjectHandle(thread, homeObject);
1923 auto method = func->GetCallTarget();
1924
1925 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
1926 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1927 JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
1928 JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::NORMAL_FUNCTION);
1929 jsFunc->SetHomeObject(thread, homeObjectHandle);
1930 ASSERT_NO_ABRUPT_COMPLETION(thread);
1931 return jsFunc.GetTaggedValue();
1932 }
1933
LdSuperByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue key,JSTaggedValue thisFunc)1934 JSTaggedValue SlowRuntimeStub::LdSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key,
1935 JSTaggedValue thisFunc)
1936 {
1937 INTERPRETER_TRACE(thread, LdSuperByValue);
1938 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1939 ASSERT(thisFunc.IsJSFunction());
1940 // get Homeobject form function
1941 JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject());
1942
1943 if (obj.IsUndefined()) {
1944 return ThrowReferenceError(thread, obj, "this is uninitialized.");
1945 }
1946 JSHandle<JSTaggedValue> objHandle(thread, obj);
1947 JSHandle<JSTaggedValue> propHandle(thread, key);
1948
1949 JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, propHandle));
1950 JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
1951 JSTaggedValue::RequireObjectCoercible(thread, superBase);
1952 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1953
1954 JSTaggedValue res = JSTaggedValue::GetProperty(thread, superBase, propKey, objHandle).GetValue().GetTaggedValue();
1955 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1956 return res;
1957 }
1958
StSuperByValue(JSThread * thread,JSTaggedValue obj,JSTaggedValue key,JSTaggedValue value,JSTaggedValue thisFunc)1959 JSTaggedValue SlowRuntimeStub::StSuperByValue(JSThread *thread, JSTaggedValue obj, JSTaggedValue key,
1960 JSTaggedValue value, JSTaggedValue thisFunc)
1961 {
1962 INTERPRETER_TRACE(thread, StSuperByValue);
1963 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1964 ASSERT(thisFunc.IsJSFunction());
1965 // get Homeobject form function
1966 JSHandle<JSTaggedValue> homeObject(thread, JSFunction::Cast(thisFunc.GetTaggedObject())->GetHomeObject());
1967
1968 if (obj.IsUndefined()) {
1969 return ThrowReferenceError(thread, obj, "this is uninitialized.");
1970 }
1971 JSHandle<JSTaggedValue> objHandle(thread, obj);
1972 JSHandle<JSTaggedValue> propHandle(thread, key);
1973 JSHandle<JSTaggedValue> valueHandle(thread, value);
1974
1975 JSHandle<JSTaggedValue> propKey(JSTaggedValue::ToPropertyKey(thread, propHandle));
1976 JSHandle<JSTaggedValue> superBase(thread, JSTaggedValue::GetSuperBase(thread, homeObject));
1977 JSTaggedValue::RequireObjectCoercible(thread, superBase);
1978 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1979
1980 // check may_throw is false?
1981 JSTaggedValue::SetProperty(thread, superBase, propKey, valueHandle, objHandle, true);
1982 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1983 return JSTaggedValue::True();
1984 }
1985
GetCallSpreadArgs(JSThread * thread,JSTaggedValue array)1986 JSTaggedValue SlowRuntimeStub::GetCallSpreadArgs(JSThread *thread, JSTaggedValue array)
1987 {
1988 INTERPRETER_TRACE(thread, GetCallSpreadArgs);
1989 [[maybe_unused]] EcmaHandleScope handleScope(thread);
1990 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1991
1992 JSHandle<JSTaggedValue> jsArray(thread, array);
1993 uint32_t argvMayMaxLength = JSHandle<JSArray>::Cast(jsArray)->GetArrayLength();
1994 JSHandle<TaggedArray> argv = factory->NewTaggedArray(argvMayMaxLength);
1995 JSHandle<JSTaggedValue> itor = JSIterator::GetIterator(thread, jsArray);
1996 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
1997 JSMutableHandle<JSTaggedValue> next(thread, JSTaggedValue::Undefined());
1998 JSMutableHandle<JSTaggedValue> nextArg(thread, JSTaggedValue::Undefined());
1999 size_t argvIndex = 0;
2000 while (true) {
2001 next.Update(JSIterator::IteratorStep(thread, itor).GetTaggedValue());
2002 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2003 if (JSTaggedValue::SameValue(next.GetTaggedValue(), JSTaggedValue::False())) {
2004 break;
2005 }
2006 nextArg.Update(JSIterator::IteratorValue(thread, next).GetTaggedValue());
2007 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2008 argv->Set(thread, argvIndex++, nextArg);
2009 }
2010
2011 argv = factory->CopyArray(argv, argvMayMaxLength, argvIndex);
2012 return argv.GetTaggedValue();
2013 }
2014
ThrowDeleteSuperProperty(JSThread * thread)2015 void SlowRuntimeStub::ThrowDeleteSuperProperty(JSThread *thread)
2016 {
2017 INTERPRETER_TRACE(thread, ThrowDeleteSuperProperty);
2018 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2019
2020 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2021 JSHandle<EcmaString> info = factory->NewFromCanBeCompressString("Can not delete super property");
2022 JSHandle<JSObject> errorObj = factory->NewJSError(base::ErrorType::REFERENCE_ERROR, info);
2023 THROW_NEW_ERROR_AND_RETURN(thread, errorObj.GetTaggedValue());
2024 }
2025
NotifyInlineCache(JSThread * thread,JSFunction * func,JSMethod * method)2026 JSTaggedValue SlowRuntimeStub::NotifyInlineCache(JSThread *thread, JSFunction *func, JSMethod *method)
2027 {
2028 INTERPRETER_TRACE(thread, NotifyInlineCache);
2029 uint32_t icSlotSize = method->GetSlotSize();
2030 if (icSlotSize > 0 && icSlotSize < ProfileTypeInfo::INVALID_SLOT_INDEX) {
2031 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2032 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2033
2034 JSHandle<JSFunction> funcHandle(thread, func);
2035 JSHandle<ProfileTypeInfo> profileTypeInfo = factory->NewProfileTypeInfo(icSlotSize);
2036 funcHandle->SetProfileTypeInfo(thread, profileTypeInfo.GetTaggedValue());
2037 return profileTypeInfo.GetTaggedValue();
2038 }
2039 return JSTaggedValue::Undefined();
2040 }
2041
ResolveClass(JSThread * thread,JSTaggedValue ctor,TaggedArray * literal,JSTaggedValue base,JSTaggedValue lexenv,ConstantPool * constpool)2042 JSTaggedValue SlowRuntimeStub::ResolveClass(JSThread *thread, JSTaggedValue ctor, TaggedArray *literal,
2043 JSTaggedValue base, JSTaggedValue lexenv, ConstantPool *constpool)
2044 {
2045 ASSERT(ctor.IsClassConstructor());
2046 JSHandle<JSFunction> cls(thread, ctor);
2047 JSHandle<TaggedArray> literalBuffer(thread, literal);
2048 JSHandle<JSTaggedValue> lexicalEnv(thread, lexenv);
2049 JSHandle<ConstantPool> constpoolHandle(thread, constpool);
2050
2051 SetClassInheritanceRelationship(thread, ctor, base);
2052 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2053
2054 uint32_t literalBufferLength = literalBuffer->GetLength();
2055
2056 // only traverse the value of key-value pair
2057 for (uint32_t index = 1; index < literalBufferLength - 1; index += 2) { // 2: key-value pair
2058 JSTaggedValue value = literalBuffer->Get(index);
2059 if (LIKELY(value.IsJSFunction())) {
2060 JSFunction::Cast(value.GetTaggedObject())->SetLexicalEnv(thread, lexicalEnv.GetTaggedValue());
2061 JSFunction::Cast(value.GetTaggedObject())->SetConstantPool(thread, constpoolHandle.GetTaggedValue());
2062 }
2063 }
2064
2065 cls->SetResolved(true);
2066 return cls.GetTaggedValue();
2067 }
2068
2069 // clone class may need re-set inheritance relationship due to extends may be a variable.
CloneClassFromTemplate(JSThread * thread,JSTaggedValue ctor,JSTaggedValue base,JSTaggedValue lexenv,ConstantPool * constpool)2070 JSTaggedValue SlowRuntimeStub::CloneClassFromTemplate(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base,
2071 JSTaggedValue lexenv, ConstantPool *constpool)
2072 {
2073 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2074 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
2075 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2076
2077 ASSERT(ctor.IsClassConstructor());
2078 JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
2079 JSHandle<JSTaggedValue> constpoolHandle(thread, JSTaggedValue(constpool));
2080 JSHandle<JSTaggedValue> baseHandle(thread, base);
2081
2082 JSHandle<JSFunction> cls(thread, ctor);
2083
2084 JSHandle<JSObject> clsPrototype(thread, cls->GetFunctionPrototype());
2085
2086 bool canShareHClass = false;
2087
2088 JSHandle<JSFunction> cloneClass = factory->CloneClassCtor(cls, lexenvHandle, canShareHClass);
2089 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2090 JSHandle<JSObject> cloneClassPrototype = factory->CloneObjectLiteral(JSHandle<JSObject>(clsPrototype), lexenvHandle,
2091 constpoolHandle, canShareHClass);
2092 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2093
2094 // After clone both, reset "constructor" and "prototype" properties.
2095 cloneClass->SetFunctionPrototype(thread, cloneClassPrototype.GetTaggedValue());
2096 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2097
2098 PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(cloneClass), true, false, true);
2099 JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(cloneClassPrototype),
2100 globalConst->GetHandledConstructorString(), ctorDesc);
2101 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2102
2103 cloneClass->SetHomeObject(thread, cloneClassPrototype);
2104
2105 if (!canShareHClass) {
2106 SetClassInheritanceRelationship(thread, cloneClass.GetTaggedValue(), baseHandle.GetTaggedValue());
2107 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
2108 }
2109
2110 return cloneClass.GetTaggedValue();
2111 }
2112
SetClassInheritanceRelationship(JSThread * thread,JSTaggedValue ctor,JSTaggedValue base)2113 JSTaggedValue SlowRuntimeStub::SetClassInheritanceRelationship(JSThread *thread, JSTaggedValue ctor, JSTaggedValue base)
2114 {
2115 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2116 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
2117 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2118
2119 JSHandle<JSTaggedValue> cls(thread, ctor);
2120 ASSERT(cls->IsJSFunction());
2121 JSMutableHandle<JSTaggedValue> parent(thread, base);
2122
2123 /*
2124 * class A / class A extends null class A extends B
2125 * a a
2126 * | |
2127 * | __proto__ | __proto__
2128 * | |
2129 * A ----> A.prototype A ----> A.prototype
2130 * | | | |
2131 * | __proto__ | __proto__ | __proto__ | __proto__
2132 * | | | |
2133 * Function.prototype Object.prototype / null B ----> B.prototype
2134 */
2135
2136 JSHandle<JSTaggedValue> parentPrototype;
2137 // hole means parent is not present
2138 if (parent->IsHole()) {
2139 JSHandle<JSFunction>::Cast(cls)->SetFunctionKind(FunctionKind::CLASS_CONSTRUCTOR);
2140 parentPrototype = env->GetObjectFunctionPrototype();
2141 parent.Update(env->GetFunctionPrototype().GetTaggedValue());
2142 } else if (parent->IsNull()) {
2143 JSHandle<JSFunction>::Cast(cls)->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
2144 parentPrototype = JSHandle<JSTaggedValue>(thread, JSTaggedValue::Null());
2145 parent.Update(env->GetFunctionPrototype().GetTaggedValue());
2146 } else if (!parent->IsConstructor()) {
2147 return ThrowTypeError(thread, "parent class is not constructor");
2148 } else {
2149 JSHandle<JSFunction>::Cast(cls)->SetFunctionKind(FunctionKind::DERIVED_CONSTRUCTOR);
2150 parentPrototype = JSTaggedValue::GetProperty(thread, parent,
2151 globalConst->GetHandledPrototypeString()).GetValue();
2152 if (!parentPrototype->IsECMAObject() && !parentPrototype->IsNull()) {
2153 return ThrowTypeError(thread, "parent class have no valid prototype");
2154 }
2155 }
2156
2157 cls->GetTaggedObject()->GetClass()->SetPrototype(thread, parent);
2158
2159 JSHandle<JSObject> clsPrototype(thread, JSHandle<JSFunction>(cls)->GetFunctionPrototype());
2160 clsPrototype->GetClass()->SetPrototype(thread, parentPrototype);
2161
2162 return JSTaggedValue::Undefined();
2163 }
2164
SetClassConstructorLength(JSThread * thread,JSTaggedValue ctor,JSTaggedValue length)2165 JSTaggedValue SlowRuntimeStub::SetClassConstructorLength(JSThread *thread, JSTaggedValue ctor, JSTaggedValue length)
2166 {
2167 ASSERT(ctor.IsClassConstructor());
2168
2169 JSFunction* cls = JSFunction::Cast(ctor.GetTaggedObject());
2170 if (LIKELY(!cls->GetClass()->IsDictionaryMode())) {
2171 cls->SetPropertyInlinedProps(thread, JSFunction::LENGTH_INLINE_PROPERTY_INDEX, length);
2172 } else {
2173 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
2174 cls->UpdatePropertyInDictionary(thread, globalConst->GetLengthString(), length);
2175 }
2176 return JSTaggedValue::Undefined();
2177 }
2178
LdBigInt(JSThread * thread,JSTaggedValue numberBigInt)2179 JSTaggedValue SlowRuntimeStub::LdBigInt(JSThread *thread, JSTaggedValue numberBigInt)
2180 {
2181 INTERPRETER_TRACE(thread, LdBigInt);
2182 [[maybe_unused]] EcmaHandleScope handleScope(thread);
2183 JSHandle<JSTaggedValue> bigint(thread, numberBigInt);
2184 return JSTaggedValue::ToBigInt(thread, bigint);
2185 }
2186 } // namespace panda::ecmascript
2187