diff --git a/runtime/builtins.cpp b/runtime/builtins.cpp index 10f16cb4740e89c5974045d6c2dface04aed133c..33370f211ba2a2fb27d5b06a26a1a6443b47427e 100644 --- a/runtime/builtins.cpp +++ b/runtime/builtins.cpp @@ -352,6 +352,7 @@ void Builtins::InitializeGlobalObject(const JSHandle &env, const JSHa SetFunction(env, globalObject, "markObject", Global::MarkObject, 1); SetFunction(env, globalObject, "getMarkQueue", Global::GetMarkQueue, 0); SetFunction(env, globalObject, "clearMarkQueue", Global::ClearMarkQueue, 0); + SetFunction(env, globalObject, "getObjectSpaceType", Global::GCObjectSpaceType, 1); #if ECMASCRIPT_ENABLE_RUNTIME_STAT SetFunction(env, globalObject, "startRuntimeStat", Global::StartRuntimeStat, 0); SetFunction(env, globalObject, "stopRuntimeStat", Global::StopRuntimeStat, 0); diff --git a/runtime/builtins/builtins_global.cpp b/runtime/builtins/builtins_global.cpp index 1f6e15062fc6d26f23e03286311bc2d90033b5e8..0822b70f9b294b0fd8f7e83f0c92e55a4e48b8fc 100644 --- a/runtime/builtins/builtins_global.cpp +++ b/runtime/builtins/builtins_global.cpp @@ -931,6 +931,51 @@ JSTaggedValue BuiltinsGlobal::ClearMarkQueue(EcmaRuntimeCallInfo *msg) return JSTaggedValue::Undefined(); } +JSTaggedValue BuiltinsGlobal::GCObjectSpaceType(EcmaRuntimeCallInfo *msg) +{ + ASSERT(msg != nullptr); + JSThread *thread = msg->GetThread(); + ASSERT(thread != nullptr); + [[maybe_unused]] EcmaHandleScope handle_scope(thread); + BUILTINS_API_TRACE(thread, Global, GCObjectSpaceType); + + JSHandle obj_handle = GetCallArg(msg, 0); + auto global_constants = thread->GlobalConstants(); + if (!obj_handle.GetTaggedValue().IsHeapObject()) { + JSHandle err = + thread->GetEcmaVM()->GetFactory()->GetJSError(ErrorType::TYPE_ERROR, "Non Heap Object"); + THROW_NEW_ERROR_AND_RETURN_VALUE(thread, err.GetTaggedValue(), JSTaggedValue::Exception()); + } + + SpaceType obj_space_type = PoolManager::GetMmapMemPool()->GetSpaceTypeForAddr( + static_cast(obj_handle.GetTaggedValue().GetHeapObject())); + switch (obj_space_type) { + case SpaceType::SPACE_TYPE_OBJECT: + return GCSpecialisedObjectSpaceType(thread, obj_handle).GetTaggedValue(); + case SpaceType::SPACE_TYPE_HUMONGOUS_OBJECT: + return global_constants->GetHandledHumongousObjectSpaceString().GetTaggedValue(); + case SpaceType::SPACE_TYPE_NON_MOVABLE_OBJECT: + return global_constants->GetHandledNonMovableObjectSpaceString().GetTaggedValue(); + default: + return global_constants->GetHandledUndefinedSpaceString().GetTaggedValue(); + } +} + +JSHandle BuiltinsGlobal::GCSpecialisedObjectSpaceType(JSThread *thread, + const JSHandle &obj_handle) +{ + auto global_constants = thread->GlobalConstants(); + if (!thread->GetEcmaVM()->GetGC()->IsGenerational()) { + return global_constants->GetHandledObjectSpaceString(); + } + + auto object_allocator = thread->GetEcmaVM()->GetHeapManager()->GetObjectAllocator().AsObjectAllocator(); + if (object_allocator->IsObjectInYoungSpace(obj_handle.GetTaggedValue().GetHeapObject())) { + return global_constants->GetHandledYoungSpaceString(); + } + return global_constants->GetHandledTenuredSpaceString(); +} + JSTaggedValue BuiltinsGlobal::CallJsBoundFunction(EcmaRuntimeCallInfo *msg) { JSThread *thread = msg->GetThread(); diff --git a/runtime/builtins/builtins_global.h b/runtime/builtins/builtins_global.h index d3b0c05d72a4583dd372b5a917ff3ed07a9bad28..c3ab4d071a652ac5138eba2f99802a89b33d1235 100644 --- a/runtime/builtins/builtins_global.h +++ b/runtime/builtins/builtins_global.h @@ -56,6 +56,7 @@ public: static JSTaggedValue MarkObject(EcmaRuntimeCallInfo *msg); static JSTaggedValue GetMarkQueue(EcmaRuntimeCallInfo *msg); static JSTaggedValue ClearMarkQueue(EcmaRuntimeCallInfo *msg); + static JSTaggedValue GCObjectSpaceType(EcmaRuntimeCallInfo *msg); static JSTaggedValue CallJsBoundFunction(EcmaRuntimeCallInfo *msg); static JSTaggedValue CallJsProxy(EcmaRuntimeCallInfo *msg); #if ECMASCRIPT_ENABLE_RUNTIME_STAT @@ -120,6 +121,8 @@ private: return -1; } static uint8_t GetValueFromTwoHex(uint16_t front, uint16_t behind); + static JSHandle GCSpecialisedObjectSpaceType(JSThread *thread, + const JSHandle &obj_handle); class GCTaskTracker : public mem::GCListener { public: diff --git a/runtime/global_env_constants.cpp b/runtime/global_env_constants.cpp index 13d400c1f0d07e587b19adba0182ab59e3327977..8e93c27807619510abc1b338c5cf0c71ee17308d 100644 --- a/runtime/global_env_constants.cpp +++ b/runtime/global_env_constants.cpp @@ -507,6 +507,15 @@ void GlobalEnvConstants::InitGlobalConstant(JSThread *thread) SetConstant(ConstantIndex::GROUPS_STRING_INDEX, factory->NewFromCanBeCompressString("groups").GetTaggedValue()); SetConstant(ConstantIndex::Y_INDEX, factory->NewFromCanBeCompressString("y").GetTaggedValue()); SetConstant(ConstantIndex::DOLLAR_INDEX, factory->NewFromCanBeCompressString("$").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_OBJECT_INDEX, factory->NewFromCanBeCompressString("object").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_YOUNG_INDEX, factory->NewFromCanBeCompressString("young").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_TENURED_INDEX, factory->NewFromCanBeCompressString("tenured").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_HUMONGOUS_OBJECT_INDEX, + factory->NewFromCanBeCompressString("humongous").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_NON_MOVABLE_OBJECT_INDEX, + factory->NewFromCanBeCompressString("nonMovable").GetTaggedValue()); + SetConstant(ConstantIndex::SPACE_UNDEFINED_INDEX, + factory->NewFromCanBeCompressString("undefined").GetTaggedValue()); auto accessor = factory->NewInternalAccessor(reinterpret_cast(JSFunction::PrototypeSetter), reinterpret_cast(JSFunction::PrototypeGetter)); diff --git a/runtime/global_env_constants.h b/runtime/global_env_constants.h index beb994d1e1602a51e799b14f61cf3fefbac50ae7..0aba1ff7cf2defbef41d7c2a2ceacb6f9e0054f5 100644 --- a/runtime/global_env_constants.h +++ b/runtime/global_env_constants.h @@ -295,6 +295,12 @@ class JSThread; V(JSTaggedValue, GregoryString, GREGORY_INDEX, gregory) \ V(JSTaggedValue, EthioaaString, ETHIOAA_INDEX, ethioaa) \ V(JSTaggedValue, ValuesString, VALUES_INDEX, values) \ + V(JSTaggedValue, ObjectSpaceString, SPACE_OBJECT_INDEX, object) \ + V(JSTaggedValue, YoungSpaceString, SPACE_YOUNG_INDEX, young) \ + V(JSTaggedValue, TenuredSpaceString, SPACE_TENURED_INDEX, tenured) \ + V(JSTaggedValue, HumongousObjectSpaceString, SPACE_HUMONGOUS_OBJECT_INDEX, humongous) \ + V(JSTaggedValue, NonMovableObjectSpaceString, SPACE_NON_MOVABLE_OBJECT_INDEX, nonMovable) \ + V(JSTaggedValue, UndefinedSpaceString, SPACE_UNDEFINED_INDEX, undefined) \ /* for regexp. */ \ V(JSTaggedValue, ExecString, EXEC_INDEX, exec) \ V(JSTaggedValue, LastIndexString, LAST_INDEX_INDEX, lastIndex) \ diff --git a/runtime/runtime_call_id.h b/runtime/runtime_call_id.h index 9eed2706d6ad63ee86d045f0bd0e6f04f55f0971..e20e66776d11e887de9d5c522bd67f9b4368638d 100644 --- a/runtime/runtime_call_id.h +++ b/runtime/runtime_call_id.h @@ -334,6 +334,7 @@ namespace panda::ecmascript { V(Global, GetMarkQueue) \ V(Global, ClearMarkQueue) \ V(Global, AllocateArrayObject) \ + V(Global, GCObjectSpaceType) \ V(Global, NewobjDynrange) \ V(Global, CallJsBoundFunction) \ V(Global, CallJsProxy) \ diff --git a/tests/runtime/common/CMakeLists.txt b/tests/runtime/common/CMakeLists.txt index 24f5ce08446b4c98a6ec789cc1133e62e8f5a37b..fa8f47a59ab60988b283c6b14f15eda29b9377c3 100644 --- a/tests/runtime/common/CMakeLists.txt +++ b/tests/runtime/common/CMakeLists.txt @@ -49,6 +49,7 @@ endfunction() # In the test we don't need the runtime triggers GC during allocation. panda_add_ecma_test(FILE startGc.js OPTIONS "--gc-trigger-type=debug-never") panda_add_ecma_test(FILE scheduleGc.js OPTIONS "--gc-trigger-type=debug-never" "--gc-use-nth-alloc-trigger=true") +panda_add_ecma_test(FILE spaceTypeTest.js OPTIONS "--gc-type=g1-gc" "--run-gc-in-place=true") add_subdirectory(helloworld) add_subdirectory(newobjdynrange) diff --git a/tests/runtime/common/spaceTypeTest.js b/tests/runtime/common/spaceTypeTest.js new file mode 100644 index 0000000000000000000000000000000000000000..5a942ae4db946d40c1abbfb869127f5bde303153 --- /dev/null +++ b/tests/runtime/common/spaceTypeTest.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function assert(value, message) { + if (value) { + return; + } + print("Assertion failed: " + message); + throw Error(); +} + +function func() { + +} + +assert(getObjectSpaceType(new WeakMap()) === 'young', "Must be young space") +assert(getObjectSpaceType(new Array(1 << 20).fill("A")) === 'tenured', "Must be tenured space") +// assert(getObjectSpaceType('spaceTypeTest') === 'nonMovable', "Must be non movable space") +// assert(getObjectSpaceType(func) === 'nonMovable', "Must be non movable space") + +try { + throw new Error(getObjectSpaceType(42)) +} catch (err) { + assert(err.message === 'Non Heap Object', "Must be non heap object") +}