diff --git a/runtime/builtins.cpp b/runtime/builtins.cpp index 5294de92e8c500b16e196f036b8f38d4fa97b9c1..e5f52859fdea101b5bcd8d2824a9f1d52973c06a 100644 --- a/runtime/builtins.cpp +++ b/runtime/builtins.cpp @@ -346,6 +346,7 @@ void Builtins::InitializeGlobalObject(const JSHandle &env, const JSHa SetFunction(env, globalObject, "gc", Global::GCEntrypoint, 0); SetFunction(env, globalObject, "startGC", Global::SpecifiedGCEntrypoint, 1); SetFunction(env, globalObject, "waitForFinishGC", Global::WaitForFinishGC, 1); + SetFunction(env, globalObject, "allocateObject", Global::AllocateObject, 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 8e7d235f57c9002183eb692c2091d823469dfcb9..520489b9188c8efd84a492bb7215b3264cad03e2 100644 --- a/runtime/builtins/builtins_global.cpp +++ b/runtime/builtins/builtins_global.cpp @@ -27,6 +27,7 @@ #include "plugins/ecmascript/runtime/js_invoker.h" #include "plugins/ecmascript/runtime/js_eval.h" #include "plugins/ecmascript/runtime/tagged_array-inl.h" +#include "plugins/ecmascript/runtime/js_array.h" #include "include/thread_scopes.h" namespace panda::ecmascript::builtins { @@ -793,6 +794,34 @@ JSTaggedValue BuiltinsGlobal::WaitForFinishGC(EcmaRuntimeCallInfo *msg) return JSTaggedValue::Undefined(); } +JSTaggedValue BuiltinsGlobal::AllocateObject(EcmaRuntimeCallInfo *msg) +{ + JSThread *thread = msg->GetThread(); + ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); + ASSERT(thread != nullptr); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + BUILTINS_API_TRACE(thread, Global, AllocateObject); + + int64_t sizeInBytes = JSTaggedValue::ToNumber(thread, GetCallArg(msg, 0)).GetNumber(); + sizeInBytes -= sizeInBytes % 8; + + if (sizeInBytes <= 0) { + JSHandle err = + thread->GetEcmaVM()->GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "The value must be >= 8"); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, err.GetTaggedValue(), JSTaggedValue::Exception()); + } + + uint32_t numElements = sizeInBytes / sizeof(TaggedType); + JSHandle array = factory->NewJSArray(); + 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 534ea064adba921bdccae96c56edb40f05b29f3e..1d71ace4656abeaddd5e3288d53f4eb8e023dc49 100644 --- a/runtime/builtins/builtins_global.h +++ b/runtime/builtins/builtins_global.h @@ -50,6 +50,7 @@ public: static JSTaggedValue GCEntrypoint(EcmaRuntimeCallInfo *msg); static JSTaggedValue SpecifiedGCEntrypoint(EcmaRuntimeCallInfo *msg); static JSTaggedValue WaitForFinishGC(EcmaRuntimeCallInfo *msg); + static JSTaggedValue AllocateObject(EcmaRuntimeCallInfo *msg); static JSTaggedValue MarkObject(EcmaRuntimeCallInfo *msg); static JSTaggedValue GetMarkQueue(EcmaRuntimeCallInfo *msg); static JSTaggedValue ClearMarkQueue(EcmaRuntimeCallInfo *msg); diff --git a/runtime/free_object.h b/runtime/free_object.h index c38456d2294dc5f69c80dd86b0869e30cc220933..b5ab7e1b0ac83907cef39e8c30254d3980123d26 100644 --- a/runtime/free_object.h +++ b/runtime/free_object.h @@ -29,6 +29,10 @@ public: { return reinterpret_cast(object); } + static FreeObject *Cast(TaggedObject *object) + { + return reinterpret_cast(object); + } static FreeObject *FillFreeObject(EcmaVM *vm, uintptr_t address, size_t size); inline bool IsEmpty() const diff --git a/runtime/object_factory.cpp b/runtime/object_factory.cpp index 4d822f55397171b07a7f2e634f1495f0fa1f1ca7..36a46c7cb215c0f242314a73f42f97978aea4023 100644 --- a/runtime/object_factory.cpp +++ b/runtime/object_factory.cpp @@ -325,6 +325,12 @@ JSHandle ObjectFactory::NewJSObject(const JSHandle &jshclass return obj; } +JSHandle ObjectFactory::NewFreeObject(const JSHandle &jshclass) +{ + JSHandle obj(thread_, FreeObject::Cast(NewDynObject(jshclass))); + return obj; +} + JSHandle ObjectFactory::CloneProperties(const JSHandle &old) { uint32_t new_length = old->GetLength(); @@ -1644,6 +1650,9 @@ JSHandle ObjectFactory::NewTaggedArrayImpl(uint32_t length, JSTagge ASSERT(!init_val.IsHeapObject()); size_t size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), length); auto header = heap_helper_.AllocateYoungGenerationOrHugeObject(weak ? weak_array_class_ : array_class_, size); + if (UNLIKELY(header == nullptr)) { + return JSHandle(); + } JSHandle array(thread_, header); // TODO(audovichenko): Remove this suppression when CSA gets recognize primitive TaggedValue (issue #I5QOJX) // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader) diff --git a/runtime/object_factory.h b/runtime/object_factory.h index 5490ac660a3825c3381a4b0e894964cc0aae991c..093470e627d53614fa6cdf496e0c806cadd085e2 100644 --- a/runtime/object_factory.h +++ b/runtime/object_factory.h @@ -385,6 +385,8 @@ public: // used for creating Function JSHandle NewJSObject(const JSHandle &jshclass); + JSHandle NewFreeObject(const JSHandle &jshclass); + // used for creating jshclass in GlobalEnv, EcmaVM template inline JSHandle CreateDynClass(JSHClass *hclass, JSType type, uint32_t flags = 0, diff --git a/runtime/runtime_call_id.h b/runtime/runtime_call_id.h index 454fabd6f0ccbdac7010d2ddbd2cf9615d590408..88f1e7ffa31800b871998bfdcd5a92869b337063 100644 --- a/runtime/runtime_call_id.h +++ b/runtime/runtime_call_id.h @@ -331,6 +331,7 @@ namespace panda::ecmascript { V(Global, MarkObject) \ V(Global, GetMarkQueue) \ V(Global, ClearMarkQueue) \ + V(Global, AllocateObject) \ V(Global, NewobjDynrange) \ V(Global, CallJsBoundFunction) \ V(Global, CallJsProxy) \ diff --git a/tests/runtime/common/startGc.js b/tests/runtime/common/startGc.js index 8056796dd8630edbfce1ff522dfda3f4719f8ba9..d61fdb45ef23da4e9d91cb66f0a38bf95085ce4a 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 = allocateObject(1024 * 8); if (i % 2 == 0) { big[i] = a; }