mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
modify transitions to weak reference
1.modify transitions to weak reference and delete parent field in JSHClass. 2.add targeted test case to intercept the issue. 3.fix weak ref in parallel gc 4.fix TaggedCastToWeakReferentUnChecked() in stub Change-Id: I118d293a04390fba6c21179a0a8ac7993dae5e96 Signed-off-by: ding <dingding5@huawei.com>
This commit is contained in:
parent
1e538180ef
commit
197e0a317c
@ -1492,7 +1492,7 @@ GateRef Stub::SetPrototypeToHClass(VariableType type, GateRef glue, GateRef hCla
|
||||
|
||||
GateRef Stub::SetProtoChangeDetailsToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef protoChange)
|
||||
{
|
||||
GateRef offset = GetIntPtrConstant(JSHClass::PROTOTYPE_INFO_OFFSET);
|
||||
GateRef offset = GetIntPtrConstant(JSHClass::PROTO_CHANGE_DETAILS_OFFSET);
|
||||
return Store(type, glue, hClass, offset, protoChange);
|
||||
}
|
||||
|
||||
@ -1502,12 +1502,6 @@ GateRef Stub::SetLayoutToHClass(VariableType type, GateRef glue, GateRef hClass,
|
||||
return Store(type, glue, hClass, offset, attr);
|
||||
}
|
||||
|
||||
GateRef Stub::SetParentToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef parent)
|
||||
{
|
||||
GateRef offset = GetIntPtrConstant(JSHClass::PARENT_OFFSET);
|
||||
return Store(type, glue, hClass, offset, parent);
|
||||
}
|
||||
|
||||
GateRef Stub::SetEnumCacheToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef key)
|
||||
{
|
||||
GateRef offset = GetIntPtrConstant(JSHClass::ENUM_CACHE_OFFSET);
|
||||
@ -1770,6 +1764,7 @@ GateRef Stub::TaggedCastToDouble(GateRef x)
|
||||
|
||||
GateRef Stub::TaggedCastToWeakReferentUnChecked(GateRef x)
|
||||
{
|
||||
x = ChangeTaggedPointerToInt64(x);
|
||||
return Int64And(x, GetInt64Constant(~JSTaggedValue::TAG_WEAK_MASK));
|
||||
}
|
||||
|
||||
|
@ -2245,8 +2245,7 @@ void Stub::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
|
||||
SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
|
||||
SetBitFieldToHClass(glue, dstHClass, GetBitFieldFromHClass(srcHClass));
|
||||
SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
|
||||
SetParentToHClass(VariableType::INT64(), glue, dstHClass, GetInt64Constant(JSTaggedValue::VALUE_NULL));
|
||||
SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, GetInt64Constant(JSTaggedValue::VALUE_NULL));
|
||||
SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED));
|
||||
SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass,
|
||||
GetInt64Constant(JSTaggedValue::VALUE_NULL));
|
||||
SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, GetInt64Constant(JSTaggedValue::VALUE_NULL));
|
||||
@ -2265,18 +2264,19 @@ GateRef Stub::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, Ga
|
||||
GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), transition);
|
||||
|
||||
Label notNull(env);
|
||||
Branch(Int64Equal(transition, GetInt64Constant(JSTaggedValue::VALUE_NULL)), &exit, ¬Null);
|
||||
Bind(¬Null);
|
||||
Label notUndefined(env);
|
||||
Branch(Int64Equal(transition, GetUndefinedConstant()), &exit, ¬Undefined);
|
||||
Bind(¬Undefined);
|
||||
{
|
||||
Label isJSHClass(env);
|
||||
Label notJSHClass(env);
|
||||
Branch(IsJSHClass(transition), &isJSHClass, ¬JSHClass);
|
||||
Bind(&isJSHClass);
|
||||
Label isWeak(env);
|
||||
Label notWeak(env);
|
||||
Branch(TaggedIsWeak(transition), &isWeak, ¬Weak);
|
||||
Bind(&isWeak);
|
||||
{
|
||||
GateRef propNums = GetNumberOfPropsFromHClass(transition);
|
||||
GateRef transitionHClass = TaggedCastToWeakReferentUnChecked(transition);
|
||||
GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
|
||||
GateRef last = Int32Sub(propNums, GetInt32Constant(1));
|
||||
GateRef layoutInfo = GetLayoutFromHClass(transition);
|
||||
GateRef layoutInfo = GetLayoutFromHClass(transitionHClass);
|
||||
GateRef cachedKey = GetKeyFromLayoutInfo(layoutInfo, last);
|
||||
GateRef cachedAttr = TaggedCastToInt32(GetPropAttrFromLayoutInfo(layoutInfo, last));
|
||||
GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
|
||||
@ -2290,9 +2290,9 @@ GateRef Stub::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, Ga
|
||||
Bind(&isMatch);
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
NotifyHClassChanged(glue, hclass, transition);
|
||||
NotifyHClassChanged(glue, hclass, transitionHClass);
|
||||
#endif
|
||||
StoreHClass(glue, receiver, transition);
|
||||
StoreHClass(glue, receiver, transitionHClass);
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
@ -2302,7 +2302,7 @@ GateRef Stub::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, Ga
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
Bind(¬JSHClass);
|
||||
Bind(¬Weak);
|
||||
{
|
||||
// need to find from dictionary
|
||||
GateRef entry = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
|
||||
@ -2310,17 +2310,30 @@ GateRef Stub::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, Ga
|
||||
Label notFound(env);
|
||||
Branch(Int32NotEqual(entry, GetInt32Constant(-1)), &isFound, ¬Found);
|
||||
Bind(&isFound);
|
||||
auto newHClass = GetValueFromDictionary<TransitionsDictionary>(
|
||||
auto value = GetValueFromDictionary<TransitionsDictionary>(
|
||||
VariableType::JS_POINTER(), transition, entry);
|
||||
result = newHClass;
|
||||
Label valueUndefined(env);
|
||||
Label valueNotUndefined(env);
|
||||
Branch(Int64NotEqual(value, GetUndefinedConstant()), &valueNotUndefined,
|
||||
&valueUndefined);
|
||||
Bind(&valueNotUndefined);
|
||||
{
|
||||
GateRef newHClass = TaggedCastToWeakReferentUnChecked(value);
|
||||
result = ChangeInt64ToTagged(newHClass);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
NotifyHClassChanged(glue, hclass, newHClass);
|
||||
NotifyHClassChanged(glue, hclass, newHClass);
|
||||
#endif
|
||||
StoreHClass(glue, receiver, newHClass);
|
||||
Jump(&exit);
|
||||
Bind(¬Found);
|
||||
result = GetNullConstant();
|
||||
Jump(&exit);
|
||||
StoreHClass(glue, receiver, newHClass);
|
||||
Jump(&exit);
|
||||
Bind(¬Found);
|
||||
result = GetNullConstant();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&valueUndefined);
|
||||
{
|
||||
result = GetNullConstant();
|
||||
Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Bind(&exit);
|
||||
|
@ -676,7 +676,6 @@ public:
|
||||
inline GateRef SetProtoChangeDetailsToHClass(VariableType type, GateRef glue, GateRef hClass,
|
||||
GateRef protoChange);
|
||||
inline GateRef SetLayoutToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef attr);
|
||||
inline GateRef SetParentToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef parent);
|
||||
inline GateRef SetEnumCacheToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef key);
|
||||
inline GateRef SetTransitionsToHClass(VariableType type, GateRef glue, GateRef hClass, GateRef transition);
|
||||
inline void SetIsProtoTypeToHClass(GateRef glue, GateRef hClass, GateRef value);
|
||||
|
@ -522,6 +522,9 @@ void HeapSnapShot::FillEdges(JSThread *thread)
|
||||
for (auto const &it : nameResources) {
|
||||
JSTaggedValue toValue = it.second;
|
||||
Node *entryTo = nullptr;
|
||||
if (toValue.IsWeak()) {
|
||||
toValue.RemoveWeakTag();
|
||||
}
|
||||
if (toValue.IsHeapObject()) {
|
||||
auto *to = reinterpret_cast<TaggedObject *>(toValue.GetHeapObject());
|
||||
entryTo = entryMap_.FindEntry(Node::NewAddress(to));
|
||||
|
@ -357,9 +357,6 @@ static void DumpHClass(JSThread *thread, const JSHClass *jshclass, std::ostream
|
||||
if (withDetail && !transtions.IsNull()) {
|
||||
transtions.Dump(thread, os);
|
||||
}
|
||||
os << " - Parent :" << std::setw(DUMP_TYPE_OFFSET);
|
||||
jshclass->GetParent().DumpTaggedValue(thread, os);
|
||||
os << "\n";
|
||||
|
||||
os << " - Flags : " << std::setw(DUMP_TYPE_OFFSET);
|
||||
os << "Ctor :" << jshclass->IsConstructor();
|
||||
@ -724,7 +721,7 @@ void JSTaggedValue::DumpHeapObjectType([[maybe_unused]] JSThread *thread, std::o
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
JSType type = GetTaggedObject()->GetClass()->GetObjectType();
|
||||
JSType type = obj->GetClass()->GetObjectType();
|
||||
if (type == JSType::STRING) {
|
||||
CString string = ConvertToString(EcmaString::Cast(obj));
|
||||
os << std::left << std::setw(DUMP_TYPE_OFFSET) << "[" + string + "]";
|
||||
|
@ -33,14 +33,14 @@ void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &
|
||||
const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes)
|
||||
{
|
||||
JSTaggedValue transitions = parent->GetTransitions();
|
||||
if (transitions.IsNull()) {
|
||||
parent->SetTransitions(thread, child.GetTaggedValue());
|
||||
child->SetParent(thread, parent.GetTaggedValue());
|
||||
if (transitions.IsUndefined()) {
|
||||
JSTaggedValue weakChild = JSTaggedValue(child.GetTaggedValue().CreateAndGetWeakRef());
|
||||
parent->SetTransitions(thread, weakChild);
|
||||
return;
|
||||
}
|
||||
JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
|
||||
if (transitions.IsJSHClass()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedObject());
|
||||
if (transitions.IsWeak()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
|
||||
int last = cachedHClass->NumberOfProps() - 1;
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
|
||||
auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
|
||||
@ -54,7 +54,6 @@ void JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &
|
||||
transitions =
|
||||
TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), attr).GetTaggedValue();
|
||||
parent->SetTransitions(thread, transitions);
|
||||
child->SetParent(thread, parent.GetTaggedValue());
|
||||
}
|
||||
|
||||
void JSHClass::AddExtensionTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent,
|
||||
@ -70,10 +69,10 @@ void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle<JSHCla
|
||||
{
|
||||
JSTaggedValue transitions = parent->GetTransitions();
|
||||
JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined());
|
||||
if (transitions.IsNull()) {
|
||||
if (transitions.IsUndefined()) {
|
||||
transitions = TransitionsDictionary::Create(thread).GetTaggedValue();
|
||||
} else if (transitions.IsJSHClass()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedObject());
|
||||
} else if (transitions.IsWeak()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
|
||||
int last = cachedHClass->NumberOfProps() - 1;
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
|
||||
auto attr = JSHandle<JSTaggedValue>(thread, JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData()));
|
||||
@ -87,18 +86,17 @@ void JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle<JSHCla
|
||||
transitions =
|
||||
TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), proto).GetTaggedValue();
|
||||
parent->SetTransitions(thread, transitions);
|
||||
child->SetParent(thread, parent.GetTaggedValue());
|
||||
}
|
||||
|
||||
inline JSHClass *JSHClass::FindTransitions(const JSTaggedValue &key, const JSTaggedValue &attributes)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
JSTaggedValue transitions = GetTransitions();
|
||||
if (transitions.IsNull()) {
|
||||
if (transitions.IsUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (transitions.IsJSHClass()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedObject());
|
||||
if (transitions.IsWeak()) {
|
||||
auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef());
|
||||
int last = cachedHClass->NumberOfProps() - 1;
|
||||
LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject());
|
||||
auto attr = layoutInfo->GetAttr(last).GetPropertyMetaData();
|
||||
@ -115,15 +113,21 @@ inline JSHClass *JSHClass::FindTransitions(const JSTaggedValue &key, const JSTag
|
||||
if (entry == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
return JSHClass::Cast(dict->GetValue(entry).GetTaggedObject());
|
||||
|
||||
JSTaggedValue ret = dict->GetValue(entry);
|
||||
if (ret.IsUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return JSHClass::Cast(ret.GetTaggedWeakRef());
|
||||
}
|
||||
|
||||
inline JSHClass *JSHClass::FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
JSTaggedValue transitions = GetTransitions();
|
||||
if (!transitions.IsTaggedArray()) {
|
||||
ASSERT(transitions.IsNull() || transitions.IsJSHClass());
|
||||
if (transitions.IsWeak() || !transitions.IsTaggedArray()) {
|
||||
ASSERT(transitions.IsUndefined() || transitions.IsWeak());
|
||||
return nullptr;
|
||||
}
|
||||
ASSERT(transitions.IsTaggedArray());
|
||||
@ -132,7 +136,13 @@ inline JSHClass *JSHClass::FindProtoTransitions(const JSTaggedValue &key, const
|
||||
if (entry == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
return JSHClass::Cast(dict->GetValue(entry).GetTaggedObject());
|
||||
|
||||
JSTaggedValue ret = dict->GetValue(entry);
|
||||
if (ret.IsUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return JSHClass::Cast(ret.GetTaggedWeakRef());
|
||||
}
|
||||
|
||||
inline void JSHClass::UpdatePropertyMetaData(const JSThread *thread, [[maybe_unused]] const JSTaggedValue &key,
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "ecmascript/weak_vector-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
// class TransitionsDictionary
|
||||
JSHandle<TransitionsDictionary> TransitionsDictionary::PutIfAbsent(const JSThread *thread,
|
||||
const JSHandle<TransitionsDictionary> &dictionary,
|
||||
const JSHandle<JSTaggedValue> &key,
|
||||
@ -46,7 +45,8 @@ JSHandle<TransitionsDictionary> TransitionsDictionary::PutIfAbsent(const JSThrea
|
||||
JSHandle<TransitionsDictionary> newDictionary(HashTableT::GrowHashTable(thread, dictionary));
|
||||
// Compute the key object.
|
||||
entry = newDictionary->FindInsertIndex(hash);
|
||||
newDictionary->SetEntry(thread, entry, key.GetTaggedValue(), value.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
JSTaggedValue val = value.GetTaggedValue();
|
||||
newDictionary->SetEntry(thread, entry, key.GetTaggedValue(), val, metaData.GetTaggedValue());
|
||||
|
||||
newDictionary->IncreaseEntries(thread);
|
||||
return newDictionary;
|
||||
@ -135,8 +135,7 @@ void JSHClass::Initialize(const JSThread *thread, uint32_t size, JSType type, ui
|
||||
SetExtensible(true);
|
||||
SetIsPrototype(false);
|
||||
SetElementRepresentation(Representation::NONE);
|
||||
SetTransitions(thread, JSTaggedValue::Null());
|
||||
SetParent(thread, JSTaggedValue::Null());
|
||||
SetTransitions(thread, JSTaggedValue::Undefined());
|
||||
SetProtoChangeMarker(thread, JSTaggedValue::Null());
|
||||
SetProtoChangeDetails(thread, JSTaggedValue::Null());
|
||||
SetEnumCache(thread, JSTaggedValue::Null());
|
||||
@ -151,8 +150,7 @@ JSHandle<JSHClass> JSHClass::Clone(const JSThread *thread, const JSHandle<JSHCla
|
||||
JSHandle<JSHClass> newJshclass = thread->GetEcmaVM()->GetFactory()->NewEcmaDynClass(size, type, numInlinedProps);
|
||||
// Copy all
|
||||
newJshclass->Copy(thread, *jshclass);
|
||||
newJshclass->SetParent(thread, JSTaggedValue::Null());
|
||||
newJshclass->SetTransitions(thread, JSTaggedValue::Null());
|
||||
newJshclass->SetTransitions(thread, JSTaggedValue::Undefined());
|
||||
newJshclass->SetProtoChangeDetails(thread, JSTaggedValue::Null());
|
||||
newJshclass->SetEnumCache(thread, JSTaggedValue::Null());
|
||||
// reuse Attributes first.
|
||||
@ -266,9 +264,9 @@ JSHandle<JSHClass> JSHClass::TransitionProto(const JSThread *thread, const JSHan
|
||||
JSHandle<JSHClass> newJshclass = JSHClass::Clone(thread, jshclass);
|
||||
newJshclass->SetPrototype(thread, proto.GetTaggedValue());
|
||||
|
||||
JSTaggedValue attrs = newJshclass->GetLayout();
|
||||
JSTaggedValue layout = newJshclass->GetLayout();
|
||||
{
|
||||
JSMutableHandle<LayoutInfo> layoutInfoHandle(thread, attrs);
|
||||
JSMutableHandle<LayoutInfo> layoutInfoHandle(thread, layout);
|
||||
layoutInfoHandle.Update(factory->CopyLayoutInfo(layoutInfoHandle).GetTaggedValue());
|
||||
newJshclass->SetLayout(thread, layoutInfoHandle);
|
||||
}
|
||||
|
@ -1105,10 +1105,9 @@ public:
|
||||
static constexpr size_t PROTOTYPE_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET);
|
||||
ACCESSORS(Layout, LAYOUT_OFFSET, TRANSTIONS_OFFSET);
|
||||
ACCESSORS(Transitions, TRANSTIONS_OFFSET, PARENT_OFFSET);
|
||||
ACCESSORS(Parent, PARENT_OFFSET, VALIDITY_CELL_OFFSET);
|
||||
ACCESSORS(ProtoChangeMarker, VALIDITY_CELL_OFFSET, PROTOTYPE_INFO_OFFSET);
|
||||
ACCESSORS(ProtoChangeDetails, PROTOTYPE_INFO_OFFSET, ENUM_CACHE_OFFSET);
|
||||
ACCESSORS(Transitions, TRANSTIONS_OFFSET, PROTO_CHANGE_MARKER_OFFSET);
|
||||
ACCESSORS(ProtoChangeMarker, PROTO_CHANGE_MARKER_OFFSET, PROTO_CHANGE_DETAILS_OFFSET);
|
||||
ACCESSORS(ProtoChangeDetails, PROTO_CHANGE_DETAILS_OFFSET, ENUM_CACHE_OFFSET);
|
||||
ACCESSORS(EnumCache, ENUM_CACHE_OFFSET, BIT_FIELD_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, BIT_FIELD1_OFFSET);
|
||||
ACCESSORS_PRIMITIVE_FIELD(BitField1, uint32_t, BIT_FIELD1_OFFSET, LAST_OFFSET)
|
||||
|
@ -48,6 +48,7 @@ public:
|
||||
parser->Add(&enableCpuprofiler_);
|
||||
parser->Add(&arkProperties_);
|
||||
parser->Add(&enableTsAot_);
|
||||
parser->Add(&maxNonmovableSpaceCapacity_);
|
||||
}
|
||||
|
||||
bool IsEnableArkTools() const
|
||||
|
@ -227,9 +227,31 @@ void ParallelEvacuation::UpdateRoot()
|
||||
objXRay_.VisitVMRoots(gcUpdateYoung, gcUpdateRangeYoung);
|
||||
}
|
||||
|
||||
void ParallelEvacuation::UpdateRecordWeakReference()
|
||||
{
|
||||
auto totalThreadCount = Platform::GetCurrentPlatform()->GetTotalThreadNum() + 1;
|
||||
for (uint32_t i = 0; i < totalThreadCount; i++) {
|
||||
ProcessQueue *queue = heap_->GetWorkList()->GetWeakReferenceQueue(i);
|
||||
|
||||
while (true) {
|
||||
auto obj = queue->PopBack();
|
||||
if (UNLIKELY(obj == nullptr)) {
|
||||
break;
|
||||
}
|
||||
ObjectSlot slot(ToUintPtr(obj));
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
ASSERT(value.IsWeak() || value.IsUndefined());
|
||||
if (!value.IsUndefined()) {
|
||||
UpdateWeakObjectSlot(value.GetTaggedWeakRef(), slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParallelEvacuation::UpdateWeakReference()
|
||||
{
|
||||
MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), UpdateWeakReference);
|
||||
UpdateRecordWeakReference();
|
||||
auto stringTable = heap_->GetEcmaVM()->GetEcmaStringTable();
|
||||
bool isFullMark = heap_->IsFullMark();
|
||||
WeakRootVisitor gcUpdateWeak = [isFullMark](TaggedObject *header) {
|
||||
|
@ -130,6 +130,7 @@ private:
|
||||
void UpdateReference();
|
||||
void UpdateRoot();
|
||||
void UpdateWeakReference();
|
||||
void UpdateRecordWeakReference();
|
||||
void UpdateRSet(Region *region);
|
||||
void UpdateNewRegionReference(Region *region);
|
||||
void UpdateAndSweepNewRegionReference(Region *region);
|
||||
|
@ -59,6 +59,10 @@ inline void NonMovableMarker::HandleRangeRoots(uint32_t threadId, [[maybe_unused
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
if (value.IsHeapObject()) {
|
||||
if (value.IsWeakForHeapObject()) {
|
||||
RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()));
|
||||
continue;
|
||||
}
|
||||
MarkObject(threadId, value.GetTaggedObject());
|
||||
}
|
||||
}
|
||||
@ -71,8 +75,12 @@ inline void NonMovableMarker::HandleOldToNewRSet(uint32_t threadId, Region *regi
|
||||
oldRSet->IterateOverMarkedChunks([this, threadId](void *mem) -> bool {
|
||||
ObjectSlot slot(ToUintPtr(mem));
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
if (value.IsHeapObject() && !value.IsWeakForHeapObject()) {
|
||||
MarkObject(threadId, value.GetTaggedObject());
|
||||
if (value.IsHeapObject()) {
|
||||
if (value.IsWeakForHeapObject()) {
|
||||
RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(mem));
|
||||
} else {
|
||||
MarkObject(threadId, value.GetTaggedObject());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@ -81,8 +89,9 @@ inline void NonMovableMarker::HandleOldToNewRSet(uint32_t threadId, Region *regi
|
||||
|
||||
inline void NonMovableMarker::RecordWeakReference(uint32_t threadId, JSTaggedType *ref)
|
||||
{
|
||||
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(ref));
|
||||
if (!objectRegion->InYoungGeneration()) {
|
||||
auto value = JSTaggedValue(*ref);
|
||||
Region *objectRegion = Region::ObjectAddressToRange(value.GetTaggedWeakRef());
|
||||
if (!objectRegion->InYoungOrCSetGeneration()) {
|
||||
heap_->GetWorkList()->PushWeakReference(threadId, ref);
|
||||
}
|
||||
}
|
||||
@ -101,7 +110,11 @@ inline void MovableMarker::HandleRangeRoots(uint32_t threadId, [[maybe_unused]]
|
||||
for (ObjectSlot slot = start; slot < end; slot++) {
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
if (value.IsHeapObject()) {
|
||||
MarkObject(threadId, value.GetTaggedObject(), slot);
|
||||
if (value.IsWeakForHeapObject()) {
|
||||
RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()));
|
||||
} else {
|
||||
MarkObject(threadId, value.GetTaggedObject(), slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ void NonMovableMarker::ProcessMarkStack(uint32_t threadId)
|
||||
obj = value.GetTaggedObject();
|
||||
MarkObject(threadId, obj);
|
||||
} else {
|
||||
RecordWeakReference(threadId, reinterpret_cast<JSTaggedType *>(slot.SlotAddress()));
|
||||
obj = value.GetWeakReferentUnChecked();
|
||||
}
|
||||
if (needBarrier) {
|
||||
|
@ -1042,12 +1042,12 @@ host_unittest_action("MemControllerTest") {
|
||||
}
|
||||
}
|
||||
|
||||
host_unittest_action("WeakRefGenGcTest") {
|
||||
host_unittest_action("WeakRefOldGcTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"weak_ref_gen_gc_test.cpp",
|
||||
"weak_ref_old_gc_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
@ -1069,12 +1069,12 @@ host_unittest_action("WeakRefGenGcTest") {
|
||||
}
|
||||
}
|
||||
|
||||
host_unittest_action("WeakRefStwGcTest") {
|
||||
host_unittest_action("WeakRefSemiGcTest") {
|
||||
module_out_path = module_output_path
|
||||
|
||||
sources = [
|
||||
# test file
|
||||
"weak_ref_stw_gc_test.cpp",
|
||||
"weak_ref_semi_gc_test.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
@ -1223,8 +1223,8 @@ group("unittest") {
|
||||
":SymbolTableTest",
|
||||
":TaggedTreeTest",
|
||||
":TaggedValueTest",
|
||||
":WeakRefGenGcTest",
|
||||
":WeakRefStwGcTest",
|
||||
":WeakRefOldGcTest",
|
||||
":WeakRefSemiGcTest",
|
||||
]
|
||||
}
|
||||
|
||||
@ -1273,7 +1273,7 @@ group("host_unittest") {
|
||||
":SymbolTableTestAction",
|
||||
":TaggedTreeTestAction",
|
||||
":TaggedValueTestAction",
|
||||
":WeakRefGenGcTestAction",
|
||||
":WeakRefStwGcTestAction",
|
||||
":WeakRefOldGcTestAction",
|
||||
":WeakRefSemiGcTestAction",
|
||||
]
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
|
||||
break;
|
||||
}
|
||||
case JSType::HCLASS: {
|
||||
CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 8)
|
||||
CHECK_DUMP_FILEDS(TaggedObject::TaggedObjectSize(), JSHClass::SIZE, 7)
|
||||
JSHandle<JSHClass> hclass = factory->NewEcmaDynClass(JSHClass::SIZE, JSType::HCLASS, proto);
|
||||
DUMP_FOR_HANDLE(hclass)
|
||||
break;
|
||||
|
@ -814,50 +814,38 @@ HWTEST_F_L0(JSObjectTest, SetterIsUndefined)
|
||||
JSTaggedValue(10));
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSObjectTest, HClass)
|
||||
HWTEST_F_L0(JSObjectTest, Transitions)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> objFunc(thread, JSObjectTestCreate(thread));
|
||||
JSHandle<JSObject> obj1 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
|
||||
JSHandle<JSHClass> hc0(thread, obj1->GetJSHClass());
|
||||
JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
|
||||
|
||||
JSHandle<JSHClass> hc1(thread, obj1->GetJSHClass());
|
||||
JSHandle<JSHClass> hc2(thread, obj2->GetJSHClass());
|
||||
EXPECT_EQ(hc1.GetTaggedValue(), hc2.GetTaggedValue());
|
||||
|
||||
JSHandle<JSTaggedValue> key1(factory->NewFromCanBeCompressString("x"));
|
||||
JSHandle<JSTaggedValue> key2(factory->NewFromCanBeCompressString("y"));
|
||||
JSHandle<JSTaggedValue> key3(factory->NewFromCanBeCompressString("z"));
|
||||
JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
|
||||
|
||||
// key1
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key1, value);
|
||||
JSHandle<JSHClass> hc1(thread, obj1->GetJSHClass());
|
||||
EXPECT_NE(hc0.GetTaggedValue(), hc1.GetTaggedValue());
|
||||
EXPECT_EQ(hc0.GetTaggedValue(), hc1->GetParent());
|
||||
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value);
|
||||
JSHandle<JSHClass> hc2(thread, obj1->GetJSHClass());
|
||||
EXPECT_NE(hc1.GetTaggedValue(), hc2.GetTaggedValue());
|
||||
EXPECT_EQ(hc1.GetTaggedValue(), hc2->GetParent());
|
||||
|
||||
JSHandle<JSObject> obj2 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
|
||||
EXPECT_EQ(hc0.GetTaggedValue().GetTaggedObject(), obj2->GetJSHClass());
|
||||
JSHandle<JSHClass> hc3(thread, obj1->GetJSHClass());
|
||||
EXPECT_NE(hc1.GetTaggedValue(), hc3.GetTaggedValue());
|
||||
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key1, value);
|
||||
EXPECT_EQ(hc1.GetTaggedValue().GetTaggedObject(), obj2->GetJSHClass());
|
||||
JSHandle<JSHClass> hc4(thread, obj2->GetJSHClass());
|
||||
EXPECT_EQ(hc3.GetTaggedValue(), hc4.GetTaggedValue());
|
||||
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key3, value);
|
||||
JSHandle<JSHClass> hc3(thread, obj2->GetJSHClass());
|
||||
EXPECT_NE(hc1.GetTaggedValue().GetTaggedObject(), obj2->GetJSHClass());
|
||||
EXPECT_EQ(hc1.GetTaggedValue(), obj2->GetJSHClass()->GetParent());
|
||||
// key2
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj1), key2, value);
|
||||
JSHandle<JSHClass> hc5(thread, obj1->GetJSHClass());
|
||||
EXPECT_NE(hc3.GetTaggedValue(), hc5.GetTaggedValue());
|
||||
|
||||
JSHandle<JSObject> obj3 = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFunc), objFunc);
|
||||
EXPECT_EQ(hc0.GetTaggedValue().GetTaggedObject(), obj3->GetJSHClass());
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key1, value);
|
||||
EXPECT_EQ(hc1.GetTaggedValue().GetTaggedObject(), obj3->GetJSHClass());
|
||||
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key2, value);
|
||||
EXPECT_EQ(hc2.GetTaggedValue().GetTaggedObject(), obj3->GetJSHClass());
|
||||
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj3), key3, value);
|
||||
EXPECT_NE(hc3.GetTaggedValue().GetTaggedObject(), obj3->GetJSHClass());
|
||||
EXPECT_EQ(hc2.GetTaggedValue(), obj3->GetJSHClass()->GetParent());
|
||||
JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj2), key2, value);
|
||||
JSHandle<JSHClass> hc6(thread, obj2->GetJSHClass());
|
||||
EXPECT_EQ(hc5.GetTaggedValue(), hc6.GetTaggedValue());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(JSObjectTest, FastToSlow)
|
||||
|
@ -23,7 +23,7 @@
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
class WeakRefGenGCTest : public testing::Test {
|
||||
class WeakRefOldGCTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
@ -50,7 +50,6 @@ public:
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static JSObject *JSObjectTestCreate(JSThread *thread)
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
|
||||
@ -62,9 +61,7 @@ static JSObject *JSObjectTestCreate(JSThread *thread)
|
||||
ecmaVM->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc1), jsFunc1);
|
||||
return *newObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static TaggedArray *ArrayTestCreate(JSThread *thread)
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
|
||||
@ -72,11 +69,9 @@ static TaggedArray *ArrayTestCreate(JSThread *thread)
|
||||
JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);
|
||||
return *array;
|
||||
}
|
||||
#endif
|
||||
|
||||
HWTEST_F_L0(WeakRefGenGCTest, ArrayNonMovable)
|
||||
HWTEST_F_L0(WeakRefOldGCTest, ArrayNonMovable)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto array = vm->GetFactory()->NewTaggedArray(2, JSTaggedValue::Undefined(), true);
|
||||
JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
|
||||
@ -88,15 +83,13 @@ HWTEST_F_L0(WeakRefGenGCTest, ArrayNonMovable)
|
||||
array->Set(thread, 1, value);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(value, array->Get(1));
|
||||
vm->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
vm->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefGenGCTest, ArrayUndefined)
|
||||
HWTEST_F_L0(WeakRefOldGCTest, ArrayUndefined)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
|
||||
EXPECT_TRUE(*array != nullptr);
|
||||
@ -109,15 +102,13 @@ HWTEST_F_L0(WeakRefGenGCTest, ArrayUndefined)
|
||||
array->Set(thread, 1, value);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(value, array->Get(1));
|
||||
ecmaVM->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
ecmaVM->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefGenGCTest, ArrayKeep)
|
||||
HWTEST_F_L0(WeakRefOldGCTest, ArrayKeep)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
|
||||
EXPECT_TRUE(*array != nullptr);
|
||||
@ -130,41 +121,36 @@ HWTEST_F_L0(WeakRefGenGCTest, ArrayKeep)
|
||||
array->Set(thread, 1, value);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(value, array->Get(1));
|
||||
ecmaVM->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
ecmaVM->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(true, array->Get(1).IsWeak());
|
||||
value = newObj2.GetTaggedValue();
|
||||
value.CreateWeakRef();
|
||||
EXPECT_EQ(value, array->Get(1));
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefGenGCTest, DynObjectUndefined)
|
||||
HWTEST_F_L0(WeakRefOldGCTest, DynObjectUndefined)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
|
||||
JSTaggedValue array(ArrayTestCreate(thread));
|
||||
array.CreateWeakRef();
|
||||
newObj1->SetElements(thread, array);
|
||||
EXPECT_EQ(newObj1->GetElements(), array);
|
||||
thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
EXPECT_EQ(newObj1->GetElements(), JSTaggedValue::Undefined());
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefGenGCTest, DynObjectKeep)
|
||||
HWTEST_F_L0(WeakRefOldGCTest, DynObjectKeep)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
|
||||
JSHandle<TaggedArray> array(thread, ArrayTestCreate(thread));
|
||||
JSTaggedValue value = array.GetTaggedValue();
|
||||
value.CreateWeakRef();
|
||||
newObj1->SetElements(thread, value);
|
||||
EXPECT_EQ(newObj1->GetElements(), value);
|
||||
thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
thread->GetEcmaVM()->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
value = array.GetTaggedValue();
|
||||
value.CreateWeakRef();
|
||||
EXPECT_EQ(newObj1->GetElements(), value);
|
||||
#endif
|
||||
}
|
||||
} // namespace panda::test
|
@ -23,7 +23,7 @@
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
class WeakRefStwGCTest : public testing::Test {
|
||||
class WeakRefSemiGCTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
@ -50,7 +50,6 @@ public:
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static JSObject *JSObjectTestCreate(JSThread *thread)
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
|
||||
@ -61,9 +60,7 @@ static JSObject *JSObjectTestCreate(JSThread *thread)
|
||||
ecmaVM->GetFactory()->NewJSObjectByConstructor(JSHandle<JSFunction>(jsFunc), jsFunc);
|
||||
return *newObj;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
static TaggedArray *ArrayTestCreate(JSThread *thread)
|
||||
{
|
||||
[[maybe_unused]] ecmascript::EcmaHandleScope scope(thread);
|
||||
@ -71,11 +68,9 @@ static TaggedArray *ArrayTestCreate(JSThread *thread)
|
||||
JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(2);
|
||||
return *array;
|
||||
}
|
||||
#endif
|
||||
|
||||
HWTEST_F_L0(WeakRefStwGCTest, ArrayUndefined)
|
||||
HWTEST_F_L0(WeakRefSemiGCTest, ArrayUndefined)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
|
||||
EXPECT_TRUE(*array != nullptr);
|
||||
@ -91,12 +86,10 @@ HWTEST_F_L0(WeakRefStwGCTest, ArrayUndefined)
|
||||
ecmaVM->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
EXPECT_EQ(newObj1.GetTaggedValue(), array->Get(0));
|
||||
EXPECT_EQ(JSTaggedValue::Undefined(), array->Get(1));
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefStwGCTest, ArrayKeep)
|
||||
HWTEST_F_L0(WeakRefSemiGCTest, ArrayKeep)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
EcmaVM *ecmaVM = thread->GetEcmaVM();
|
||||
JSHandle<TaggedArray> array = ecmaVM->GetFactory()->NewTaggedArray(2);
|
||||
EXPECT_TRUE(*array != nullptr);
|
||||
@ -115,12 +108,10 @@ HWTEST_F_L0(WeakRefStwGCTest, ArrayKeep)
|
||||
value = newObj2.GetTaggedValue();
|
||||
value.CreateWeakRef();
|
||||
EXPECT_EQ(value, array->Get(1));
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefStwGCTest, DynObjectUndefined)
|
||||
HWTEST_F_L0(WeakRefSemiGCTest, DynObjectUndefined)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
|
||||
JSTaggedValue array(ArrayTestCreate(thread));
|
||||
array.CreateWeakRef();
|
||||
@ -128,12 +119,10 @@ HWTEST_F_L0(WeakRefStwGCTest, DynObjectUndefined)
|
||||
EXPECT_EQ(newObj1->GetElements(), array);
|
||||
thread->GetEcmaVM()->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
EXPECT_EQ(newObj1->GetElements(), JSTaggedValue::Undefined());
|
||||
#endif
|
||||
}
|
||||
|
||||
HWTEST_F_L0(WeakRefStwGCTest, DynObjectKeep)
|
||||
HWTEST_F_L0(WeakRefSemiGCTest, DynObjectKeep)
|
||||
{
|
||||
#if !defined(NDEBUG)
|
||||
JSHandle<JSObject> newObj1(thread, JSObjectTestCreate(thread));
|
||||
JSHandle<TaggedArray> array(thread, ArrayTestCreate(thread));
|
||||
JSTaggedValue value = array.GetTaggedValue();
|
||||
@ -144,6 +133,5 @@ HWTEST_F_L0(WeakRefStwGCTest, DynObjectKeep)
|
||||
value = array.GetTaggedValue();
|
||||
value.CreateWeakRef();
|
||||
EXPECT_EQ(newObj1->GetElements(), value);
|
||||
#endif
|
||||
}
|
||||
} // namespace panda::test
|
||||
} // namespace panda::test
|
@ -96,17 +96,19 @@ public:
|
||||
int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
|
||||
return HashTableT::Get(index);
|
||||
}
|
||||
|
||||
inline void SetAttributes(const JSThread *thread, int entry, JSTaggedValue metaData)
|
||||
{
|
||||
int index = GetEntryIndex(entry) + ENTRY_DETAILS_INDEX;
|
||||
HashTableT::Set(thread, index, metaData);
|
||||
}
|
||||
|
||||
inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value,
|
||||
inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, JSTaggedValue &value,
|
||||
const JSTaggedValue &metaData)
|
||||
{
|
||||
SetKey(thread, entry, key);
|
||||
SetValue(thread, entry, value);
|
||||
JSTaggedValue weakValue = JSTaggedValue(value.CreateAndGetWeakRef());
|
||||
SetValue(thread, entry, weakValue);
|
||||
SetAttributes(thread, entry, metaData);
|
||||
}
|
||||
|
||||
@ -135,4 +137,4 @@ public:
|
||||
DECL_DUMP()
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif
|
||||
#endif
|
||||
|
@ -35,4 +35,7 @@ group("ark_js_moduletest") {
|
||||
"throwdyn:throwdynAction",
|
||||
"yieldstar:yieldstarAction",
|
||||
]
|
||||
if (!is_debug) {
|
||||
deps += [ "weaktransitions:weaktransitionsAction" ]
|
||||
}
|
||||
}
|
||||
|
19
test/moduletest/weaktransitions/BUILD.gn
Normal file
19
test/moduletest/weaktransitions/BUILD.gn
Normal file
@ -0,0 +1,19 @@
|
||||
# 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.
|
||||
|
||||
import("//ark/js_runtime/test/test_helper.gni")
|
||||
|
||||
host_moduletest_action("weaktransitions") {
|
||||
deps = []
|
||||
is_set_maxNonmovableSpaceCapacity = true
|
||||
}
|
14
test/moduletest/weaktransitions/expect_output.txt
Normal file
14
test/moduletest/weaktransitions/expect_output.txt
Normal file
@ -0,0 +1,14 @@
|
||||
# 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.
|
||||
|
||||
success
|
33
test/moduletest/weaktransitions/weaktransitions.js
Normal file
33
test/moduletest/weaktransitions/weaktransitions.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var count = 0;
|
||||
|
||||
function addProperty(obj, index) {
|
||||
let key = count.toString() + "-" +index.toString() + "key";
|
||||
let val = {value: index.toString() + "value"};
|
||||
Object.defineProperty(obj, key, val);
|
||||
}
|
||||
|
||||
for (let idx = 0; idx < 1000; ++idx) {
|
||||
let o = {a:1};
|
||||
for (let i = 0; i < 1000; ++i) {
|
||||
addProperty(o, i);
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
print("success");
|
@ -30,6 +30,7 @@ def parse_args():
|
||||
"""parse arguments."""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--script-file', help='execute script file')
|
||||
parser.add_argument('--script-options', help='execute script options')
|
||||
parser.add_argument('--script-args', help='args of script')
|
||||
parser.add_argument('--expect-output', help='expect output')
|
||||
parser.add_argument('--expect-file', help='expect file')
|
||||
@ -42,6 +43,8 @@ def judge_output(args):
|
||||
"""run testcase and judge is success or not."""
|
||||
start_time = time.time()
|
||||
cmd = input_args.script_file
|
||||
if input_args.script_options:
|
||||
cmd += input_args.script_options
|
||||
if input_args.script_args:
|
||||
cmd += " " + input_args.script_args
|
||||
subp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
||||
|
@ -119,9 +119,17 @@ template("host_moduletest_action") {
|
||||
|
||||
script = "//ark/js_runtime/test/run_ark_executable.py"
|
||||
|
||||
js_vm_options = " "
|
||||
if (defined(invoker.is_set_maxNonmovableSpaceCapacity) &&
|
||||
invoker.is_set_maxNonmovableSpaceCapacity) {
|
||||
js_vm_options += "--maxNonmovableSpaceCapacity=524288" # 0.5M
|
||||
}
|
||||
|
||||
args = [
|
||||
"--script-file",
|
||||
rebase_path(_root_out_dir_) + "/ark/ark_js_runtime/ark_js_vm",
|
||||
"--script-options",
|
||||
js_vm_options,
|
||||
"--script-args",
|
||||
_test_abc_paths_,
|
||||
"--expect-file",
|
||||
|
Loading…
Reference in New Issue
Block a user