1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/js_function.h"
17
18 #include "ecmascript/debugger/js_debugger_manager.h"
19 #include "ecmascript/ecma_context.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/interpreter/interpreter.h"
22 #include "ecmascript/js_object-inl.h"
23 #include "ecmascript/module/module_resolver.h"
24 #include "ecmascript/object_factory-inl.h"
25 #include "ecmascript/pgo_profiler/pgo_profiler.h"
26 #include "ecmascript/require/js_require_manager.h"
27 #include "ecmascript/ic/profile_type_info.h"
28
29 namespace panda::ecmascript {
InitializeJSFunction(JSThread * thread,const JSHandle<JSFunction> & func,FunctionKind kind)30 void JSFunction::InitializeJSFunction(JSThread *thread, const JSHandle<JSFunction> &func, FunctionKind kind)
31 {
32 InitializeWithDefaultValue(thread, func);
33 auto globalConst = thread->GlobalConstants();
34 if (HasPrototype(kind)) {
35 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
36 if (kind == FunctionKind::BASE_CONSTRUCTOR || kind == FunctionKind::GENERATOR_FUNCTION ||
37 kind == FunctionKind::ASYNC_GENERATOR_FUNCTION || kind == FunctionKind::NONE_FUNCTION) {
38 func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
39 accessor = globalConst->GetHandledFunctionNameAccessor();
40 func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
41 accessor = globalConst->GetHandledFunctionLengthAccessor();
42 func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
43 if (kind == FunctionKind::ASYNC_GENERATOR_FUNCTION) {
44 // Not duplicate codes, it will slow the performace if combining and put outside!
45 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
46 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
47 JSHandle<JSFunction> objFun(env->GetObjectFunction());
48 JSHandle<JSObject> initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun);
49 JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetAsyncGeneratorPrototype());
50 func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype);
51 }
52 if (kind == FunctionKind::GENERATOR_FUNCTION) {
53 // Not duplicate codes, it will slow the performace if combining and put outside!
54 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
55 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
56 JSHandle<JSFunction> objFun(env->GetObjectFunction());
57 JSHandle<JSObject> initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun);
58 JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetGeneratorPrototype());
59 func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype);
60 }
61 } else if (!JSFunction::IsClassConstructor(kind)) { // class ctor do nothing
62 PropertyDescriptor desc(thread, accessor, kind != FunctionKind::BUILTIN_CONSTRUCTOR, false, false);
63 [[maybe_unused]] bool success = JSObject::DefineOwnProperty(
64 thread, JSHandle<JSObject>(func), globalConst->GetHandledPrototypeString(), desc, SCheckMode::SKIP);
65 ASSERT(success);
66 }
67 } else if (HasAccessor(kind)) {
68 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionNameAccessor();
69 func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
70 accessor = globalConst->GetHandledFunctionLengthAccessor();
71 func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
72 }
73 }
74
InitializeSFunction(JSThread * thread,const JSHandle<JSFunction> & func,FunctionKind kind)75 void JSFunction::InitializeSFunction(JSThread *thread, const JSHandle<JSFunction> &func, FunctionKind kind)
76 {
77 InitializeWithDefaultValue(thread, func);
78 auto globalConst = thread->GlobalConstants();
79 JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
80 if (HasAccessor(kind) || IsBaseConstructorKind(kind)) {
81 if (IsBaseConstructorKind(kind)) {
82 func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
83 }
84 accessor = globalConst->GetHandledFunctionNameAccessor();
85 func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
86 accessor = globalConst->GetHandledFunctionLengthAccessor();
87 func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
88 }
89 }
90
InitializeWithDefaultValue(JSThread * thread,const JSHandle<JSFunction> & func)91 void JSFunction::InitializeWithDefaultValue(JSThread *thread, const JSHandle<JSFunction> &func)
92 {
93 func->SetProtoOrHClass(thread, JSTaggedValue::Hole(), SKIP_BARRIER);
94 func->SetHomeObject(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
95 func->SetWorkNodePointer(reinterpret_cast<uintptr_t>(nullptr));
96 func->SetLexicalEnv(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
97 func->SetMachineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
98 func->SetBaselineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
99 func->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
100 func->SetMethod(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
101 func->SetModule(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
102 func->SetCodeEntry(reinterpret_cast<uintptr_t>(nullptr));
103 func->ClearCompiledCodeFlags();
104 func->SetTaskConcurrentFuncFlag(0); // 0 : default value
105 func->SetCallNapi(false);
106 }
107
NewJSFunctionPrototype(JSThread * thread,const JSHandle<JSFunction> & func)108 JSHandle<JSObject> JSFunction::NewJSFunctionPrototype(JSThread *thread, const JSHandle<JSFunction> &func)
109 {
110 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
111 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
112 JSHandle<JSFunction> objFun;
113 if (func->IsSharedFunction()) {
114 objFun = JSHandle<JSFunction>(env->GetSObjectFunction());
115 } else {
116 objFun = JSHandle<JSFunction>(env->GetObjectFunction());
117 }
118 JSHandle<JSObject> funPro = thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(objFun);
119 SetFunctionPrototypeOrInstanceHClass(thread, func, funPro.GetTaggedValue());
120
121 // set "constructor" in prototype
122 JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
123 PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(func), true, false, true);
124 JSObject::DefineOwnProperty(thread, funPro, constructorKey, descriptor);
125
126 return funPro;
127 }
128
GetOrCreateInitialJSHClass(JSThread * thread,const JSHandle<JSFunction> & fun)129 JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle<JSFunction> &fun)
130 {
131 JSTaggedValue protoOrHClass(fun->GetProtoOrHClass());
132 if (protoOrHClass.IsJSHClass()) {
133 return reinterpret_cast<JSHClass *>(protoOrHClass.GetTaggedObject());
134 }
135
136 JSHandle<JSTaggedValue> proto;
137 bool needProfileTransition = false;
138 if (!fun->HasFunctionPrototype()) {
139 proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, fun));
140 if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
141 thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(),
142 JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
143 }
144 } else {
145 proto = JSHandle<JSTaggedValue>(thread, fun->GetProtoOrHClass());
146 needProfileTransition = proto->IsECMAObject();
147 }
148
149 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
150 JSHandle<JSHClass> hclass;
151 if (thread->GetEcmaVM()->GetJSOptions().IsEnableInlinePropertyOptimization()) {
152 bool isStartObjSizeTracking = true;
153 uint32_t expectedOfProperties = JSFunction::CalcuExpotedOfProperties(fun, &isStartObjSizeTracking);
154 hclass = factory->NewEcmaHClass(JSObject::SIZE, expectedOfProperties, JSType::JS_OBJECT, proto);
155 if (isStartObjSizeTracking) {
156 hclass->StartObjSizeTracking();
157 }
158 } else {
159 hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, proto);
160 }
161 fun->SetProtoOrHClass(thread, hclass);
162 if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
163 if (!needProfileTransition) {
164 thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(), hclass.GetTaggedType());
165 } else {
166 thread->GetEcmaVM()->GetPGOProfiler()->ProfileProtoTransitionClass(fun, hclass, proto);
167 }
168 }
169 return *hclass;
170 }
171
CalcuExpotedOfProperties(const JSHandle<JSFunction> & fun,bool * isStartObjSizeTracking)172 uint32_t JSFunction::CalcuExpotedOfProperties(const JSHandle<JSFunction> &fun, bool *isStartObjSizeTracking)
173 {
174 JSTaggedValue prototype = fun.GetTaggedValue();
175 uint32_t expectedPropertyCount = 0;
176 while (prototype.IsJSFunction()) {
177 JSTaggedValue method = JSFunction::Cast(prototype.GetTaggedObject())->GetMethod();
178 uint32_t count = Method::Cast(method.GetTaggedObject())->GetExpectedPropertyCount();
179 prototype = JSObject::GetPrototype(prototype);
180 // if equal MAX_EXPECTED_PROPERTY_COUNT means none expectedProperty in method
181 if (count == MethodLiteral::MAX_EXPECTED_PROPERTY_COUNT) {
182 continue;
183 }
184 expectedPropertyCount += count;
185 }
186 expectedPropertyCount += JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
187 // if equal DEFAULT_CAPACITY_OF_IN_OBJECTS mean none expectedProperty in func
188 if (expectedPropertyCount == JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
189 *isStartObjSizeTracking = false;
190 return expectedPropertyCount;
191 }
192 if (expectedPropertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
193 return PropertyAttributes::MAX_FAST_PROPS_CAPACITY;
194 }
195 return expectedPropertyCount;
196 }
197
PrototypeGetter(JSThread * thread,const JSHandle<JSObject> & self)198 JSTaggedValue JSFunction::PrototypeGetter(JSThread *thread, const JSHandle<JSObject> &self)
199 {
200 JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(self);
201 if (!func->HasFunctionPrototype()) {
202 JSHandle<JSTaggedValue> proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, func));
203 if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
204 thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(),
205 JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
206 }
207 }
208 return JSFunction::Cast(*self)->GetFunctionPrototype();
209 }
210
PrototypeSetter(JSThread * thread,const JSHandle<JSObject> & self,const JSHandle<JSTaggedValue> & value,bool mayThrow)211 bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
212 [[maybe_unused]] bool mayThrow)
213 {
214 JSHandle<JSFunction> func(self);
215 JSTaggedValue protoOrHClass = func->GetProtoOrHClass();
216 if (protoOrHClass.IsJSHClass()) {
217 // need transition
218 JSHandle<JSHClass> hclass(thread, JSHClass::Cast(protoOrHClass.GetTaggedObject()));
219 hclass->CompleteObjSizeTracking();
220 JSHandle<JSHClass> newClass = JSHClass::SetPrototypeWithNotification(thread, hclass, value);
221 func->SetProtoOrHClass(thread, newClass);
222 // Forbide to profile for changing the function prototype after an instance of the function has been created
223 if (!hclass->IsAOT() && thread->GetEcmaVM()->IsEnablePGOProfiler()) {
224 EntityId ctorMethodId = Method::Cast(func->GetMethod().GetTaggedObject())->GetMethodId();
225 thread->GetEcmaVM()->GetPGOProfiler()->InsertSkipCtorMethodIdSafe(ctorMethodId);
226 }
227 } else {
228 if (!value->IsECMAObject()) {
229 func->SetProtoOrHClass(thread, value.GetTaggedValue());
230 return true;
231 }
232
233 bool enablePgo = thread->GetEcmaVM()->IsEnablePGOProfiler();
234 JSMutableHandle<JSTaggedValue> oldPrototype(thread, func->GetProtoOrHClass());
235 // For pgo, we need the oldPrototype to record the old ihc and phc.
236 if (enablePgo && oldPrototype->IsHole()) {
237 oldPrototype.Update(JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, func)));
238 }
239 JSHandle<JSTaggedValue> baseIhc(thread, value->GetTaggedObject()->GetClass());
240 func->SetProtoOrHClass(thread, value.GetTaggedValue());
241 JSHClass::OptimizePrototypeForIC(thread, value, true);
242 if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
243 thread->GetEcmaVM()->GetPGOProfiler()->ProfileProtoTransitionPrototype(func, value, oldPrototype, baseIhc);
244 }
245 }
246 return true;
247 }
248
SetFunctionPrototypeOrInstanceHClass(const JSThread * thread,const JSHandle<JSFunction> & fun,JSTaggedValue protoOrHClass)249 void JSFunction::SetFunctionPrototypeOrInstanceHClass(const JSThread *thread, const JSHandle<JSFunction> &fun,
250 JSTaggedValue protoOrHClass)
251 {
252 JSHandle<JSTaggedValue> protoHandle(thread, protoOrHClass);
253 fun->SetProtoOrHClass(thread, protoHandle.GetTaggedValue());
254 if (protoHandle->IsJSHClass()) {
255 protoHandle = JSHandle<JSTaggedValue>(thread,
256 JSHClass::Cast(protoHandle->GetTaggedObject())->GetPrototype());
257 }
258 if (protoHandle->IsECMAObject()) {
259 JSHClass::OptimizePrototypeForIC(thread, protoHandle);
260 }
261 }
262
GetFunctionNameString(ObjectFactory * factory,JSHandle<EcmaString> concatString,JSHandle<JSTaggedValue> target)263 EcmaString* JSFunction::GetFunctionNameString(ObjectFactory *factory, JSHandle<EcmaString> concatString,
264 JSHandle<JSTaggedValue> target)
265 {
266 if (target->IsJSFunction()) {
267 JSTaggedValue method = JSHandle<JSFunction>::Cast(target)->GetMethod();
268 if (!method.IsUndefined()) {
269 std::string funcName = Method::Cast(method.GetTaggedObject())->ParseFunctionName();
270 if (!funcName.empty()) {
271 return *factory->ConcatFromString(concatString, factory->NewFromStdString(funcName));
272 }
273 }
274 }
275 return *concatString;
276 }
277
NameGetter(JSThread * thread,const JSHandle<JSObject> & self)278 JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle<JSObject> &self)
279 {
280 if (self->IsBoundFunction()) {
281 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
282 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
283 JSHandle<JSBoundFunction> boundFunction(self);
284 JSHandle<JSTaggedValue> target(thread, boundFunction->GetBoundTarget());
285
286 JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
287 JSHandle<JSTaggedValue> boundName = thread->GlobalConstants()->GetHandledBoundString();
288 JSHandle<JSTaggedValue> targetName = JSObject::GetProperty(thread, target, nameKey).GetValue();
289 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
290
291 JSHandle<EcmaString> handlePrefixString = JSTaggedValue::ToString(thread, boundName);
292 JSHandle<EcmaString> spaceString(globalConst->GetHandledSpaceString());
293 JSHandle<EcmaString> concatString = factory->ConcatFromString(handlePrefixString, spaceString);
294
295 EcmaString *newString;
296 if (!targetName->IsString()) {
297 newString = GetFunctionNameString(factory, concatString, target);
298 } else {
299 JSHandle<EcmaString> functionName = JSHandle<EcmaString>::Cast(targetName);
300 newString = *factory->ConcatFromString(concatString, functionName);
301 }
302
303 return JSTaggedValue(newString);
304 }
305
306 JSTaggedValue method = JSHandle<JSFunction>::Cast(self)->GetMethod();
307 if (method.IsUndefined()) {
308 return JSTaggedValue::Undefined();
309 }
310 Method *target = Method::Cast(method.GetTaggedObject());
311 if (target->IsNativeWithCallField()) {
312 return JSTaggedValue::Undefined();
313 }
314 auto [funcName, isASCII] = target->ParseFunctionNameView();
315 if (funcName.empty()) {
316 return thread->GlobalConstants()->GetEmptyString();
317 }
318 ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
319 const JSHandle<EcmaString> nameHdl = factory->NewFromUtf8(funcName, isASCII);
320 if (JSHandle<JSFunction>::Cast(self)->GetFunctionKind() == FunctionKind::GETTER_FUNCTION) {
321 return factory->ConcatFromString(
322 JSHandle<EcmaString>(thread->GlobalConstants()->GetHandledGetWithSpaceString()), nameHdl).GetTaggedValue();
323 }
324 if (JSHandle<JSFunction>::Cast(self)->GetFunctionKind() == FunctionKind::SETTER_FUNCTION) {
325 return factory->ConcatFromString(
326 JSHandle<EcmaString>(thread->GlobalConstants()->GetHandledSetWithSpaceString()), nameHdl).GetTaggedValue();
327 }
328 return nameHdl.GetTaggedValue();
329 }
330
LengthGetter(JSThread * thread,const JSHandle<JSObject> & self)331 JSTaggedValue JSFunction::LengthGetter(JSThread *thread, const JSHandle<JSObject> &self)
332 {
333 // LengthGetter only support BoundFunction
334 if (self->IsBoundFunction()) {
335 JSMutableHandle<JSBoundFunction> boundFunction(thread, self.GetTaggedValue());
336 JSHandle<JSTaggedValue> arguments(thread, boundFunction->GetBoundArguments());
337 uint32_t argsLength = TaggedArray::Cast(arguments->GetTaggedObject())->GetLength();
338 while (boundFunction->GetBoundTarget().IsBoundFunction()) {
339 boundFunction.Update(boundFunction->GetBoundTarget());
340 argsLength += TaggedArray::Cast(boundFunction->GetBoundArguments())->GetLength();
341 }
342
343 JSHandle<JSTaggedValue> target(thread, boundFunction->GetBoundTarget());
344 JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
345
346 bool targetHasLength =
347 JSTaggedValue::HasOwnProperty(thread, target, lengthKey);
348 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
349 uint32_t lengthValue = 0;
350 if (targetHasLength) {
351 JSHandle<JSTaggedValue> targetLength = JSTaggedValue::GetProperty(thread, target, lengthKey).GetValue();
352 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
353 if (targetLength->IsNumber()) {
354 lengthValue =
355 std::max(0.0, JSTaggedValue::ToNumber(thread, targetLength).GetNumber() -
356 static_cast<double>(argsLength));
357 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
358 }
359 }
360 return JSTaggedValue(lengthValue);
361 }
362
363 JSHandle<JSFunction> func(self);
364 return JSTaggedValue(func->GetLength());
365 }
366
OrdinaryHasInstance(JSThread * thread,const JSHandle<JSTaggedValue> & constructor,const JSHandle<JSTaggedValue> & obj)367 bool JSFunction::OrdinaryHasInstance(JSThread *thread, const JSHandle<JSTaggedValue> &constructor,
368 const JSHandle<JSTaggedValue> &obj)
369 {
370 // 1. If IsCallable(C) is false, return false.
371 if (!constructor->IsCallable()) {
372 return false;
373 }
374
375 // 2. If C has a [[BoundTargetFunction]] internal slot, then
376 // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
377 // b. Return InstanceofOperator(O,BC) (see 12.9.4).
378 if (constructor->IsBoundFunction()) {
379 STACK_LIMIT_CHECK(thread, false);
380 JSHandle<JSBoundFunction> boundFunction(thread, JSBoundFunction::Cast(constructor->GetTaggedObject()));
381 JSTaggedValue boundTarget = boundFunction->GetBoundTarget();
382 return JSObject::InstanceOf(thread, obj, JSHandle<JSTaggedValue>(thread, boundTarget));
383 }
384 // 3. If Type(O) is not Object, return false
385 if (!obj->IsECMAObject()) {
386 return false;
387 }
388
389 // 4. Let P be Get(C, "prototype").
390 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
391 JSHandle<JSTaggedValue> prototypeString = globalConst->GetHandledPrototypeString();
392 JSMutableHandle<JSTaggedValue> constructorPrototype(thread, JSTaggedValue::Undefined());
393 if (constructor->IsJSFunction()) {
394 JSHandle<JSFunction> ctor(thread, constructor->GetTaggedObject());
395 JSHandle<JSTaggedValue> ctorProtoOrHclass(thread, ctor->GetProtoOrHClass());
396 if (!ctorProtoOrHclass->IsHole()) {
397 if (!ctorProtoOrHclass->IsJSHClass()) {
398 constructorPrototype.Update(ctorProtoOrHclass);
399 } else {
400 JSTaggedValue ctorProto = JSHClass::Cast(ctorProtoOrHclass->GetTaggedObject())->GetProto();
401 constructorPrototype.Update(ctorProto);
402 }
403 } else {
404 constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue());
405 }
406 } else {
407 constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue());
408 }
409
410 // 5. ReturnIfAbrupt(P).
411 // no throw exception, so needn't return
412 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
413
414 // 6. If Type(P) is not Object, throw a TypeError exception.
415 if (!constructorPrototype->IsECMAObject()) {
416 THROW_TYPE_ERROR_AND_RETURN(thread, "HasInstance: is not Object", false);
417 }
418
419 // 7. Repeat
420 // a.Let O be O.[[GetPrototypeOf]]().
421 // b.ReturnIfAbrupt(O).
422 // c.If O is null, return false.
423 // d.If SameValue(P, O) is true, return true.
424 JSMutableHandle<JSTaggedValue> object(thread, obj.GetTaggedValue());
425 while (!object->IsNull()) {
426 object.Update(JSTaggedValue::GetPrototype(thread, object));
427 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
428 if (JSTaggedValue::SameValue(object, constructorPrototype)) {
429 return true;
430 }
431 }
432 return false;
433 }
434
MakeConstructor(JSThread * thread,const JSHandle<JSFunction> & func,const JSHandle<JSTaggedValue> & proto,bool writable)435 bool JSFunction::MakeConstructor(JSThread *thread, const JSHandle<JSFunction> &func,
436 const JSHandle<JSTaggedValue> &proto, bool writable)
437 {
438 ASSERT_PRINT(proto->IsHeapObject() || proto->IsUndefined(), "proto must be JSObject or Undefined");
439 ASSERT_PRINT(func->IsConstructor(), "func must be Constructor type");
440 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
441 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
442 JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
443
444 ASSERT_PRINT(func->GetProtoOrHClass().IsHole() && func->IsExtensible(),
445 "function doesn't has proto_type property and is extensible object");
446 ASSERT_PRINT(JSObject::HasProperty(thread, JSHandle<JSObject>(func), constructorKey),
447 "function must have constructor");
448
449 // proto.constructor = func
450 bool status = false;
451 if (proto->IsUndefined()) {
452 // Let prototype be ObjectCreate(%ObjectPrototype%).
453 JSHandle<JSTaggedValue> objPrototype = env->GetObjectFunctionPrototype();
454 PropertyDescriptor constructorDesc(thread, JSHandle<JSTaggedValue>::Cast(func), writable, false, true);
455 status = JSTaggedValue::DefinePropertyOrThrow(thread, objPrototype, constructorKey, constructorDesc);
456 } else {
457 PropertyDescriptor constructorDesc(thread, JSHandle<JSTaggedValue>::Cast(func), writable, false, true);
458 status = JSTaggedValue::DefinePropertyOrThrow(thread, proto, constructorKey, constructorDesc);
459 }
460 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
461
462 ASSERT_PRINT(status, "DefineProperty construct failed");
463 // func.prototype = proto
464 // Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]:
465 // prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}).
466 SetFunctionPrototypeOrInstanceHClass(thread, func, proto.GetTaggedValue());
467
468 ASSERT_PRINT(status, "DefineProperty proto_type failed");
469 return status;
470 }
471
Call(EcmaRuntimeCallInfo * info)472 JSTaggedValue JSFunction::Call(EcmaRuntimeCallInfo *info)
473 {
474 if (info == nullptr) {
475 return JSTaggedValue::Exception();
476 }
477
478 JSThread *thread = info->GetThread();
479 // 1. ReturnIfAbrupt(F).
480 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
481 JSHandle<JSTaggedValue> func = info->GetFunction();
482 // 2. If argumentsList was not passed, let argumentsList be a new empty List.
483 // 3. If IsCallable(F) is false, throw a TypeError exception.
484 if (!func->IsCallable()) {
485 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
486 THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception());
487 }
488
489 auto *hclass = func->GetTaggedObject()->GetClass();
490 if (hclass->IsClassConstructor()) {
491 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
492 THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call", JSTaggedValue::Exception());
493 }
494 return EcmaInterpreter::Execute(info);
495 }
496
Construct(EcmaRuntimeCallInfo * info)497 JSTaggedValue JSFunction::Construct(EcmaRuntimeCallInfo *info)
498 {
499 if (info == nullptr) {
500 return JSTaggedValue::Exception();
501 }
502
503 JSThread *thread = info->GetThread();
504 JSHandle<JSTaggedValue> func(info->GetFunction());
505 JSHandle<JSTaggedValue> target = info->GetNewTarget();
506 if (target->IsUndefined()) {
507 target = func;
508 info->SetNewTarget(target.GetTaggedValue());
509 }
510 if (!(func->IsConstructor() && target->IsConstructor())) {
511 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
512 THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
513 }
514
515 if (func->IsJSFunction()) {
516 return JSFunction::ConstructInternal(info);
517 } else if (func->IsJSProxy()) {
518 return JSProxy::ConstructInternal(info);
519 } else {
520 ASSERT(func->IsBoundFunction());
521 return JSBoundFunction::ConstructInternal(info);
522 }
523 }
524
Invoke(EcmaRuntimeCallInfo * info,const JSHandle<JSTaggedValue> & key)525 JSTaggedValue JSFunction::Invoke(EcmaRuntimeCallInfo *info, const JSHandle<JSTaggedValue> &key)
526 {
527 if (info == nullptr) {
528 return JSTaggedValue::Exception();
529 }
530
531 ASSERT(JSTaggedValue::IsPropertyKey(key));
532 JSThread *thread = info->GetThread();
533 JSHandle<JSTaggedValue> thisArg = info->GetThis();
534 JSHandle<JSTaggedValue> func(JSTaggedValue::GetProperty(thread, thisArg, key).GetValue());
535 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
536 info->SetFunction(func.GetTaggedValue());
537 return JSFunction::Call(info);
538 }
539
InvokeOptimizedEntrypoint(JSThread * thread,JSHandle<JSFunction> mainFunc,JSHandle<JSTaggedValue> & thisArg,CJSInfo * cjsInfo)540 JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> mainFunc,
541 JSHandle<JSTaggedValue> &thisArg, CJSInfo* cjsInfo)
542 {
543 ASSERT(thread->IsInManagedState());
544 if (mainFunc->IsClassConstructor()) {
545 {
546 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
547 JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
548 "class constructor cannot called without 'new'", StackCheck::NO);
549 thread->SetException(error.GetTaggedValue());
550 }
551 return thread->GetException();
552 }
553 Method *method = mainFunc->GetCallTarget();
554 size_t actualNumArgs = method->GetNumArgs();
555 const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
556 JSTaggedValue res;
557 std::vector<JSTaggedType> args;
558 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
559 RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType(), true);
560 #endif
561 if (mainFunc->IsCompiledFastCall()) {
562 // entry of aot
563 args = JSFunction::GetArgsData(true, thisArg, mainFunc, cjsInfo);
564 res = thread->GetEcmaVM()->FastCallAot(actualNumArgs, args.data(), prevFp);
565 } else {
566 args = JSFunction::GetArgsData(false, thisArg, mainFunc, cjsInfo);
567 // entry of aot
568 res = thread->GetCurrentEcmaContext()->ExecuteAot(actualNumArgs, args.data(), prevFp, false);
569 }
570 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
571 RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType());
572 #endif
573 if (thread->HasPendingException()) {
574 return thread->GetException();
575 }
576 return res;
577 }
578
GetArgsData(bool isFastCall,JSHandle<JSTaggedValue> & thisArg,JSHandle<JSFunction> mainFunc,CJSInfo * cjsInfo)579 std::vector<JSTaggedType> JSFunction::GetArgsData(bool isFastCall, JSHandle<JSTaggedValue> &thisArg,
580 JSHandle<JSFunction> mainFunc, CJSInfo* cjsInfo)
581 {
582 size_t argsNum;
583 uint32_t mandatoryNum;
584 Method *method = mainFunc->GetCallTarget();
585 size_t actualNumArgs = method->GetNumArgs();
586 if (isFastCall) {
587 argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 1;
588 mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS - 1;
589 } else {
590 argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS;
591 mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS;
592 }
593 std::vector<JSTaggedType> args(argsNum, JSTaggedValue::Undefined().GetRawData());
594 args[0] = mainFunc.GetTaggedValue().GetRawData();
595 if (isFastCall) {
596 args[1] = thisArg.GetTaggedValue().GetRawData(); // 1: args number
597 } else {
598 args[2] = thisArg.GetTaggedValue().GetRawData(); // 2: args number
599 }
600 if (cjsInfo != nullptr) {
601 args[mandatoryNum++] = cjsInfo->exportsHdl.GetTaggedValue().GetRawData();
602 args[mandatoryNum++] = cjsInfo->requireHdl.GetTaggedValue().GetRawData();
603 args[mandatoryNum++] = cjsInfo->moduleHdl.GetTaggedValue().GetRawData();
604 args[mandatoryNum++] = cjsInfo->filenameHdl.GetTaggedValue().GetRawData();
605 args[mandatoryNum] = cjsInfo->dirnameHdl.GetTaggedValue().GetRawData();
606 }
607 return args;
608 }
609
InvokeOptimizedEntrypoint(JSThread * thread,JSHandle<JSFunction> func,EcmaRuntimeCallInfo * info)610 JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> func,
611 EcmaRuntimeCallInfo *info)
612 {
613 ASSERT(thread->IsInManagedState());
614 Method *method = func->GetCallTarget();
615 JSTaggedValue resultValue;
616 size_t numArgs = method->GetNumArgsWithCallField();
617 bool needPushArgv = numArgs > info->GetArgsNumber();
618 const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
619 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
620 RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), func.GetTaggedType(), true);
621 #endif
622 if (func->IsCompiledFastCall()) {
623 if (needPushArgv) {
624 info = EcmaInterpreter::ReBuildRuntimeCallInfo(thread, info, numArgs);
625 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
626 }
627 JSTaggedType *stackArgs = info->GetArgs();
628 stackArgs[1] = stackArgs[0];
629 resultValue = thread->GetEcmaVM()->FastCallAot(info->GetArgsNumber(), stackArgs + 1, prevFp);
630 } else {
631 resultValue = thread->GetCurrentEcmaContext()->ExecuteAot(info->GetArgsNumber(),
632 info->GetArgs(), prevFp, needPushArgv);
633 }
634 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
635 RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), func.GetTaggedType());
636 #endif
637 return resultValue;
638 }
639
640 // [[Construct]]
ConstructInternal(EcmaRuntimeCallInfo * info)641 JSTaggedValue JSFunction::ConstructInternal(EcmaRuntimeCallInfo *info)
642 {
643 ASSERT(info != nullptr);
644 JSThread *thread = info->GetThread();
645 // func need to create a new handle, because optimized EcmaRuntimeCallInfo may overwrite this position.
646 JSHandle<JSFunction> func(thread, info->GetFunction().GetTaggedValue());
647 JSHandle<JSTaggedValue> newTarget(info->GetNewTarget());
648 ASSERT(newTarget->IsECMAObject());
649 if (!func->IsConstructor()) {
650 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
651 THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
652 }
653
654 JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
655 if (func->IsBase()) {
656 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
657 obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(func, newTarget));
658 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
659 }
660
661 JSTaggedValue resultValue;
662 info->SetThis(obj.GetTaggedValue());
663 if (func->IsCompiledCode()) {
664 resultValue = InvokeOptimizedEntrypoint(thread, func, info);
665 const JSTaggedType *curSp = thread->GetCurrentSPFrame();
666 InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(curSp);
667 JSTaggedType *prevSp = entryState->base.prev;
668 thread->SetCurrentSPFrame(prevSp);
669 } else {
670 resultValue = EcmaInterpreter::Execute(info);
671 }
672 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
673 // 9.3.2 [[Construct]] (argumentsList, newTarget)
674 if (resultValue.IsECMAObject()) {
675 return resultValue;
676 }
677 if (func->IsBase()) {
678 return obj.GetTaggedValue();
679 }
680 // derived ctor(sub class) return the obj which created by base ctor(parent class)
681 if (func->IsDerivedConstructor()) {
682 if (!resultValue.IsECMAObject() && !resultValue.IsUndefined()) {
683 THROW_TYPE_ERROR_AND_RETURN(thread,
684 "derived class constructor must return an object or undefined", JSTaggedValue::Exception());
685 }
686 return resultValue;
687 }
688 if (!resultValue.IsUndefined()) {
689 RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
690 THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
691 }
692 return obj.GetTaggedValue();
693 }
694
GetFunctionName(JSThread * thread,const JSHandle<JSFunctionBase> & func)695 JSHandle<JSTaggedValue> JSFunctionBase::GetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func)
696 {
697 JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
698
699 return JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(func), nameKey).GetValue();
700 }
701
SetFunctionName(JSThread * thread,const JSHandle<JSFunctionBase> & func,const JSHandle<JSTaggedValue> & name,const JSHandle<JSTaggedValue> & prefix)702 bool JSFunctionBase::SetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func,
703 const JSHandle<JSTaggedValue> &name, const JSHandle<JSTaggedValue> &prefix)
704 {
705 ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
706 ASSERT_PRINT(name->IsStringOrSymbol(), "name must be string or symbol");
707 bool needPrefix = false;
708 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
709 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
710 if (!prefix->IsUndefined()) {
711 ASSERT_PRINT(prefix->IsString(), "prefix must be string");
712 needPrefix = true;
713 }
714 // If Type(name) is Symbol, then
715 // Let description be name’s [[Description]] value.
716 // If description is undefined, let name be the empty String.
717 // Else, let name be the concatenation of "[", description, and "]".
718 JSHandle<EcmaString> functionName;
719 if (name->IsSymbol()) {
720 JSTaggedValue description = JSHandle<JSSymbol>::Cast(name)->GetDescription();
721 JSHandle<EcmaString> descriptionHandle(thread, description);
722 if (description.IsUndefined()) {
723 functionName = factory->GetEmptyString();
724 } else {
725 JSHandle<EcmaString> leftBrackets(globalConst->GetHandledLeftSquareBracketString());
726 JSHandle<EcmaString> rightBrackets(globalConst->GetHandledRightSquareBracketString());
727 functionName = factory->ConcatFromString(leftBrackets, descriptionHandle);
728 functionName = factory->ConcatFromString(functionName, rightBrackets);
729 }
730 } else {
731 functionName = JSHandle<EcmaString>::Cast(name);
732 }
733 EcmaString *newString;
734 if (needPrefix) {
735 JSHandle<EcmaString> handlePrefixString = JSTaggedValue::ToString(thread, prefix);
736 JSHandle<EcmaString> spaceString(globalConst->GetHandledSpaceString());
737 JSHandle<EcmaString> concatString = factory->ConcatFromString(handlePrefixString, spaceString);
738 newString = *factory->ConcatFromString(concatString, functionName);
739 } else {
740 newString = *functionName;
741 }
742 JSHandle<JSTaggedValue> nameHandle(thread, newString);
743 // String.prototype.trimLeft.name shoud be trimStart
744 if (!nameHandle.IsEmpty()
745 && nameHandle.GetTaggedValue() == globalConst->GetHandledTrimLeftString().GetTaggedValue()) {
746 nameHandle = globalConst->GetHandledTrimStartString();
747 }
748 // String.prototype.trimRight.name shoud be trimEnd
749 if (!nameHandle.IsEmpty()
750 && nameHandle.GetTaggedValue() == globalConst->GetHandledTrimRightString().GetTaggedValue()) {
751 nameHandle = globalConst->GetHandledTrimEndString();
752 }
753 JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
754 PropertyDescriptor nameDesc(thread, nameHandle, false, false, true);
755 JSHandle<JSTaggedValue> funcHandle(func);
756 return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, nameKey, nameDesc);
757 }
758
SetFunctionLength(JSThread * thread,const JSHandle<JSFunction> & func,JSTaggedValue length,bool cfg)759 bool JSFunction::SetFunctionLength(JSThread *thread, const JSHandle<JSFunction> &func, JSTaggedValue length, bool cfg)
760 {
761 ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
762 ASSERT_PRINT(length.IsInteger(), "length must be integer");
763 JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
764 ASSERT_PRINT(!JSTaggedValue::Less(thread, JSHandle<JSTaggedValue>(thread, length),
765 JSHandle<JSTaggedValue>(thread, JSTaggedValue(0))),
766 "length must be non negative integer");
767 PropertyDescriptor lengthDesc(thread, JSHandle<JSTaggedValue>(thread, length), false, false, cfg);
768 JSHandle<JSTaggedValue> funcHandle(func);
769 return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, lengthKeyHandle, lengthDesc);
770 }
771
772 // 9.4.1.2[[Construct]](argumentsList, newTarget)
ConstructInternal(EcmaRuntimeCallInfo * info)773 JSTaggedValue JSBoundFunction::ConstructInternal(EcmaRuntimeCallInfo *info)
774 {
775 JSThread *thread = info->GetThread();
776 JSHandle<JSBoundFunction> func(info->GetFunction());
777 JSHandle<JSTaggedValue> target(thread, func->GetBoundTarget());
778 if (!target->IsConstructor()) {
779 THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
780 }
781 JSHandle<JSTaggedValue> newTarget = info->GetNewTarget();
782 JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTarget.GetTaggedValue());
783 if (JSTaggedValue::SameValue(func.GetTaggedValue(), newTarget.GetTaggedValue())) {
784 newTargetMutable.Update(target.GetTaggedValue());
785 }
786
787 JSHandle<TaggedArray> boundArgs(thread, func->GetBoundArguments());
788 const uint32_t boundLength = boundArgs->GetLength();
789 const uint32_t argsLength = info->GetArgsNumber() + boundLength;
790 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
791 uint32_t argc = info->GetArgsNumber();
792 std::vector<JSTaggedType> argArray(argc);
793 for (uint32_t index = 0; index < argc; ++index) {
794 argArray[index] = info->GetCallArgValue(index).GetRawData();
795 }
796 JSTaggedType *currentSp = reinterpret_cast<JSTaggedType *>(info);
797 InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp);
798 JSTaggedType *prevSp = currentEntryState->base.prev;
799 thread->SetCurrentSPFrame(prevSp);
800 EcmaRuntimeCallInfo *runtimeInfo =
801 EcmaInterpreter::NewRuntimeCallInfo(thread, target, undefined, newTargetMutable, argsLength);
802 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
803 if (boundLength != 0) {
804 runtimeInfo->SetCallArg(boundLength, boundArgs);
805 }
806 for (uint32_t index = 0; index < argc; index++) {
807 runtimeInfo->SetCallArg(static_cast<uint32_t>(index + boundLength), JSTaggedValue(argArray[index]));
808 }
809 return JSFunction::Construct(runtimeInfo);
810 }
811
ProxyRevocFunctions(const JSThread * thread,const JSHandle<JSProxyRevocFunction> & revoker)812 void JSProxyRevocFunction::ProxyRevocFunctions(const JSThread *thread, const JSHandle<JSProxyRevocFunction> &revoker)
813 {
814 // 1.Let p be the value of F’s [[RevocableProxy]] internal slot.
815 JSTaggedValue proxy = revoker->GetRevocableProxy();
816 // 2.If p is null, return undefined.
817 if (proxy.IsNull()) {
818 return;
819 }
820
821 // 3.Set the value of F’s [[RevocableProxy]] internal slot to null.
822 revoker->SetRevocableProxy(thread, JSTaggedValue::Null());
823
824 // 4.Assert: p is a Proxy object.
825 ASSERT(proxy.IsJSProxy());
826 JSHandle<JSProxy> proxyHandle(thread, proxy);
827
828 // 5 ~ 6 Set internal slot of p to null.
829 proxyHandle->SetTarget(thread, JSTaggedValue::Null());
830 proxyHandle->SetHandler(thread, JSTaggedValue::Null());
831 proxyHandle->SetIsRevoked(true);
832 }
833
AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo * argv)834 JSTaggedValue JSFunction::AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo *argv)
835 {
836 THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(),
837 "Under strict mode, 'caller' and 'arguments' properties must not be accessed.",
838 JSTaggedValue::Exception());
839 }
840
IntlNameGetter(JSThread * thread,const JSHandle<JSObject> & self)841 JSTaggedValue JSIntlBoundFunction::IntlNameGetter(JSThread *thread, [[maybe_unused]] const JSHandle<JSObject> &self)
842 {
843 return thread->GlobalConstants()->GetEmptyString();
844 }
845
SetFunctionNameNoPrefix(JSThread * thread,JSFunction * func,JSTaggedValue name)846 void JSFunction::SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name)
847 {
848 ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
849 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
850 const GlobalEnvConstants *globalConst = thread->GlobalConstants();
851
852 JSHandle<JSTaggedValue> funcHandle(thread, func);
853 {
854 JSMutableHandle<JSTaggedValue> nameHandle(thread, JSTaggedValue::Undefined());
855 if (!name.IsSymbol()) {
856 nameHandle.Update(name);
857 } else {
858 JSHandle<JSTaggedValue> nameBegin(thread, name);
859 JSTaggedValue description = JSSymbol::Cast(name.GetTaggedObject())->GetDescription();
860 if (description.IsUndefined()) {
861 nameHandle.Update(globalConst->GetEmptyString());
862 } else {
863 JSHandle<EcmaString> leftBrackets(globalConst->GetHandledLeftSquareBracketString());
864 JSHandle<EcmaString> rightBrackets(globalConst->GetHandledRightSquareBracketString());
865 JSHandle<EcmaString> concatName = factory->ConcatFromString(leftBrackets,
866 JSHandle<EcmaString>(thread, JSSymbol::Cast(nameBegin->GetTaggedObject())->GetDescription()));
867 concatName = factory->ConcatFromString(concatName, rightBrackets);
868 nameHandle.Update(concatName.GetTaggedValue());
869 }
870 }
871 PropertyDescriptor nameDesc(thread, nameHandle, false, false, true);
872 JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, globalConst->GetHandledNameString(), nameDesc);
873 }
874 }
875
GetInstanceJSHClass(JSThread * thread,JSHandle<JSFunction> constructor,JSHandle<JSTaggedValue> newTarget)876 JSHandle<JSHClass> JSFunction::GetInstanceJSHClass(JSThread *thread, JSHandle<JSFunction> constructor,
877 JSHandle<JSTaggedValue> newTarget)
878 {
879 JSHandle<JSHClass> ctorInitialJSHClass(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor));
880 // newTarget is construct itself
881 if (newTarget.GetTaggedValue() == constructor.GetTaggedValue()) {
882 return ctorInitialJSHClass;
883 }
884
885 // newTarget is derived-class of constructor
886 if (newTarget->IsJSFunction()) {
887 JSHandle<JSFunction> newTargetFunc = JSHandle<JSFunction>::Cast(newTarget);
888 if (newTargetFunc->IsDerivedConstructor()) {
889 JSMutableHandle<JSTaggedValue> mutableNewTarget(thread, newTarget.GetTaggedValue());
890 JSMutableHandle<JSTaggedValue> mutableNewTargetProto(thread, JSTaggedValue::Undefined());
891 while (!mutableNewTargetProto->IsNull()) {
892 mutableNewTargetProto.Update(JSTaggedValue::GetPrototype(thread, mutableNewTarget));
893 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread);
894 if (mutableNewTargetProto.GetTaggedValue() == constructor.GetTaggedValue()) {
895 return GetOrCreateDerivedJSHClass(thread, newTargetFunc, ctorInitialJSHClass);
896 }
897 mutableNewTarget.Update(mutableNewTargetProto.GetTaggedValue());
898 }
899 }
900 }
901
902 // ECMA2015 9.1.15 3.Let proto be Get(constructor, "prototype").
903 JSMutableHandle<JSTaggedValue> prototype(thread, JSTaggedValue::Undefined());
904 if (newTarget->IsJSFunction()) {
905 JSHandle<JSFunction> newTargetFunc = JSHandle<JSFunction>::Cast(newTarget);
906 FunctionKind kind = newTargetFunc->GetFunctionKind();
907 if (HasPrototype(kind)) {
908 prototype.Update(PrototypeGetter(thread, JSHandle<JSObject>::Cast(newTargetFunc)));
909 }
910 } else {
911 // Such case: bound function and define a "prototype" property.
912 JSHandle<JSTaggedValue> customizePrototype =
913 JSTaggedValue::GetProperty(thread, newTarget, thread->GlobalConstants()->GetHandledPrototypeString())
914 .GetValue();
915 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread);
916 prototype.Update(customizePrototype.GetTaggedValue());
917 // Reload JSHClass of constructor, where the lookup of 'prototype' property may change it.
918 ctorInitialJSHClass = JSHandle<JSHClass>(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor));
919 }
920
921 if (!prototype->IsECMAObject()) {
922 prototype.Update(constructor->GetFunctionPrototype());
923 }
924
925 JSHandle<JSHClass> newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
926 newJSHClass->SetElementsKind(ElementsKind::GENERIC);
927 newJSHClass->SetPrototype(thread, prototype);
928
929 return newJSHClass;
930 }
931
GetOrCreateDerivedJSHClass(JSThread * thread,JSHandle<JSFunction> derived,JSHandle<JSHClass> ctorInitialJSHClass)932 JSHandle<JSHClass> JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle<JSFunction> derived,
933 JSHandle<JSHClass> ctorInitialJSHClass)
934 {
935 JSTaggedValue protoOrHClass(derived->GetProtoOrHClass());
936 // has cached JSHClass, return directly
937 if (protoOrHClass.IsJSHClass()) {
938 return JSHandle<JSHClass>(thread, protoOrHClass);
939 }
940 JSHandle<JSHClass> newJSHClass;
941 if (thread->GetEcmaVM()->GetJSOptions().IsEnableInlinePropertyOptimization()) {
942 bool isStartObjSizeTracking = true;
943 uint32_t expectedOfProperties = CalcuExpotedOfProperties(derived, &isStartObjSizeTracking);
944 if (isStartObjSizeTracking) {
945 newJSHClass = JSHClass::CloneAndIncInlinedProperties(thread, ctorInitialJSHClass, expectedOfProperties);
946 newJSHClass->StartObjSizeTracking();
947 } else {
948 newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
949 }
950 } else {
951 newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
952 }
953 newJSHClass->SetElementsKind(ElementsKind::GENERIC);
954 // guarante derived has function prototype
955 JSHandle<JSTaggedValue> prototype(thread, derived->GetProtoOrHClass());
956 ASSERT(!prototype->IsHole());
957 newJSHClass->SetPrototype(thread, prototype);
958 derived->SetProtoOrHClass(thread, newJSHClass);
959
960 if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
961 thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(derived.GetTaggedType(),
962 newJSHClass.GetTaggedType());
963 }
964
965 return newJSHClass;
966 }
967
GetRecordName() const968 CString JSFunction::GetRecordName() const
969 {
970 JSTaggedValue module = GetModule();
971 if (module.IsSourceTextModule()) {
972 return SourceTextModule::GetModuleName(module);
973 }
974 if (module.IsString()) {
975 return ConvertToString(module);
976 }
977 LOG_INTERPRETER(DEBUG) << "record name is undefined";
978 return "";
979 }
980
981 // Those interface below is discarded
InitializeJSFunction(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSFunction> & func,FunctionKind kind)982 void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle<GlobalEnv> &env,
983 const JSHandle<JSFunction> &func, FunctionKind kind)
984 {
985 InitializeJSFunction(thread, func, kind);
986 }
987
NameSetter(JSThread * thread,const JSHandle<JSObject> & self,const JSHandle<JSTaggedValue> & value,bool mayThrow)988 bool JSFunction::NameSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
989 [[maybe_unused]] bool mayThrow)
990 {
991 if (self->IsPropertiesDict()) {
992 // replace setter with value
993 JSHandle<JSTaggedValue> nameString = thread->GlobalConstants()->GetHandledNameString();
994 return self->UpdatePropertyInDictionary(thread, nameString.GetTaggedValue(), value.GetTaggedValue());
995 }
996 self->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, value.GetTaggedValue());
997 return true;
998 }
999
1000 // NOTE: move to INL file?
SetFunctionLength(const JSThread * thread,JSTaggedValue length)1001 void JSFunction::SetFunctionLength(const JSThread *thread, JSTaggedValue length)
1002 {
1003 ASSERT(!IsPropertiesDict());
1004 SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, length);
1005 }
1006
1007 // static
SetFunctionExtraInfo(JSThread * thread,const JSHandle<JSFunction> & func,void * nativeFunc,const NativePointerCallback & deleter,void * data,size_t nativeBindingsize,Concurrent isConcurrent)1008 void JSFunction::SetFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
1009 const NativePointerCallback &deleter, void *data, size_t nativeBindingsize,
1010 Concurrent isConcurrent)
1011 {
1012 JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(*func, HASH_OFFSET);
1013 EcmaVM *vm = thread->GetEcmaVM();
1014 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField));
1015 JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data,
1016 false, nativeBindingsize, isConcurrent);
1017 if (!func->HasHash()) {
1018 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1019 return;
1020 }
1021 if (value->IsHeapObject()) {
1022 if (value->IsJSNativePointer()) {
1023 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1024 return;
1025 }
1026 JSHandle<TaggedArray> array(value);
1027
1028 uint32_t nativeFieldCount = array->GetExtraLength();
1029 if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1030 array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1031 } else {
1032 JSHandle<TaggedArray> newArray = vm->GetFactory()->NewTaggedArray(nativeFieldCount + RESOLVED_MAX_SIZE);
1033 newArray->SetExtraLength(nativeFieldCount);
1034 for (uint32_t i = 0; i < nativeFieldCount; i++) {
1035 newArray->Set(thread, i, array->Get(i));
1036 }
1037 newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX));
1038 newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1039 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1040 }
1041 } else {
1042 JSHandle<TaggedArray> newArray = vm->GetFactory()->NewTaggedArray(RESOLVED_MAX_SIZE);
1043 newArray->SetExtraLength(0);
1044 newArray->Set(thread, HASH_INDEX, value);
1045 newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer);
1046 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1047 }
1048 }
1049
1050 // static
SetSFunctionExtraInfo(JSThread * thread,const JSHandle<JSFunction> & func,void * nativeFunc,const NativePointerCallback & deleter,void * data,size_t nativeBindingsize)1051 void JSFunction::SetSFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
1052 const NativePointerCallback &deleter, void *data, size_t nativeBindingsize)
1053 {
1054 JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(*func, HASH_OFFSET);
1055 EcmaVM *vm = thread->GetEcmaVM();
1056 JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField));
1057 JSHandle<JSNativePointer> pointer =
1058 vm->GetFactory()->NewSJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize);
1059 if (!func->HasHash()) {
1060 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1061 return;
1062 }
1063 if (value->IsHeapObject()) {
1064 if (value->IsJSNativePointer()) {
1065 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1066 return;
1067 }
1068 JSHandle<TaggedArray> array(value);
1069
1070 uint32_t nativeFieldCount = array->GetExtraLength();
1071 if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1072 array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1073 } else {
1074 JSHandle<TaggedArray> newArray =
1075 vm->GetFactory()->NewSTaggedArrayWithoutInit(nativeFieldCount + RESOLVED_MAX_SIZE);
1076 newArray->SetExtraLength(nativeFieldCount);
1077 for (uint32_t i = 0; i < nativeFieldCount; i++) {
1078 newArray->Set(thread, i, array->Get(i));
1079 }
1080 newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX));
1081 newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1082 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1083 }
1084 } else {
1085 JSHandle<TaggedArray> newArray = vm->GetFactory()->NewSTaggedArrayWithoutInit(RESOLVED_MAX_SIZE);
1086 newArray->SetExtraLength(0);
1087 newArray->Set(thread, HASH_INDEX, value);
1088 newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer);
1089 Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1090 }
1091 }
1092
SetProfileTypeInfo(const JSThread * thread,const JSHandle<JSFunction> & func,const JSHandle<JSTaggedValue> & value,BarrierMode mode)1093 void JSFunction::SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
1094 const JSHandle<JSTaggedValue> &value, BarrierMode mode)
1095 {
1096 JSHandle<ProfileTypeInfoCell> handleRaw(thread, func->GetRawProfileTypeInfo());
1097 if (handleRaw->IsEmptyProfileTypeInfoCell(thread)) {
1098 JSHandle<ProfileTypeInfoCell> handleProfileTypeInfoCell =
1099 thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(value);
1100 func->SetRawProfileTypeInfo(thread, handleProfileTypeInfoCell, WRITE_BARRIER);
1101 return;
1102 }
1103 handleRaw->SetValue(thread, value, mode);
1104 }
1105
UpdateProfileTypeInfoCell(JSThread * thread,JSHandle<FunctionTemplate> literalFunc,JSHandle<JSFunction> targetFunc)1106 void JSFunction::UpdateProfileTypeInfoCell(JSThread *thread, JSHandle<FunctionTemplate> literalFunc,
1107 JSHandle<JSFunction> targetFunc)
1108 {
1109 auto profileTypeInfoCellVal = literalFunc->GetRawProfileTypeInfo();
1110 ASSERT(profileTypeInfoCellVal.IsProfileTypeInfoCell());
1111 auto profileTypeInfoCell = ProfileTypeInfoCell::Cast(profileTypeInfoCellVal);
1112 if (profileTypeInfoCell->IsEmptyProfileTypeInfoCell(thread)) {
1113 JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
1114 JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
1115 thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
1116 literalFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
1117 targetFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
1118 } else {
1119 ProfileTypeInfoCell::Cast(profileTypeInfoCell)->UpdateProfileTypeInfoCellType(thread);
1120 targetFunc->SetRawProfileTypeInfo(thread, profileTypeInfoCellVal);
1121 }
1122 }
1123
SetJitMachineCodeCache(const JSThread * thread,const JSHandle<MachineCode> & machineCode)1124 void JSFunction::SetJitMachineCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode)
1125 {
1126 JSHandle<ProfileTypeInfoCell> handleRaw(thread, GetRawProfileTypeInfo());
1127 ASSERT(!handleRaw->IsEmptyProfileTypeInfoCell(thread));
1128 handleRaw->SetMachineCode(thread, machineCode.GetTaggedValue().CreateAndGetWeakRef(), WRITE_BARRIER);
1129 }
1130
SetBaselineJitCodeCache(const JSThread * thread,const JSHandle<MachineCode> & machineCode)1131 void JSFunction::SetBaselineJitCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode)
1132 {
1133 JSHandle<ProfileTypeInfoCell> handleRaw(thread, GetRawProfileTypeInfo());
1134 if (handleRaw->IsEmptyProfileTypeInfoCell(thread)) {
1135 LOG_BASELINEJIT(ERROR) << "skip set baselinejit cache, as profileTypeInfoCell is empty.";
1136 return;
1137 }
1138 handleRaw->SetBaselineCode(thread, machineCode.GetTaggedValue().CreateAndGetWeakRef(), WRITE_BARRIER);
1139 }
1140
GetFunctionExtraInfo() const1141 JSTaggedValue JSFunctionBase::GetFunctionExtraInfo() const
1142 {
1143 JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
1144 JSTaggedValue value(hashField);
1145 if (value.IsHeapObject()) {
1146 if (value.IsTaggedArray()) {
1147 TaggedArray *array = TaggedArray::Cast(value.GetTaggedObject());
1148 uint32_t nativeFieldCount = array->GetExtraLength();
1149 if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1150 return array->Get(nativeFieldCount + FUNCTION_EXTRA_INDEX);
1151 }
1152 }
1153 if (value.IsJSNativePointer()) {
1154 return value;
1155 }
1156 JSType valueType = value.GetTaggedObject()->GetClass()->GetObjectType();
1157 JSType thisType = this->GetClass()->GetObjectType();
1158 LOG_ECMA(FATAL) << "this branch is unreachable, thisType is " << static_cast<uint8_t>(thisType)
1159 << ", value type is " << static_cast<uint8_t>(valueType);
1160 UNREACHABLE();
1161 }
1162 return JSTaggedValue::Undefined();
1163 }
1164
GetNativeFunctionExtraInfo() const1165 JSTaggedValue JSFunction::GetNativeFunctionExtraInfo() const
1166 {
1167 JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
1168 JSTaggedValue value(hashField);
1169 if (value.CheckIsJSNativePointer()) {
1170 return value;
1171 }
1172 return JSTaggedValue::Undefined();
1173 }
1174
InitializeForConcurrentFunction(JSThread * thread,JSHandle<JSFunction> & func)1175 void JSFunction::InitializeForConcurrentFunction(JSThread *thread, JSHandle<JSFunction> &func)
1176 {
1177 JSHandle<Method> method(thread, func->GetMethod());
1178 JSMutableHandle<JSTaggedValue> sendableEnv(thread, JSTaggedValue::Undefined());
1179 if (func->IsSharedFunction() && !func->GetModule().IsUndefined()) {
1180 sendableEnv.Update(SourceTextModule::Cast(func->GetModule())->GetSendableEnv());
1181 }
1182 const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
1183 if (jsPandaFile == nullptr) {
1184 LOG_ECMA(ERROR) << "JSPandaFile is nullptr";
1185 return;
1186 }
1187 ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc();
1188 ecmascript::CString recordName = method->GetRecordNameStr();
1189
1190 // check ESM or CJS
1191 ecmascript::JSRecordInfo *recordInfo = jsPandaFile->CheckAndGetRecordInfo(recordName);
1192 if (recordInfo == nullptr) {
1193 CString msg = "Cannot find module '" + recordName + "' , which is application Entry Point";
1194 LOG_ECMA(ERROR) << msg;
1195 return;
1196 }
1197
1198 if (!jsPandaFile->IsModule(recordInfo)) {
1199 LOG_ECMA(DEBUG) << "Current function is not from ES Module's file.";
1200 return;
1201 }
1202 ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
1203 LOG_ECMA(DEBUG) << "CompileMode is " << (jsPandaFile->IsBundlePack() ? "jsbundle" : "esmodule");
1204 JSHandle<ecmascript::JSTaggedValue> moduleRecord =
1205 ModuleResolver::HostResolveImportedModule(thread, moduleName, recordName);
1206 RETURN_IF_ABRUPT_COMPLETION(thread);
1207 ecmascript::SourceTextModule::Instantiate(thread, moduleRecord);
1208 RETURN_IF_ABRUPT_COMPLETION(thread);
1209 JSHandle<ecmascript::SourceTextModule> module = JSHandle<ecmascript::SourceTextModule>::Cast(moduleRecord);
1210 module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED);
1211 ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module, method);
1212 RETURN_IF_ABRUPT_COMPLETION(thread);
1213 if (!jsPandaFile->IsBundlePack() && func->IsSharedFunction()) {
1214 JSHandle<JSTaggedValue> sendableClassRecord = moduleManager->GenerateSendableFuncModule(moduleRecord);
1215 SourceTextModule::Cast(sendableClassRecord.GetTaggedValue())->SetSendableEnv(thread, sendableEnv);
1216 func->SetModule(thread, sendableClassRecord);
1217 } else {
1218 func->SetModule(thread, moduleRecord);
1219 }
1220
1221 // for debugger, to notify the script loaded and parsed which the concurrent function is in
1222 auto *notificationMgr = thread->GetEcmaVM()->GetJsDebuggerManager()->GetNotificationManager();
1223 notificationMgr->LoadModuleEvent(moduleName, recordName);
1224 }
1225
IsSendableOrConcurrentFunction() const1226 bool JSFunction::IsSendableOrConcurrentFunction() const
1227 {
1228 if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction() ||
1229 this->GetFunctionKind() == ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
1230 return true;
1231 }
1232 return false;
1233 }
1234
IsSharedFunction() const1235 bool JSFunction::IsSharedFunction() const
1236 {
1237 if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction()) {
1238 return true;
1239 }
1240 return false;
1241 }
1242
SetCompiledFuncEntry(uintptr_t codeEntry,bool isFastCall)1243 void JSFunctionBase::SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall)
1244 {
1245 ASSERT(codeEntry != 0);
1246 SetCodeEntry(codeEntry);
1247 SetIsCompiledFastCall(isFastCall);
1248 SetCompiledCodeBit(true);
1249 }
1250
SetJitCompiledFuncEntry(JSThread * thread,JSHandle<MachineCode> & machineCode,bool isFastCall)1251 void JSFunction::SetJitCompiledFuncEntry(JSThread *thread, JSHandle<MachineCode> &machineCode, bool isFastCall)
1252 {
1253 uintptr_t codeEntry = machineCode->GetFuncAddr();
1254 ASSERT(codeEntry != 0);
1255
1256 SetMachineCode(thread, machineCode);
1257 SetCompiledFuncEntry(codeEntry, isFastCall);
1258 }
1259
SetJitHotnessCnt(uint16_t cnt)1260 void JSFunction::SetJitHotnessCnt(uint16_t cnt)
1261 {
1262 JSTaggedValue profileTypeInfoVal = GetProfileTypeInfo();
1263 if (!profileTypeInfoVal.IsUndefined()) {
1264 ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
1265 profileTypeInfo->SetJitHotnessCnt(cnt);
1266 }
1267 }
1268
ClearCompiledCodeFlags()1269 void JSFunctionBase::ClearCompiledCodeFlags()
1270 {
1271 SetCompiledCodeBit(false);
1272 SetIsCompiledFastCall(false);
1273 }
1274
ClearMachineCode(const JSThread * thread)1275 void JSFunction::ClearMachineCode(const JSThread *thread)
1276 {
1277 SetMachineCode(thread, JSTaggedValue::Undefined());
1278 }
1279 } // namespace panda::ecmascript
1280