From 038e069b654c7cb3fe80a9b5a9c5f8657ab1104c Mon Sep 17 00:00:00 2001 From: Roman Sannikov Date: Wed, 19 Oct 2022 21:33:33 +0300 Subject: [PATCH] Add AllocateObject intrinsic Signed-off-by: Roman Sannikov --- runtime/builtins.cpp | 1 + runtime/builtins/builtins_global.cpp | 50 ++++++++++++++++++++++++++++ runtime/builtins/builtins_global.h | 1 + runtime/runtime_call_id.h | 1 + tests/runtime/common/startGc.js | 3 +- 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/runtime/builtins.cpp b/runtime/builtins.cpp index 5bd4ee9c2..10f16cb47 100644 --- a/runtime/builtins.cpp +++ b/runtime/builtins.cpp @@ -348,6 +348,7 @@ void Builtins::InitializeGlobalObject(const JSHandle &env, const JSHa SetFunction(env, globalObject, "waitForFinishGC", Global::WaitForFinishGC, 1); SetFunction(env, globalObject, "scheduleGcAfterNthAlloc", Global::ScheduleGCAfterNthAlloc, 2); SetFunction(env, globalObject, "isScheduledGcTriggered", Global::IsScheduledGCTriggered, 0); + SetFunction(env, globalObject, "allocateArrayObject", Global::AllocateArrayObject, 1); SetFunction(env, globalObject, "markObject", Global::MarkObject, 1); SetFunction(env, globalObject, "getMarkQueue", Global::GetMarkQueue, 0); SetFunction(env, globalObject, "clearMarkQueue", Global::ClearMarkQueue, 0); diff --git a/runtime/builtins/builtins_global.cpp b/runtime/builtins/builtins_global.cpp index 400d9a72b..1f6e15062 100644 --- a/runtime/builtins/builtins_global.cpp +++ b/runtime/builtins/builtins_global.cpp @@ -26,6 +26,7 @@ #include "plugins/ecmascript/runtime/interpreter/slow_runtime_helper.h" #include "plugins/ecmascript/runtime/js_invoker.h" #include "plugins/ecmascript/runtime/js_eval.h" +#include "plugins/ecmascript/runtime/js_array.h" #include "plugins/ecmascript/runtime/tagged_array-inl.h" #include "include/thread_scopes.h" @@ -846,6 +847,55 @@ JSTaggedValue BuiltinsGlobal::IsScheduledGCTriggered(EcmaRuntimeCallInfo *msg) return JSTaggedValue(sched_trigger->IsTriggered()); } +JSTaggedValue BuiltinsGlobal::AllocateArrayObject(EcmaRuntimeCallInfo *msg) +{ + JSThread *thread = msg->GetThread(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + ASSERT(thread != nullptr); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + BUILTINS_API_TRACE(thread, Global, AllocateArrayObject); + + int64_t sizeInBytes = 0; + + if (GetCallArg(msg, 0)->IsInt()) { + sizeInBytes = GetCallArg(msg, 0)->GetInt(); + } else if (GetCallArg(msg, 0)->IsDouble()) { + sizeInBytes = GetCallArg(msg, 0)->GetDouble(); + } else { + JSHandle err = + thread->GetEcmaVM()->GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "The value must be an integer"); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, err.GetTaggedValue(), JSTaggedValue::Exception()); + } + + if (sizeInBytes < 0) { + JSHandle err = + thread->GetEcmaVM()->GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "The value must be positive"); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, err.GetTaggedValue(), JSTaggedValue::Exception()); + } + + sizeInBytes = RoundUp(sizeInBytes, sizeof(TaggedType)) - JSArray::SIZE; + + if (sizeInBytes < 0) { + sizeInBytes = 0; + } + + uint32_t numElements = sizeInBytes / sizeof(TaggedType); + JSHandle array = factory->NewJSArray(); + + if (numElements > 0) { + JSHandle elements = factory->NewTaggedArray(numElements); + + if (elements.IsEmpty()) { + return JSTaggedValue::Exception(); + } + + array->SetElements(thread, elements); + array->SetArrayLength(thread, numElements); + } + + return array.GetTaggedValue(); +} + JSTaggedValue BuiltinsGlobal::MarkObject(EcmaRuntimeCallInfo *msg) { JSThread *thread = msg->GetThread(); diff --git a/runtime/builtins/builtins_global.h b/runtime/builtins/builtins_global.h index fdf7caebd..d3b0c05d7 100644 --- a/runtime/builtins/builtins_global.h +++ b/runtime/builtins/builtins_global.h @@ -52,6 +52,7 @@ public: static JSTaggedValue WaitForFinishGC(EcmaRuntimeCallInfo *msg); static JSTaggedValue ScheduleGCAfterNthAlloc(EcmaRuntimeCallInfo *msg); static JSTaggedValue IsScheduledGCTriggered(EcmaRuntimeCallInfo *msg); + static JSTaggedValue AllocateArrayObject(EcmaRuntimeCallInfo *msg); static JSTaggedValue MarkObject(EcmaRuntimeCallInfo *msg); static JSTaggedValue GetMarkQueue(EcmaRuntimeCallInfo *msg); static JSTaggedValue ClearMarkQueue(EcmaRuntimeCallInfo *msg); diff --git a/runtime/runtime_call_id.h b/runtime/runtime_call_id.h index 59b81bed8..9eed2706d 100644 --- a/runtime/runtime_call_id.h +++ b/runtime/runtime_call_id.h @@ -333,6 +333,7 @@ namespace panda::ecmascript { V(Global, MarkObject) \ V(Global, GetMarkQueue) \ V(Global, ClearMarkQueue) \ + V(Global, AllocateArrayObject) \ V(Global, NewobjDynrange) \ V(Global, CallJsBoundFunction) \ V(Global, CallJsProxy) \ diff --git a/tests/runtime/common/startGc.js b/tests/runtime/common/startGc.js index 8056796dd..04b6d2509 100644 --- a/tests/runtime/common/startGc.js +++ b/tests/runtime/common/startGc.js @@ -33,8 +33,7 @@ function allocLargeObject() { // Only length setter does this. let big = new Array(); for (let i = 0; i < 60; ++i) { - let a = new Array(); - a.length = 1024; + let a = allocateArrayObject(1024 * 8); if (i % 2 == 0) { big[i] = a; } -- Gitee