mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 01:59:58 +00:00
!7436 【ark】optimize napi_call_function
Merge pull request !7436 from huangzhenghua/master20240516
This commit is contained in:
commit
7c36338bd1
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user