!7436 【ark】optimize napi_call_function

Merge pull request !7436 from huangzhenghua/master20240516
This commit is contained in:
openharmony_ci 2024-06-04 02:11:43 +00:00 committed by Gitee
commit 7c36338bd1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
16 changed files with 152 additions and 123 deletions

View File

@ -42,7 +42,7 @@ JSTaggedValue BuiltinsWeakRef::WeakRefConstructor(EcmaRuntimeCallInfo *argv)
JSHandle<JSObject> obj = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 4. Perform ! AddToKeptObjects(target).
thread->GetEcmaVM()->GetHeap()->AddToKeptObjects(target);
thread->GetCurrentEcmaContext()->AddToKeptObjects(target);
// 5. Set weakRef.[[WeakRefTarget]] to target.
// 6. Return weakRef.
JSHandle<JSWeakRef> weakRef = JSHandle<JSWeakRef>::Cast(obj);

View File

@ -32,6 +32,8 @@ public:
oldState_ = self_->GetState();
if constexpr (std::is_same_v<DaemonThread, T>) {
if (oldState_ != newState) {
ASSERT(hasSwitchState_ == false);
hasSwitchState_ = true;
if constexpr (newState == ThreadState::RUNNING) {
self_->TransferDaemonThreadToRunning();
} else {
@ -52,6 +54,8 @@ public:
vm->IncreaseUpdateThreadStateTransCount();
}
#endif
ASSERT(hasSwitchState_ == false);
hasSwitchState_ = true;
self_->UpdateState(newState);
}
}
@ -59,7 +63,7 @@ public:
~ThreadStateTransitionScope()
{
if (oldState_ != self_->GetState()) {
if (hasSwitchState_) {
if constexpr (std::is_same_v<DaemonThread, T>) {
if (oldState_ == ThreadState::RUNNING) {
self_->TransferDaemonThreadToRunning();
@ -75,6 +79,7 @@ public:
private:
T* self_;
ThreadState oldState_;
bool hasSwitchState_ {false};
NO_COPY_SEMANTIC(ThreadStateTransitionScope);
};

View File

@ -37,6 +37,7 @@
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/log.h"
#include "ecmascript/log_wrapper.h"
#include "ecmascript/module/module_path_helper.h"
@ -192,7 +193,10 @@ EcmaContext::~EcmaContext()
}
handleStorageNodes_.clear();
currentHandleStorageIndex_ = -1;
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
handleScopeCount_ = 0;
primitiveScopeCount_ = 0;
#endif
handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr;
for (auto n : primitiveStorageNodes_) {
@ -200,7 +204,6 @@ EcmaContext::~EcmaContext()
}
primitiveStorageNodes_.clear();
currentPrimitiveStorageIndex_ = -1;
primitiveScopeCount_ = 0;
primitiveScopeStorageNext_ = primitiveScopeStorageEnd_ = nullptr;
if (vm_->IsEnableBaselineJit() || vm_->IsEnableFastJit()) {
@ -779,10 +782,12 @@ void EcmaContext::PrintJSErrorInfo(JSThread *thread, const JSHandle<JSTaggedValu
bool EcmaContext::HasPendingJob()
{
// This interface only determines whether PromiseJobQueue is empty, rather than ScriptJobQueue.
if (UNLIKELY(thread_->HasTerminated())) {
return false;
}
return job::MicroJobQueue::HasPendingJob(thread_, GetMicroJobQueue());
TaggedQueue* promiseQueue = TaggedQueue::Cast(GetMicroJobQueue()->GetPromiseJobQueue().GetTaggedObject());
return !promiseQueue->Empty();
}
bool EcmaContext::ExecutePromisePendingJob()
@ -1184,4 +1189,28 @@ void EcmaContext::RemoveSustainingJSHandle(SustainingJSHandle *sustainingHandle)
sustainingJSHandleList_->RemoveSustainingJSHandle(sustainingHandle);
}
}
void EcmaContext::ClearKeptObjects()
{
if (LIKELY(GetGlobalEnv()->GetTaggedWeakRefKeepObjects().IsUndefined())) {
return;
}
GetGlobalEnv()->SetWeakRefKeepObjects(thread_, JSTaggedValue::Undefined());
hasKeptObjects_ = false;
}
void EcmaContext::AddToKeptObjects(JSHandle<JSTaggedValue> value)
{
JSHandle<GlobalEnv> globalEnv = GetGlobalEnv();
JSHandle<LinkedHashSet> linkedSet;
if (globalEnv->GetWeakRefKeepObjects()->IsUndefined()) {
linkedSet = LinkedHashSet::Create(thread_);
} else {
linkedSet = JSHandle<LinkedHashSet>(thread_,
LinkedHashSet::Cast(globalEnv->GetWeakRefKeepObjects()->GetTaggedObject()));
}
linkedSet = LinkedHashSet::Add(thread_, linkedSet, value);
globalEnv->SetWeakRefKeepObjects(thread_, linkedSet);
hasKeptObjects_ = true;
}
} // namespace panda::ecmascript

View File

@ -370,6 +370,7 @@ public:
return currentHandleStorageIndex_;
}
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
void HandleScopeCountAdd()
{
handleScopeCount_++;
@ -380,6 +381,17 @@ public:
handleScopeCount_--;
}
void PrimitiveScopeCountAdd()
{
primitiveScopeCount_++;
}
void PrimitiveScopeCountDec()
{
primitiveScopeCount_--;
}
#endif
void SetLastHandleScope(EcmaHandleScope *scope)
{
lastHandleScope_ = scope;
@ -415,16 +427,6 @@ public:
return currentPrimitiveStorageIndex_;
}
void PrimitiveScopeCountAdd()
{
primitiveScopeCount_++;
}
void PrimitiveScopeCountDec()
{
primitiveScopeCount_--;
}
void SetLastPrimitiveScope(EcmaHandleScope *scope)
{
lastPrimitiveScope_ = scope;
@ -561,6 +563,12 @@ public:
void AddSustainingJSHandle(SustainingJSHandle*);
void RemoveSustainingJSHandle(SustainingJSHandle*);
void ClearKeptObjects();
void AddToKeptObjects(JSHandle<JSTaggedValue> value);
inline bool HasKeptObjects() const
{
return hasKeptObjects_;
}
private:
void CJSExecution(JSHandle<JSFunction> &func, JSHandle<JSTaggedValue> &thisArg,
const JSPandaFile *jsPandaFile, std::string_view entryPoint);
@ -658,7 +666,10 @@ private:
JSTaggedType *handleScopeStorageEnd_ {nullptr};
std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> handleStorageNodes_ {};
int32_t currentHandleStorageIndex_ {-1};
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
int32_t handleScopeCount_ {0};
int32_t primitiveScopeCount_ {0};
#endif
EcmaHandleScope *lastHandleScope_ {nullptr};
// PrimitveScope
static constexpr int32_t MIN_PRIMITIVE_STORAGE_SIZE = 2;
@ -666,7 +677,6 @@ private:
JSTaggedType *primitiveScopeStorageEnd_ {nullptr};
std::vector<std::array<JSTaggedType, NODE_BLOCK_SIZE> *> primitiveStorageNodes_ {};
int32_t currentPrimitiveStorageIndex_ {-1};
int32_t primitiveScopeCount_ {0};
EcmaHandleScope *lastPrimitiveScope_ {nullptr};
// Frame pointer
@ -688,6 +698,8 @@ private:
// SustainingJSHandleList for jit compile hold ref
SustainingJSHandleList *sustainingJSHandleList_ {nullptr};
bool hasKeptObjects_ {false};
friend class EcmaHandleScope;
friend class JSPandaFileExecutor;
friend class ObjectFactory;

View File

@ -275,6 +275,7 @@ void GlobalEnvConstants::InitSharedMiscellanious(JSThread *thread, ObjectFactory
// Specials
SetConstant(ConstantIndex::UNDEFINED_INDEX, JSTaggedValue::Undefined());
SetConstant(ConstantIndex::NULL_INDEX, JSTaggedValue::Null());
SetConstant(ConstantIndex::HOLE_INDEX, JSTaggedValue::Hole());
SetConstant(ConstantIndex::TRUE_INDEX, JSTaggedValue::True());
SetConstant(ConstantIndex::FALSE_INDEX, JSTaggedValue::False());
// Emptys

View File

@ -626,6 +626,7 @@ class ObjectFactory;
#define SHARED_GLOBAL_ENV_CONSTANT_SPECIAL(V) \
V(JSTaggedValue, Undefined, UNDEFINED_INDEX, ecma_roots_special) \
V(JSTaggedValue, Null, NULL_INDEX, ecma_roots_special) \
V(JSTaggedValue, Hole, HOLE_INDEX, ecma_roots_special) \
V(JSTaggedValue, True, TRUE_INDEX, ecma_roots_special) \
V(JSTaggedValue, False, FALSE_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptyString, EMPTY_STRING_OBJECT_INDEX, ecma_roots_special) \

View File

@ -126,11 +126,4 @@ void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue>
}
}
}
bool MicroJobQueue::HasPendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue());
return !promiseQueue->Empty();
}
} // namespace panda::ecmascript::job

View File

@ -39,7 +39,6 @@ public:
static void EnqueueJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue, QueueType queueType,
const JSHandle<JSFunction> &job, const JSHandle<TaggedArray> &argv);
static void ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue);
static bool HasPendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue);
static constexpr size_t PROMISE_JOB_QUEUE_OFFSET = Record::SIZE;
ACCESSORS(PromiseJobQueue, PROMISE_JOB_QUEUE_OFFSET, SCRIPT_JOB_QUEUE_OFFSET);

View File

@ -629,21 +629,23 @@ size_t JSThread::GetBuiltinPrototypeHClassOffset(BuiltinTypeId type, bool isArch
void JSThread::CheckSwitchDebuggerBCStub()
{
auto isDebug = GetEcmaVM()->GetJsDebuggerManager()->IsDebugMode();
if (isDebug &&
glueData_.bcDebuggerStubEntries_.Get(0) == glueData_.bcDebuggerStubEntries_.Get(1)) {
for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
auto stubEntry = glueData_.bcStubEntries_.Get(i);
auto debuggerStubEbtry = glueData_.bcDebuggerStubEntries_.Get(i);
glueData_.bcDebuggerStubEntries_.Set(i, stubEntry);
glueData_.bcStubEntries_.Set(i, debuggerStubEbtry);
if (LIKELY(!isDebug)) {
if (glueData_.bcStubEntries_.Get(0) == glueData_.bcStubEntries_.Get(1)) {
for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
auto stubEntry = glueData_.bcDebuggerStubEntries_.Get(i);
auto debuggerStubEbtry = glueData_.bcStubEntries_.Get(i);
glueData_.bcStubEntries_.Set(i, stubEntry);
glueData_.bcDebuggerStubEntries_.Set(i, debuggerStubEbtry);
}
}
} else if (!isDebug &&
glueData_.bcStubEntries_.Get(0) == glueData_.bcStubEntries_.Get(1)) {
for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
auto stubEntry = glueData_.bcDebuggerStubEntries_.Get(i);
auto debuggerStubEbtry = glueData_.bcStubEntries_.Get(i);
glueData_.bcStubEntries_.Set(i, stubEntry);
glueData_.bcDebuggerStubEntries_.Set(i, debuggerStubEbtry);
} else {
if (glueData_.bcDebuggerStubEntries_.Get(0) == glueData_.bcDebuggerStubEntries_.Get(1)) {
for (size_t i = 0; i < BCStubEntries::BC_HANDLER_COUNT; i++) {
auto stubEntry = glueData_.bcStubEntries_.Get(i);
auto debuggerStubEbtry = glueData_.bcDebuggerStubEntries_.Get(i);
glueData_.bcDebuggerStubEntries_.Set(i, stubEntry);
glueData_.bcStubEntries_.Set(i, debuggerStubEbtry);
}
}
}
}

View File

@ -849,14 +849,13 @@ public:
volatile auto interruptValue =
reinterpret_cast<volatile std::atomic<uint64_t> *>(&glueData_.interruptVector_);
uint64_t oldValue = interruptValue->load(std::memory_order_relaxed);
uint64_t oldValueBeforeCAS;
auto newValue = oldValue;
do {
auto newValue = oldValue;
newValue = oldValue;
T::Set(value, &newValue);
oldValueBeforeCAS = oldValue;
std::atomic_compare_exchange_strong_explicit(interruptValue, &oldValue, newValue,
std::memory_order_release, std::memory_order_relaxed);
} while (oldValue != oldValueBeforeCAS);
} while (!std::atomic_compare_exchange_strong_explicit(interruptValue, &oldValue, newValue,
std::memory_order_release,
std::memory_order_relaxed));
}
void InvokeWeakNodeFreeGlobalCallBack();

View File

@ -38,7 +38,7 @@ public:
// 3. Return undefined.
JSHandle<JSTaggedValue> target(thread, weakRef->GetFromWeak());
if (!target->IsUndefined()) {
thread->GetEcmaVM()->GetHeap()->AddToKeptObjects(target);
thread->GetCurrentEcmaContext()->AddToKeptObjects(target);
}
return target.GetTaggedValue();
}

View File

@ -25,7 +25,6 @@
#include "ecmascript/free_object.h"
#include "ecmascript/js_finalization_registry.h"
#include "ecmascript/js_native_pointer.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/assert_scope.h"
#include "ecmascript/mem/concurrent_marker.h"
#include "ecmascript/mem/concurrent_sweeper.h"
@ -1336,20 +1335,6 @@ void Heap::OnMoveEvent([[maybe_unused]] uintptr_t address, [[maybe_unused]] Tagg
#endif
}
void Heap::AddToKeptObjects(JSHandle<JSTaggedValue> value) const
{
JSHandle<GlobalEnv> env = ecmaVm_->GetGlobalEnv();
JSHandle<LinkedHashSet> linkedSet;
if (env->GetWeakRefKeepObjects()->IsUndefined()) {
linkedSet = LinkedHashSet::Create(thread_);
} else {
linkedSet =
JSHandle<LinkedHashSet>(thread_, LinkedHashSet::Cast(env->GetWeakRefKeepObjects()->GetTaggedObject()));
}
linkedSet = LinkedHashSet::Add(thread_, linkedSet, value);
env->SetWeakRefKeepObjects(thread_, linkedSet);
}
void Heap::AdjustSpaceSizeForAppSpawn()
{
SetHeapMode(HeapMode::SPAWN);
@ -1390,11 +1375,6 @@ void Heap::ClearAllocationInspectorFromAllSpaces()
hugeMachineCodeSpace_->ClearAllocationInspector();
}
void Heap::ClearKeptObjects() const
{
ecmaVm_->GetGlobalEnv()->SetWeakRefKeepObjects(thread_, JSTaggedValue::Undefined());
}
void Heap::RecomputeLimits()
{
double gcSpeed = memController_->CalculateMarkCompactSpeedPerMS();

View File

@ -1166,8 +1166,6 @@ public:
}
#endif
void OnMoveEvent(uintptr_t address, TaggedObject* forwardAddress, size_t size);
void AddToKeptObjects(JSHandle<JSTaggedValue> value) const;
void ClearKeptObjects() const;
// add allocationInspector to each space
void AddAllocationInspectorToAllSpaces(AllocationInspector *inspector);

View File

@ -384,6 +384,7 @@ class ECMA_PUBLIC_API JSValueRef {
public:
static Local<PrimitiveRef> Undefined(const EcmaVM *vm);
static Local<PrimitiveRef> Null(const EcmaVM *vm);
static Local<PrimitiveRef> Hole(const EcmaVM *vm);
static Local<PrimitiveRef> True(const EcmaVM *vm);
static Local<PrimitiveRef> False(const EcmaVM *vm);
@ -926,10 +927,6 @@ protected:
inline LocalScope(const EcmaVM *vm, JSTaggedType value);
private:
void OpenLocalScope(EcmaContext *context);
void OpenPrimitiveScope(EcmaContext *context);
void CloseLocalScope(EcmaContext *context);
void ClosePrimitiveScope(EcmaContext *context);
void *prevNext_ = nullptr;
void *prevEnd_ = nullptr;
int prevHandleStorageIndex_ {-1};

View File

@ -225,6 +225,12 @@ Local<PrimitiveRef> JSValueRef::Null(const EcmaVM *vm)
vm->GetJSThread()->GlobalConstants()->GetHandledNull());
}
Local<PrimitiveRef> JSValueRef::Hole(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
vm->GetJSThread()->GlobalConstants()->GetHandledHole());
}
Local<PrimitiveRef> JSValueRef::True(const EcmaVM *vm)
{
return JSNApiHelper::ToLocal<PrimitiveRef>(
@ -1514,7 +1520,7 @@ bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, uintptr_t value)
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
thread->GetCurrentEcmaContext()->ClearKeptObjects();
return true;
}
@ -1538,7 +1544,7 @@ bool PromiseCapabilityRef::Resolve(const EcmaVM *vm, Local<JSValueRef> value)
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
thread->GetCurrentEcmaContext()->ClearKeptObjects();
return true;
}
@ -1563,7 +1569,7 @@ bool PromiseCapabilityRef::Reject(const EcmaVM *vm, uintptr_t reason)
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
thread->GetCurrentEcmaContext()->ClearKeptObjects();
return true;
}
@ -1588,7 +1594,7 @@ bool PromiseCapabilityRef::Reject(const EcmaVM *vm, Local<JSValueRef> reason)
thread->GetCurrentEcmaContext()->ExecutePromisePendingJob();
RETURN_VALUE_IF_ABRUPT(thread, false);
vm->GetHeap()->ClearKeptObjects();
thread->GetCurrentEcmaContext()->ClearKeptObjects();
return true;
}
@ -1872,61 +1878,62 @@ LocalScope::LocalScope(const EcmaVM *vm) : thread_(vm->GetJSThread())
{
// Only get handle ptr here. Do not need to swtich state.
auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
OpenLocalScope(context);
OpenPrimitiveScope(context);
}
void LocalScope::OpenLocalScope(EcmaContext *context)
{
prevNext_ = context->GetHandleScopeStorageNext();
prevEnd_ = context->GetHandleScopeStorageEnd();
prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex();
context->HandleScopeCountAdd();
}
void LocalScope::OpenPrimitiveScope(EcmaContext *context)
{
prevPrimitiveNext_ = context->GetPrimitiveScopeStorageNext();
prevPrimitiveEnd_ = context->GetPrimitiveScopeStorageEnd();
prevPrimitiveStorageIndex_ = context->GetCurrentPrimitiveStorageIndex();
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
context->HandleScopeCountAdd();
context->PrimitiveScopeCountAdd();
#endif
}
LocalScope::LocalScope(const EcmaVM *vm, JSTaggedType value) : thread_(vm->GetJSThread())
{
ecmascript::ThreadManagedScope managedScope(reinterpret_cast<JSThread *>(thread_));
auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
// Simply reserve a slot on the handlescope. The escaped handle will still be retained in this slot.
ecmascript::EcmaHandleScope::NewHandle(reinterpret_cast<JSThread *>(thread_), value);
OpenLocalScope(context);
OpenPrimitiveScope(context);
auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
prevNext_ = context->GetHandleScopeStorageNext();
prevEnd_ = context->GetHandleScopeStorageEnd();
prevHandleStorageIndex_ = context->GetCurrentHandleStorageIndex();
prevPrimitiveNext_ = context->GetPrimitiveScopeStorageNext();
prevPrimitiveEnd_ = context->GetPrimitiveScopeStorageEnd();
prevPrimitiveStorageIndex_ = context->GetCurrentPrimitiveStorageIndex();
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
context->HandleScopeCountAdd();
context->PrimitiveScopeCountAdd();
#endif
}
LocalScope::~LocalScope()
{
ecmascript::ThreadManagedScope managedScope(reinterpret_cast<JSThread *>(thread_));
auto context = reinterpret_cast<JSThread *>(thread_)->GetCurrentEcmaContext();
CloseLocalScope(context);
ClosePrimitiveScope(context);
}
void LocalScope::CloseLocalScope(EcmaContext *context)
{
#ifdef ECMASCRIPT_ENABLE_HANDLE_LEAK_CHECK
context->HandleScopeCountDec();
context->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
if (context->GetHandleScopeStorageEnd() != prevEnd_) {
context->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
context->ShrinkHandleStorage(prevHandleStorageIndex_);
}
}
void LocalScope::ClosePrimitiveScope(EcmaContext *context)
{
context->PrimitiveScopeCountDec();
#endif
context->SetHandleScopeStorageNext(static_cast<JSTaggedType *>(prevNext_));
context->SetPrimitiveScopeStorageNext(static_cast<JSTaggedType *>(prevPrimitiveNext_));
if (context->GetPrimitiveScopeStorageEnd() != prevPrimitiveEnd_) {
context->SetPrimitiveScopeStorageEnd(static_cast<JSTaggedType *>(prevPrimitiveEnd_));
context->ShrinkPrimitiveStorage(prevPrimitiveStorageIndex_);
bool handleScopeNeedShrink = (context->GetHandleScopeStorageEnd() != prevEnd_);
bool primitiveScopeNeedShrink = (context->GetPrimitiveScopeStorageEnd() != prevPrimitiveEnd_);
if (LIKELY(!handleScopeNeedShrink && !primitiveScopeNeedShrink)) {
return;
}
{
ecmascript::ThreadManagedScope managedScope(reinterpret_cast<JSThread *>(thread_));
if (handleScopeNeedShrink) {
context->SetHandleScopeStorageEnd(static_cast<JSTaggedType *>(prevEnd_));
context->ShrinkHandleStorage(prevHandleStorageIndex_);
}
if (primitiveScopeNeedShrink) {
context->SetPrimitiveScopeStorageEnd(static_cast<JSTaggedType *>(prevPrimitiveEnd_));
context->ShrinkPrimitiveStorage(prevPrimitiveStorageIndex_);
}
}
}
@ -2995,7 +3002,7 @@ Local<JSValueRef> FunctionRef::Call(const EcmaVM *vm, Local<JSValueRef> thisObj,
RETURN_VALUE_IF_ABRUPT(thread, JSValueRef::Undefined(vm));
JSHandle<JSTaggedValue> resultValue(thread, result);
vm->GetHeap()->ClearKeptObjects();
thread->GetCurrentEcmaContext()->ClearKeptObjects();
vm->GetJsDebuggerManager()->NotifyReturnNative();
return scope.Escape(JSNApiHelper::ToLocal<JSValueRef>(resultValue));
}
@ -3004,7 +3011,7 @@ JSValueRef* FunctionRef::CallForNapi(const EcmaVM *vm, JSValueRef *thisObj,
JSValueRef *const argv[], // NOLINTNEXTLINE(modernize-avoid-c-arrays)
int32_t length)
{
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Undefined(vm));
CROSS_THREAD_AND_EXCEPTION_CHECK_WITH_RETURN(vm, *JSValueRef::Hole(vm));
ecmascript::ThreadManagedScope managedScope(thread);
JSTaggedValue result;
FunctionCallScope callScope(EcmaVM::ConstCast(vm));
@ -3012,7 +3019,8 @@ JSValueRef* FunctionRef::CallForNapi(const EcmaVM *vm, JSValueRef *thisObj,
{
LocalScope scope(vm);
ecmascript::tooling::JsDebuggerManager *dm = vm->GetJsDebuggerManager();
if (dm->IsDebugApp()) {
bool isDebugApp = dm->IsDebugApp();
if (isDebugApp) {
dm->ClearSingleStepper();
}
JSTaggedValue func = *reinterpret_cast<JSTaggedValue *>(this);
@ -3023,30 +3031,30 @@ JSValueRef* FunctionRef::CallForNapi(const EcmaVM *vm, JSValueRef *thisObj,
}
EcmaRuntimeCallInfo *info =
ecmascript::EcmaInterpreter::NewRuntimeCallInfo(thread, func, thisValue, undefined, length);
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Hole(vm));
for (int32_t i = 0; i < length; i++) {
JSTaggedValue arg =
argv[i] == nullptr ? JSTaggedValue::Undefined() : JSNApiHelper::ToJSTaggedValue(argv[i]);
info->SetCallArg(i, arg);
if (argv[i]) {
// NewRuntimeCallInfo has set Undefined defaultly in Argv's slot.
info->SetCallArg(i, JSNApiHelper::ToJSTaggedValue(argv[i]));
}
}
if (thread->IsAsmInterpreter()) {
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, reinterpret_cast<JSValueRef *>(
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()).GetAddress()));
STACK_LIMIT_CHECK(thread, reinterpret_cast<JSValueRef *>(
JSHandle<JSTaggedValue>(thread, JSTaggedValue::Exception()).GetAddress()));
if (LIKELY(thread->IsAsmInterpreter())) {
STACK_LIMIT_CHECK(thread, reinterpret_cast<JSValueRef *>(*JSValueRef::Hole(vm)));
auto *hclass = func.GetTaggedObject()->GetClass();
if (hclass->IsClassConstructor()) {
RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call",
reinterpret_cast<JSValueRef *>(JSHandle<JSTaggedValue>(thread, undefined).GetAddress()));
reinterpret_cast<JSValueRef *>(*JSValueRef::Hole(vm)));
}
result = ecmascript::InterpreterAssembly::Execute(info);
} else {
result = JSFunction::Call(info);
}
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Undefined(vm));
vm->GetHeap()->ClearKeptObjects();
if (dm->IsMixedDebugEnabled()) {
RETURN_VALUE_IF_ABRUPT(thread, *JSValueRef::Hole(vm));
if (thread->GetCurrentEcmaContext()->HasKeptObjects()) {
thread->GetCurrentEcmaContext()->ClearKeptObjects();
}
if (isDebugApp && dm->IsMixedDebugEnabled()) {
dm->NotifyReturnNative();
}
}

View File

@ -36,9 +36,14 @@ HWTEST_F_L0(GlueRegsTest, ConstantClassTest)
ASSERT_NE(globalConst, nullptr);
const JSTaggedValue *address = globalConst->BeginSlot();
size_t curIndex = static_cast<size_t>(ConstantIndex::CONSTANT_BEGIN);
size_t holeIndex = static_cast<size_t>(ConstantIndex::HOLE_INDEX);
while (address < globalConst->EndSlot()) {
EXPECT_TRUE(!(*address).IsHole()); // Visit barely
if (curIndex != holeIndex) {
EXPECT_TRUE(!(*address).IsHole()); // Visit barely
}
address += 1;
curIndex += 1;
}
}